[PATCH v4 00/64] drivers: usb: dwc3: sync code with Linux v6.16
Mattijs Korpershoek
mkorpershoek at kernel.org
Wed Jul 1 12:51:24 CEST 2026
Hi Jens,
On Tue, Jun 30, 2026 at 15:38, Mattijs Korpershoek <mkorpershoek at kernel.org> wrote:
> On Tue, Jun 30, 2026 at 11:36, Mattijs Korpershoek <mkorpershoek at kernel.org> wrote:
>
>>
>> I've tried this out on the Khadas VIM3 board using
>> khadas-vim3_android_defconfig and usb gadget (with fastboot) seems to
>> misbehave.
>>
>> With the series applied, I see:
>> """
>> U-Boot 2026.07-rc3-00064-g511db6941796 (Jun 30 2026 - 11:20:08 +0200) khadas-vim3
>>
>> Model: Khadas VIM3
>> SoC: Amlogic Meson G12B (A311D) Revision 29:b (10:2)
>> DRAM: 2 GiB (total 3.8 GiB)
>> Core: 408 devices, 37 uclasses, devicetree: separate
>> MMC: mmc at ffe03000: 0, mmc at ffe05000: 1, mmc at ffe07000: 2
>> Loading Environment from MMC... MMC Device -1 not found
>> *** Warning - No MMC card found, using default environment
>>
>> In: usbkbd,serial
>> Out: vidconsole,serial
>> Err: vidconsole,serial
>> Net: eth0: ethernet at ff3f0000
>>
>> Hit any key to stop autoboot: 0
>> => fastboot usb 0
>> failed to start <NULL>: -12
>> g_dnl_register: failed!, error: -12
>> exit not allowed from main input shell.
>> """
>>
>> With v2026.07-rc3, I see:
>> """
>> U-Boot 2026.07-rc3 (Jun 30 2026 - 11:24:04 +0200) khadas-vim3
>>
>> Model: Khadas VIM3
>> SoC: Amlogic Meson G12B (A311D) Revision 29:b (10:2)
>> DRAM: 2 GiB (total 3.8 GiB)
>> Core: 408 devices, 37 uclasses, devicetree: separate
>> MMC: mmc at ffe03000: 0, mmc at ffe05000: 1, mmc at ffe07000: 2
>> Loading Environment from MMC... MMC Device -1 not found
>> *** Warning - No MMC card found, using default environment
>>
>> In: usbkbd,serial
>> Out: vidconsole,serial
>> Err: vidconsole,serial
>> Net: eth0: ethernet at ff3f0000
>>
>> Hit any key to stop autoboot: 0
>> => fastboot usb 0
>> crq->brequest:0x0
>> """
>>
>> The failure code path seems to go through:
>> g_dnl_register("usb_dnl_fastboot");
>> usb_composite_register(&g_dnl_driver);
>> usb_gadget_register_driver(&composite_driver);
>> usb_gadget_probe_driver(driver);
>> udc_bind_to_driver(udc, driver);
>> driver->bind(udc->gadget);
>>
>>
>> I don't know why it's happening but I wanted to give some feedback early
>> on.
>> I'll have a closer look.
>
> I spend a bit more time on this.
>
> driver->bind() calls fastboot_bind() which fails to configure the input
> endpoint with the following code:
>
> f_fb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
>
> Looking more closely at usb_ep_autoconfig():
> * in v2026.07-rc3 we have an ep_matches() that finds the relevant
> endpoint
> * with this series, we now have usb_gadget_ep_match_desc() which does
> not behave the same way.
>
> If i put back the original ep_matches() implementation (from
> v2026.07-rc3) and call that instead of usb_gadget_ep_match_desc() in
> usb_ep_autoconfig_ss(), I can use fastboot again.
>
> I have not studied how different ep_matches() and
> usb_gadget_ep_match_desc() are.
usb_gadget_ep_match_desc() uses the endpoint's capabilities (the cap
member of that struct) to find matching endpoints.
This is significantly different from ep_matches(), which relied on
endpoint names.
Because of this change, I had to add the following diff to
drivers/usb/gadget/dwc2_udc_otg.c:
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 9f037d1e8016..01c9a938bd79 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -741,6 +741,7 @@ static const struct usb_gadget_ops dwc2_udc_ops = {
#endif
};
static struct dwc2_udc memory = {
.usb_address = 0,
.gadget = {
@@ -755,6 +756,11 @@ static struct dwc2_udc memory = {
.name = ep0name,
.ops = &dwc2_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = {
+ .type_control = 1,
+ .dir_in = 1,
+ .dir_out = 1,
+ },
},
.dev = &memory,
@@ -770,6 +776,10 @@ static struct dwc2_udc memory = {
.name = "ep1in-bulk",
.ops = &dwc2_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = {
+ .type_bulk = 1,
+ .dir_in = 1,
+ },
},
.dev = &memory,
@@ -785,6 +795,10 @@ static struct dwc2_udc memory = {
.name = "ep2out-bulk",
.ops = &dwc2_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = {
+ .type_bulk = 1,
+ .dir_out = 1,
+ },
},
.dev = &memory,
@@ -800,6 +814,10 @@ static struct dwc2_udc memory = {
.name = "ep3in-int",
.ops = &dwc2_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = {
+ .type_int = 1,
+ .dir_in = 1,
+ },
},
This was not sufficient. I also had to update the .maxpacket fields to
.maxpacket_limit as following:
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 01c9a938bd79..4a62cd60cb7d 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -755,7 +755,7 @@ static struct dwc2_udc memory = {
.ep = {
.name = ep0name,
.ops = &dwc2_ep_ops,
- .maxpacket = EP0_FIFO_SIZE,
+ .maxpacket_limit = EP0_FIFO_SIZE,
.caps = {
.type_control = 1,
.dir_in = 1,
@@ -775,7 +775,7 @@ static struct dwc2_udc memory = {
.ep = {
.name = "ep1in-bulk",
.ops = &dwc2_ep_ops,
- .maxpacket = EP_FIFO_SIZE,
+ .maxpacket_limit = EP_FIFO_SIZE,
.caps = {
.type_bulk = 1,
.dir_in = 1,
@@ -794,7 +794,7 @@ static struct dwc2_udc memory = {
.ep = {
.name = "ep2out-bulk",
.ops = &dwc2_ep_ops,
- .maxpacket = EP_FIFO_SIZE,
+ .maxpacket_limit = EP_FIFO_SIZE,
.caps = {
.type_bulk = 1,
.dir_out = 1,
@@ -813,7 +813,7 @@ static struct dwc2_udc memory = {
.ep = {
.name = "ep3in-int",
.ops = &dwc2_ep_ops,
- .maxpacket = EP_FIFO_SIZE,
+ .maxpacket_limit = EP_FIFO_SIZE,
.caps = {
.type_int = 1,
.dir_in = 1,
Because this series introduces usb_gadget_ep_match_desc(), we should
make sure that all the in-tree udc drivers have these capabilities set.
In my opinion, we should do this as part of this series, otherwise we
are breaking all the UDC drivers.
Note that all drivers might not require this update, since drivers can
also implement the usb_gadget_ops.match_ep() function instead.
>
>>
>> Thanks,
>> Mattijs
>>
More information about the U-Boot
mailing list