Re: [PATCH v5 00/75] usb: dwc3: sync code with Linux v6.16

Anders Roxell <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <anzDvgtMh_7Fl9Ig@monster>
On 2026-08-10 15:26, Anshul Dalal wrote:
> On Mon Aug 10, 2026 at 1:52 PM IST, Anders Roxell wrote:
> > On 2026-08-06 18:47, Anshul Dalal wrote:
> >> On Thu, 16 Jul 2026 15:41:30 +0200, Anders Roxell <[email protected]> wrote:
> >> > [...]

[...]

> >
> > And in dwc3_gadget_uboot_handle_interrupt(), same file:
> >
> > -		struct dwc3_event_buffer *evt;
> > -		dwc3_thread_interrupt(0, dwc);
> > +		struct dwc3_event_buffer *evt = dwc->ev_buf;
> > +		dwc3_thread_interrupt(0, evt);
> 
> Thanks for the pointers Anders but I encounter a similar failure even
> with the diff you suggested. I enabled some logging for the SPL by
> defining the DEBUG macro in the following files (dfu.c spl.c spl_ram.c
> dwc3-am62.c composite.c g_dnl.c).

Hi Anshul,

Good news. I found two more bugs on top of the two I already sent you
(the event buffer and allow_connect). With all four the device
enumerates.

> 
> Failure logs:
> 
> 	U-Boot SPL 2026.07-00860-g5a9b7a715be2 (Aug 10 2026 - 15:06:27 +0530)
> 	SYSFW ABI: 4.0 (firmware rev 0x000c '12.1.0--v12.01.00 (Clever Cat)')
> 	Set clock rates for '/a53@0', CPU: 1250MHz at Speed Grade 'V'
> 	SPL initial stack usage: 17104 bytes
> 	SPL malloc() before relocation used 0x64d0 bytes (25 KB)
> 	>>SPL: board_init_r()
> 	spl_init
> 	Trying to boot from DFU
> 	g_dnl_register: g_dnl_driver.name = usb_dnl_dfu
> 	g_dnl_bind: gadget: 0x81c44a98 cdev: 0x81c66bc0
> 	usb_add_config: adding config #1 'usb_dnload'/81c67cc0
> 	g_dnl_do_config: configuration: 0x81c67cc0 composite dev: 0x81c66bc0
> 	adding 'dfu'/81c67d34 to config 'usb_dnload'/81c67cc0
> 	cfg 1/81c67cc0 speeds: high full
> 	usb_add_config: interface 0 = dfu/81c67d34
> 	g_dnl_bind: calling usb_gadget_connect for controller 'dwc3-gadget'
> 	usb_dnl_dfu: ready
> 
> <CTRL-C> from user
> 
> 	unbind function 'dfu'/81c67d34
> 	g_dnl_unbind: calling usb_gadget_disconnect for controller 'dwc3-gadget'
> 	Legacy image
> 	u_boot_pos = ffffffff
> 	Raw boot image support not enabled, proceeding to other boot methods
> 	Error: -22
> 	SPL: Unsupported Boot Device!
> 	SPL: failed to boot from all boot devices
> 	### ERROR ### Please RESET the board ###
> 
> Succes logs (same debug symbols ontop of main branch):
> 
> 	U-Boot SPL 2026.10-rc1-00209-g0bdd5e5daf95 (Aug 10 2026 - 14:58:28 +0530)
> 	SYSFW ABI: 4.0 (firmware rev 0x000c '12.1.0--v12.01.00 (Clever Cat)')
> 	Set clock rates for '/a53@0', CPU: 1250MHz at Speed Grade 'V'
> 	SPL initial stack usage: 17104 bytes
> 	SPL malloc() before relocation used 0x64d0 bytes (25 KB)
> 	>>SPL: board_init_r()
> 	spl_init
> 	Trying to boot from DFU
> 	g_dnl_register: g_dnl_driver.name = usb_dnl_dfu
> 	g_dnl_bind: gadget: 0x81c44aa4 cdev: 0x81c4af40
> 	usb_add_config: adding config #1 'usb_dnload'/81c4c040
> 	g_dnl_do_config: configuration: 0x81c4c040 composite dev: 0x81c4af40
> 	adding 'dfu'/81c4c0b4 to config 'usb_dnload'/81c4c040
> 	cfg 1/81c4c040 speeds: high full
> 	usb_add_config: interface 0 = dfu/81c4c0b4
> 	g_dnl_bind: calling usb_gadget_connect for controller 'dwc3-gadget'
> 	usb_dnl_dfu: ready
> 	composite_suspend: suspend
> 	set_config: high speed config #1: usb_dnload
> 	non-core control reqa1.03 v0000 i0000 l6
> 	non-core control req21.01 v0000 i0000 l4096
> ...(repeated)
> 	#non-core control reqa1.03 v0000 i0000 l6
> 	non-core control reqa1.03 v0000 i0000 l6
> 	DOWNLOAD ... OK
> 	Ctrl+C to exit ...
> 
> I'm not that familiar with the DW3 driver, let me know if you need me to
> test with any further changes.
> 
> >
> > evt was used there without being set as well.
> >
> > All of this is in v6 that I plan to send out. I have no AM62p and it is
> > only compile tested, so please try it on your board so we know if it
> > solves your issue before I send out v6.
> 
> I was able to reproduce the issue on beagleplay since it uses the same
> DWC3. You can try it locally if you have that board with you by
> resetting to DFU mode from U-Boot prompt:
> 
> => mw.w 43000030 53; res

I could not use the mw.w 43000030 53; res trick on the BeagleBoard-X15
that I found. But I can run DFU directly, it is the same DWC3 gadget
path you hit.

How I tested on x15:

  env set dfu_alt_info "${dfu_alt_info_ram}"
  dfu 0 ram 0

On the host dfu-util finds it:

  Found DFU: [0451:d022] ... name="kernel"/"fdt"/"ramdisk"

The two new bugs:

3. udc-core never sets dwc->async_callbacks. So the gadget setup() is
   never called and every GET_DESCRIPTOR returns -EINVAL.

4. ep0. The trb and the ep0 buffers are normal cached memory. In u-boot
   dma_alloc_coherent is not coherent, so nothing keeps them in sync with
   the controller dma. The resync dropped the manual flush and invalidate,
   so the controller reads a stale trb and stale buffers.

The patch below is only 3 and 4. Keep the first two you already have,
this goes on top. It is against v5. I built it and tested it on x15,
it works.

Can you test it on BeaglePlay with your reset trick? These fixes will
be part of the coming usb_dwc3_sync_v6 branch.

Cheers,
Anders


diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 0a4f69cbc28a..2ba05fc3f573 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -54,6 +54,9 @@ static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep,
 	else
 		trb->ctrl |= (DWC3_TRB_CTRL_IOC
 				| DWC3_TRB_CTRL_LST);
+
+	dwc3_flush_cache((uintptr_t)buf_dma, len);
+	dwc3_flush_cache((uintptr_t)trb, sizeof(*trb));
 }
 
 static int dwc3_ep0_start_trans(struct dwc3_ep *dep)
@@ -811,6 +814,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
 	int ret = -EINVAL;
 	u32 len;
 
+	dwc3_invalidate_cache((uintptr_t)ctrl, sizeof(*ctrl));
+
 	if (!dwc->gadget_driver || !dwc->softconnect || !dwc->connected)
 		goto out;
 
@@ -856,6 +861,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
 	trb = dwc->ep0_trb;
 
+	dwc3_invalidate_cache((uintptr_t)trb, sizeof(*trb) * 2);
+
 	r = next_request(&ep0->pending_list);
 	if (!r)
 		return;
@@ -873,6 +880,9 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 
 	length = trb->size & DWC3_TRB_SIZE_MASK;
 	transferred = ur->length - length;
+
+	if (ur->buf && !r->direction)
+		dwc3_invalidate_cache((uintptr_t)ur->dma, ur->length);
 	ur->actual += transferred;
 
 	if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index 6355931f9ff1..f03ff937dfde 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -941,6 +941,8 @@ static inline void usb_gadget_udc_set_speed(struct usb_udc *udc,
 		gadget->ops->udc_set_speed(gadget, s);
 }
 
+static inline void usb_gadget_enable_async_callbacks(struct usb_udc *udc);
+
 static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver)
 {
         int ret;
@@ -960,6 +962,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
                 driver->unbind(udc->gadget);
                 goto err1;
         }
+        usb_gadget_enable_async_callbacks(udc);
         udc->allow_connect = true;
         usb_gadget_connect(udc->gadget);
 
@@ -1156,6 +1159,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 			udc->driver->function);
 
 	udc->allow_connect = false;
+	usb_gadget_disable_async_callbacks(udc);
 	usb_gadget_disconnect(udc->gadget);
 	udc->driver->disconnect(udc->gadget);
 	udc->driver->unbind(udc->gadget);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.