| From fe659bcc9b173bcfdd958ce2aec75e47651e74e1 Mon Sep 17 00:00:00 2001 |
| From: Alan Stern <stern@rowland.harvard.edu> |
| Date: Tue, 26 Sep 2017 15:15:22 -0400 |
| Subject: USB: dummy-hcd: fix connection failures (wrong speed) |
| |
| From: Alan Stern <stern@rowland.harvard.edu> |
| |
| commit fe659bcc9b173bcfdd958ce2aec75e47651e74e1 upstream. |
| |
| The dummy-hcd UDC driver is not careful about the way it handles |
| connection speeds. It ignores the module parameter that is supposed |
| to govern the maximum connection speed and it doesn't set the HCD |
| flags properly for the case where it ends up running at full speed. |
| |
| The result is that in many cases, gadget enumeration over dummy-hcd |
| fails because the bMaxPacketSize byte in the device descriptor is set |
| incorrectly. For example, the default settings call for a high-speed |
| connection, but the maxpacket value for ep0 ends up being set for a |
| Super-Speed connection. |
| |
| This patch fixes the problem by initializing the gadget's max_speed |
| and the HCD flags correctly. |
| |
| Signed-off-by: Alan Stern <stern@rowland.harvard.edu> |
| Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/gadget/udc/dummy_hcd.c | 15 +++++++++++---- |
| 1 file changed, 11 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/usb/gadget/udc/dummy_hcd.c |
| +++ b/drivers/usb/gadget/udc/dummy_hcd.c |
| @@ -976,7 +976,12 @@ static int dummy_udc_probe(struct platfo |
| memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); |
| dum->gadget.name = gadget_name; |
| dum->gadget.ops = &dummy_ops; |
| - dum->gadget.max_speed = USB_SPEED_SUPER; |
| + if (mod_data.is_super_speed) |
| + dum->gadget.max_speed = USB_SPEED_SUPER; |
| + else if (mod_data.is_high_speed) |
| + dum->gadget.max_speed = USB_SPEED_HIGH; |
| + else |
| + dum->gadget.max_speed = USB_SPEED_FULL; |
| |
| dum->gadget.dev.parent = &pdev->dev; |
| init_dummy_udc_hw(dum); |
| @@ -2492,8 +2497,6 @@ static struct hc_driver dummy_hcd = { |
| .product_desc = "Dummy host controller", |
| .hcd_priv_size = sizeof(struct dummy_hcd), |
| |
| - .flags = HCD_USB3 | HCD_SHARED, |
| - |
| .reset = dummy_setup, |
| .start = dummy_start, |
| .stop = dummy_stop, |
| @@ -2522,8 +2525,12 @@ static int dummy_hcd_probe(struct platfo |
| dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); |
| dum = *((void **)dev_get_platdata(&pdev->dev)); |
| |
| - if (!mod_data.is_super_speed) |
| + if (mod_data.is_super_speed) |
| + dummy_hcd.flags = HCD_USB3 | HCD_SHARED; |
| + else if (mod_data.is_high_speed) |
| dummy_hcd.flags = HCD_USB2; |
| + else |
| + dummy_hcd.flags = HCD_USB11; |
| hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); |
| if (!hs_hcd) |
| return -ENOMEM; |