The max packet size within the FS descriptor has to be highest possible
value and _not_ the one that is (or will be) used on FS.
The way the code works (since day 1) is that usb_ep_autoconfig() is
invoked _only_ on the FS endpoint and then the endpoint address is
copies over to HS/SS endpoints. If the any of the "critical" options are
different between FS and HS then we have to pass the HS value and
correct later.

What now happens is that we look for an INT-OUT endpoint of 64bytes. The
code will return an endpoint matching this category. Further the
sourcesink will take this endpoint and increase the MPS to 1024. On
net2280 for instance the code tries to be clever to return an endpoint
which can only do 64 MPS. The same happens on musb where we mostlike get
an endpoint which can only do 512. The result is then on the host side:

|~# testusb -a -t 9 -c 2
|unknown speed   /dev/bus/usb/002/045    0
|usbtest 2-1:3.0: TEST 9:  ch9 (subset) control tests, 2 times
|usbtest 2-1:3.0: can't set_interface = 2, -32
|usbtest 2-1:3.0: ch9 subset failed, iterations left 1
|/dev/bus/usb/002/045 test 9 --> 32 (Broken pipe)

because the on the gadget side we can't enable the endpoint because
desc->size > ep->max_size.

Fixes: ef11982dd7a6 ("usb: gadget: zero: Add support for interrupt EP")
Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de>
---
 drivers/usb/gadget/function/f_sourcesink.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/gadget/function/f_sourcesink.c 
b/drivers/usb/gadget/function/f_sourcesink.c
index 80be25b32cd7..7d8f0216e1a6 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -161,7 +161,7 @@ static struct usb_endpoint_descriptor fs_int_source_desc = {
 
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(64),
+       .wMaxPacketSize =       cpu_to_le16(1024),
        .bInterval =            GZERO_INT_INTERVAL,
 };
 
@@ -171,7 +171,7 @@ static struct usb_endpoint_descriptor fs_int_sink_desc = {
 
        .bEndpointAddress =     USB_DIR_OUT,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(64),
+       .wMaxPacketSize =       cpu_to_le16(1024),
        .bInterval =            GZERO_INT_INTERVAL,
 };
 
@@ -556,16 +556,6 @@ sourcesink_bind(struct usb_configuration *c, struct 
usb_function *f)
        if (int_maxburst > 15)
                int_maxburst = 15;
 
-       /* fill in the FS interrupt descriptors from the module parameters */
-       fs_int_source_desc.wMaxPacketSize = int_maxpacket > 64 ?
-                                               64 : int_maxpacket;
-       fs_int_source_desc.bInterval = int_interval > 255 ?
-                                               255 : int_interval;
-       fs_int_sink_desc.wMaxPacketSize = int_maxpacket > 64 ?
-                                               64 : int_maxpacket;
-       fs_int_sink_desc.bInterval = int_interval > 255 ?
-                                               255 : int_interval;
-
        /* allocate int endpoints */
        ss->int_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_source_desc);
        if (!ss->int_in_ep)
@@ -587,6 +577,16 @@ sourcesink_bind(struct usb_configuration *c, struct 
usb_function *f)
        if (int_maxpacket > 1024)
                int_maxpacket = 1024;
 
+       /* fill in the FS interrupt descriptors from the module parameters */
+       fs_int_source_desc.wMaxPacketSize = int_maxpacket > 64 ?
+                                               64 : int_maxpacket;
+       fs_int_source_desc.bInterval = int_interval > 255 ?
+                                               255 : int_interval;
+       fs_int_sink_desc.wMaxPacketSize = int_maxpacket > 64 ?
+                                               64 : int_maxpacket;
+       fs_int_sink_desc.bInterval = int_interval > 255 ?
+                                               255 : int_interval;
+
        /* support high speed hardware */
        hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
        hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
-- 
2.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to