diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/usb/gadget/function/f_sourcesink.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/usb/gadget/function/f_sourcesink.c')
-rw-r--r-- | kernel/drivers/usb/gadget/function/f_sourcesink.c | 256 |
1 files changed, 115 insertions, 141 deletions
diff --git a/kernel/drivers/usb/gadget/function/f_sourcesink.c b/kernel/drivers/usb/gadget/function/f_sourcesink.c index 3a5ae9900..9f3ced62d 100644 --- a/kernel/drivers/usb/gadget/function/f_sourcesink.c +++ b/kernel/drivers/usb/gadget/function/f_sourcesink.c @@ -20,7 +20,6 @@ #include <linux/err.h> #include "g_zero.h" -#include "gadget_chips.h" #include "u_f.h" /* @@ -42,11 +41,6 @@ * queues are relatively independent, will receive a range of packet sizes, * and can often be made to run out completely. Those issues are important * when stress testing peripheral controller drivers. - * - * - * This is currently packaged as a configuration driver, which can't be - * combined with other functions to make composite devices. However, it - * can be combined with other independent configurations. */ struct f_sourcesink { struct usb_function function; @@ -56,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) @@ -63,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 = { @@ -304,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) @@ -317,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, @@ -361,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: /* @@ -409,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; @@ -421,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 */ @@ -443,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, @@ -495,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: @@ -516,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; } @@ -531,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; @@ -562,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; @@ -611,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; @@ -635,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); @@ -689,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; } @@ -708,7 +698,6 @@ fail: fail2: ep = ss->out_ep; usb_ep_disable(ep); - ep->driver_data = NULL; goto fail; } @@ -730,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; } } @@ -752,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; } } @@ -769,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); } @@ -878,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; @@ -904,9 +889,6 @@ static inline struct f_ss_opts *to_f_ss_opts(struct config_item *item) func_inst.group); } -CONFIGFS_ATTR_STRUCT(f_ss_opts); -CONFIGFS_ATTR_OPS(f_ss_opts); - static void ss_attr_release(struct config_item *item) { struct f_ss_opts *ss_opts = to_f_ss_opts(item); @@ -916,24 +898,24 @@ static void ss_attr_release(struct config_item *item) static struct configfs_item_operations ss_item_ops = { .release = ss_attr_release, - .show_attribute = f_ss_opts_attr_show, - .store_attribute = f_ss_opts_attr_store, }; -static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page) +static ssize_t f_ss_opts_pattern_show(struct config_item *item, char *page) { + struct f_ss_opts *opts = to_f_ss_opts(item); 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; } -static ssize_t f_ss_opts_pattern_store(struct f_ss_opts *opts, +static ssize_t f_ss_opts_pattern_store(struct config_item *item, const char *page, size_t len) { + struct f_ss_opts *opts = to_f_ss_opts(item); int ret; u8 num; @@ -959,25 +941,24 @@ end: return ret; } -static struct f_ss_opts_attribute f_ss_opts_pattern = - __CONFIGFS_ATTR(pattern, S_IRUGO | S_IWUSR, - f_ss_opts_pattern_show, - f_ss_opts_pattern_store); +CONFIGFS_ATTR(f_ss_opts_, pattern); -static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page) +static ssize_t f_ss_opts_isoc_interval_show(struct config_item *item, char *page) { + struct f_ss_opts *opts = to_f_ss_opts(item); 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; } -static ssize_t f_ss_opts_isoc_interval_store(struct f_ss_opts *opts, +static ssize_t f_ss_opts_isoc_interval_store(struct config_item *item, const char *page, size_t len) { + struct f_ss_opts *opts = to_f_ss_opts(item); int ret; u8 num; @@ -1003,25 +984,24 @@ end: return ret; } -static struct f_ss_opts_attribute f_ss_opts_isoc_interval = - __CONFIGFS_ATTR(isoc_interval, S_IRUGO | S_IWUSR, - f_ss_opts_isoc_interval_show, - f_ss_opts_isoc_interval_store); +CONFIGFS_ATTR(f_ss_opts_, isoc_interval); -static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page) +static ssize_t f_ss_opts_isoc_maxpacket_show(struct config_item *item, char *page) { + struct f_ss_opts *opts = to_f_ss_opts(item); 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; } -static ssize_t f_ss_opts_isoc_maxpacket_store(struct f_ss_opts *opts, +static ssize_t f_ss_opts_isoc_maxpacket_store(struct config_item *item, const char *page, size_t len) { + struct f_ss_opts *opts = to_f_ss_opts(item); int ret; u16 num; @@ -1047,25 +1027,24 @@ end: return ret; } -static struct f_ss_opts_attribute f_ss_opts_isoc_maxpacket = - __CONFIGFS_ATTR(isoc_maxpacket, S_IRUGO | S_IWUSR, - f_ss_opts_isoc_maxpacket_show, - f_ss_opts_isoc_maxpacket_store); +CONFIGFS_ATTR(f_ss_opts_, isoc_maxpacket); -static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page) +static ssize_t f_ss_opts_isoc_mult_show(struct config_item *item, char *page) { + struct f_ss_opts *opts = to_f_ss_opts(item); 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; } -static ssize_t f_ss_opts_isoc_mult_store(struct f_ss_opts *opts, +static ssize_t f_ss_opts_isoc_mult_store(struct config_item *item, const char *page, size_t len) { + struct f_ss_opts *opts = to_f_ss_opts(item); int ret; u8 num; @@ -1091,25 +1070,24 @@ end: return ret; } -static struct f_ss_opts_attribute f_ss_opts_isoc_mult = - __CONFIGFS_ATTR(isoc_mult, S_IRUGO | S_IWUSR, - f_ss_opts_isoc_mult_show, - f_ss_opts_isoc_mult_store); +CONFIGFS_ATTR(f_ss_opts_, isoc_mult); -static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page) +static ssize_t f_ss_opts_isoc_maxburst_show(struct config_item *item, char *page) { + struct f_ss_opts *opts = to_f_ss_opts(item); 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; } -static ssize_t f_ss_opts_isoc_maxburst_store(struct f_ss_opts *opts, +static ssize_t f_ss_opts_isoc_maxburst_store(struct config_item *item, const char *page, size_t len) { + struct f_ss_opts *opts = to_f_ss_opts(item); int ret; u8 num; @@ -1135,25 +1113,24 @@ end: return ret; } -static struct f_ss_opts_attribute f_ss_opts_isoc_maxburst = - __CONFIGFS_ATTR(isoc_maxburst, S_IRUGO | S_IWUSR, - f_ss_opts_isoc_maxburst_show, - f_ss_opts_isoc_maxburst_store); +CONFIGFS_ATTR(f_ss_opts_, isoc_maxburst); -static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page) +static ssize_t f_ss_opts_bulk_buflen_show(struct config_item *item, char *page) { + struct f_ss_opts *opts = to_f_ss_opts(item); 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; } -static ssize_t f_ss_opts_bulk_buflen_store(struct f_ss_opts *opts, +static ssize_t f_ss_opts_bulk_buflen_store(struct config_item *item, const char *page, size_t len) { + struct f_ss_opts *opts = to_f_ss_opts(item); int ret; u32 num; @@ -1174,18 +1151,15 @@ end: return ret; } -static struct f_ss_opts_attribute f_ss_opts_bulk_buflen = - __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR, - f_ss_opts_bulk_buflen_show, - f_ss_opts_bulk_buflen_store); +CONFIGFS_ATTR(f_ss_opts_, bulk_buflen); static struct configfs_attribute *ss_attrs[] = { - &f_ss_opts_pattern.attr, - &f_ss_opts_isoc_interval.attr, - &f_ss_opts_isoc_maxpacket.attr, - &f_ss_opts_isoc_mult.attr, - &f_ss_opts_isoc_maxburst.attr, - &f_ss_opts_bulk_buflen.attr, + &f_ss_opts_attr_pattern, + &f_ss_opts_attr_isoc_interval, + &f_ss_opts_attr_isoc_maxpacket, + &f_ss_opts_attr_isoc_mult, + &f_ss_opts_attr_isoc_maxburst, + &f_ss_opts_attr_bulk_buflen, NULL, }; |