[U-Boot] DWC2 driver issues

Marek,
Following on from my Google+ post about DWC2/RPi USB host controller issues in U-Boot.
There are 3 issues I've identified so far:
1)
On an RPi with the DWC2 controller connected directly to a single external USB connector (i.e model A, A+), a LS (and perhaps FS) device pluged directly into the board doesn't work due to the small max packet size limit.
Your patch 9b1161af8c51 "usb: dwc2: Add support for multi-packet control xfers" in u-boot-usb.git topic/dwc2 addresses this issue for control transfers at least. With your patch, I can now enumerate a USB kbd on a model A+. That's a great improvement; thanks for the quick response with a patch.
However, when I enable CONFIG_USB_KEYBOARD, I see errors when the USB keyboard input driver initializes:
starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found dev = 0df92ac0 pipe = 0x40408380 buf = 0db4a780 size = 8 int = 10 Failed to get keyboard state from device 413c:2010
I haven't investigated this further yet.
2)
On any RPi with a HS USB hub connected between the DWC2 controller and an LS/FS device (e.g. model A/A+ with external hub, model B/B+ with on-board hub), LS/FS devices don't work since the driver needs to issue USB "split transactions". This involves communicating with the Transaction Translator in the USB hub nearest to the LS/FS device. Namely, performing each transaction first with DWC2_HCSPLT_SPLTENA, then repeating (perhaps polling until we get the final response?) it with DWC2_HCSPLT_COMPSPLT to pick up the response.
Reference:
http://www.usbmadesimple.co.uk/ums_7.htm#split_trans
http://am.renesas.com/applications/key_technology/connectivity/usb/about_usb...
To fully cover both (1) and (2) for all types of transfer, I think we should create a couple functions to do the low-level handling of USB transfers:
a) Perform a large transfer by splitting it up into smaller transactions, each as large as the max packet size. This is what your patch does, but perhaps it'd be better as a separate function so the logic can be shared with transfer types other than control; I assume this size-based splitting is relevant everywhere?
b) Perform an individual transfer on the wire. This will optionally perform split transactions when necessary. I'm sure this will be needed by all transaction types.
Existing code that invokes USB transfers will call (a) once. (a) will call (b) as many times as needed to break up the packet into small chunks. (b) will either send the transaction to the HW (HS devices or directly attached LS/FS devices), or perform the split transaction handling (remotely attached LS/FS devices).
Does that sound like a reasonable approach?
I can start looking into getting split transactions going; I just couldn't motivate myself last Friday night.
3)
On the RPI 2, even directly attached HS devices (i.e. the on-board USB hub, Ethernet) don't work correctly. I haven't tracked down the cause yet, since I got side-tracked on the two issues above, initially thinking they might have the same/similar root-cause. However, I don't think this issue is related, since the RPi2 on-board devices don't fall into either of the categories above.
In theory, the HW should work the same since both the BCM2835/2836 have the same rev of the DWC2 controller. The only difference is the CPUs and perhaps some bus logic. I vaguely wonder about memory barrier or timing issues, but who knows yet.

On Monday, February 16, 2015 at 07:28:45 PM, Stephen Warren wrote:
Marek,
Hello Stephen,
Following on from my Google+ post about DWC2/RPi USB host controller issues in U-Boot.
There are 3 issues I've identified so far:
so far :)
On an RPi with the DWC2 controller connected directly to a single external USB connector (i.e model A, A+), a LS (and perhaps FS) device pluged directly into the board doesn't work due to the small max packet size limit.
Your patch 9b1161af8c51 "usb: dwc2: Add support for multi-packet control xfers" in u-boot-usb.git topic/dwc2 addresses this issue for control transfers at least. With your patch, I can now enumerate a USB kbd on a model A+. That's a great improvement; thanks for the quick response with a patch.
Jeroen was complaining about the same thing, so I cooked this preliminary patch. I'm CCing him. Glad it helped, but I think the patch needs further work.
However, when I enable CONFIG_USB_KEYBOARD, I see errors when the USB
keyboard input driver initializes:
starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found
dev = 0df92ac0 pipe = 0x40408380 buf = 0db4a780 size = 8 int = 10 Failed to get keyboard state from device 413c:2010
I haven't investigated this further yet.
Wow, this error is new, I have not seen this one on SoCFPGA.
On any RPi with a HS USB hub connected between the DWC2 controller and an LS/FS device (e.g. model A/A+ with external hub, model B/B+ with on-board hub), LS/FS devices don't work since the driver needs to issue USB "split transactions".
Yep. CCing Hans, the USB Guru.
This involves communicating with the Transaction Translator in the USB hub nearest to the LS/FS device. Namely, performing each transaction first with DWC2_HCSPLT_SPLTENA, then repeating (perhaps polling until we get the final response?) it with DWC2_HCSPLT_COMPSPLT to pick up the response.
Reference:
http://www.usbmadesimple.co.uk/ums_7.htm#split_trans
http://am.renesas.com/applications/key_technology/connectivity/usb/about_us b/usb2_0/usb2_8/index.jsp
To fully cover both (1) and (2) for all types of transfer, I think we should create a couple functions to do the low-level handling of USB transfers:
a) Perform a large transfer by splitting it up into smaller transactions, each as large as the max packet size. This is what your patch does, but perhaps it'd be better as a separate function so the logic can be shared with transfer types other than control; I assume this size-based splitting is relevant everywhere?
Yes, and in case you look closely, the functions for doing control and bulk transfers are almost identical in their "core" mechanics.
b) Perform an individual transfer on the wire. This will optionally perform split transactions when necessary. I'm sure this will be needed by all transaction types.
Yes.
Existing code that invokes USB transfers will call (a) once. (a) will call (b) as many times as needed to break up the packet into small chunks. (b) will either send the transaction to the HW (HS devices or directly attached LS/FS devices), or perform the split transaction handling (remotely attached LS/FS devices).
Does that sound like a reasonable approach?
I can start looking into getting split transactions going; I just couldn't motivate myself last Friday night.
Do you plan to do this on the USB stack level or USB controller driver level please ?
On the RPI 2, even directly attached HS devices (i.e. the on-board USB hub, Ethernet) don't work correctly. I haven't tracked down the cause yet, since I got side-tracked on the two issues above, initially thinking they might have the same/similar root-cause. However, I don't think this issue is related, since the RPi2 on-board devices don't fall into either of the categories above.
Do you get some kind of an error message ?
In theory, the HW should work the same since both the BCM2835/2836 have the same rev of the DWC2 controller. The only difference is the CPUs and perhaps some bus logic. I vaguely wonder about memory barrier or timing issues, but who knows yet.
Which controller version is that, 2.80a in both ? I recall SoCFPGA has 2.93, just for reference. I also recall there was some bug in the DWC2 lower than 2.90 (?), I don't remember the exact details, but this should be documented in the DWC2 driver source code.

On Thu, 19 Feb 2015, Marek Vasut wrote:
+cc: John Youn
John took over the maintainership of the DWC2 driver in linux as Paul Zimmerman is no longer at Synopsys.
On Monday, February 16, 2015 at 07:28:45 PM, Stephen Warren wrote:
Marek,
Hello Stephen,
Following on from my Google+ post about DWC2/RPi USB host controller issues in U-Boot.
There are 3 issues I've identified so far:
so far :)
On an RPi with the DWC2 controller connected directly to a single external USB connector (i.e model A, A+), a LS (and perhaps FS) device pluged directly into the board doesn't work due to the small max packet size limit.
Your patch 9b1161af8c51 "usb: dwc2: Add support for multi-packet control xfers" in u-boot-usb.git topic/dwc2 addresses this issue for control transfers at least. With your patch, I can now enumerate a USB kbd on a model A+. That's a great improvement; thanks for the quick response with a patch.
Jeroen was complaining about the same thing, so I cooked this preliminary patch. I'm CCing him. Glad it helped, but I think the patch needs further work.
However, when I enable CONFIG_USB_KEYBOARD, I see errors when the USB
keyboard input driver initializes:
starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found
dev = 0df92ac0 pipe = 0x40408380 buf = 0db4a780 size = 8 int = 10 Failed to get keyboard state from device 413c:2010
I haven't investigated this further yet.
Wow, this error is new, I have not seen this one on SoCFPGA.
On any RPi with a HS USB hub connected between the DWC2 controller and an LS/FS device (e.g. model A/A+ with external hub, model B/B+ with on-board hub), LS/FS devices don't work since the driver needs to issue USB "split transactions".
Yep. CCing Hans, the USB Guru.
This involves communicating with the Transaction Translator in the USB hub nearest to the LS/FS device. Namely, performing each transaction first with DWC2_HCSPLT_SPLTENA, then repeating (perhaps polling until we get the final response?) it with DWC2_HCSPLT_COMPSPLT to pick up the response.
Reference:
http://www.usbmadesimple.co.uk/ums_7.htm#split_trans
http://am.renesas.com/applications/key_technology/connectivity/usb/about_us b/usb2_0/usb2_8/index.jsp
To fully cover both (1) and (2) for all types of transfer, I think we should create a couple functions to do the low-level handling of USB transfers:
a) Perform a large transfer by splitting it up into smaller transactions, each as large as the max packet size. This is what your patch does, but perhaps it'd be better as a separate function so the logic can be shared with transfer types other than control; I assume this size-based splitting is relevant everywhere?
Yes, and in case you look closely, the functions for doing control and bulk transfers are almost identical in their "core" mechanics.
b) Perform an individual transfer on the wire. This will optionally perform split transactions when necessary. I'm sure this will be needed by all transaction types.
Yes.
Existing code that invokes USB transfers will call (a) once. (a) will call (b) as many times as needed to break up the packet into small chunks. (b) will either send the transaction to the HW (HS devices or directly attached LS/FS devices), or perform the split transaction handling (remotely attached LS/FS devices).
Does that sound like a reasonable approach?
I can start looking into getting split transactions going; I just couldn't motivate myself last Friday night.
Do you plan to do this on the USB stack level or USB controller driver level please ?
On the RPI 2, even directly attached HS devices (i.e. the on-board USB hub, Ethernet) don't work correctly. I haven't tracked down the cause yet, since I got side-tracked on the two issues above, initially thinking they might have the same/similar root-cause. However, I don't think this issue is related, since the RPi2 on-board devices don't fall into either of the categories above.
Do you get some kind of an error message ?
In theory, the HW should work the same since both the BCM2835/2836 have the same rev of the DWC2 controller. The only difference is the CPUs and perhaps some bus logic. I vaguely wonder about memory barrier or timing issues, but who knows yet.
Which controller version is that, 2.80a in both ? I recall SoCFPGA has 2.93, just for reference. I also recall there was some bug in the DWC2 lower than 2.90 (?), I don't remember the exact details, but this should be documented in the DWC2 driver source code.
Yes, SoCFPGA has v2.93.
BR, Dinh

On 02/19/2015 07:29 AM, Marek Vasut wrote:
On Monday, February 16, 2015 at 07:28:45 PM, Stephen Warren wrote:
Marek,
...
To fully cover both (1) and (2) for all types of transfer, I think we should create a couple functions to do the low-level handling of USB transfers:
a) Perform a large transfer by splitting it up into smaller transactions, each as large as the max packet size. This is what your patch does, but perhaps it'd be better as a separate function so the logic can be shared with transfer types other than control; I assume this size-based splitting is relevant everywhere?
Yes, and in case you look closely, the functions for doing control and bulk transfers are almost identical in their "core" mechanics.
b) Perform an individual transfer on the wire. This will optionally perform split transactions when necessary. I'm sure this will be needed by all transaction types.
Yes.
Existing code that invokes USB transfers will call (a) once. (a) will call (b) as many times as needed to break up the packet into small chunks. (b) will either send the transaction to the HW (HS devices or directly attached LS/FS devices), or perform the split transaction handling (remotely attached LS/FS devices).
Does that sound like a reasonable approach?
I can start looking into getting split transactions going; I just couldn't motivate myself last Friday night.
Do you plan to do this on the USB stack level or USB controller driver level please ?
I expect I'd put at least the split transaction stuff into the USB controller driver. While I'm not that familiar with anything other than standard EHCI, I'd guess the need to manually manage split transaction was unique to DWC2?
The split of transfers into max-packet-sized transfers could plausibly be useful in the core, but again my guess is that the need to do this is DWC2-specific?
On the RPI 2, even directly attached HS devices (i.e. the on-board USB hub, Ethernet) don't work correctly. I haven't tracked down the cause yet, since I got side-tracked on the two issues above, initially thinking they might have the same/similar root-cause. However, I don't think this issue is related, since the RPi2 on-board devices don't fall into either of the categories above.
Do you get some kind of an error message ?
Yes. It's similar to the message about "can't read descriptor" that I used to get with a LS device on the original RPis, which is why I started looking at keyboards. Your patch to split up large transactions didn't affect this, so I believe they're separate issues now.
In theory, the HW should work the same since both the BCM2835/2836 have the same rev of the DWC2 controller. The only difference is the CPUs and perhaps some bus logic. I vaguely wonder about memory barrier or timing issues, but who knows yet.
Which controller version is that, 2.80a in both ? I recall SoCFPGA has 2.93, just for reference. I also recall there was some bug in the DWC2 lower than 2.90 (?), I don't remember the exact details, but this should be documented in the DWC2 driver source code.
Yes, both are 2.80a according to what the driver prints.

On Friday, February 20, 2015 at 04:22:58 AM, Stephen Warren wrote:
Hi!
[...]
Existing code that invokes USB transfers will call (a) once. (a) will call (b) as many times as needed to break up the packet into small chunks. (b) will either send the transaction to the HW (HS devices or directly attached LS/FS devices), or perform the split transaction handling (remotely attached LS/FS devices).
Does that sound like a reasonable approach?
I can start looking into getting split transactions going; I just couldn't motivate myself last Friday night.
Do you plan to do this on the USB stack level or USB controller driver level please ?
I expect I'd put at least the split transaction stuff into the USB controller driver. While I'm not that familiar with anything other than standard EHCI, I'd guess the need to manually manage split transaction was unique to DWC2?
Looks that way. +CC Kishon , what about DWC3 ?
The split of transfers into max-packet-sized transfers could plausibly be useful in the core, but again my guess is that the need to do this is DWC2-specific?
Kishon ?
On the RPI 2, even directly attached HS devices (i.e. the on-board USB hub, Ethernet) don't work correctly. I haven't tracked down the cause yet, since I got side-tracked on the two issues above, initially thinking they might have the same/similar root-cause. However, I don't think this issue is related, since the RPi2 on-board devices don't fall into either of the categories above.
Do you get some kind of an error message ?
Yes. It's similar to the message about "can't read descriptor" that I used to get with a LS device on the original RPis, which is why I started looking at keyboards. Your patch to split up large transactions didn't affect this, so I believe they're separate issues now.
OK
[...]

On Monday 02 March 2015 05:08 PM, Marek Vasut wrote:
On Friday, February 20, 2015 at 04:22:58 AM, Stephen Warren wrote:
Hi!
[...]
Existing code that invokes USB transfers will call (a) once. (a) will call (b) as many times as needed to break up the packet into small chunks. (b) will either send the transaction to the HW (HS devices or directly attached LS/FS devices), or perform the split transaction handling (remotely attached LS/FS devices).
Does that sound like a reasonable approach?
I can start looking into getting split transactions going; I just couldn't motivate myself last Friday night.
Do you plan to do this on the USB stack level or USB controller driver level please ?
I expect I'd put at least the split transaction stuff into the USB controller driver. While I'm not that familiar with anything other than standard EHCI, I'd guess the need to manually manage split transaction was unique to DWC2?
Looks that way. +CC Kishon , what about DWC3 ?
SPLIT transaction is specific to host controller and the DWC3 work I did is gadget driver. So I'd assume it should be handled by xhci driver.
The split of transfers into max-packet-sized transfers could plausibly be useful in the core, but again my guess is that the need to do this is DWC2-specific?
Kishon ?
AFAIK dwc3 requires max-packet "aligned" request sizes and we manage it by using bounce buffer and chained TRBs. The hw itself takes care of sending max-packet-sized transfers. But again I'm talking w.r.t gadget driver.
Cheers Kishon

On 02/19/2015 07:29 AM, Marek Vasut wrote:
On Monday, February 16, 2015 at 07:28:45 PM, Stephen Warren wrote:
Following on from my Google+ post about DWC2/RPi USB host controller issues in U-Boot.
...
On an RPi with the DWC2 controller connected directly to a single external USB connector (i.e model A, A+), a LS (and perhaps FS) device pluged directly into the board doesn't work due to the small max packet size limit.
Your patch 9b1161af8c51 "usb: dwc2: Add support for multi-packet control xfers" in u-boot-usb.git topic/dwc2 addresses this issue for control transfers at least. With your patch, I can now enumerate a USB kbd on a model A+. That's a great improvement; thanks for the quick response with a patch.
However, when I enable CONFIG_USB_KEYBOARD, I see errors when the USB
keyboard input driver initializes:
starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found
dev = 0df92ac0 pipe = 0x40408380 buf = 0db4a780 size = 8 int = 10 Failed to get keyboard state from device 413c:2010
I haven't investigated this further yet.
Wow, this error is new, I have not seen this one on SoCFPGA.
This error is because the keyboard driver uses interrupt transfers, and these aren't implemented in DWC2. I worked around this by forcing the keyboard driver to use control transfers, and fixing what I think is a bug in this case; see patch below. With this, USB keyboard works on an RPI A+, although it hangs pretty quickly. I assume one of the busy loops in dwc2.c without a time out isn't completing.
diff --git a/common/usb_kbd.c b/common/usb_kbd.c index ecc3085cc081..237dbbaf4fe0 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -457,6 +457,8 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) USB_KBD_BOOT_REPORT_SIZE, data->new, data->intinterval); if (!data->intq) { +#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
if (0) {
#else if (usb_submit_int_msg(dev, data->intpipe, data->new, data->intpktsize, data->intinterval) < 0) { diff --git a/include/configs/rpi.h b/include/configs/rpi.h index c94f4112026e..8d01bc845d73 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -91,6 +91,9 @@ #define CONFIG_USB_HOST_ETHER #define CONFIG_USB_ETHER_SMSC95XX #define CONFIG_MISC_INIT_R +#define CONFIG_USB_KEYBOARD +#define CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP +#define CONFIG_SYS_STDIO_DEREGISTER #endif
/* Console UART */

On Saturday, February 28, 2015 at 05:33:31 AM, Stephen Warren wrote:
On 02/19/2015 07:29 AM, Marek Vasut wrote:
On Monday, February 16, 2015 at 07:28:45 PM, Stephen Warren wrote:
Following on from my Google+ post about DWC2/RPi USB host controller issues in U-Boot.
...
On an RPi with the DWC2 controller connected directly to a single external USB connector (i.e model A, A+), a LS (and perhaps FS) device pluged directly into the board doesn't work due to the small max packet size limit.
Your patch 9b1161af8c51 "usb: dwc2: Add support for multi-packet control xfers" in u-boot-usb.git topic/dwc2 addresses this issue for control transfers at least. With your patch, I can now enumerate a USB kbd on a model A+. That's a great improvement; thanks for the quick response with a patch.
However, when I enable CONFIG_USB_KEYBOARD, I see errors when the USB
keyboard input driver initializes:
starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found
dev = 0df92ac0 pipe = 0x40408380 buf = 0db4a780 size = 8 int = 10 Failed to get keyboard state from device 413c:2010
I haven't investigated this further yet.
Wow, this error is new, I have not seen this one on SoCFPGA.
This error is because the keyboard driver uses interrupt transfers, and these aren't implemented in DWC2.
Uh, the debugging spit in submit_int_msg() should certainly be converted into something more human readable.
I worked around this by forcing the keyboard driver to use control transfers, and fixing what I think is a bug in this case; see patch below. With this, USB keyboard works on an RPI A+
Cool, good job.
although it hangs pretty quickly. I assume one of the busy loops in dwc2.c without a time out isn't completing.
Oh, dang. Those should certainly be fixed.
Looking at the patch, could it be that CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP support in usb_kbd.c is broken altogether ?

On 03/02/2015 04:42 AM, Marek Vasut wrote:
On Saturday, February 28, 2015 at 05:33:31 AM, Stephen Warren wrote:
On 02/19/2015 07:29 AM, Marek Vasut wrote:
On Monday, February 16, 2015 at 07:28:45 PM, Stephen Warren wrote:
Following on from my Google+ post about DWC2/RPi USB host controller issues in U-Boot.
...
On an RPi with the DWC2 controller connected directly to a single external USB connector (i.e model A, A+), a LS (and perhaps FS) device pluged directly into the board doesn't work due to the small max packet size limit.
Your patch 9b1161af8c51 "usb: dwc2: Add support for multi-packet control xfers" in u-boot-usb.git topic/dwc2 addresses this issue for control transfers at least. With your patch, I can now enumerate a USB kbd on a model A+. That's a great improvement; thanks for the quick response with a patch.
However, when I enable CONFIG_USB_KEYBOARD, I see errors when the USB
keyboard input driver initializes:
starting USB... USB0: Core Release: 2.80a scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found scanning usb for ethernet devices... 0 Ethernet Device(s) found
dev = 0df92ac0 pipe = 0x40408380 buf = 0db4a780 size = 8 int = 10 Failed to get keyboard state from device 413c:2010
I haven't investigated this further yet.
Wow, this error is new, I have not seen this one on SoCFPGA.
This error is because the keyboard driver uses interrupt transfers, and these aren't implemented in DWC2.
Uh, the debugging spit in submit_int_msg() should certainly be converted into something more human readable.
I worked around this by forcing the keyboard driver to use control transfers, and fixing what I think is a bug in this case; see patch below. With this, USB keyboard works on an RPI A+
Cool, good job.
although it hangs pretty quickly. I assume one of the busy loops in dwc2.c without a time out isn't completing.
Oh, dang. Those should certainly be fixed.
Looking at the patch, could it be that CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP support in usb_kbd.c is broken altogether ?
Well, once I applied that patch I did manage to type a few characters into the U-Boot shell via usbkbd one of the two times I tested, so it's not *completely* broken. It's still possible it's quite broken though, given the hangs:-)

On Tuesday, March 03, 2015 at 12:33:41 AM, Stephen Warren wrote:
[...]
although it hangs pretty quickly. I assume one of the busy loops in dwc2.c without a time out isn't completing.
Oh, dang. Those should certainly be fixed.
Looking at the patch, could it be that CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP support in usb_kbd.c is broken altogether ?
Well, once I applied that patch I did manage to type a few characters into the U-Boot shell via usbkbd one of the two times I tested, so it's not *completely* broken. It's still possible it's quite broken though, given the hangs:-)
Well, that's a good progress all right :)
Best regards, Marek Vasut
participants (4)
-
Dinh Nguyen
-
Kishon Vijay Abraham I
-
Marek Vasut
-
Stephen Warren