Re: [PATCH] usb: dwc2: Disable gadget descriptor DMA for Sophgo CV18XX/SG200X
From: Vadim Yuzifovich
Date: Thu Oct 29 2026 - 03:33:00 EST
On Fri, Oct 24, 2026 at 07:52:20PM +0800, Chen-Yu Yeh wrote:
> dwc2_set_cv1800_params() disables gadget DMA (g_dma) but leaves
> g_dma_desc at its default, which dwc2_set_default_params() takes from
> the hardware capability. Descriptor DMA requires g_dma, so
> dwc2_check_params() rejects the combination at probe time:
With g_dma off this only removes the warning, so no objection to the
patch itself.
For the record, in case someone later wants gadget DMA on this SoC:
we run the SG2002 (NanoKVM, DWC_otg 4.20a) as a peripheral with g_dma
and g_dma_desc both on (mass storage, HID, ACM, UAC1). Descriptor DMA
works there, but only with three dwc2 changes. Without them it is not
usable, which may be why the platform parameters turn DMA off.
1. Bulk and interrupt endpoints raise BNA and are never restarted.
With the video pipeline loading DRAM, the mass-storage bulk IN
endpoint hit BNA every minute or two. dwc2 only logs that at debug
level. The endpoint stayed disabled with an 18-byte REQUEST SENSE
reply current and the CSW queued behind it, the host's command timed
out after 30 s and it reset the port, taking HID and the console
with it. Once, after a run of resets, the reset itself wedged the
core. When read in the BNA handler, the descriptor is host ready,
last, short, IOC, 18 bytes (0x0e000012).
2. The cause: the core fetches the descriptor before the CPU's stores
reach DRAM.
dwc2 writes the chain to coherent memory and then enables the
endpoint with writel(), whose fence orders the stores before the
MMIO write. On the C906 that is not enough. A host sent TEST UNIT
READY (plus REQUEST SENSE) to a CD-ROM LUN as fast as it could,
about 2600 a second, while a 1080p60 H.264 stream loaded DRAM.
About 0.8% of transfer starts raised BNA, 99.5% of them within
20 us of the enable, with DxEPDMA still at the head of the chain.
Without the stream: none in 254000 commands.
BNAs per variant, on one boot (diagnostic build, about 780000
transfer starts a minute each):
as is 6215, 6510
mb(), read last descriptor back, mb() 0
th.sync.s 0
udelay(2) 2
descriptor as two word stores, status last,
dma_wmb() between 3728
Mapping coherent memory non-bufferable (MAE type SH) did not change
the rate. Reading the last descriptor of the chain back between two
full fences before setting EPENA fixed it: none in 6.2 million
transfer starts under the same flood, and none in a 60 minute run
at 1080p60.
3. Isochronous OUT endpoints are not restarted after BNA.
After a BNA, dwc2_gadget_handle_ep_disabled() runs its buffer DMA
frame loop and moves target_frame off TARGET_FRAME_INITIAL, so the
OUT token handler never restarts the chain. Meanwhile the core
raises BNA for the disabled endpoint as fast as the handler clears
it. With a UAC1 capture endpoint and eight requests, one 8 ms
interrupt latency was enough to take the whole core until the host
reset the port.
(1) and (3) look generic to dwc2 descriptor DMA. (2) is specific to
the C906 or this SoC's interconnect. We have not checked whether other
drivers that rely on writel() to order coherent-memory stores are
affected too.
The patches, against 7.3:
https://www.google.com/url?q=https://github.com/yuzi-co/linux-sg2002/commit/80fca5c88a2c&source=gmail&ust=1793345520406000&sa=E
https://www.google.com/url?q=https://github.com/yuzi-co/linux-sg2002/commit/ea6319d5d4e1&source=gmail&ust=1793345520406000&sa=E
https://www.google.com/url?q=https://github.com/yuzi-co/linux-sg2002/commit/1efd0cda1069&source=gmail&ust=1793345520406000&sa=E
If there is interest, I can post them as a series.