[U-Boot] [PATCH 0/1] dm: usb: Fix divide by 0 errors in host drivers caused by not setting maxpsize

Hi Simon,
While working on moving the sunxi ehci code over to the driver model I've found this bug in the usb uclass which causes a div by zero error.
I've spend a couple of hours yesterday evening debugging this and I'm happy to report that I've a fix now. This fix has not seen as much testing as I would have liked, but I believe it is correct and want to share it now anyways to avoid people doing double work.
While thinking more about this I've come up with what I believe is a better way to deal with this all together. I'll send that out right after this one, note that the intend is that only one of the 2 patches gets applied, preferably the latter as I believe that one is the best.
Regards,
Hans
p.s.
I've found 2 other issues with the dm usb code:
1) usb-1 devices / hubs behind a usb-2 (root)hub do not seem to work, this is a familiar issue which I fixed in the pre dm usb code a while back. I'll investigate this one myself.
2) "usb reset" is buggered, it either hangs or reboots the system. I would appreciate if you could take a look (assuming you can reproduce it).

usb_child_pre_probe() initializes the final struct usb_device by redoingthe usb_select_config() done by usb_scan_device() but not the usb_prepare_device() call, this leads to a call into the hcd to get the device descriptors without ep0's maxpacketsize being set, which leads to a device by 0 error in the ehci driver.
This commit fixes this by passing the maxpacketsize through the usb_device_platdata and setting it in usb_child_pre_probe().
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/usb/host/usb-uclass.c | 4 ++++ include/usb.h | 3 +++ 2 files changed, 7 insertions(+)
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 714bc0e..2af8611 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -539,6 +539,7 @@ int usb_scan_device(struct udevice *parent, int port, plat->speed = udev->speed; plat->slot_id = udev->slot_id; plat->portnr = port; + plat->maxpacketsize = udev->maxpacketsize; debug("** device '%s': stashing slot_id=%d\n", dev->name, plat->slot_id); priv->next_addr++; @@ -613,6 +614,9 @@ int usb_child_pre_probe(struct udevice *dev) udev->slot_id = plat->slot_id; udev->portnr = plat->portnr; udev->speed = plat->speed; + udev->maxpacketsize = plat->maxpacketsize; + udev->epmaxpacketin[0] = 1 << (udev->maxpacketsize + 3); + udev->epmaxpacketout[0] = 1 << (udev->maxpacketsize + 3); debug("** device '%s': getting slot_id=%d\n", dev->name, plat->slot_id);
ret = usb_select_config(udev); diff --git a/include/usb.h b/include/usb.h index 1984e8f..a5eb7fe 100644 --- a/include/usb.h +++ b/include/usb.h @@ -576,6 +576,7 @@ struct usb_platdata { * @slot_id: USB3 slot ID, which is separate from the device address * @portnr: Port number of this device on its parent hub, numbered from 1 * (0 mean this device is the root hub) + * @maxpacketsize: EP0 maxpacketsize * @strings: List of descriptor strings (for sandbox emulation purposes) * @desc_list: List of descriptors (for sandbox emulation purposes) */ @@ -585,6 +586,8 @@ struct usb_dev_platdata { int devnum; int slot_id; int portnr; /* Hub port number, 1..n */ + int maxpacketsize; /* Maximum packet size; one of: PACKET_SIZE_* */ + #ifdef CONFIG_SANDBOX struct usb_string *strings; /* NULL-terminated list of descriptor pointers */

On 29 April 2015 at 03:40, Hans de Goede hdegoede@redhat.com wrote:
usb_child_pre_probe() initializes the final struct usb_device by redoingthe usb_select_config() done by usb_scan_device() but not the usb_prepare_device() call, this leads to a call into the hcd to get the device descriptors without ep0's maxpacketsize being set, which leads to a device by 0 error in the ehci driver.
This commit fixes this by passing the maxpacketsize through the usb_device_platdata and setting it in usb_child_pre_probe().
Signed-off-by: Hans de Goede hdegoede@redhat.com
drivers/usb/host/usb-uclass.c | 4 ++++ include/usb.h | 3 +++ 2 files changed, 7 insertions(+)
Acked-by: Simon Glass sjg@chromium.org
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 714bc0e..2af8611 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -539,6 +539,7 @@ int usb_scan_device(struct udevice *parent, int port, plat->speed = udev->speed; plat->slot_id = udev->slot_id; plat->portnr = port;
plat->maxpacketsize = udev->maxpacketsize; debug("** device '%s': stashing slot_id=%d\n", dev->name, plat->slot_id); priv->next_addr++;
@@ -613,6 +614,9 @@ int usb_child_pre_probe(struct udevice *dev) udev->slot_id = plat->slot_id; udev->portnr = plat->portnr; udev->speed = plat->speed;
udev->maxpacketsize = plat->maxpacketsize;
udev->epmaxpacketin[0] = 1 << (udev->maxpacketsize + 3);
udev->epmaxpacketout[0] = 1 << (udev->maxpacketsize + 3); debug("** device '%s': getting slot_id=%d\n", dev->name, plat->slot_id); ret = usb_select_config(udev);
diff --git a/include/usb.h b/include/usb.h index 1984e8f..a5eb7fe 100644 --- a/include/usb.h +++ b/include/usb.h @@ -576,6 +576,7 @@ struct usb_platdata {
- @slot_id: USB3 slot ID, which is separate from the device address
- @portnr: Port number of this device on its parent hub, numbered from 1
(0 mean this device is the root hub)
*/
- @maxpacketsize: EP0 maxpacketsize
- @strings: List of descriptor strings (for sandbox emulation purposes)
- @desc_list: List of descriptors (for sandbox emulation purposes)
@@ -585,6 +586,8 @@ struct usb_dev_platdata { int devnum; int slot_id; int portnr; /* Hub port number, 1..n */
int maxpacketsize; /* Maximum packet size; one of: PACKET_SIZE_* */
#ifdef CONFIG_SANDBOX struct usb_string *strings; /* NULL-terminated list of descriptor pointers */ -- 2.3.6
participants (2)
-
Hans de Goede
-
Simon Glass