]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/usb/gadget/function/f_sourcesink.c
Merge remote-tracking branch 'target-updates/for-next'
[karo-tx-linux.git] / drivers / usb / gadget / function / f_sourcesink.c
index 878a5815450ed85f0740539c6e379270b9c93440..9f3ced62d9162c991c03b0db68d10fd0cbe06ea9 100644 (file)
@@ -50,6 +50,13 @@ struct f_sourcesink {
        struct usb_ep           *iso_in_ep;
        struct usb_ep           *iso_out_ep;
        int                     cur_alt;
+
+       unsigned pattern;
+       unsigned isoc_interval;
+       unsigned isoc_maxpacket;
+       unsigned isoc_mult;
+       unsigned isoc_maxburst;
+       unsigned buflen;
 };
 
 static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -57,13 +64,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
        return container_of(f, struct f_sourcesink, function);
 }
 
-static unsigned pattern;
-static unsigned isoc_interval;
-static unsigned isoc_maxpacket;
-static unsigned isoc_mult;
-static unsigned isoc_maxburst;
-static unsigned buflen;
-
 /*-------------------------------------------------------------------------*/
 
 static struct usb_interface_descriptor source_sink_intf_alt0 = {
@@ -298,7 +298,9 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
 
 static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
 {
-       return alloc_ep_req(ep, len, buflen);
+       struct f_sourcesink             *ss = ep->driver_data;
+
+       return alloc_ep_req(ep, len, ss->buflen);
 }
 
 void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@@ -311,13 +313,9 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
 {
        int                     value;
 
-       if (ep->driver_data) {
-               value = usb_ep_disable(ep);
-               if (value < 0)
-                       DBG(cdev, "disable %s --> %d\n",
-                                       ep->name, value);
-               ep->driver_data = NULL;
-       }
+       value = usb_ep_disable(ep);
+       if (value < 0)
+               DBG(cdev, "disable %s --> %d\n", ep->name, value);
 }
 
 void disable_endpoints(struct usb_composite_dev *cdev,
@@ -355,42 +353,37 @@ autoconf_fail:
                        f->name, cdev->gadget->name);
                return -ENODEV;
        }
-       ss->in_ep->driver_data = cdev;  /* claim */
 
        ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
        if (!ss->out_ep)
                goto autoconf_fail;
-       ss->out_ep->driver_data = cdev; /* claim */
 
        /* sanity check the isoc module parameters */
-       if (isoc_interval < 1)
-               isoc_interval = 1;
-       if (isoc_interval > 16)
-               isoc_interval = 16;
-       if (isoc_mult > 2)
-               isoc_mult = 2;
-       if (isoc_maxburst > 15)
-               isoc_maxburst = 15;
+       if (ss->isoc_interval < 1)
+               ss->isoc_interval = 1;
+       if (ss->isoc_interval > 16)
+               ss->isoc_interval = 16;
+       if (ss->isoc_mult > 2)
+               ss->isoc_mult = 2;
+       if (ss->isoc_maxburst > 15)
+               ss->isoc_maxburst = 15;
 
        /* fill in the FS isoc descriptors from the module parameters */
-       fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
-                                               1023 : isoc_maxpacket;
-       fs_iso_source_desc.bInterval = isoc_interval;
-       fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
-                                               1023 : isoc_maxpacket;
-       fs_iso_sink_desc.bInterval = isoc_interval;
+       fs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket > 1023 ?
+                                               1023 : ss->isoc_maxpacket;
+       fs_iso_source_desc.bInterval = ss->isoc_interval;
+       fs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket > 1023 ?
+                                               1023 : ss->isoc_maxpacket;
+       fs_iso_sink_desc.bInterval = ss->isoc_interval;
 
        /* allocate iso endpoints */
        ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc);
        if (!ss->iso_in_ep)
                goto no_iso;
-       ss->iso_in_ep->driver_data = cdev;      /* claim */
 
        ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc);
-       if (ss->iso_out_ep) {
-               ss->iso_out_ep->driver_data = cdev;     /* claim */
-       } else {
-               ss->iso_in_ep->driver_data = NULL;
+       if (!ss->iso_out_ep) {
+               usb_ep_autoconfig_release(ss->iso_in_ep);
                ss->iso_in_ep = NULL;
 no_iso:
                /*
@@ -403,8 +396,8 @@ no_iso:
                ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
        }
 
-       if (isoc_maxpacket > 1024)
-               isoc_maxpacket = 1024;
+       if (ss->isoc_maxpacket > 1024)
+               ss->isoc_maxpacket = 1024;
 
        /* support high speed hardware */
        hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
@@ -415,15 +408,15 @@ no_iso:
         * We assume that the user knows what they are doing and won't
         * give parameters that their UDC doesn't support.
         */
-       hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-       hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
-       hs_iso_source_desc.bInterval = isoc_interval;
+       hs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       hs_iso_source_desc.wMaxPacketSize |= ss->isoc_mult << 11;
+       hs_iso_source_desc.bInterval = ss->isoc_interval;
        hs_iso_source_desc.bEndpointAddress =
                fs_iso_source_desc.bEndpointAddress;
 
-       hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-       hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
-       hs_iso_sink_desc.bInterval = isoc_interval;
+       hs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       hs_iso_sink_desc.wMaxPacketSize |= ss->isoc_mult << 11;
+       hs_iso_sink_desc.bInterval = ss->isoc_interval;
        hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
        /* support super speed hardware */
@@ -437,21 +430,21 @@ no_iso:
         * We assume that the user knows what they are doing and won't
         * give parameters that their UDC doesn't support.
         */
-       ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-       ss_iso_source_desc.bInterval = isoc_interval;
-       ss_iso_source_comp_desc.bmAttributes = isoc_mult;
-       ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
-       ss_iso_source_comp_desc.wBytesPerInterval =
-               isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+       ss_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       ss_iso_source_desc.bInterval = ss->isoc_interval;
+       ss_iso_source_comp_desc.bmAttributes = ss->isoc_mult;
+       ss_iso_source_comp_desc.bMaxBurst = ss->isoc_maxburst;
+       ss_iso_source_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
+               (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
        ss_iso_source_desc.bEndpointAddress =
                fs_iso_source_desc.bEndpointAddress;
 
-       ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-       ss_iso_sink_desc.bInterval = isoc_interval;
-       ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
-       ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
-       ss_iso_sink_comp_desc.wBytesPerInterval =
-               isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+       ss_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       ss_iso_sink_desc.bInterval = ss->isoc_interval;
+       ss_iso_sink_comp_desc.bmAttributes = ss->isoc_mult;
+       ss_iso_sink_comp_desc.bMaxBurst = ss->isoc_maxburst;
+       ss_iso_sink_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
+               (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
        ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
        ret = usb_assign_descriptors(f, fs_source_sink_descs,
@@ -489,12 +482,13 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
        unsigned                i;
        u8                      *buf = req->buf;
        struct usb_composite_dev *cdev = ss->function.config->cdev;
+       int max_packet_size = le16_to_cpu(ss->out_ep->desc->wMaxPacketSize);
 
-       if (pattern == 2)
+       if (ss->pattern == 2)
                return 0;
 
        for (i = 0; i < req->actual; i++, buf++) {
-               switch (pattern) {
+               switch (ss->pattern) {
 
                /* all-zeroes has no synchronization issues */
                case 0:
@@ -510,7 +504,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
                 * stutter for any reason, including buffer duplication...)
                 */
                case 1:
-                       if (*buf == (u8)(i % 63))
+                       if (*buf == (u8)((i % max_packet_size) % 63))
                                continue;
                        break;
                }
@@ -525,14 +519,16 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
 {
        unsigned        i;
        u8              *buf = req->buf;
+       int max_packet_size = le16_to_cpu(ep->desc->wMaxPacketSize);
+       struct f_sourcesink *ss = ep->driver_data;
 
-       switch (pattern) {
+       switch (ss->pattern) {
        case 0:
                memset(req->buf, 0, req->length);
                break;
        case 1:
                for  (i = 0; i < req->length; i++)
-                       *buf++ = (u8) (i % 63);
+                       *buf++ = (u8) ((i % max_packet_size) % 63);
                break;
        case 2:
                break;
@@ -556,7 +552,7 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
        case 0:                         /* normal completion? */
                if (ep == ss->out_ep) {
                        check_read_data(ss, req);
-                       if (pattern != 2)
+                       if (ss->pattern != 2)
                                memset(req->buf, 0x55, req->length);
                }
                break;
@@ -605,15 +601,16 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
                if (is_iso) {
                        switch (speed) {
                        case USB_SPEED_SUPER:
-                               size = isoc_maxpacket * (isoc_mult + 1) *
-                                               (isoc_maxburst + 1);
+                               size = ss->isoc_maxpacket *
+                                               (ss->isoc_mult + 1) *
+                                               (ss->isoc_maxburst + 1);
                                break;
                        case USB_SPEED_HIGH:
-                               size = isoc_maxpacket * (isoc_mult + 1);
+                               size = ss->isoc_maxpacket * (ss->isoc_mult + 1);
                                break;
                        default:
-                               size = isoc_maxpacket > 1023 ?
-                                               1023 : isoc_maxpacket;
+                               size = ss->isoc_maxpacket > 1023 ?
+                                               1023 : ss->isoc_maxpacket;
                                break;
                        }
                        ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
@@ -629,7 +626,7 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
                req->complete = source_sink_complete;
                if (is_in)
                        reinit_write_data(ep, req);
-               else if (pattern != 2)
+               else if (ss->pattern != 2)
                        memset(req->buf, 0x55, req->length);
 
                status = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -683,7 +680,6 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
 fail:
                ep = ss->in_ep;
                usb_ep_disable(ep);
-               ep->driver_data = NULL;
                return result;
        }
 
@@ -702,7 +698,6 @@ fail:
 fail2:
                ep = ss->out_ep;
                usb_ep_disable(ep);
-               ep->driver_data = NULL;
                goto fail;
        }
 
@@ -724,10 +719,8 @@ fail2:
                if (result < 0) {
 fail3:
                        ep = ss->iso_in_ep;
-                       if (ep) {
+                       if (ep)
                                usb_ep_disable(ep);
-                               ep->driver_data = NULL;
-                       }
                        goto fail2;
                }
        }
@@ -746,7 +739,6 @@ fail3:
                result = source_sink_start_ep(ss, false, true, speed);
                if (result < 0) {
                        usb_ep_disable(ep);
-                       ep->driver_data = NULL;
                        goto fail3;
                }
        }
@@ -763,8 +755,7 @@ static int sourcesink_set_alt(struct usb_function *f,
        struct f_sourcesink             *ss = func_to_ss(f);
        struct usb_composite_dev        *cdev = f->config->cdev;
 
-       if (ss->in_ep->driver_data)
-               disable_source_sink(ss);
+       disable_source_sink(ss);
        return enable_source_sink(cdev, ss, alt);
 }
 
@@ -872,12 +863,12 @@ static struct usb_function *source_sink_alloc_func(
        ss_opts->refcnt++;
        mutex_unlock(&ss_opts->lock);
 
-       pattern = ss_opts->pattern;
-       isoc_interval = ss_opts->isoc_interval;
-       isoc_maxpacket = ss_opts->isoc_maxpacket;
-       isoc_mult = ss_opts->isoc_mult;
-       isoc_maxburst = ss_opts->isoc_maxburst;
-       buflen = ss_opts->bulk_buflen;
+       ss->pattern = ss_opts->pattern;
+       ss->isoc_interval = ss_opts->isoc_interval;
+       ss->isoc_maxpacket = ss_opts->isoc_maxpacket;
+       ss->isoc_mult = ss_opts->isoc_mult;
+       ss->isoc_maxburst = ss_opts->isoc_maxburst;
+       ss->buflen = ss_opts->bulk_buflen;
 
        ss->function.name = "source/sink";
        ss->function.bind = sourcesink_bind;
@@ -915,7 +906,7 @@ static ssize_t f_ss_opts_pattern_show(struct config_item *item, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->pattern);
+       result = sprintf(page, "%u\n", opts->pattern);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -958,7 +949,7 @@ static ssize_t f_ss_opts_isoc_interval_show(struct config_item *item, char *page
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_interval);
+       result = sprintf(page, "%u\n", opts->isoc_interval);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1001,7 +992,7 @@ static ssize_t f_ss_opts_isoc_maxpacket_show(struct config_item *item, char *pag
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_maxpacket);
+       result = sprintf(page, "%u\n", opts->isoc_maxpacket);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1044,7 +1035,7 @@ static ssize_t f_ss_opts_isoc_mult_show(struct config_item *item, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_mult);
+       result = sprintf(page, "%u\n", opts->isoc_mult);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1087,7 +1078,7 @@ static ssize_t f_ss_opts_isoc_maxburst_show(struct config_item *item, char *page
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_maxburst);
+       result = sprintf(page, "%u\n", opts->isoc_maxburst);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1130,7 +1121,7 @@ static ssize_t f_ss_opts_bulk_buflen_show(struct config_item *item, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->bulk_buflen);
+       result = sprintf(page, "%u\n", opts->bulk_buflen);
        mutex_unlock(&opts->lock);
 
        return result;