From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757642AbcBCM4v (ORCPT ); Wed, 3 Feb 2016 07:56:51 -0500 Received: from mailout1.samsung.com ([203.254.224.24]:33343 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751824AbcBCMkN (ORCPT ); Wed, 3 Feb 2016 07:40:13 -0500 X-AuditID: cbfee61b-f793c6d00000236c-92-56b1f52bfcdb From: Robert Baldyga To: balbi@ti.com Cc: gregkh@linuxfoundation.org, andrzej.p@samsung.com, m.szyprowski@samsung.com, b.zolnierkie@samsung.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Robert Baldyga Subject: [PATCH v4 01/43] usb: gadget: f_sourcesink: make ISO altset user-selectable Date: Wed, 03 Feb 2016 13:39:09 +0100 Message-id: <1454503191-11796-2-git-send-email-r.baldyga@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1454503191-11796-1-git-send-email-r.baldyga@samsung.com> References: <1454503191-11796-1-git-send-email-r.baldyga@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprKLMWRmVeSWpSXmKPExsVy+t9jQV2drxvDDJrvMFvMetnOYrFxxnpW i4P36y2aF69ns7i8aw6bxaJlrcwWa4/cZbd4cHgnuwOHx/65a9g9+rasYvQ4fmM7k8fnTXIB LFFcNimpOZllqUX6dglcGRuvT2Yq2OpWMfXLerYGxq9WXYycHBICJhIPZqxhgrDFJC7cW8/W xcjFISQwi1Fi3YlVLCAJIYGfjBKvn9mD2GwCOhJbvk9gBLFFBAQk1r+4xA7SwCxwjlHi4Z02 sISwQJjE2afdYDaLgKrE9G3/wAbxCrhK7HoNMVRCQE7i5LHJrF2MHBycAm4SD485QOwCKmn9 zjiBkXcBI8MqRonUguSC4qT0XKO81HK94sTc4tK8dL3k/NxNjODAeia9g/HwLvdDjAIcjEo8 vBG/NoQJsSaWFVfmHmKU4GBWEuE1+rwxTIg3JbGyKrUoP76oNCe1+BCjNAeLkjjv4//rwoQE 0hNLUrNTUwtSi2CyTBycUg2MW5eUpiS9i2x+e/Ll7LJWl60dsz285/wyyfkXzx7W0aIiVlNb sKy+3iKgaYdC/VLZaRuzQsoe6os39Cnd76v7Yn3l6Fc9rneSIXavNLlm94WmxUk9KZ30zHTe uZ0dKhvMXbVOy79b2LZsU2NwZ+oWyylrLWeZq6w3dux3U9td/GjHpbv3HM4qsRRnJBpqMRcV JwIAbtQG+ygCAAA= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org So far it was decided during the bind process whether is iso altsetting included to f_sourcesink function or not. This decision was based on availability of isochronous endpoints. Since we can assemble gadget driver using composite framework and configfs from many different functions, availability of given type of endpoint can depend on selected components or even on their order in given configuration. This can result with non-obvious behavior - even small, seemingly unrelated change in gadget configuration can decide if we have second altsetting with iso endpoints in given sourcesink function instance or not. Because of this it's way better to have additional parameter allowing user to decide if he/she wants to have iso altsetting, and if iso altsetting is included, and there are no iso endpoints available, function bind will fail instead of silently allowing to have non-complete function bound. Signed-off-by: Robert Baldyga --- drivers/usb/gadget/function/f_sourcesink.c | 98 ++++++++++++++++++++---------- drivers/usb/gadget/function/g_zero.h | 3 + drivers/usb/gadget/legacy/zero.c | 6 ++ 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 242ba5c..e950031 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -49,6 +49,7 @@ struct f_sourcesink { unsigned isoc_maxpacket; unsigned isoc_mult; unsigned isoc_maxburst; + unsigned isoc_enabled; unsigned buflen; unsigned bulk_qlen; unsigned iso_qlen; @@ -336,17 +337,28 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) /* allocate bulk endpoints */ ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); - if (!ss->in_ep) { -autoconf_fail: - ERROR(cdev, "%s: can't autoconfigure on %s\n", - f->name, cdev->gadget->name); - return -ENODEV; - } + if (!ss->in_ep) + goto autoconf_fail; ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc); if (!ss->out_ep) goto autoconf_fail; + /* support high speed hardware */ + hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; + hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; + + /* support super speed hardware */ + ss_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; + ss_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; + + if (!ss->isoc_enabled) { + fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL; + hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL; + ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL; + goto no_iso; + } + /* sanity check the isoc module parameters */ if (ss->isoc_interval < 1) ss->isoc_interval = 1; @@ -368,30 +380,14 @@ autoconf_fail: /* allocate iso endpoints */ ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc); if (!ss->iso_in_ep) - goto no_iso; + goto autoconf_fail; ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc); - if (!ss->iso_out_ep) { - usb_ep_autoconfig_release(ss->iso_in_ep); - ss->iso_in_ep = NULL; -no_iso: - /* - * We still want to work even if the UDC doesn't have isoc - * endpoints, so null out the alt interface that contains - * them and continue. - */ - fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL; - hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL; - ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL; - } + if (!ss->iso_out_ep) + goto autoconf_fail; if (ss->isoc_maxpacket > 1024) ss->isoc_maxpacket = 1024; - - /* support high speed hardware */ - hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; - hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; - /* * Fill in the HS isoc descriptors from the module parameters. * We assume that the user knows what they are doing and won't @@ -408,12 +404,6 @@ no_iso: hs_iso_sink_desc.bInterval = ss->isoc_interval; hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; - /* support super speed hardware */ - ss_source_desc.bEndpointAddress = - fs_source_desc.bEndpointAddress; - ss_sink_desc.bEndpointAddress = - fs_sink_desc.bEndpointAddress; - /* * Fill in the SS isoc descriptors from the module parameters. * We assume that the user knows what they are doing and won't @@ -436,6 +426,7 @@ no_iso: (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1); ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; +no_iso: ret = usb_assign_descriptors(f, fs_source_sink_descs, hs_source_sink_descs, ss_source_sink_descs); if (ret) @@ -448,6 +439,11 @@ no_iso: ss->iso_in_ep ? ss->iso_in_ep->name : "", ss->iso_out_ep ? ss->iso_out_ep->name : ""); return 0; + +autoconf_fail: + ERROR(cdev, "%s: can't autoconfigure on %s\n", + f->name, cdev->gadget->name); + return -ENODEV; } static void @@ -857,6 +853,7 @@ static struct usb_function *source_sink_alloc_func( ss->isoc_maxpacket = ss_opts->isoc_maxpacket; ss->isoc_mult = ss_opts->isoc_mult; ss->isoc_maxburst = ss_opts->isoc_maxburst; + ss->isoc_enabled = ss_opts->isoc_enabled; ss->buflen = ss_opts->bulk_buflen; ss->bulk_qlen = ss_opts->bulk_qlen; ss->iso_qlen = ss_opts->iso_qlen; @@ -1106,6 +1103,44 @@ end: CONFIGFS_ATTR(f_ss_opts_, isoc_maxburst); +static ssize_t f_ss_opts_isoc_enabled_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\n", opts->isoc_enabled); + mutex_unlock(&opts->lock); + + return result; +} + +static ssize_t f_ss_opts_isoc_enabled_store(struct config_item *item, + const char *page, size_t len) +{ + struct f_ss_opts *opts = to_f_ss_opts(item); + int ret; + bool enabled; + + mutex_lock(&opts->lock); + if (opts->refcnt) { + ret = -EBUSY; + goto end; + } + + ret = strtobool(page, &enabled); + if (ret) + goto end; + + opts->isoc_enabled = enabled; + ret = len; +end: + mutex_unlock(&opts->lock); + return ret; +} + +CONFIGFS_ATTR(f_ss_opts_, isoc_enabled); + 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); @@ -1226,6 +1261,7 @@ static struct configfs_attribute *ss_attrs[] = { &f_ss_opts_attr_isoc_maxpacket, &f_ss_opts_attr_isoc_mult, &f_ss_opts_attr_isoc_maxburst, + &f_ss_opts_attr_isoc_enabled, &f_ss_opts_attr_bulk_buflen, &f_ss_opts_attr_bulk_qlen, &f_ss_opts_attr_iso_qlen, diff --git a/drivers/usb/gadget/function/g_zero.h b/drivers/usb/gadget/function/g_zero.h index 492924d0..ae03278 100644 --- a/drivers/usb/gadget/function/g_zero.h +++ b/drivers/usb/gadget/function/g_zero.h @@ -10,6 +10,7 @@ #define GZERO_QLEN 32 #define GZERO_ISOC_INTERVAL 4 #define GZERO_ISOC_MAXPACKET 1024 +#define GZERO_ISOC_ENABLED 1 #define GZERO_SS_BULK_QLEN 1 #define GZERO_SS_ISO_QLEN 8 @@ -19,6 +20,7 @@ struct usb_zero_options { unsigned isoc_maxpacket; unsigned isoc_mult; unsigned isoc_maxburst; + unsigned isoc_enabled; unsigned bulk_buflen; unsigned qlen; unsigned ss_bulk_qlen; @@ -32,6 +34,7 @@ struct f_ss_opts { unsigned isoc_maxpacket; unsigned isoc_mult; unsigned isoc_maxburst; + unsigned isoc_enabled; unsigned bulk_buflen; unsigned bulk_qlen; unsigned iso_qlen; diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c index d02e2ce..6adfc88 100644 --- a/drivers/usb/gadget/legacy/zero.c +++ b/drivers/usb/gadget/legacy/zero.c @@ -66,6 +66,7 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR); static struct usb_zero_options gzero_options = { .isoc_interval = GZERO_ISOC_INTERVAL, .isoc_maxpacket = GZERO_ISOC_MAXPACKET, + .isoc_enabled = GZERO_ISOC_ENABLED, .bulk_buflen = GZERO_BULK_BUFLEN, .qlen = GZERO_QLEN, .ss_bulk_qlen = GZERO_SS_BULK_QLEN, @@ -251,6 +252,10 @@ module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)"); +module_param_named(isoc_enabled, gzero_options.isoc_enabled, uint, + S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(isoc_enabled, "0 - disabled, 1 - enabled"); + static struct usb_function *func_lb; static struct usb_function_instance *func_inst_lb; @@ -294,6 +299,7 @@ static int zero_bind(struct usb_composite_dev *cdev) ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket; ss_opts->isoc_mult = gzero_options.isoc_mult; ss_opts->isoc_maxburst = gzero_options.isoc_maxburst; + ss_opts->isoc_enabled = gzero_options.isoc_enabled; ss_opts->bulk_buflen = gzero_options.bulk_buflen; ss_opts->bulk_qlen = gzero_options.ss_bulk_qlen; ss_opts->iso_qlen = gzero_options.ss_iso_qlen; -- 1.9.1