summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/usb/gadget
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/usb/gadget')
-rw-r--r--kernel/drivers/usb/gadget/Kconfig2
-rw-r--r--kernel/drivers/usb/gadget/composite.c47
-rw-r--r--kernel/drivers/usb/gadget/config.c56
-rw-r--r--kernel/drivers/usb/gadget/configfs.c326
-rw-r--r--kernel/drivers/usb/gadget/epautoconf.c296
-rw-r--r--kernel/drivers/usb/gadget/function/f_acm.c50
-rw-r--r--kernel/drivers/usb/gadget/function/f_ecm.c43
-rw-r--r--kernel/drivers/usb/gadget/function/f_eem.c24
-rw-r--r--kernel/drivers/usb/gadget/function/f_fs.c16
-rw-r--r--kernel/drivers/usb/gadget/function/f_hid.c50
-rw-r--r--kernel/drivers/usb/gadget/function/f_loopback.c198
-rw-r--r--kernel/drivers/usb/gadget/function/f_mass_storage.c299
-rw-r--r--kernel/drivers/usb/gadget/function/f_mass_storage.h6
-rw-r--r--kernel/drivers/usb/gadget/function/f_midi.c72
-rw-r--r--kernel/drivers/usb/gadget/function/f_ncm.c42
-rw-r--r--kernel/drivers/usb/gadget/function/f_obex.c58
-rw-r--r--kernel/drivers/usb/gadget/function/f_phonet.c33
-rw-r--r--kernel/drivers/usb/gadget/function/f_printer.c49
-rw-r--r--kernel/drivers/usb/gadget/function/f_rndis.c92
-rw-r--r--kernel/drivers/usb/gadget/function/f_serial.c37
-rw-r--r--kernel/drivers/usb/gadget/function/f_sourcesink.c256
-rw-r--r--kernel/drivers/usb/gadget/function/f_subset.c18
-rw-r--r--kernel/drivers/usb/gadget/function/f_uac1.c43
-rw-r--r--kernel/drivers/usb/gadget/function/f_uac2.c41
-rw-r--r--kernel/drivers/usb/gadget/function/f_uvc.c49
-rw-r--r--kernel/drivers/usb/gadget/function/rndis.c352
-rw-r--r--kernel/drivers/usb/gadget/function/rndis.h33
-rw-r--r--kernel/drivers/usb/gadget/function/storage_common.c2
-rw-r--r--kernel/drivers/usb/gadget/function/storage_common.h2
-rw-r--r--kernel/drivers/usb/gadget/function/u_ether.c11
-rw-r--r--kernel/drivers/usb/gadget/function/u_ether.h4
-rw-r--r--kernel/drivers/usb/gadget/function/u_ether_configfs.h44
-rw-r--r--kernel/drivers/usb/gadget/function/u_rndis.h2
-rw-r--r--kernel/drivers/usb/gadget/function/u_serial.c11
-rw-r--r--kernel/drivers/usb/gadget/function/u_uac1.h2
-rw-r--r--kernel/drivers/usb/gadget/function/uvc.h1
-rw-r--r--kernel/drivers/usb/gadget/function/uvc_configfs.c387
-rw-r--r--kernel/drivers/usb/gadget/function/uvc_queue.c28
-rw-r--r--kernel/drivers/usb/gadget/function/uvc_queue.h4
-rw-r--r--kernel/drivers/usb/gadget/legacy/Kconfig2
-rw-r--r--kernel/drivers/usb/gadget/legacy/acm_ms.c41
-rw-r--r--kernel/drivers/usb/gadget/legacy/audio.c41
-rw-r--r--kernel/drivers/usb/gadget/legacy/cdc2.c35
-rw-r--r--kernel/drivers/usb/gadget/legacy/dbgp.c28
-rw-r--r--kernel/drivers/usb/gadget/legacy/ether.c36
-rw-r--r--kernel/drivers/usb/gadget/legacy/g_ffs.c32
-rw-r--r--kernel/drivers/usb/gadget/legacy/gmidi.c8
-rw-r--r--kernel/drivers/usb/gadget/legacy/hid.c37
-rw-r--r--kernel/drivers/usb/gadget/legacy/inode.c9
-rw-r--r--kernel/drivers/usb/gadget/legacy/mass_storage.c41
-rw-r--r--kernel/drivers/usb/gadget/legacy/multi.c43
-rw-r--r--kernel/drivers/usb/gadget/legacy/ncm.c34
-rw-r--r--kernel/drivers/usb/gadget/legacy/nokia.c105
-rw-r--r--kernel/drivers/usb/gadget/legacy/printer.c51
-rw-r--r--kernel/drivers/usb/gadget/legacy/serial.c38
-rw-r--r--kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.c255
-rw-r--r--kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.h12
-rw-r--r--kernel/drivers/usb/gadget/legacy/zero.c41
-rw-r--r--kernel/drivers/usb/gadget/udc/Kconfig2
-rw-r--r--kernel/drivers/usb/gadget/udc/amd5536udc.c724
-rw-r--r--kernel/drivers/usb/gadget/udc/amd5536udc.h5
-rw-r--r--kernel/drivers/usb/gadget/udc/at91_udc.c39
-rw-r--r--kernel/drivers/usb/gadget/udc/at91_udc.h8
-rw-r--r--kernel/drivers/usb/gadget/udc/atmel_usba_udc.c55
-rw-r--r--kernel/drivers/usb/gadget/udc/atmel_usba_udc.h2
-rw-r--r--kernel/drivers/usb/gadget/udc/bcm63xx_udc.c29
-rw-r--r--kernel/drivers/usb/gadget/udc/bdc/bdc.h2
-rw-r--r--kernel/drivers/usb/gadget/udc/bdc/bdc_core.c3
-rw-r--r--kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c15
-rw-r--r--kernel/drivers/usb/gadget/udc/dummy_hcd.c147
-rw-r--r--kernel/drivers/usb/gadget/udc/fotg210-udc.c32
-rw-r--r--kernel/drivers/usb/gadget/udc/fsl_qe_udc.c11
-rw-r--r--kernel/drivers/usb/gadget/udc/fsl_udc_core.c13
-rw-r--r--kernel/drivers/usb/gadget/udc/fusb300_udc.c11
-rw-r--r--kernel/drivers/usb/gadget/udc/gadget_chips.h55
-rw-r--r--kernel/drivers/usb/gadget/udc/goku_udc.c38
-rw-r--r--kernel/drivers/usb/gadget/udc/gr_udc.c14
-rw-r--r--kernel/drivers/usb/gadget/udc/lpc32xx_udc.c32
-rw-r--r--kernel/drivers/usb/gadget/udc/m66592-udc.c11
-rw-r--r--kernel/drivers/usb/gadget/udc/mv_u3d_core.c12
-rw-r--r--kernel/drivers/usb/gadget/udc/mv_udc_core.c12
-rw-r--r--kernel/drivers/usb/gadget/udc/net2272.c15
-rw-r--r--kernel/drivers/usb/gadget/udc/net2280.c237
-rw-r--r--kernel/drivers/usb/gadget/udc/omap_udc.c22
-rw-r--r--kernel/drivers/usb/gadget/udc/pch_udc.c46
-rw-r--r--kernel/drivers/usb/gadget/udc/pxa25x_udc.c30
-rw-r--r--kernel/drivers/usb/gadget/udc/pxa27x_udc.c6
-rw-r--r--kernel/drivers/usb/gadget/udc/pxa27x_udc.h40
-rw-r--r--kernel/drivers/usb/gadget/udc/r8a66597-udc.c10
-rw-r--r--kernel/drivers/usb/gadget/udc/s3c-hsudc.c15
-rw-r--r--kernel/drivers/usb/gadget/udc/s3c2410_udc.c38
-rw-r--r--kernel/drivers/usb/gadget/udc/udc-core.c104
-rw-r--r--kernel/drivers/usb/gadget/udc/udc-xilinx.c9
93 files changed, 2905 insertions, 2914 deletions
diff --git a/kernel/drivers/usb/gadget/Kconfig b/kernel/drivers/usb/gadget/Kconfig
index bcf83c0a6..33834aa09 100644
--- a/kernel/drivers/usb/gadget/Kconfig
+++ b/kernel/drivers/usb/gadget/Kconfig
@@ -113,7 +113,7 @@ config USB_GADGET_VBUS_DRAW
config USB_GADGET_STORAGE_NUM_BUFFERS
int "Number of storage pipeline buffers"
- range 2 4
+ range 2 32
default 2
help
Usually 2 buffers are enough to establish a good buffering
diff --git a/kernel/drivers/usb/gadget/composite.c b/kernel/drivers/usb/gadget/composite.c
index 58b4657fc..8b14c2a13 100644
--- a/kernel/drivers/usb/gadget/composite.c
+++ b/kernel/drivers/usb/gadget/composite.c
@@ -19,6 +19,7 @@
#include <linux/utsname.h>
#include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
#include <asm/unaligned.h>
#include "u_os_desc.h"
@@ -209,6 +210,12 @@ int usb_add_function(struct usb_configuration *config,
function->config = config;
list_add_tail(&function->list, &config->functions);
+ if (function->bind_deactivated) {
+ value = usb_function_deactivate(function);
+ if (value)
+ goto done;
+ }
+
/* REVISIT *require* function->bind? */
if (function->bind) {
value = function->bind(config, function);
@@ -279,7 +286,7 @@ int usb_function_deactivate(struct usb_function *function)
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->deactivations == 0)
- status = usb_gadget_disconnect(cdev->gadget);
+ status = usb_gadget_deactivate(cdev->gadget);
if (status == 0)
cdev->deactivations++;
@@ -311,7 +318,7 @@ int usb_function_activate(struct usb_function *function)
else {
cdev->deactivations--;
if (cdev->deactivations == 0)
- status = usb_gadget_connect(cdev->gadget);
+ status = usb_gadget_activate(cdev->gadget);
}
spin_unlock_irqrestore(&cdev->lock, flags);
@@ -832,9 +839,7 @@ int usb_add_config(struct usb_composite_dev *cdev,
}
}
- /* set_alt(), or next bind(), sets up
- * ep->driver_data as needed.
- */
+ /* set_alt(), or next bind(), sets up ep->claimed as needed */
usb_ep_autoconfig_reset(cdev->gadget);
done:
@@ -896,7 +901,7 @@ void usb_remove_config(struct usb_composite_dev *cdev,
/* We support strings in multiple languages ... string descriptor zero
* says which languages are supported. The typical case will be that
- * only one language (probably English) is used, with I18N handled on
+ * only one language (probably English) is used, with i18n handled on
* the host side.
*/
@@ -949,7 +954,7 @@ static int get_string(struct usb_composite_dev *cdev,
struct usb_function *f;
int len;
- /* Yes, not only is USB's I18N support probably more than most
+ /* Yes, not only is USB's i18n support probably more than most
* folk will ever care about ... also, it's all supported here.
* (Except for UTF8 support for Unicode's "Astral Planes".)
*/
@@ -1499,6 +1504,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
} else {
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
}
+ } else {
+ cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
value = min(w_length, (u16) sizeof cdev->desc);
@@ -1534,6 +1541,32 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) value);
}
break;
+ case USB_DT_OTG:
+ if (gadget_is_otg(gadget)) {
+ struct usb_configuration *config;
+ int otg_desc_len = 0;
+
+ if (cdev->config)
+ config = cdev->config;
+ else
+ config = list_first_entry(
+ &cdev->configs,
+ struct usb_configuration, list);
+ if (!config)
+ goto done;
+
+ if (gadget->otg_caps &&
+ (gadget->otg_caps->otg_rev >= 0x0200))
+ otg_desc_len += sizeof(
+ struct usb_otg20_descriptor);
+ else
+ otg_desc_len += sizeof(
+ struct usb_otg_descriptor);
+
+ value = min_t(int, w_length, otg_desc_len);
+ memcpy(req->buf, config->descriptors[0], value);
+ }
+ break;
}
break;
diff --git a/kernel/drivers/usb/gadget/config.c b/kernel/drivers/usb/gadget/config.c
index 34e12fc52..0fafa7a1b 100644
--- a/kernel/drivers/usb/gadget/config.c
+++ b/kernel/drivers/usb/gadget/config.c
@@ -20,6 +20,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
@@ -195,3 +196,58 @@ void usb_free_all_descriptors(struct usb_function *f)
usb_free_descriptors(f->ss_descriptors);
}
EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
+
+struct usb_descriptor_header *usb_otg_descriptor_alloc(
+ struct usb_gadget *gadget)
+{
+ struct usb_descriptor_header *otg_desc;
+ unsigned length = 0;
+
+ if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200))
+ length = sizeof(struct usb_otg20_descriptor);
+ else
+ length = sizeof(struct usb_otg_descriptor);
+
+ otg_desc = kzalloc(length, GFP_KERNEL);
+ return otg_desc;
+}
+EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc);
+
+int usb_otg_descriptor_init(struct usb_gadget *gadget,
+ struct usb_descriptor_header *otg_desc)
+{
+ struct usb_otg_descriptor *otg1x_desc;
+ struct usb_otg20_descriptor *otg20_desc;
+ struct usb_otg_caps *otg_caps = gadget->otg_caps;
+ u8 otg_attributes = 0;
+
+ if (!otg_desc)
+ return -EINVAL;
+
+ if (otg_caps && otg_caps->otg_rev) {
+ if (otg_caps->hnp_support)
+ otg_attributes |= USB_OTG_HNP;
+ if (otg_caps->srp_support)
+ otg_attributes |= USB_OTG_SRP;
+ if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200))
+ otg_attributes |= USB_OTG_ADP;
+ } else {
+ otg_attributes = USB_OTG_SRP | USB_OTG_HNP;
+ }
+
+ if (otg_caps && (otg_caps->otg_rev >= 0x0200)) {
+ otg20_desc = (struct usb_otg20_descriptor *)otg_desc;
+ otg20_desc->bLength = sizeof(struct usb_otg20_descriptor);
+ otg20_desc->bDescriptorType = USB_DT_OTG;
+ otg20_desc->bmAttributes = otg_attributes;
+ otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev);
+ } else {
+ otg1x_desc = (struct usb_otg_descriptor *)otg_desc;
+ otg1x_desc->bLength = sizeof(struct usb_otg_descriptor);
+ otg1x_desc->bDescriptorType = USB_DT_OTG;
+ otg1x_desc->bmAttributes = otg_attributes;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_descriptor_init);
diff --git a/kernel/drivers/usb/gadget/configfs.c b/kernel/drivers/usb/gadget/configfs.c
index 0495c94a2..163d305e1 100644
--- a/kernel/drivers/usb/gadget/configfs.c
+++ b/kernel/drivers/usb/gadget/configfs.c
@@ -41,6 +41,8 @@ int check_user_usb_string(const char *name,
#define MAX_NAME_LEN 40
#define MAX_USB_STRING_LANGS 2
+static const struct usb_descriptor_header *otg_desc[2];
+
struct gadget_info {
struct config_group group;
struct config_group functions_group;
@@ -55,9 +57,6 @@ struct gadget_info {
struct list_head available_func;
const char *udc_name;
-#ifdef CONFIG_USB_OTG
- struct usb_otg_descriptor otg;
-#endif
struct usb_composite_driver composite;
struct usb_composite_dev cdev;
bool use_os_desc;
@@ -65,6 +64,11 @@ struct gadget_info {
char qw_sign[OS_STRING_QW_SIGN_LEN];
};
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct gadget_info, group);
+}
+
struct config_usb_cfg {
struct config_group group;
struct config_group strings_group;
@@ -75,6 +79,12 @@ struct config_usb_cfg {
struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
};
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct config_usb_cfg,
+ group);
+}
+
struct gadget_strings {
struct usb_gadget_strings stringtab_dev;
struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
@@ -118,32 +128,25 @@ static int usb_string_copy(const char *s, char **s_copy)
return 0;
}
-CONFIGFS_ATTR_STRUCT(gadget_info);
-CONFIGFS_ATTR_STRUCT(config_usb_cfg);
-
-#define GI_DEVICE_DESC_ITEM_ATTR(name) \
- static struct gadget_info_attribute gadget_cdev_desc_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- gadget_dev_desc_##name##_show, \
- gadget_dev_desc_##name##_store)
-
#define GI_DEVICE_DESC_SIMPLE_R_u8(__name) \
- static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
char *page) \
{ \
- return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \
+ return sprintf(page, "0x%02x\n", \
+ to_gadget_info(item)->cdev.desc.__name); \
}
#define GI_DEVICE_DESC_SIMPLE_R_u16(__name) \
- static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##__name##_show(struct config_item *item, \
char *page) \
{ \
- return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+ return sprintf(page, "0x%04x\n", \
+ le16_to_cpup(&to_gadget_info(item)->cdev.desc.__name)); \
}
#define GI_DEVICE_DESC_SIMPLE_W_u8(_name) \
- static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
u8 val; \
@@ -151,12 +154,12 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
ret = kstrtou8(page, 0, &val); \
if (ret) \
return ret; \
- gi->cdev.desc._name = val; \
+ to_gadget_info(item)->cdev.desc._name = val; \
return len; \
}
#define GI_DEVICE_DESC_SIMPLE_W_u16(_name) \
- static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+static ssize_t gadget_dev_desc_##_name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
u16 val; \
@@ -164,7 +167,7 @@ CONFIGFS_ATTR_STRUCT(config_usb_cfg);
ret = kstrtou16(page, 0, &val); \
if (ret) \
return ret; \
- gi->cdev.desc._name = cpu_to_le16p(&val); \
+ to_gadget_info(item)->cdev.desc._name = cpu_to_le16p(&val); \
return len; \
}
@@ -194,7 +197,7 @@ static ssize_t is_valid_bcd(u16 bcd_val)
return 0;
}
-static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdDevice_store(struct config_item *item,
const char *page, size_t len)
{
u16 bcdDevice;
@@ -207,11 +210,11 @@ static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
if (ret)
return ret;
- gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+ to_gadget_info(item)->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
return len;
}
-static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_bcdUSB_store(struct config_item *item,
const char *page, size_t len)
{
u16 bcdUSB;
@@ -224,13 +227,13 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
if (ret)
return ret;
- gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+ to_gadget_info(item)->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
return len;
}
-static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page)
{
- return sprintf(page, "%s\n", gi->udc_name ?: "");
+ return sprintf(page, "%s\n", to_gadget_info(item)->udc_name ?: "");
}
static int unregister_gadget(struct gadget_info *gi)
@@ -248,9 +251,10 @@ static int unregister_gadget(struct gadget_info *gi)
return 0;
}
-static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
const char *page, size_t len)
{
+ struct gadget_info *gi = to_gadget_info(item);
char *name;
int ret;
@@ -284,34 +288,29 @@ err:
return ret;
}
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
-GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
-GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
-GI_DEVICE_DESC_ITEM_ATTR(idVendor);
-GI_DEVICE_DESC_ITEM_ATTR(idProduct);
-GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
-GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
-GI_DEVICE_DESC_ITEM_ATTR(UDC);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
+CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
+CONFIGFS_ATTR(gadget_dev_desc_, bMaxPacketSize0);
+CONFIGFS_ATTR(gadget_dev_desc_, idVendor);
+CONFIGFS_ATTR(gadget_dev_desc_, idProduct);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
+CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
+CONFIGFS_ATTR(gadget_dev_desc_, UDC);
static struct configfs_attribute *gadget_root_attrs[] = {
- &gadget_cdev_desc_bDeviceClass.attr,
- &gadget_cdev_desc_bDeviceSubClass.attr,
- &gadget_cdev_desc_bDeviceProtocol.attr,
- &gadget_cdev_desc_bMaxPacketSize0.attr,
- &gadget_cdev_desc_idVendor.attr,
- &gadget_cdev_desc_idProduct.attr,
- &gadget_cdev_desc_bcdDevice.attr,
- &gadget_cdev_desc_bcdUSB.attr,
- &gadget_cdev_desc_UDC.attr,
+ &gadget_dev_desc_attr_bDeviceClass,
+ &gadget_dev_desc_attr_bDeviceSubClass,
+ &gadget_dev_desc_attr_bDeviceProtocol,
+ &gadget_dev_desc_attr_bMaxPacketSize0,
+ &gadget_dev_desc_attr_idVendor,
+ &gadget_dev_desc_attr_idProduct,
+ &gadget_dev_desc_attr_bcdDevice,
+ &gadget_dev_desc_attr_bcdUSB,
+ &gadget_dev_desc_attr_UDC,
NULL,
};
-static inline struct gadget_info *to_gadget_info(struct config_item *item)
-{
- return container_of(to_config_group(item), struct gadget_info, group);
-}
-
static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
{
return container_of(to_config_group(item), struct gadget_strings,
@@ -325,12 +324,6 @@ static inline struct gadget_config_name *to_gadget_config_name(
group);
}
-static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
-{
- return container_of(to_config_group(item), struct config_usb_cfg,
- group);
-}
-
static inline struct usb_function_instance *to_usb_function_instance(
struct config_item *item)
{
@@ -349,12 +342,8 @@ static void gadget_info_attr_release(struct config_item *item)
kfree(gi);
}
-CONFIGFS_ATTR_OPS(gadget_info);
-
static struct configfs_item_operations gadget_root_item_ops = {
.release = gadget_info_attr_release,
- .show_attribute = gadget_info_attr_show,
- .store_attribute = gadget_info_attr_store,
};
static void gadget_config_attr_release(struct config_item *item)
@@ -455,24 +444,20 @@ static int config_usb_cfg_unlink(
return 0;
}
-CONFIGFS_ATTR_OPS(config_usb_cfg);
-
static struct configfs_item_operations gadget_config_item_ops = {
.release = gadget_config_attr_release,
- .show_attribute = config_usb_cfg_attr_show,
- .store_attribute = config_usb_cfg_attr_store,
.allow_link = config_usb_cfg_link,
.drop_link = config_usb_cfg_unlink,
};
-static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_show(struct config_item *item,
char *page)
{
- return sprintf(page, "%u\n", cfg->c.MaxPower);
+ return sprintf(page, "%u\n", to_config_usb_cfg(item)->c.MaxPower);
}
-static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_MaxPower_store(struct config_item *item,
const char *page, size_t len)
{
u16 val;
@@ -482,17 +467,18 @@ static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
return ret;
if (DIV_ROUND_UP(val, 8) > 0xff)
return -ERANGE;
- cfg->c.MaxPower = val;
+ to_config_usb_cfg(item)->c.MaxPower = val;
return len;
}
-static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_item *item,
char *page)
{
- return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+ return sprintf(page, "0x%02x\n",
+ to_config_usb_cfg(item)->c.bmAttributes);
}
-static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_item *item,
const char *page, size_t len)
{
u8 val;
@@ -505,22 +491,16 @@ static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
USB_CONFIG_ATT_WAKEUP))
return -EINVAL;
- cfg->c.bmAttributes = val;
+ to_config_usb_cfg(item)->c.bmAttributes = val;
return len;
}
-#define CFG_CONFIG_DESC_ITEM_ATTR(name) \
- static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- gadget_config_desc_##name##_show, \
- gadget_config_desc_##name##_store)
-
-CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
-CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+CONFIGFS_ATTR(gadget_config_desc_, MaxPower);
+CONFIGFS_ATTR(gadget_config_desc_, bmAttributes);
static struct configfs_attribute *gadget_config_attrs[] = {
- &gadget_usb_cfg_MaxPower.attr,
- &gadget_usb_cfg_bmAttributes.attr,
+ &gadget_config_desc_attr_MaxPower,
+ &gadget_config_desc_attr_bmAttributes,
NULL,
};
@@ -571,7 +551,7 @@ static struct config_group *function_make(
if (IS_ERR(fi))
return ERR_CAST(fi);
- ret = config_item_set_name(&fi->group.cg_item, name);
+ ret = config_item_set_name(&fi->group.cg_item, "%s", name);
if (ret) {
usb_put_function_instance(fi);
return ERR_PTR(ret);
@@ -617,11 +597,10 @@ static struct config_item_type functions_type = {
.ct_owner = THIS_MODULE,
};
-CONFIGFS_ATTR_STRUCT(gadget_config_name);
GS_STRINGS_RW(gadget_config_name, configuration);
static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
- &gadget_config_name_configuration.attr,
+ &gadget_config_name_attr_configuration,
NULL,
};
@@ -720,15 +699,14 @@ static struct config_item_type config_desc_type = {
.ct_owner = THIS_MODULE,
};
-CONFIGFS_ATTR_STRUCT(gadget_strings);
GS_STRINGS_RW(gadget_strings, manufacturer);
GS_STRINGS_RW(gadget_strings, product);
GS_STRINGS_RW(gadget_strings, serialnumber);
static struct configfs_attribute *gadget_strings_langid_attrs[] = {
- &gadget_strings_manufacturer.attr,
- &gadget_strings_product.attr,
- &gadget_strings_serialnumber.attr,
+ &gadget_strings_attr_manufacturer,
+ &gadget_strings_attr_product,
+ &gadget_strings_attr_serialnumber,
NULL,
};
@@ -752,27 +730,25 @@ static inline struct os_desc *to_os_desc(struct config_item *item)
return container_of(to_config_group(item), struct os_desc, group);
}
-CONFIGFS_ATTR_STRUCT(os_desc);
-CONFIGFS_ATTR_OPS(os_desc);
-
-static ssize_t os_desc_use_show(struct os_desc *os_desc, char *page)
+static inline struct gadget_info *os_desc_item_to_gadget_info(
+ struct config_item *item)
{
- struct gadget_info *gi;
-
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+ return to_gadget_info(to_os_desc(item)->group.cg_item.ci_parent);
+}
- return sprintf(page, "%d", gi->use_os_desc);
+static ssize_t os_desc_use_show(struct config_item *item, char *page)
+{
+ return sprintf(page, "%d",
+ os_desc_item_to_gadget_info(item)->use_os_desc);
}
-static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_use_store(struct config_item *item, const char *page,
size_t len)
{
- struct gadget_info *gi;
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int ret;
bool use;
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
mutex_lock(&gi->lock);
ret = strtobool(page, &use);
if (!ret) {
@@ -784,29 +760,19 @@ static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
return ret;
}
-static struct os_desc_attribute os_desc_use =
- __CONFIGFS_ATTR(use, S_IRUGO | S_IWUSR,
- os_desc_use_show,
- os_desc_use_store);
-
-static ssize_t os_desc_b_vendor_code_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page)
{
- struct gadget_info *gi;
-
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
- return sprintf(page, "%d", gi->b_vendor_code);
+ return sprintf(page, "%d",
+ os_desc_item_to_gadget_info(item)->b_vendor_code);
}
-static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
+static ssize_t os_desc_b_vendor_code_store(struct config_item *item,
const char *page, size_t len)
{
- struct gadget_info *gi;
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int ret;
u8 b_vendor_code;
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
-
mutex_lock(&gi->lock);
ret = kstrtou8(page, 0, &b_vendor_code);
if (!ret) {
@@ -818,29 +784,20 @@ static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
return ret;
}
-static struct os_desc_attribute os_desc_b_vendor_code =
- __CONFIGFS_ATTR(b_vendor_code, S_IRUGO | S_IWUSR,
- os_desc_b_vendor_code_show,
- os_desc_b_vendor_code_store);
-
-static ssize_t os_desc_qw_sign_show(struct os_desc *os_desc, char *page)
+static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)
{
- struct gadget_info *gi;
-
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
-
return OS_STRING_QW_SIGN_LEN;
}
-static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
+static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
size_t len)
{
- struct gadget_info *gi;
+ struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int res, l;
- gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
if (page[l - 1] == '\n')
--l;
@@ -856,15 +813,14 @@ static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
return res;
}
-static struct os_desc_attribute os_desc_qw_sign =
- __CONFIGFS_ATTR(qw_sign, S_IRUGO | S_IWUSR,
- os_desc_qw_sign_show,
- os_desc_qw_sign_store);
+CONFIGFS_ATTR(os_desc_, use);
+CONFIGFS_ATTR(os_desc_, b_vendor_code);
+CONFIGFS_ATTR(os_desc_, qw_sign);
static struct configfs_attribute *os_desc_attrs[] = {
- &os_desc_use.attr,
- &os_desc_b_vendor_code.attr,
- &os_desc_qw_sign.attr,
+ &os_desc_attr_use,
+ &os_desc_attr_b_vendor_code,
+ &os_desc_attr_qw_sign,
NULL,
};
@@ -927,8 +883,6 @@ static int os_desc_unlink(struct config_item *os_desc_ci,
static struct configfs_item_operations os_desc_ops = {
.release = os_desc_attr_release,
- .show_attribute = os_desc_attr_show,
- .store_attribute = os_desc_attr_store,
.allow_link = os_desc_link,
.drop_link = os_desc_unlink,
};
@@ -939,28 +893,21 @@ static struct config_item_type os_desc_type = {
.ct_owner = THIS_MODULE,
};
-CONFIGFS_ATTR_STRUCT(usb_os_desc);
-CONFIGFS_ATTR_OPS(usb_os_desc);
-
-
static inline struct usb_os_desc_ext_prop
*to_usb_os_desc_ext_prop(struct config_item *item)
{
return container_of(item, struct usb_os_desc_ext_prop, item);
}
-CONFIGFS_ATTR_STRUCT(usb_os_desc_ext_prop);
-CONFIGFS_ATTR_OPS(usb_os_desc_ext_prop);
-
-static ssize_t ext_prop_type_show(struct usb_os_desc_ext_prop *ext_prop,
- char *page)
+static ssize_t ext_prop_type_show(struct config_item *item, char *page)
{
- return sprintf(page, "%d", ext_prop->type);
+ return sprintf(page, "%d", to_usb_os_desc_ext_prop(item)->type);
}
-static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_type_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
u8 type;
int ret;
@@ -998,9 +945,9 @@ end:
return ret;
}
-static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
- char *page)
+static ssize_t ext_prop_data_show(struct config_item *item, char *page)
{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
int len = ext_prop->data_len;
if (ext_prop->type == USB_EXT_PROP_UNICODE ||
@@ -1012,9 +959,10 @@ static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
return len;
}
-static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
+static ssize_t ext_prop_data_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
char *new_data;
size_t ret_len = len;
@@ -1045,17 +993,12 @@ static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
return ret_len;
}
-static struct usb_os_desc_ext_prop_attribute ext_prop_type =
- __CONFIGFS_ATTR(type, S_IRUGO | S_IWUSR,
- ext_prop_type_show, ext_prop_type_store);
-
-static struct usb_os_desc_ext_prop_attribute ext_prop_data =
- __CONFIGFS_ATTR(data, S_IRUGO | S_IWUSR,
- ext_prop_data_show, ext_prop_data_store);
+CONFIGFS_ATTR(ext_prop_, type);
+CONFIGFS_ATTR(ext_prop_, data);
static struct configfs_attribute *ext_prop_attrs[] = {
- &ext_prop_type.attr,
- &ext_prop_data.attr,
+ &ext_prop_attr_type,
+ &ext_prop_attr_data,
NULL,
};
@@ -1068,8 +1011,6 @@ static void usb_os_desc_ext_prop_release(struct config_item *item)
static struct configfs_item_operations ext_prop_ops = {
.release = usb_os_desc_ext_prop_release,
- .show_attribute = usb_os_desc_ext_prop_attr_show,
- .store_attribute = usb_os_desc_ext_prop_attr_store,
};
static struct config_item *ext_prop_make(
@@ -1138,21 +1079,17 @@ static struct configfs_group_operations interf_grp_ops = {
.drop_item = &ext_prop_drop,
};
-static struct configfs_item_operations interf_item_ops = {
- .show_attribute = usb_os_desc_attr_show,
- .store_attribute = usb_os_desc_attr_store,
-};
-
-static ssize_t interf_grp_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_show(struct config_item *item,
char *page)
{
- memcpy(page, desc->ext_compat_id, 8);
+ memcpy(page, to_usb_os_desc(item)->ext_compat_id, 8);
return 8;
}
-static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_compatible_id_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc *desc = to_usb_os_desc(item);
int l;
l = min_t(int, 8, len);
@@ -1168,21 +1105,17 @@ static ssize_t interf_grp_compatible_id_store(struct usb_os_desc *desc,
return len;
}
-static struct usb_os_desc_attribute interf_grp_attr_compatible_id =
- __CONFIGFS_ATTR(compatible_id, S_IRUGO | S_IWUSR,
- interf_grp_compatible_id_show,
- interf_grp_compatible_id_store);
-
-static ssize_t interf_grp_sub_compatible_id_show(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_show(struct config_item *item,
char *page)
{
- memcpy(page, desc->ext_compat_id + 8, 8);
+ memcpy(page, to_usb_os_desc(item)->ext_compat_id + 8, 8);
return 8;
}
-static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
+static ssize_t interf_grp_sub_compatible_id_store(struct config_item *item,
const char *page, size_t len)
{
+ struct usb_os_desc *desc = to_usb_os_desc(item);
int l;
l = min_t(int, 8, len);
@@ -1198,14 +1131,12 @@ static ssize_t interf_grp_sub_compatible_id_store(struct usb_os_desc *desc,
return len;
}
-static struct usb_os_desc_attribute interf_grp_attr_sub_compatible_id =
- __CONFIGFS_ATTR(sub_compatible_id, S_IRUGO | S_IWUSR,
- interf_grp_sub_compatible_id_show,
- interf_grp_sub_compatible_id_store);
+CONFIGFS_ATTR(interf_grp_, compatible_id);
+CONFIGFS_ATTR(interf_grp_, sub_compatible_id);
static struct configfs_attribute *interf_grp_attrs[] = {
- &interf_grp_attr_compatible_id.attr,
- &interf_grp_attr_sub_compatible_id.attr,
+ &interf_grp_attr_compatible_id,
+ &interf_grp_attr_sub_compatible_id,
NULL
};
@@ -1243,7 +1174,6 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent,
f_default_groups[0] = os_desc_group;
os_desc_group->default_groups = interface_groups;
- interface_type->ct_item_ops = &interf_item_ops;
interface_type->ct_group_ops = &interf_grp_ops;
interface_type->ct_attrs = interf_grp_attrs;
interface_type->ct_owner = owner;
@@ -1376,6 +1306,19 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
}
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc) {
+ ret = -ENOMEM;
+ goto err_comp_cleanup;
+ }
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) {
struct config_usb_cfg *cfg;
@@ -1383,6 +1326,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
struct usb_function *tmp;
struct gadget_config_name *cn;
+ if (gadget_is_otg(gadget))
+ c->descriptors = otg_desc;
+
cfg = container_of(c, struct config_usb_cfg, c);
if (!list_empty(&cfg->string_list)) {
i = 0;
@@ -1437,6 +1383,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
cdev = get_gadget_data(gadget);
gi = container_of(cdev, struct gadget_info, cdev);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
purge_configs_funcs(gi);
composite_dev_cleanup(cdev);
usb_ep_autoconfig_reset(cdev->gadget);
@@ -1510,12 +1458,6 @@ static struct config_group *gadgets_make(
if (!gi->composite.gadget_driver.function)
goto err;
-#ifdef CONFIG_USB_OTG
- gi->otg.bLength = sizeof(struct usb_otg_descriptor);
- gi->otg.bDescriptorType = USB_DT_OTG;
- gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
-#endif
-
config_group_init_type_name(&gi->group, name,
&gadget_root_type);
return &gi->group;
diff --git a/kernel/drivers/usb/gadget/epautoconf.c b/kernel/drivers/usb/gadget/epautoconf.c
index 0567cca14..30fdab0ae 100644
--- a/kernel/drivers/usb/gadget/epautoconf.c
+++ b/kernel/drivers/usb/gadget/epautoconf.c
@@ -20,186 +20,6 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include "gadget_chips.h"
-
-/*
- * This should work with endpoints from controller drivers sharing the
- * same endpoint naming convention. By example:
- *
- * - ep1, ep2, ... address is fixed, not direction or type
- * - ep1in, ep2out, ... address and direction are fixed, not type
- * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
- * - ep1in-bulk, ep2out-iso, ... all three are fixed
- * - ep-* ... no functionality restrictions
- *
- * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
- * Less common restrictions are implied by gadget_is_*().
- *
- * NOTE: each endpoint is unidirectional, as specified by its USB
- * descriptor; and isn't specific to a configuration or altsetting.
- */
-static int
-ep_matches (
- struct usb_gadget *gadget,
- struct usb_ep *ep,
- struct usb_endpoint_descriptor *desc,
- struct usb_ss_ep_comp_descriptor *ep_comp
-)
-{
- u8 type;
- const char *tmp;
- u16 max;
-
- int num_req_streams = 0;
-
- /* endpoint already claimed? */
- if (NULL != ep->driver_data)
- return 0;
-
- /* only support ep0 for portable CONTROL traffic */
- type = usb_endpoint_type(desc);
- if (USB_ENDPOINT_XFER_CONTROL == type)
- return 0;
-
- /* some other naming convention */
- if ('e' != ep->name[0])
- return 0;
-
- /* type-restriction: "-iso", "-bulk", or "-int".
- * direction-restriction: "in", "out".
- */
- if ('-' != ep->name[2]) {
- tmp = strrchr (ep->name, '-');
- if (tmp) {
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* bulk endpoints handle interrupt transfers,
- * except the toggle-quirky iso-synch kind
- */
- if ('s' == tmp[2]) // == "-iso"
- return 0;
- /* for now, avoid PXA "interrupt-in";
- * it's documented as never using DATA1.
- */
- if (gadget_is_pxa (gadget)
- && 'i' == tmp [1])
- return 0;
- break;
- case USB_ENDPOINT_XFER_BULK:
- if ('b' != tmp[1]) // != "-bulk"
- return 0;
- break;
- case USB_ENDPOINT_XFER_ISOC:
- if ('s' != tmp[2]) // != "-iso"
- return 0;
- }
- } else {
- tmp = ep->name + strlen (ep->name);
- }
-
- /* direction-restriction: "..in-..", "out-.." */
- tmp--;
- if (!isdigit (*tmp)) {
- if (desc->bEndpointAddress & USB_DIR_IN) {
- if ('n' != *tmp)
- return 0;
- } else {
- if ('t' != *tmp)
- return 0;
- }
- }
- }
-
- /*
- * Get the number of required streams from the EP companion
- * descriptor and see if the EP matches it
- */
- if (usb_endpoint_xfer_bulk(desc)) {
- if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
- num_req_streams = ep_comp->bmAttributes & 0x1f;
- if (num_req_streams > ep->max_streams)
- return 0;
- }
-
- }
-
- /*
- * If the protocol driver hasn't yet decided on wMaxPacketSize
- * and wants to know the maximum possible, provide the info.
- */
- if (desc->wMaxPacketSize == 0)
- desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
-
- /* endpoint maxpacket size is an input parameter, except for bulk
- * where it's an output parameter representing the full speed limit.
- * the usb spec fixes high speed bulk maxpacket at 512 bytes.
- */
- max = 0x7ff & usb_endpoint_maxp(desc);
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* INT: limit 64 bytes full speed, 1024 high/super speed */
- if (!gadget_is_dualspeed(gadget) && max > 64)
- return 0;
- /* FALLTHROUGH */
-
- case USB_ENDPOINT_XFER_ISOC:
- /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
- if (ep->maxpacket_limit < max)
- return 0;
- if (!gadget_is_dualspeed(gadget) && max > 1023)
- return 0;
-
- /* BOTH: "high bandwidth" works only at high speed */
- if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
- if (!gadget_is_dualspeed(gadget))
- return 0;
- /* configure your hardware with enough buffering!! */
- }
- break;
- }
-
- /* MATCH!! */
-
- /* report address */
- desc->bEndpointAddress &= USB_DIR_IN;
- if (isdigit (ep->name [2])) {
- u8 num = simple_strtoul (&ep->name [2], NULL, 10);
- desc->bEndpointAddress |= num;
- } else if (desc->bEndpointAddress & USB_DIR_IN) {
- if (++gadget->in_epnum > 15)
- return 0;
- desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
- } else {
- if (++gadget->out_epnum > 15)
- return 0;
- desc->bEndpointAddress |= gadget->out_epnum;
- }
-
- /* report (variable) full speed bulk maxpacket */
- if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
- int size = ep->maxpacket_limit;
-
- /* min() doesn't work on bitfields with gcc-3.5 */
- if (size > 64)
- size = 64;
- desc->wMaxPacketSize = cpu_to_le16(size);
- }
- ep->address = desc->bEndpointAddress;
- return 1;
-}
-
-static struct usb_ep *
-find_ep (struct usb_gadget *gadget, const char *name)
-{
- struct usb_ep *ep;
-
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (0 == strcmp (ep->name, name))
- return ep;
- }
- return NULL;
-}
-
/**
* usb_ep_autoconfig_ss() - choose an endpoint matching the ep
* descriptor and ep companion descriptor
@@ -233,14 +53,14 @@ find_ep (struct usb_gadget *gadget, const char *name)
* the restrictions that may apply. Some combinations of driver
* and hardware won't be able to autoconfigure.
*
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * On success, this returns an claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed and
* the bmAttribute field in the ep companion descriptor is
* updated with the assigned number of streams if it is
* different from the original value. To prevent the endpoint
- * from being returned by a later autoconfig call, claim it by
- * assigning ep->driver_data to some non-null value.
+ * from being returned by a later autoconfig call, claims it by
+ * assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@@ -255,64 +75,58 @@ struct usb_ep *usb_ep_autoconfig_ss(
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
- /* First, apply chip-specific "best usage" knowledge.
- * This might make a good usb_gadget_ops hook ...
- */
- if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
- /* ep-e, ep-f are PIO with only 64 byte fifos */
- ep = find_ep (gadget, "ep-e");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
+ if (gadget->ops->match_ep) {
+ ep = gadget->ops->match_ep(gadget, desc, ep_comp);
+ if (ep)
goto found_ep;
- ep = find_ep (gadget, "ep-f");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
-
- } else if (gadget_is_goku (gadget)) {
- if (USB_ENDPOINT_XFER_INT == type) {
- /* single buffering is enough */
- ep = find_ep(gadget, "ep3-bulk");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- } else if (USB_ENDPOINT_XFER_BULK == type
- && (USB_DIR_IN & desc->bEndpointAddress)) {
- /* DMA may be available */
- ep = find_ep(gadget, "ep2-bulk");
- if (ep && ep_matches(gadget, ep, desc,
- ep_comp))
- goto found_ep;
- }
-
-#ifdef CONFIG_BLACKFIN
- } else if (gadget_is_musbhdrc(gadget)) {
- if ((USB_ENDPOINT_XFER_BULK == type) ||
- (USB_ENDPOINT_XFER_ISOC == type)) {
- if (USB_DIR_IN & desc->bEndpointAddress)
- ep = find_ep (gadget, "ep5in");
- else
- ep = find_ep (gadget, "ep6out");
- } else if (USB_ENDPOINT_XFER_INT == type) {
- if (USB_DIR_IN & desc->bEndpointAddress)
- ep = find_ep(gadget, "ep1in");
- else
- ep = find_ep(gadget, "ep2out");
- } else
- ep = NULL;
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
-#endif
}
/* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (ep_matches(gadget, ep, desc, ep_comp))
+ if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
goto found_ep;
}
/* Fail */
return NULL;
found_ep:
+
+ /*
+ * If the protocol driver hasn't yet decided on wMaxPacketSize
+ * and wants to know the maximum possible, provide the info.
+ */
+ if (desc->wMaxPacketSize == 0)
+ desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
+
+ /* report address */
+ desc->bEndpointAddress &= USB_DIR_IN;
+ if (isdigit(ep->name[2])) {
+ u8 num = simple_strtoul(&ep->name[2], NULL, 10);
+ desc->bEndpointAddress |= num;
+ } else if (desc->bEndpointAddress & USB_DIR_IN) {
+ if (++gadget->in_epnum > 15)
+ return NULL;
+ desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
+ } else {
+ if (++gadget->out_epnum > 15)
+ return NULL;
+ desc->bEndpointAddress |= gadget->out_epnum;
+ }
+
+ /* report (variable) full speed bulk maxpacket */
+ if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) {
+ int size = ep->maxpacket_limit;
+
+ /* min() doesn't work on bitfields with gcc-3.5 */
+ if (size > 64)
+ size = 64;
+ desc->wMaxPacketSize = cpu_to_le16(size);
+ }
+
+ ep->address = desc->bEndpointAddress;
ep->desc = NULL;
ep->comp_desc = NULL;
+ ep->claimed = true;
return ep;
}
EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
@@ -340,11 +154,11 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
* USB controller, and it can't know all the restrictions that may apply.
* Some combinations of driver and hardware won't be able to autoconfigure.
*
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * On success, this returns an claimed usb_ep, and modifies the endpoint
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent
- * the endpoint from being returned by a later autoconfig call, claim it
- * by assigning ep->driver_data to some non-null value.
+ * the endpoint from being returned by a later autoconfig call, claims it
+ * by assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@@ -358,12 +172,29 @@ struct usb_ep *usb_ep_autoconfig(
EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
/**
+ * usb_ep_autoconfig_release - releases endpoint and set it to initial state
+ * @ep: endpoint which should be released
+ *
+ * This function can be used during function bind for endpoints obtained
+ * from usb_ep_autoconfig(). It unclaims endpoint claimed by
+ * usb_ep_autoconfig() to make it available for other functions. Endpoint
+ * which was released is no longer invalid and shouldn't be used in
+ * context of function which released it.
+ */
+void usb_ep_autoconfig_release(struct usb_ep *ep)
+{
+ ep->claimed = false;
+ ep->driver_data = NULL;
+}
+EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release);
+
+/**
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
* @gadget: device for which autoconfig state will be reset
*
* Use this for devices where one configuration may need to assign
* endpoint resources very differently from the next one. It clears
- * state such as ep->driver_data and the record of assigned endpoints
+ * state such as ep->claimed and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
@@ -371,6 +202,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
struct usb_ep *ep;
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
+ ep->claimed = false;
ep->driver_data = NULL;
}
gadget->in_epnum = 0;
diff --git a/kernel/drivers/usb/gadget/function/f_acm.c b/kernel/drivers/usb/gadget/function/f_acm.c
index aad8165e9..2fa1e80a3 100644
--- a/kernel/drivers/usb/gadget/function/f_acm.c
+++ b/kernel/drivers/usb/gadget/function/f_acm.c
@@ -21,7 +21,6 @@
#include <linux/err.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/*
@@ -429,21 +428,18 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
if (intf == acm->ctrl_id) {
- if (acm->notify->driver_data) {
- dev_vdbg(&cdev->gadget->dev,
- "reset acm control interface %d\n", intf);
- usb_ep_disable(acm->notify);
- }
+ dev_vdbg(&cdev->gadget->dev,
+ "reset acm control interface %d\n", intf);
+ usb_ep_disable(acm->notify);
if (!acm->notify->desc)
if (config_ep_by_speed(cdev->gadget, f, acm->notify))
return -EINVAL;
usb_ep_enable(acm->notify);
- acm->notify->driver_data = acm;
} else if (intf == acm->data_id) {
- if (acm->port.in->driver_data) {
+ if (acm->notify->enabled) {
dev_dbg(&cdev->gadget->dev,
"reset acm ttyGS%d\n", acm->port_num);
gserial_disconnect(&acm->port);
@@ -476,7 +472,6 @@ static void acm_disable(struct usb_function *f)
dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n", acm->port_num);
gserial_disconnect(&acm->port);
usb_ep_disable(acm->notify);
- acm->notify->driver_data = NULL;
}
/*-------------------------------------------------------------------------*/
@@ -656,19 +651,16 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
acm->port.in = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
if (!ep)
goto fail;
acm->port.out = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
if (!ep)
goto fail;
acm->notify = ep;
- ep->driver_data = cdev; /* claim */
/* allocate notification */
acm->notify_req = gs_alloc_req(ep,
@@ -710,14 +702,6 @@ fail:
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
- /* we might as well release our claims on endpoints */
- if (acm->notify)
- acm->notify->driver_data = NULL;
- if (acm->port.out)
- acm->port.out->driver_data = NULL;
- if (acm->port.in)
- acm->port.in->driver_data = NULL;
-
ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
return status;
@@ -777,21 +761,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_acm_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_serial_opts *opts = to_f_serial_opts(item);
- struct f_serial_opts_attribute *f_serial_opts_attr =
- container_of(attr, struct f_serial_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_serial_opts_attr->show)
- ret = f_serial_opts_attr->show(opts, page);
- return ret;
-}
-
static void acm_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -801,20 +770,17 @@ static void acm_attr_release(struct config_item *item)
static struct configfs_item_operations acm_item_ops = {
.release = acm_attr_release,
- .show_attribute = f_acm_attr_show,
};
-static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_acm_port_num_show(struct config_item *item, char *page)
{
- return sprintf(page, "%u\n", opts->port_num);
+ return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
}
-static struct f_serial_opts_attribute f_acm_port_num =
- __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
-
+CONFIGFS_ATTR_RO(f_acm_port_, num);
static struct configfs_attribute *acm_attrs[] = {
- &f_acm_port_num.attr,
+ &f_acm_port_attr_num,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_ecm.c b/kernel/drivers/usb/gadget/function/f_ecm.c
index 798760fa7..7ad60ee41 100644
--- a/kernel/drivers/usb/gadget/function/f_ecm.c
+++ b/kernel/drivers/usb/gadget/function/f_ecm.c
@@ -541,24 +541,21 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt != 0)
goto fail;
- if (ecm->notify->driver_data) {
- VDBG(cdev, "reset ecm control %d\n", intf);
- usb_ep_disable(ecm->notify);
- }
+ VDBG(cdev, "reset ecm control %d\n", intf);
+ usb_ep_disable(ecm->notify);
if (!(ecm->notify->desc)) {
VDBG(cdev, "init ecm ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
goto fail;
}
usb_ep_enable(ecm->notify);
- ecm->notify->driver_data = ecm;
/* Data interface has two altsettings, 0 and 1 */
} else if (intf == ecm->data_id) {
if (alt > 1)
goto fail;
- if (ecm->port.in_ep->driver_data) {
+ if (ecm->port.in_ep->enabled) {
DBG(cdev, "reset ecm\n");
gether_disconnect(&ecm->port);
}
@@ -585,8 +582,8 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* Enable zlps by default for ECM conformance;
* override for musb_hdrc (avoids txdma ovhead).
*/
- ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget)
- );
+ ecm->port.is_zlp_ok =
+ gadget_is_zlp_supported(cdev->gadget);
ecm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ecm\n");
net = gether_connect(&ecm->port);
@@ -618,7 +615,7 @@ static int ecm_get_alt(struct usb_function *f, unsigned intf)
if (intf == ecm->ctrl_id)
return 0;
- return ecm->port.in_ep->driver_data ? 1 : 0;
+ return ecm->port.in_ep->enabled ? 1 : 0;
}
static void ecm_disable(struct usb_function *f)
@@ -628,14 +625,11 @@ static void ecm_disable(struct usb_function *f)
DBG(cdev, "ecm deactivated\n");
- if (ecm->port.in_ep->driver_data)
+ if (ecm->port.in_ep->enabled)
gether_disconnect(&ecm->port);
- if (ecm->notify->driver_data) {
- usb_ep_disable(ecm->notify);
- ecm->notify->driver_data = NULL;
- ecm->notify->desc = NULL;
- }
+ usb_ep_disable(ecm->notify);
+ ecm->notify->desc = NULL;
}
/*-------------------------------------------------------------------------*/
@@ -750,13 +744,11 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
ecm->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
if (!ep)
goto fail;
ecm->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
/* NOTE: a status/notification endpoint is *OPTIONAL* but we
* don't treat it that way. It's simpler, and some newer CDC
@@ -766,7 +758,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
ecm->notify = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -820,14 +811,6 @@ fail:
usb_ep_free_request(ecm->notify, ecm->notify_req);
}
- /* we might as well release our claims on endpoints */
- if (ecm->notify)
- ecm->notify->driver_data = NULL;
- if (ecm->port.out_ep)
- ecm->port.out_ep->driver_data = NULL;
- if (ecm->port.in_ep)
- ecm->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -855,10 +838,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm);
static struct configfs_attribute *ecm_attrs[] = {
- &f_ecm_opts_dev_addr.attr,
- &f_ecm_opts_host_addr.attr,
- &f_ecm_opts_qmult.attr,
- &f_ecm_opts_ifname.attr,
+ &ecm_opts_attr_dev_addr,
+ &ecm_opts_attr_host_addr,
+ &ecm_opts_attr_qmult,
+ &ecm_opts_attr_ifname,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_eem.c b/kernel/drivers/usb/gadget/function/f_eem.c
index c9e90de5b..cad35a502 100644
--- a/kernel/drivers/usb/gadget/function/f_eem.c
+++ b/kernel/drivers/usb/gadget/function/f_eem.c
@@ -195,11 +195,8 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
goto fail;
if (intf == eem->ctrl_id) {
-
- if (eem->port.in_ep->driver_data) {
- DBG(cdev, "reset eem\n");
- gether_disconnect(&eem->port);
- }
+ DBG(cdev, "reset eem\n");
+ gether_disconnect(&eem->port);
if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) {
DBG(cdev, "init eem\n");
@@ -237,7 +234,7 @@ static void eem_disable(struct usb_function *f)
DBG(cdev, "eem deactivated\n");
- if (eem->port.in_ep->driver_data)
+ if (eem->port.in_ep->enabled)
gether_disconnect(&eem->port);
}
@@ -293,13 +290,11 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
eem->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &eem_fs_out_desc);
if (!ep)
goto fail;
eem->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -325,11 +320,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (eem->port.out_ep)
- eem->port.out_ep->driver_data = NULL;
- if (eem->port.in_ep)
- eem->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -555,10 +545,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(eem);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(eem);
static struct configfs_attribute *eem_attrs[] = {
- &f_eem_opts_dev_addr.attr,
- &f_eem_opts_host_addr.attr,
- &f_eem_opts_qmult.attr,
- &f_eem_opts_ifname.attr,
+ &eem_opts_attr_dev_addr,
+ &eem_opts_attr_host_addr,
+ &eem_opts_attr_qmult,
+ &eem_opts_attr_ifname,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_fs.c b/kernel/drivers/usb/gadget/function/f_fs.c
index f51bb8939..4d475284a 100644
--- a/kernel/drivers/usb/gadget/function/f_fs.c
+++ b/kernel/drivers/usb/gadget/function/f_fs.c
@@ -423,7 +423,7 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
spin_unlock_irq(&ffs->ev.waitq.lock);
mutex_unlock(&ffs->mutex);
- return unlikely(__copy_to_user(buf, events, size)) ? -EFAULT : size;
+ return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size;
}
static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
@@ -513,7 +513,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
/* unlocks spinlock */
ret = __ffs_ep0_queue_wait(ffs, data, len);
- if (likely(ret > 0) && unlikely(__copy_to_user(buf, data, len)))
+ if (likely(ret > 0) && unlikely(copy_to_user(buf, data, len)))
ret = -EFAULT;
goto done_mutex;
@@ -1405,7 +1405,7 @@ static void ffs_data_put(struct ffs_data *ffs)
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
- swaitqueue_active(&ffs->ep0req_completion.wait));
+ swait_active(&ffs->ep0req_completion.wait));
kfree(ffs->dev_name);
kfree(ffs);
}
@@ -2897,11 +2897,17 @@ static int ffs_func_bind(struct usb_configuration *c,
struct usb_function *f)
{
struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
+ struct ffs_function *func = ffs_func_from_usb(f);
+ int ret;
if (IS_ERR(ffs_opts))
return PTR_ERR(ffs_opts);
- return _ffs_func_bind(c, f);
+ ret = _ffs_func_bind(c, f);
+ if (ret && !--ffs_opts->refcnt)
+ functionfs_unbind(func->ffs);
+
+ return ret;
}
@@ -3487,7 +3493,7 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len)
if (unlikely(!data))
return ERR_PTR(-ENOMEM);
- if (unlikely(__copy_from_user(data, buf, len))) {
+ if (unlikely(copy_from_user(data, buf, len))) {
kfree(data);
return ERR_PTR(-EFAULT);
}
diff --git a/kernel/drivers/usb/gadget/function/f_hid.c b/kernel/drivers/usb/gadget/function/f_hid.c
index f7f35a36c..99285b416 100644
--- a/kernel/drivers/usb/gadget/function/f_hid.c
+++ b/kernel/drivers/usb/gadget/function/f_hid.c
@@ -492,10 +492,7 @@ static void hidg_disable(struct usb_function *f)
struct f_hidg_req_list *list, *next;
usb_ep_disable(hidg->in_ep);
- hidg->in_ep->driver_data = NULL;
-
usb_ep_disable(hidg->out_ep);
- hidg->out_ep->driver_data = NULL;
list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
list_del(&list->list);
@@ -513,8 +510,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (hidg->in_ep != NULL) {
/* restart endpoint */
- if (hidg->in_ep->driver_data != NULL)
- usb_ep_disable(hidg->in_ep);
+ usb_ep_disable(hidg->in_ep);
status = config_ep_by_speed(f->config->cdev->gadget, f,
hidg->in_ep);
@@ -533,8 +529,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (hidg->out_ep != NULL) {
/* restart endpoint */
- if (hidg->out_ep->driver_data != NULL)
- usb_ep_disable(hidg->out_ep);
+ usb_ep_disable(hidg->out_ep);
status = config_ep_by_speed(f->config->cdev->gadget, f,
hidg->out_ep);
@@ -566,7 +561,6 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
hidg->out_ep->name, status);
} else {
usb_ep_disable(hidg->out_ep);
- hidg->out_ep->driver_data = NULL;
status = -ENOMEM;
goto fail;
}
@@ -614,13 +608,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
if (!ep)
goto fail;
- ep->driver_data = c->cdev; /* claim */
hidg->in_ep = ep;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
if (!ep)
goto fail;
- ep->driver_data = c->cdev; /* claim */
hidg->out_ep = ep;
/* preallocate request and buffer */
@@ -699,6 +691,10 @@ static inline int hidg_get_minor(void)
int ret;
ret = ida_simple_get(&hidg_ida, 0, 0, GFP_KERNEL);
+ if (ret >= HIDG_MINORS) {
+ ida_simple_remove(&hidg_ida, ret);
+ ret = -ENODEV;
+ }
return ret;
}
@@ -709,9 +705,6 @@ static inline struct f_hid_opts *to_f_hid_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_hid_opts);
-CONFIGFS_ATTR_OPS(f_hid_opts);
-
static void hid_attr_release(struct config_item *item)
{
struct f_hid_opts *opts = to_f_hid_opts(item);
@@ -721,13 +714,12 @@ static void hid_attr_release(struct config_item *item)
static struct configfs_item_operations hidg_item_ops = {
.release = hid_attr_release,
- .show_attribute = f_hid_opts_attr_show,
- .store_attribute = f_hid_opts_attr_store,
};
#define F_HID_OPT(name, prec, limit) \
-static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\
+static ssize_t f_hid_opts_##name##_show(struct config_item *item, char *page)\
{ \
+ struct f_hid_opts *opts = to_f_hid_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -737,9 +729,10 @@ static ssize_t f_hid_opts_##name##_show(struct f_hid_opts *opts, char *page)\
return result; \
} \
\
-static ssize_t f_hid_opts_##name##_store(struct f_hid_opts *opts, \
+static ssize_t f_hid_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_hid_opts *opts = to_f_hid_opts(item); \
int ret; \
u##prec num; \
\
@@ -765,16 +758,15 @@ end: \
return ret; \
} \
\
-static struct f_hid_opts_attribute f_hid_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_hid_opts_##name##_show,\
- f_hid_opts_##name##_store)
+CONFIGFS_ATTR(f_hid_opts_, name)
F_HID_OPT(subclass, 8, 255);
F_HID_OPT(protocol, 8, 255);
F_HID_OPT(report_length, 16, 65535);
-static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page)
+static ssize_t f_hid_opts_report_desc_show(struct config_item *item, char *page)
{
+ struct f_hid_opts *opts = to_f_hid_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -785,9 +777,10 @@ static ssize_t f_hid_opts_report_desc_show(struct f_hid_opts *opts, char *page)
return result;
}
-static ssize_t f_hid_opts_report_desc_store(struct f_hid_opts *opts,
+static ssize_t f_hid_opts_report_desc_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_hid_opts *opts = to_f_hid_opts(item);
int ret = -EBUSY;
char *d;
@@ -814,16 +807,13 @@ end:
return ret;
}
-static struct f_hid_opts_attribute f_hid_opts_report_desc =
- __CONFIGFS_ATTR(report_desc, S_IRUGO | S_IWUSR,
- f_hid_opts_report_desc_show,
- f_hid_opts_report_desc_store);
+CONFIGFS_ATTR(f_hid_opts_, report_desc);
static struct configfs_attribute *hid_attrs[] = {
- &f_hid_opts_subclass.attr,
- &f_hid_opts_protocol.attr,
- &f_hid_opts_report_length.attr,
- &f_hid_opts_report_desc.attr,
+ &f_hid_opts_attr_subclass,
+ &f_hid_opts_attr_protocol,
+ &f_hid_opts_attr_report_length,
+ &f_hid_opts_attr_report_desc,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_loopback.c b/kernel/drivers/usb/gadget/function/f_loopback.c
index 39f49f1ad..ddc3aad88 100644
--- a/kernel/drivers/usb/gadget/function/f_loopback.c
+++ b/kernel/drivers/usb/gadget/function/f_loopback.c
@@ -28,17 +28,15 @@
* This takes messages of various sizes written OUT to a device, and loops
* them back so they can be read IN from it. It has been used by certain
* test applications. It supports limited testing of data queueing logic.
- *
- *
- * 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_loopback {
struct usb_function function;
struct usb_ep *in_ep;
struct usb_ep *out_ep;
+
+ unsigned qlen;
+ unsigned buflen;
};
static inline struct f_loopback *func_to_loop(struct usb_function *f)
@@ -46,13 +44,10 @@ static inline struct f_loopback *func_to_loop(struct usb_function *f)
return container_of(f, struct f_loopback, function);
}
-static unsigned qlen;
-static unsigned buflen;
-
/*-------------------------------------------------------------------------*/
static struct usb_interface_descriptor loopback_intf = {
- .bLength = sizeof loopback_intf,
+ .bLength = sizeof(loopback_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bNumEndpoints = 2,
@@ -200,12 +195,10 @@ autoconf_fail:
f->name, cdev->gadget->name);
return -ENODEV;
}
- loop->in_ep->driver_data = cdev; /* claim */
loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
if (!loop->out_ep)
goto autoconf_fail;
- loop->out_ep->driver_data = cdev; /* claim */
/* support high speed hardware */
hs_loop_source_desc.bEndpointAddress =
@@ -250,22 +243,38 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
int status = req->status;
switch (status) {
-
case 0: /* normal completion? */
if (ep == loop->out_ep) {
- req->zero = (req->actual < req->length);
- req->length = req->actual;
+ /*
+ * We received some data from the host so let's
+ * queue it so host can read the from our in ep
+ */
+ struct usb_request *in_req = req->context;
+
+ in_req->zero = (req->actual < req->length);
+ in_req->length = req->actual;
+ ep = loop->in_ep;
+ req = in_req;
+ } else {
+ /*
+ * We have just looped back a bunch of data
+ * to host. Now let's wait for some more data.
+ */
+ req = req->context;
+ ep = loop->out_ep;
}
- /* queue the buffer for some later OUT packet */
- req->length = buflen;
+ /* queue the buffer back to host or for next bunch of data */
status = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (status == 0)
+ if (status == 0) {
return;
+ } else {
+ ERROR(cdev, "Unable to loop back buffer to %s: %d\n",
+ ep->name, status);
+ goto free_req;
+ }
/* "should never get here" */
- /* FALLTHROUGH */
-
default:
ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
status, req->actual, req->length);
@@ -279,6 +288,10 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
+free_req:
+ usb_ep_free_request(ep == loop->in_ep ?
+ loop->out_ep : loop->in_ep,
+ req->context);
free_ep_req(ep, req);
return;
}
@@ -295,53 +308,77 @@ static void disable_loopback(struct f_loopback *loop)
static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
{
- return alloc_ep_req(ep, len, buflen);
+ struct f_loopback *loop = ep->driver_data;
+
+ return alloc_ep_req(ep, len, loop->buflen);
}
-static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop,
- struct usb_ep *ep)
+static int alloc_requests(struct usb_composite_dev *cdev,
+ struct f_loopback *loop)
{
- struct usb_request *req;
- unsigned i;
- int result;
-
- /*
- * one endpoint writes data back IN to the host while another endpoint
- * just reads OUT packets
- */
- result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
- if (result)
- goto fail0;
- result = usb_ep_enable(ep);
- if (result < 0)
- goto fail0;
- ep->driver_data = loop;
+ struct usb_request *in_req, *out_req;
+ int i;
+ int result = 0;
/*
* allocate a bunch of read buffers and queue them all at once.
- * we buffer at most 'qlen' transfers; fewer if any need more
- * than 'buflen' bytes each.
+ * we buffer at most 'qlen' transfers; We allocate buffers only
+ * for out transfer and reuse them in IN transfers to implement
+ * our loopback functionality
*/
- for (i = 0; i < qlen && result == 0; i++) {
- req = lb_alloc_ep_req(ep, 0);
- if (!req)
- goto fail1;
+ for (i = 0; i < loop->qlen && result == 0; i++) {
+ result = -ENOMEM;
+
+ in_req = usb_ep_alloc_request(loop->in_ep, GFP_ATOMIC);
+ if (!in_req)
+ goto fail;
+
+ out_req = lb_alloc_ep_req(loop->out_ep, 0);
+ if (!out_req)
+ goto fail_in;
- req->complete = loopback_complete;
- result = usb_ep_queue(ep, req, GFP_ATOMIC);
+ in_req->complete = loopback_complete;
+ out_req->complete = loopback_complete;
+
+ in_req->buf = out_req->buf;
+ /* length will be set in complete routine */
+ in_req->context = out_req;
+ out_req->context = in_req;
+
+ result = usb_ep_queue(loop->out_ep, out_req, GFP_ATOMIC);
if (result) {
ERROR(cdev, "%s queue req --> %d\n",
- ep->name, result);
- goto fail1;
+ loop->out_ep->name, result);
+ goto fail_out;
}
}
return 0;
-fail1:
- usb_ep_disable(ep);
+fail_out:
+ free_ep_req(loop->out_ep, out_req);
+fail_in:
+ usb_ep_free_request(loop->in_ep, in_req);
+fail:
+ return result;
+}
+
+static int enable_endpoint(struct usb_composite_dev *cdev,
+ struct f_loopback *loop, struct usb_ep *ep)
+{
+ int result;
+
+ result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
+ if (result)
+ goto out;
+
+ result = usb_ep_enable(ep);
+ if (result < 0)
+ goto out;
+ ep->driver_data = loop;
+ result = 0;
-fail0:
+out:
return result;
}
@@ -352,13 +389,24 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
result = enable_endpoint(cdev, loop, loop->in_ep);
if (result)
- return result;
+ goto out;
result = enable_endpoint(cdev, loop, loop->out_ep);
if (result)
- return result;
+ goto disable_in;
+
+ result = alloc_requests(cdev, loop);
+ if (result)
+ goto disable_out;
DBG(cdev, "%s enabled\n", loop->function.name);
+ return 0;
+
+disable_out:
+ usb_ep_disable(loop->out_ep);
+disable_in:
+ usb_ep_disable(loop->in_ep);
+out:
return result;
}
@@ -369,8 +417,7 @@ static int loopback_set_alt(struct usb_function *f,
struct usb_composite_dev *cdev = f->config->cdev;
/* we know alt is zero */
- if (loop->in_ep->driver_data)
- disable_loopback(loop);
+ disable_loopback(loop);
return enable_loopback(cdev, loop);
}
@@ -396,10 +443,10 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
lb_opts->refcnt++;
mutex_unlock(&lb_opts->lock);
- buflen = lb_opts->bulk_buflen;
- qlen = lb_opts->qlen;
- if (!qlen)
- qlen = 32;
+ loop->buflen = lb_opts->bulk_buflen;
+ loop->qlen = lb_opts->qlen;
+ if (!loop->qlen)
+ loop->qlen = 32;
loop->function.name = "loopback";
loop->function.bind = loopback_bind;
@@ -418,9 +465,6 @@ static inline struct f_lb_opts *to_f_lb_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_lb_opts);
-CONFIGFS_ATTR_OPS(f_lb_opts);
-
static void lb_attr_release(struct config_item *item)
{
struct f_lb_opts *lb_opts = to_f_lb_opts(item);
@@ -430,24 +474,24 @@ static void lb_attr_release(struct config_item *item)
static struct configfs_item_operations lb_item_ops = {
.release = lb_attr_release,
- .show_attribute = f_lb_opts_attr_show,
- .store_attribute = f_lb_opts_attr_store,
};
-static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
+static ssize_t f_lb_opts_qlen_show(struct config_item *item, char *page)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%d", opts->qlen);
+ result = sprintf(page, "%d\n", opts->qlen);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_lb_opts_qlen_store(struct f_lb_opts *opts,
+static ssize_t f_lb_opts_qlen_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int ret;
u32 num;
@@ -468,25 +512,24 @@ end:
return ret;
}
-static struct f_lb_opts_attribute f_lb_opts_qlen =
- __CONFIGFS_ATTR(qlen, S_IRUGO | S_IWUSR,
- f_lb_opts_qlen_show,
- f_lb_opts_qlen_store);
+CONFIGFS_ATTR(f_lb_opts_, qlen);
-static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
+static ssize_t f_lb_opts_bulk_buflen_show(struct config_item *item, char *page)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int result;
mutex_lock(&opts->lock);
- result = sprintf(page, "%d", opts->bulk_buflen);
+ result = sprintf(page, "%d\n", opts->bulk_buflen);
mutex_unlock(&opts->lock);
return result;
}
-static ssize_t f_lb_opts_bulk_buflen_store(struct f_lb_opts *opts,
+static ssize_t f_lb_opts_bulk_buflen_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_lb_opts *opts = to_f_lb_opts(item);
int ret;
u32 num;
@@ -507,14 +550,11 @@ end:
return ret;
}
-static struct f_lb_opts_attribute f_lb_opts_bulk_buflen =
- __CONFIGFS_ATTR(buflen, S_IRUGO | S_IWUSR,
- f_lb_opts_bulk_buflen_show,
- f_lb_opts_bulk_buflen_store);
+CONFIGFS_ATTR(f_lb_opts_, bulk_buflen);
static struct configfs_attribute *lb_attrs[] = {
- &f_lb_opts_qlen.attr,
- &f_lb_opts_bulk_buflen.attr,
+ &f_lb_opts_attr_qlen,
+ &f_lb_opts_attr_bulk_buflen,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_mass_storage.c b/kernel/drivers/usb/gadget/function/f_mass_storage.c
index 15c307155..223ccf89d 100644
--- a/kernel/drivers/usb/gadget/function/f_mass_storage.c
+++ b/kernel/drivers/usb/gadget/function/f_mass_storage.c
@@ -54,7 +54,7 @@
* following fields:
*
* nluns Number of LUNs function have (anywhere from 1
- * to FSG_MAX_LUNS which is 8).
+ * to FSG_MAX_LUNS).
* luns An array of LUN configuration values. This
* should be filled for each LUN that
* function will include (ie. for "nluns"
@@ -214,12 +214,12 @@
#include <linux/string.h>
#include <linux/freezer.h>
#include <linux/module.h>
+#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
-#include "gadget_chips.h"
#include "configfs.h"
@@ -279,9 +279,8 @@ struct fsg_common {
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
- unsigned int nluns;
unsigned int lun;
- struct fsg_lun **luns;
+ struct fsg_lun *luns[FSG_MAX_LUNS];
struct fsg_lun *curlun;
unsigned int bulk_out_maxpacket;
@@ -490,6 +489,16 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
spin_unlock(&common->lock);
}
+static int _fsg_common_get_max_lun(struct fsg_common *common)
+{
+ int i = ARRAY_SIZE(common->luns) - 1;
+
+ while (i >= 0 && !common->luns[i])
+ --i;
+
+ return i;
+}
+
static int fsg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@@ -533,7 +542,7 @@ static int fsg_setup(struct usb_function *f,
w_length != 1)
return -EDOM;
VDBG(fsg, "get max LUN\n");
- *(u8 *)req->buf = fsg->common->nluns - 1;
+ *(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
/* Respond with data/status */
req->length = min((u16)1, w_length);
@@ -2131,8 +2140,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
/* Is the CBW meaningful? */
- if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
- cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
+ if (cbw->Lun >= ARRAY_SIZE(common->luns) ||
+ cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 ||
+ cbw->Length > MAX_COMMAND_SIZE) {
DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
"cmdlen %u\n",
cbw->Lun, cbw->Flags, cbw->Length);
@@ -2159,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
if (common->data_size == 0)
common->data_dir = DATA_DIR_NONE;
common->lun = cbw->Lun;
- if (common->lun < common->nluns)
+ if (common->lun < ARRAY_SIZE(common->luns))
common->curlun = common->luns[common->lun];
else
common->curlun = NULL;
@@ -2248,12 +2258,10 @@ reset:
/* Disable the endpoints */
if (fsg->bulk_in_enabled) {
usb_ep_disable(fsg->bulk_in);
- fsg->bulk_in->driver_data = NULL;
fsg->bulk_in_enabled = 0;
}
if (fsg->bulk_out_enabled) {
usb_ep_disable(fsg->bulk_out);
- fsg->bulk_out->driver_data = NULL;
fsg->bulk_out_enabled = 0;
}
@@ -2307,7 +2315,7 @@ reset:
}
common->running = 1;
- for (i = 0; i < common->nluns; ++i)
+ for (i = 0; i < ARRAY_SIZE(common->luns); ++i)
if (common->luns[i])
common->luns[i]->unit_attention_data =
SS_RESET_OCCURRED;
@@ -2337,7 +2345,6 @@ static void fsg_disable(struct usb_function *f)
static void handle_exception(struct fsg_common *common)
{
- siginfo_t info;
int i;
struct fsg_buffhd *bh;
enum fsg_state old_state;
@@ -2349,8 +2356,7 @@ static void handle_exception(struct fsg_common *common)
* into a high-priority EXIT exception.
*/
for (;;) {
- int sig =
- dequeue_signal_lock(current, &current->blocked, &info);
+ int sig = kernel_dequeue_signal(NULL);
if (!sig)
break;
if (sig != SIGUSR1) {
@@ -2409,7 +2415,7 @@ static void handle_exception(struct fsg_common *common)
if (old_state == FSG_STATE_ABORT_BULK_OUT)
common->state = FSG_STATE_STATUS_PHASE;
else {
- for (i = 0; i < common->nluns; ++i) {
+ for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
curlun = common->luns[i];
if (!curlun)
continue;
@@ -2453,7 +2459,7 @@ static void handle_exception(struct fsg_common *common)
* a waste of time. Ditto for the INTERFACE_CHANGE and
* CONFIG_CHANGE cases.
*/
- /* for (i = 0; i < common->nluns; ++i) */
+ /* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */
/* if (common->luns[i]) */
/* common->luns[i]->unit_attention_data = */
/* SS_RESET_OCCURRED; */
@@ -2552,12 +2558,11 @@ static int fsg_main_thread(void *common_)
if (!common->ops || !common->ops->thread_exits
|| common->ops->thread_exits(common) < 0) {
- struct fsg_lun **curlun_it = common->luns;
- unsigned i = common->nluns;
+ int i;
down_write(&common->filesem);
- for (; i--; ++curlun_it) {
- struct fsg_lun *curlun = *curlun_it;
+ for (i = 0; i < ARRAY_SIZE(common->luns); --i) {
+ struct fsg_lun *curlun = common->luns[i];
if (!curlun || !fsg_lun_is_open(curlun))
continue;
@@ -2653,10 +2658,12 @@ EXPORT_SYMBOL_GPL(fsg_common_put);
/* check if fsg_num_buffers is within a valid range */
static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
{
- if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
+#define FSG_MAX_NUM_BUFFERS 32
+
+ if (fsg_num_buffers >= 2 && fsg_num_buffers <= FSG_MAX_NUM_BUFFERS)
return 0;
pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
- fsg_num_buffers, 2, 4);
+ fsg_num_buffers, 2, FSG_MAX_NUM_BUFFERS);
return -EINVAL;
}
@@ -2676,6 +2683,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
init_completion(&common->thread_notifier);
init_waitqueue_head(&common->fsg_wait);
common->state = FSG_STATE_TERMINATED;
+ memset(common->luns, 0, sizeof(common->luns));
return common;
}
@@ -2742,9 +2750,9 @@ error_release:
}
EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers);
-void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
+void fsg_common_remove_lun(struct fsg_lun *lun)
{
- if (sysfs)
+ if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
fsg_lun_close(lun);
kfree(lun);
@@ -2757,48 +2765,16 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n)
for (i = 0; i < n; ++i)
if (common->luns[i]) {
- fsg_common_remove_lun(common->luns[i], common->sysfs);
+ fsg_common_remove_lun(common->luns[i]);
common->luns[i] = NULL;
}
}
-EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_remove_luns(struct fsg_common *common)
{
- _fsg_common_remove_luns(common, common->nluns);
-}
-
-void fsg_common_free_luns(struct fsg_common *common)
-{
- fsg_common_remove_luns(common);
- kfree(common->luns);
- common->luns = NULL;
-}
-EXPORT_SYMBOL_GPL(fsg_common_free_luns);
-
-int fsg_common_set_nluns(struct fsg_common *common, int nluns)
-{
- struct fsg_lun **curlun;
-
- /* Find out how many LUNs there should be */
- if (nluns < 1 || nluns > FSG_MAX_LUNS) {
- pr_err("invalid number of LUNs: %u\n", nluns);
- return -EINVAL;
- }
-
- curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL);
- if (unlikely(!curlun))
- return -ENOMEM;
-
- if (common->luns)
- fsg_common_free_luns(common);
-
- common->luns = curlun;
- common->nluns = nluns;
-
- return 0;
+ _fsg_common_remove_luns(common, ARRAY_SIZE(common->luns));
}
-EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
+EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops)
@@ -2836,7 +2812,8 @@ int fsg_common_set_cdev(struct fsg_common *common,
* halt bulk endpoints correctly. If one of them is present,
* disable stalls.
*/
- common->can_stall = can_stall && !(gadget_is_at91(common->gadget));
+ common->can_stall = can_stall &&
+ gadget_is_stall_supported(common->gadget);
return 0;
}
@@ -2880,7 +2857,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
char *pathbuf, *p;
int rc = -ENOMEM;
- if (!common->nluns || !common->luns)
+ if (id >= ARRAY_SIZE(common->luns))
return -ENODEV;
if (common->luns[id])
@@ -2934,7 +2911,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
if (fsg_lun_is_open(lun)) {
p = "(error)";
if (pathbuf) {
- p = d_path(&lun->filp->f_path, pathbuf, PATH_MAX);
+ p = file_path(lun->filp, pathbuf, PATH_MAX);
if (IS_ERR(p))
p = "(error)";
}
@@ -2949,7 +2926,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
return 0;
error_lun:
- if (common->sysfs)
+ if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
fsg_lun_close(lun);
common->luns[id] = NULL;
@@ -2964,14 +2941,16 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
char buf[8]; /* enough for 100000000 different numbers, decimal */
int i, rc;
- for (i = 0; i < common->nluns; ++i) {
+ fsg_common_remove_luns(common);
+
+ for (i = 0; i < cfg->nluns; ++i) {
snprintf(buf, sizeof(buf), "lun%d", i);
rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL);
if (rc)
goto fail;
}
- pr_info("Number of LUNs=%d\n", common->nluns);
+ pr_info("Number of LUNs=%d\n", cfg->nluns);
return 0;
@@ -3020,6 +2999,7 @@ EXPORT_SYMBOL_GPL(fsg_common_run_thread);
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
+ int i;
/* If the thread isn't already dead, tell it to exit now */
if (common->state != FSG_STATE_TERMINATED) {
@@ -3027,22 +3007,14 @@ static void fsg_common_release(struct kref *ref)
wait_for_completion(&common->thread_notifier);
}
- if (likely(common->luns)) {
- struct fsg_lun **lun_it = common->luns;
- unsigned i = common->nluns;
-
- /* In error recovery common->nluns may be zero. */
- for (; i; --i, ++lun_it) {
- struct fsg_lun *lun = *lun_it;
- if (!lun)
- continue;
- fsg_lun_close(lun);
- if (common->sysfs)
- device_unregister(&lun->dev);
- kfree(lun);
- }
-
- kfree(common->luns);
+ for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
+ struct fsg_lun *lun = common->luns[i];
+ if (!lun)
+ continue;
+ fsg_lun_close(lun);
+ if (device_is_registered(&lun->dev))
+ device_unregister(&lun->dev);
+ kfree(lun);
}
_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
@@ -3056,6 +3028,7 @@ static void fsg_common_release(struct kref *ref)
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
+ struct fsg_common *common = fsg->common;
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
@@ -3063,6 +3036,13 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
int ret;
struct fsg_opts *opts;
+ /* Don't allow to bind if we don't have at least one LUN */
+ ret = _fsg_common_get_max_lun(common);
+ if (ret < 0) {
+ pr_err("There should be at least one LUN.\n");
+ return -EINVAL;
+ }
+
opts = fsg_opts_from_func_inst(f->fi);
if (!opts->no_configfs) {
ret = fsg_common_set_cdev(fsg->common, c->cdev,
@@ -3080,7 +3060,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
/* New interface */
i = usb_interface_id(c, f);
if (i < 0)
- return i;
+ goto fail;
fsg_intf_desc.bInterfaceNumber = i;
fsg->interface_number = i;
@@ -3088,13 +3068,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
if (!ep)
goto autoconf_fail;
- ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_in = ep;
ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
if (!ep)
goto autoconf_fail;
- ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep;
/* Assume endpoint addresses are the same for both speeds */
@@ -3123,7 +3101,14 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
- return -ENOTSUPP;
+ i = -ENOTSUPP;
+fail:
+ /* terminate the thread */
+ if (fsg->common->state != FSG_STATE_TERMINATED) {
+ raise_exception(fsg->common, FSG_STATE_EXIT);
+ wait_for_completion(&fsg->common->thread_notifier);
+ }
+ return i;
}
/****************************** ALLOCATE FUNCTION *************************/
@@ -3155,9 +3140,6 @@ static inline struct fsg_opts *to_fsg_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(fsg_lun_opts);
-CONFIGFS_ATTR_OPS(fsg_lun_opts);
-
static void fsg_lun_attr_release(struct config_item *item)
{
struct fsg_lun_opts *lun_opts;
@@ -3168,110 +3150,93 @@ static void fsg_lun_attr_release(struct config_item *item)
static struct configfs_item_operations fsg_lun_item_ops = {
.release = fsg_lun_attr_release,
- .show_attribute = fsg_lun_opts_attr_show,
- .store_attribute = fsg_lun_opts_attr_store,
};
-static ssize_t fsg_lun_opts_file_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_file_show(struct config_item *item, char *page)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_show_file(opts->lun, &fsg_opts->common->filesem, page);
}
-static ssize_t fsg_lun_opts_file_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_file_store(struct config_item *item,
const char *page, size_t len)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_file(opts->lun, &fsg_opts->common->filesem, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_file =
- __CONFIGFS_ATTR(file, S_IRUGO | S_IWUSR, fsg_lun_opts_file_show,
- fsg_lun_opts_file_store);
+CONFIGFS_ATTR(fsg_lun_opts_, file);
-static ssize_t fsg_lun_opts_ro_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_ro_show(struct config_item *item, char *page)
{
- return fsg_show_ro(opts->lun, page);
+ return fsg_show_ro(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_ro_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_ro_store(struct config_item *item,
const char *page, size_t len)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_ro(opts->lun, &fsg_opts->common->filesem, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_ro =
- __CONFIGFS_ATTR(ro, S_IRUGO | S_IWUSR, fsg_lun_opts_ro_show,
- fsg_lun_opts_ro_store);
+CONFIGFS_ATTR(fsg_lun_opts_, ro);
-static ssize_t fsg_lun_opts_removable_show(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_removable_show(struct config_item *item,
char *page)
{
- return fsg_show_removable(opts->lun, page);
+ return fsg_show_removable(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_removable_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_removable_store(struct config_item *item,
const char *page, size_t len)
{
- return fsg_store_removable(opts->lun, page, len);
+ return fsg_store_removable(to_fsg_lun_opts(item)->lun, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_removable =
- __CONFIGFS_ATTR(removable, S_IRUGO | S_IWUSR,
- fsg_lun_opts_removable_show,
- fsg_lun_opts_removable_store);
+CONFIGFS_ATTR(fsg_lun_opts_, removable);
-static ssize_t fsg_lun_opts_cdrom_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_cdrom_show(struct config_item *item, char *page)
{
- return fsg_show_cdrom(opts->lun, page);
+ return fsg_show_cdrom(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_cdrom_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_cdrom_store(struct config_item *item,
const char *page, size_t len)
{
- struct fsg_opts *fsg_opts;
-
- fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
return fsg_store_cdrom(opts->lun, &fsg_opts->common->filesem, page,
len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_cdrom =
- __CONFIGFS_ATTR(cdrom, S_IRUGO | S_IWUSR, fsg_lun_opts_cdrom_show,
- fsg_lun_opts_cdrom_store);
+CONFIGFS_ATTR(fsg_lun_opts_, cdrom);
-static ssize_t fsg_lun_opts_nofua_show(struct fsg_lun_opts *opts, char *page)
+static ssize_t fsg_lun_opts_nofua_show(struct config_item *item, char *page)
{
- return fsg_show_nofua(opts->lun, page);
+ return fsg_show_nofua(to_fsg_lun_opts(item)->lun, page);
}
-static ssize_t fsg_lun_opts_nofua_store(struct fsg_lun_opts *opts,
+static ssize_t fsg_lun_opts_nofua_store(struct config_item *item,
const char *page, size_t len)
{
- return fsg_store_nofua(opts->lun, page, len);
+ return fsg_store_nofua(to_fsg_lun_opts(item)->lun, page, len);
}
-static struct fsg_lun_opts_attribute fsg_lun_opts_nofua =
- __CONFIGFS_ATTR(nofua, S_IRUGO | S_IWUSR, fsg_lun_opts_nofua_show,
- fsg_lun_opts_nofua_store);
+CONFIGFS_ATTR(fsg_lun_opts_, nofua);
static struct configfs_attribute *fsg_lun_attrs[] = {
- &fsg_lun_opts_file.attr,
- &fsg_lun_opts_ro.attr,
- &fsg_lun_opts_removable.attr,
- &fsg_lun_opts_cdrom.attr,
- &fsg_lun_opts_nofua.attr,
+ &fsg_lun_opts_attr_file,
+ &fsg_lun_opts_attr_ro,
+ &fsg_lun_opts_attr_removable,
+ &fsg_lun_opts_attr_cdrom,
+ &fsg_lun_opts_attr_nofua,
NULL,
};
@@ -3355,7 +3320,7 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item)
unregister_gadget_item(gadget);
}
- fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs);
+ fsg_common_remove_lun(lun_opts->lun);
fsg_opts->common->luns[lun_opts->lun_id] = NULL;
lun_opts->lun_id = 0;
mutex_unlock(&fsg_opts->lock);
@@ -3363,9 +3328,6 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item)
config_item_put(item);
}
-CONFIGFS_ATTR_STRUCT(fsg_opts);
-CONFIGFS_ATTR_OPS(fsg_opts);
-
static void fsg_attr_release(struct config_item *item)
{
struct fsg_opts *opts = to_fsg_opts(item);
@@ -3375,12 +3337,11 @@ static void fsg_attr_release(struct config_item *item)
static struct configfs_item_operations fsg_item_ops = {
.release = fsg_attr_release,
- .show_attribute = fsg_opts_attr_show,
- .store_attribute = fsg_opts_attr_store,
};
-static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
+static ssize_t fsg_opts_stall_show(struct config_item *item, char *page)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -3390,9 +3351,10 @@ static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
return result;
}
-static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
+static ssize_t fsg_opts_stall_store(struct config_item *item, const char *page,
size_t len)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int ret;
bool stall;
@@ -3414,13 +3376,12 @@ static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
return ret;
}
-static struct fsg_opts_attribute fsg_opts_stall =
- __CONFIGFS_ATTR(stall, S_IRUGO | S_IWUSR, fsg_opts_stall_show,
- fsg_opts_stall_store);
+CONFIGFS_ATTR(fsg_opts_, stall);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
+static ssize_t fsg_opts_num_buffers_show(struct config_item *item, char *page)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -3430,9 +3391,10 @@ static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
return result;
}
-static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts,
+static ssize_t fsg_opts_num_buffers_store(struct config_item *item,
const char *page, size_t len)
{
+ struct fsg_opts *opts = to_fsg_opts(item);
int ret;
u8 num;
@@ -3457,17 +3419,13 @@ end:
return ret;
}
-static struct fsg_opts_attribute fsg_opts_num_buffers =
- __CONFIGFS_ATTR(num_buffers, S_IRUGO | S_IWUSR,
- fsg_opts_num_buffers_show,
- fsg_opts_num_buffers_store);
-
+CONFIGFS_ATTR(fsg_opts_, num_buffers);
#endif
static struct configfs_attribute *fsg_attrs[] = {
- &fsg_opts_stall.attr,
+ &fsg_opts_attr_stall,
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- &fsg_opts_num_buffers.attr,
+ &fsg_opts_attr_num_buffers,
#endif
NULL,
};
@@ -3509,14 +3467,11 @@ static struct usb_function_instance *fsg_alloc_inst(void)
rc = PTR_ERR(opts->common);
goto release_opts;
}
- rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
- if (rc)
- goto release_opts;
rc = fsg_common_set_num_buffers(opts->common,
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
if (rc)
- goto release_luns;
+ goto release_opts;
pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
@@ -3524,6 +3479,9 @@ static struct usb_function_instance *fsg_alloc_inst(void)
config.removable = true;
rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0",
(const char **)&opts->func_inst.group.cg_item.ci_name);
+ if (rc)
+ goto release_buffers;
+
opts->lun0.lun = opts->common->luns[0];
opts->lun0.lun_id = 0;
config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
@@ -3534,8 +3492,8 @@ static struct usb_function_instance *fsg_alloc_inst(void)
return &opts->func_inst;
-release_luns:
- kfree(opts->common->luns);
+release_buffers:
+ fsg_common_free_buffers(opts->common);
release_opts:
kfree(opts);
return ERR_PTR(rc);
@@ -3561,23 +3519,12 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
struct fsg_common *common = opts->common;
struct fsg_dev *fsg;
- unsigned nluns, i;
fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
if (unlikely(!fsg))
return ERR_PTR(-ENOMEM);
mutex_lock(&opts->lock);
- if (!opts->refcnt) {
- for (nluns = i = 0; i < FSG_MAX_LUNS; ++i)
- if (common->luns[i])
- nluns = i + 1;
- if (!nluns)
- pr_warn("No LUNS defined, continuing anyway\n");
- else
- common->nluns = nluns;
- pr_info("Number of LUNs=%u\n", common->nluns);
- }
opts->refcnt++;
mutex_unlock(&opts->lock);
diff --git a/kernel/drivers/usb/gadget/function/f_mass_storage.h b/kernel/drivers/usb/gadget/function/f_mass_storage.h
index b4866fcef..445df6775 100644
--- a/kernel/drivers/usb/gadget/function/f_mass_storage.h
+++ b/kernel/drivers/usb/gadget/function/f_mass_storage.h
@@ -137,14 +137,10 @@ void fsg_common_free_buffers(struct fsg_common *common);
int fsg_common_set_cdev(struct fsg_common *common,
struct usb_composite_dev *cdev, bool can_stall);
-void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs);
+void fsg_common_remove_lun(struct fsg_lun *lun);
void fsg_common_remove_luns(struct fsg_common *common);
-void fsg_common_free_luns(struct fsg_common *common);
-
-int fsg_common_set_nluns(struct fsg_common *common, int nluns);
-
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops);
diff --git a/kernel/drivers/usb/gadget/function/f_midi.c b/kernel/drivers/usb/gadget/function/f_midi.c
index 6316aa5b1..898a57031 100644
--- a/kernel/drivers/usb/gadget/function/f_midi.c
+++ b/kernel/drivers/usb/gadget/function/f_midi.c
@@ -302,8 +302,7 @@ static int f_midi_start_ep(struct f_midi *midi,
int err;
struct usb_composite_dev *cdev = f->config->cdev;
- if (ep->driver_data)
- usb_ep_disable(ep);
+ usb_ep_disable(ep);
err = config_ep_by_speed(midi->gadget, f, ep);
if (err) {
@@ -329,6 +328,10 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
unsigned i;
int err;
+ /* For Control Device interface we do nothing */
+ if (intf == 0)
+ return 0;
+
err = f_midi_start_ep(midi, f, midi->in_ep);
if (err)
return err;
@@ -337,8 +340,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (err)
return err;
- if (midi->out_ep->driver_data)
- usb_ep_disable(midi->out_ep);
+ usb_ep_disable(midi->out_ep);
err = config_ep_by_speed(midi->gadget, f, midi->out_ep);
if (err) {
@@ -368,6 +370,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (err) {
ERROR(midi, "%s queue req: %d\n",
midi->out_ep->name, err);
+ free_ep_req(midi->out_ep, req);
}
}
@@ -543,10 +546,16 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
}
}
- if (req->length > 0)
- usb_ep_queue(ep, req, GFP_ATOMIC);
- else
+ if (req->length > 0 && ep->enabled) {
+ int err;
+
+ err = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (err < 0)
+ ERROR(midi, "%s queue req: %d\n",
+ midi->in_ep->name, err);
+ } else {
free_ep_req(ep, req);
+ }
}
static void f_midi_in_tasklet(unsigned long data)
@@ -753,12 +762,10 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc);
if (!midi->in_ep)
goto fail;
- midi->in_ep->driver_data = cdev; /* claim */
midi->out_ep = usb_ep_autoconfig(cdev->gadget, &bulk_out_desc);
if (!midi->out_ep)
goto fail;
- midi->out_ep->driver_data = cdev; /* claim */
/* allocate temporary function list */
midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
@@ -885,12 +892,6 @@ fail_f_midi:
fail:
f_midi_unregister_card(midi);
fail_register:
- /* we might as well release our claims on endpoints */
- if (midi->out_ep)
- midi->out_ep->driver_data = NULL;
- if (midi->in_ep)
- midi->in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -902,9 +903,6 @@ static inline struct f_midi_opts *to_f_midi_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_midi_opts);
-CONFIGFS_ATTR_OPS(f_midi_opts);
-
static void midi_attr_release(struct config_item *item)
{
struct f_midi_opts *opts = to_f_midi_opts(item);
@@ -914,13 +912,12 @@ static void midi_attr_release(struct config_item *item)
static struct configfs_item_operations midi_item_ops = {
.release = midi_attr_release,
- .show_attribute = f_midi_opts_attr_show,
- .store_attribute = f_midi_opts_attr_store,
};
#define F_MIDI_OPT(name, test_limit, limit) \
-static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
+static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \
{ \
+ struct f_midi_opts *opts = to_f_midi_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -930,9 +927,10 @@ static ssize_t f_midi_opts_##name##_show(struct f_midi_opts *opts, char *page) \
return result; \
} \
\
-static ssize_t f_midi_opts_##name##_store(struct f_midi_opts *opts, \
+static ssize_t f_midi_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_midi_opts *opts = to_f_midi_opts(item); \
int ret; \
u32 num; \
\
@@ -958,9 +956,7 @@ end: \
return ret; \
} \
\
-static struct f_midi_opts_attribute f_midi_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, f_midi_opts_##name##_show, \
- f_midi_opts_##name##_store)
+CONFIGFS_ATTR(f_midi_opts_, name);
F_MIDI_OPT(index, true, SNDRV_CARDS);
F_MIDI_OPT(buflen, false, 0);
@@ -968,8 +964,9 @@ F_MIDI_OPT(qlen, false, 0);
F_MIDI_OPT(in_ports, true, MAX_PORTS);
F_MIDI_OPT(out_ports, true, MAX_PORTS);
-static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
+static ssize_t f_midi_opts_id_show(struct config_item *item, char *page)
{
+ struct f_midi_opts *opts = to_f_midi_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -985,9 +982,10 @@ static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page)
return result;
}
-static ssize_t f_midi_opts_id_store(struct f_midi_opts *opts,
+static ssize_t f_midi_opts_id_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_midi_opts *opts = to_f_midi_opts(item);
int ret;
char *c;
@@ -1012,17 +1010,15 @@ end:
return ret;
}
-static struct f_midi_opts_attribute f_midi_opts_id =
- __CONFIGFS_ATTR(id, S_IRUGO | S_IWUSR, f_midi_opts_id_show,
- f_midi_opts_id_store);
+CONFIGFS_ATTR(f_midi_opts_, id);
static struct configfs_attribute *midi_attrs[] = {
- &f_midi_opts_index.attr,
- &f_midi_opts_buflen.attr,
- &f_midi_opts_qlen.attr,
- &f_midi_opts_in_ports.attr,
- &f_midi_opts_out_ports.attr,
- &f_midi_opts_id.attr,
+ &f_midi_opts_attr_index,
+ &f_midi_opts_attr_buflen,
+ &f_midi_opts_attr_qlen,
+ &f_midi_opts_attr_in_ports,
+ &f_midi_opts_attr_out_ports,
+ &f_midi_opts_attr_id,
NULL,
};
@@ -1145,7 +1141,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
if (opts->id && !midi->id) {
status = -ENOMEM;
mutex_unlock(&opts->lock);
- goto kstrdup_fail;
+ goto setup_fail;
}
midi->in_ports = opts->in_ports;
midi->out_ports = opts->out_ports;
@@ -1164,8 +1160,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
return &midi->func;
-kstrdup_fail:
- f_midi_unregister_card(midi);
setup_fail:
for (--i; i >= 0; i--)
kfree(midi->in_port[i]);
diff --git a/kernel/drivers/usb/gadget/function/f_ncm.c b/kernel/drivers/usb/gadget/function/f_ncm.c
index bdcda9f51..7ad798ace 100644
--- a/kernel/drivers/usb/gadget/function/f_ncm.c
+++ b/kernel/drivers/usb/gadget/function/f_ncm.c
@@ -586,7 +586,7 @@ static void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
unsigned in_size;
struct usb_function *f = req->context;
struct f_ncm *ncm = func_to_ncm(f);
- struct usb_composite_dev *cdev = ep->driver_data;
+ struct usb_composite_dev *cdev = f->config->cdev;
req->context = NULL;
if (req->status || req->actual != req->length) {
@@ -803,10 +803,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt != 0)
goto fail;
- if (ncm->notify->driver_data) {
- DBG(cdev, "reset ncm control %d\n", intf);
- usb_ep_disable(ncm->notify);
- }
+ DBG(cdev, "reset ncm control %d\n", intf);
+ usb_ep_disable(ncm->notify);
if (!(ncm->notify->desc)) {
DBG(cdev, "init ncm ctrl %d\n", intf);
@@ -814,14 +812,13 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
goto fail;
}
usb_ep_enable(ncm->notify);
- ncm->notify->driver_data = ncm;
/* Data interface has two altsettings, 0 and 1 */
} else if (intf == ncm->data_id) {
if (alt > 1)
goto fail;
- if (ncm->port.in_ep->driver_data) {
+ if (ncm->port.in_ep->enabled) {
DBG(cdev, "reset ncm\n");
ncm->timer_stopping = true;
ncm->netdev = NULL;
@@ -853,9 +850,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* Enable zlps by default for NCM conformance;
* override for musb_hdrc (avoids txdma ovhead)
*/
- ncm->port.is_zlp_ok = !(
- gadget_is_musbhdrc(cdev->gadget)
- );
+ ncm->port.is_zlp_ok =
+ gadget_is_zlp_supported(cdev->gadget);
ncm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ncm\n");
net = gether_connect(&ncm->port);
@@ -886,7 +882,7 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
if (intf == ncm->ctrl_id)
return 0;
- return ncm->port.in_ep->driver_data ? 1 : 0;
+ return ncm->port.in_ep->enabled ? 1 : 0;
}
static struct sk_buff *package_for_tx(struct f_ncm *ncm)
@@ -1277,15 +1273,14 @@ static void ncm_disable(struct usb_function *f)
DBG(cdev, "ncm deactivated\n");
- if (ncm->port.in_ep->driver_data) {
+ if (ncm->port.in_ep->enabled) {
ncm->timer_stopping = true;
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
}
- if (ncm->notify->driver_data) {
+ if (ncm->notify->enabled) {
usb_ep_disable(ncm->notify);
- ncm->notify->driver_data = NULL;
ncm->notify->desc = NULL;
}
}
@@ -1403,19 +1398,16 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
ncm->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc);
if (!ep)
goto fail;
ncm->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc);
if (!ep)
goto fail;
ncm->notify = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -1469,14 +1461,6 @@ fail:
usb_ep_free_request(ncm->notify, ncm->notify_req);
}
- /* we might as well release our claims on endpoints */
- if (ncm->notify)
- ncm->notify->driver_data = NULL;
- if (ncm->port.out_ep)
- ncm->port.out_ep->driver_data = NULL;
- if (ncm->port.in_ep)
- ncm->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -1504,10 +1488,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm);
static struct configfs_attribute *ncm_attrs[] = {
- &f_ncm_opts_dev_addr.attr,
- &f_ncm_opts_host_addr.attr,
- &f_ncm_opts_qmult.attr,
- &f_ncm_opts_ifname.attr,
+ &ncm_opts_attr_dev_addr,
+ &ncm_opts_attr_host_addr,
+ &ncm_opts_attr_qmult,
+ &ncm_opts_attr_ifname,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_obex.c b/kernel/drivers/usb/gadget/function/f_obex.c
index a1b79c534..d6396e090 100644
--- a/kernel/drivers/usb/gadget/function/f_obex.c
+++ b/kernel/drivers/usb/gadget/function/f_obex.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/*
@@ -37,7 +36,6 @@ struct f_obex {
u8 data_id;
u8 cur_alt;
u8 port_num;
- u8 can_activate;
};
static inline struct f_obex *func_to_obex(struct usb_function *f)
@@ -208,7 +206,7 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt > 1)
goto fail;
- if (obex->port.in->driver_data) {
+ if (obex->port.in->enabled) {
dev_dbg(&cdev->gadget->dev,
"reset obex ttyGS%d\n", obex->port_num);
gserial_disconnect(&obex->port);
@@ -268,9 +266,6 @@ static void obex_connect(struct gserial *g)
struct usb_composite_dev *cdev = g->func.config->cdev;
int status;
- if (!obex->can_activate)
- return;
-
status = usb_function_activate(&g->func);
if (status)
dev_dbg(&cdev->gadget->dev,
@@ -284,9 +279,6 @@ static void obex_disconnect(struct gserial *g)
struct usb_composite_dev *cdev = g->func.config->cdev;
int status;
- if (!obex->can_activate)
- return;
-
status = usb_function_deactivate(&g->func);
if (status)
dev_dbg(&cdev->gadget->dev,
@@ -304,7 +296,7 @@ static inline bool can_support_obex(struct usb_configuration *c)
*
* Altsettings are mandatory, however...
*/
- if (!gadget_supports_altsettings(c->cdev->gadget))
+ if (!gadget_is_altset_supported(c->cdev->gadget))
return false;
/* everything else is *probably* fine ... */
@@ -356,13 +348,11 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
obex->port.in = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc);
if (!ep)
goto fail;
obex->port.out = ep;
- ep->driver_data = cdev; /* claim */
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@@ -378,17 +368,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
if (status)
goto fail;
- /* Avoid letting this gadget enumerate until the userspace
- * OBEX server is active.
- */
- status = usb_function_deactivate(f);
- if (status < 0)
- WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
- obex->port_num, status);
- else
- obex->can_activate = true;
-
-
dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
obex->port_num,
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -397,12 +376,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- /* we might as well release our claims on endpoints */
- if (obex->port.out)
- obex->port.out->driver_data = NULL;
- if (obex->port.in)
- obex->port.in->driver_data = NULL;
-
ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
return status;
@@ -414,22 +387,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_obex_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_serial_opts *opts = to_f_serial_opts(item);
- struct f_serial_opts_attribute *f_serial_opts_attr =
- container_of(attr, struct f_serial_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_serial_opts_attr->show)
- ret = f_serial_opts_attr->show(opts, page);
-
- return ret;
-}
-
static void obex_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -439,19 +396,17 @@ static void obex_attr_release(struct config_item *item)
static struct configfs_item_operations obex_item_ops = {
.release = obex_attr_release,
- .show_attribute = f_obex_attr_show,
};
-static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_obex_port_num_show(struct config_item *item, char *page)
{
- return sprintf(page, "%u\n", opts->port_num);
+ return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
}
-static struct f_serial_opts_attribute f_obex_port_num =
- __CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+CONFIGFS_ATTR_RO(f_obex_, port_num);
static struct configfs_attribute *acm_attrs[] = {
- &f_obex_port_num.attr,
+ &f_obex_attr_port_num,
NULL,
};
@@ -529,6 +484,7 @@ static struct usb_function *obex_alloc(struct usb_function_instance *fi)
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
obex->port.func.free_func = obex_free;
+ obex->port.func.bind_deactivated = true;
return &obex->port.func;
}
diff --git a/kernel/drivers/usb/gadget/function/f_phonet.c b/kernel/drivers/usb/gadget/function/f_phonet.c
index c0c3ef272..157441dbf 100644
--- a/kernel/drivers/usb/gadget/function/f_phonet.c
+++ b/kernel/drivers/usb/gadget/function/f_phonet.c
@@ -418,7 +418,7 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
spin_lock(&port->lock);
- if (fp->in_ep->driver_data)
+ if (fp->in_ep->enabled)
__pn_reset(f);
if (alt == 1) {
@@ -530,13 +530,11 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto err;
fp->out_ep = ep;
- ep->driver_data = fp; /* Claim */
ep = usb_ep_autoconfig(gadget, &pn_fs_source_desc);
if (!ep)
goto err;
fp->in_ep = ep;
- ep->driver_data = fp; /* Claim */
pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
@@ -575,10 +573,6 @@ err_req:
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
usb_free_all_descriptors(f);
err:
- if (fp->out_ep)
- fp->out_ep->driver_data = NULL;
- if (fp->in_ep)
- fp->in_ep->driver_data = NULL;
ERROR(cdev, "USB CDC Phonet: cannot autoconfigure\n");
return status;
}
@@ -589,21 +583,6 @@ static inline struct f_phonet_opts *to_f_phonet_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_phonet_opts);
-static ssize_t f_phonet_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_phonet_opts *opts = to_f_phonet_opts(item);
- struct f_phonet_opts_attribute *f_phonet_opts_attr =
- container_of(attr, struct f_phonet_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_phonet_opts_attr->show)
- ret = f_phonet_opts_attr->show(opts, page);
- return ret;
-}
-
static void phonet_attr_release(struct config_item *item)
{
struct f_phonet_opts *opts = to_f_phonet_opts(item);
@@ -613,19 +592,17 @@ static void phonet_attr_release(struct config_item *item)
static struct configfs_item_operations phonet_item_ops = {
.release = phonet_attr_release,
- .show_attribute = f_phonet_attr_show,
};
-static ssize_t f_phonet_ifname_show(struct f_phonet_opts *opts, char *page)
+static ssize_t f_phonet_ifname_show(struct config_item *item, char *page)
{
- return gether_get_ifname(opts->net, page, PAGE_SIZE);
+ return gether_get_ifname(to_f_phonet_opts(item)->net, page, PAGE_SIZE);
}
-static struct f_phonet_opts_attribute f_phonet_ifname =
- __CONFIGFS_ATTR_RO(ifname, f_phonet_ifname_show);
+CONFIGFS_ATTR_RO(f_phonet_, ifname);
static struct configfs_attribute *phonet_attrs[] = {
- &f_phonet_ifname.attr,
+ &f_phonet_attr_ifname,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_printer.c b/kernel/drivers/usb/gadget/function/f_printer.c
index 44173df27..0fbfb2b2a 100644
--- a/kernel/drivers/usb/gadget/function/f_printer.c
+++ b/kernel/drivers/usb/gadget/function/f_printer.c
@@ -804,6 +804,8 @@ done:
static void printer_reset_interface(struct printer_dev *dev)
{
+ unsigned long flags;
+
if (dev->interface < 0)
return;
@@ -815,9 +817,11 @@ static void printer_reset_interface(struct printer_dev *dev)
if (dev->out_ep->desc)
usb_ep_disable(dev->out_ep);
+ spin_lock_irqsave(&dev->lock, flags);
dev->in_ep->desc = NULL;
dev->out_ep->desc = NULL;
dev->interface = -1;
+ spin_unlock_irqrestore(&dev->lock, flags);
}
/* Change our operational Interface. */
@@ -1035,12 +1039,10 @@ autoconf_fail:
cdev->gadget->name);
return -ENODEV;
}
- in_ep->driver_data = in_ep; /* claim */
out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
if (!out_ep)
goto autoconf_fail;
- out_ep->driver_data = out_ep; /* claim */
/* assumes that all endpoints are dual-speed */
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
@@ -1131,13 +1133,10 @@ static int printer_func_set_alt(struct usb_function *f,
static void printer_func_disable(struct usb_function *f)
{
struct printer_dev *dev = func_to_printer(f);
- unsigned long flags;
DBG(dev, "%s\n", __func__);
- spin_lock_irqsave(&dev->lock, flags);
printer_reset_interface(dev);
- spin_unlock_irqrestore(&dev->lock, flags);
}
static inline struct f_printer_opts
@@ -1147,9 +1146,6 @@ static inline struct f_printer_opts
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_printer_opts);
-CONFIGFS_ATTR_OPS(f_printer_opts);
-
static void printer_attr_release(struct config_item *item)
{
struct f_printer_opts *opts = to_f_printer_opts(item);
@@ -1159,13 +1155,12 @@ static void printer_attr_release(struct config_item *item)
static struct configfs_item_operations printer_item_ops = {
.release = printer_attr_release,
- .show_attribute = f_printer_opts_attr_show,
- .store_attribute = f_printer_opts_attr_store,
};
-static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
char *page)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -1175,9 +1170,10 @@ static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
return result;
}
-static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_pnp_string_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int result, l;
mutex_lock(&opts->lock);
@@ -1190,14 +1186,12 @@ static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
return result;
}
-static struct f_printer_opts_attribute f_printer_opts_pnp_string =
- __CONFIGFS_ATTR(pnp_string, S_IRUGO | S_IWUSR,
- f_printer_opts_pnp_string_show,
- f_printer_opts_pnp_string_store);
+CONFIGFS_ATTR(f_printer_opts_, pnp_string);
-static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_q_len_show(struct config_item *item,
char *page)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int result;
mutex_lock(&opts->lock);
@@ -1207,9 +1201,10 @@ static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
return result;
}
-static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts,
+static ssize_t f_printer_opts_q_len_store(struct config_item *item,
const char *page, size_t len)
{
+ struct f_printer_opts *opts = to_f_printer_opts(item);
int ret;
u16 num;
@@ -1230,13 +1225,11 @@ end:
return ret;
}
-static struct f_printer_opts_attribute f_printer_opts_q_len =
- __CONFIGFS_ATTR(q_len, S_IRUGO | S_IWUSR, f_printer_opts_q_len_show,
- f_printer_opts_q_len_store);
+CONFIGFS_ATTR(f_printer_opts_, q_len);
static struct configfs_attribute *printer_attrs[] = {
- &f_printer_opts_pnp_string.attr,
- &f_printer_opts_q_len.attr,
+ &f_printer_opts_attr_pnp_string,
+ &f_printer_opts_attr_q_len,
NULL,
};
@@ -1248,7 +1241,15 @@ static struct config_item_type printer_func_type = {
static inline int gprinter_get_minor(void)
{
- return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
+ int ret;
+
+ ret = ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
+ if (ret >= PRINTER_MINORS) {
+ ida_simple_remove(&printer_ida, ret);
+ ret = -ENODEV;
+ }
+
+ return ret;
}
static inline void gprinter_put_minor(int minor)
diff --git a/kernel/drivers/usb/gadget/function/f_rndis.c b/kernel/drivers/usb/gadget/function/f_rndis.c
index 829edf878..e587767e3 100644
--- a/kernel/drivers/usb/gadget/function/f_rndis.c
+++ b/kernel/drivers/usb/gadget/function/f_rndis.c
@@ -76,7 +76,7 @@ struct f_rndis {
u8 ethaddr[ETH_ALEN];
u32 vendorID;
const char *manufacturer;
- int config;
+ struct rndis_params *params;
struct usb_ep *notify;
struct usb_request *notify_req;
@@ -453,7 +453,7 @@ static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
// spin_lock(&dev->lock);
- status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
+ status = rndis_msg_parser(rndis->params, (u8 *) req->buf);
if (status < 0)
pr_err("RNDIS command error %d, %d/%d\n",
status, req->actual, req->length);
@@ -499,12 +499,12 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
u32 n;
/* return the result */
- buf = rndis_get_next_response(rndis->config, &n);
+ buf = rndis_get_next_response(rndis->params, &n);
if (buf) {
memcpy(req->buf, buf, n);
req->complete = rndis_response_complete;
req->context = rndis;
- rndis_free_response(rndis->config, buf);
+ rndis_free_response(rndis->params, buf);
value = n;
}
/* else stalls ... spec says to avoid that */
@@ -543,22 +543,20 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0 */
if (intf == rndis->ctrl_id) {
- if (rndis->notify->driver_data) {
- VDBG(cdev, "reset rndis control %d\n", intf);
- usb_ep_disable(rndis->notify);
- }
+ VDBG(cdev, "reset rndis control %d\n", intf);
+ usb_ep_disable(rndis->notify);
+
if (!rndis->notify->desc) {
VDBG(cdev, "init rndis ctrl %d\n", intf);
if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
goto fail;
}
usb_ep_enable(rndis->notify);
- rndis->notify->driver_data = rndis;
} else if (intf == rndis->data_id) {
struct net_device *net;
- if (rndis->port.in_ep->driver_data) {
+ if (rndis->port.in_ep->enabled) {
DBG(cdev, "reset rndis\n");
gether_disconnect(&rndis->port);
}
@@ -597,7 +595,7 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (IS_ERR(net))
return PTR_ERR(net);
- rndis_set_param_dev(rndis->config, net,
+ rndis_set_param_dev(rndis->params, net,
&rndis->port.cdc_filter);
} else
goto fail;
@@ -612,16 +610,15 @@ static void rndis_disable(struct usb_function *f)
struct f_rndis *rndis = func_to_rndis(f);
struct usb_composite_dev *cdev = f->config->cdev;
- if (!rndis->notify->driver_data)
+ if (!rndis->notify->enabled)
return;
DBG(cdev, "rndis deactivated\n");
- rndis_uninit(rndis->config);
+ rndis_uninit(rndis->params);
gether_disconnect(&rndis->port);
usb_ep_disable(rndis->notify);
- rndis->notify->driver_data = NULL;
}
/*-------------------------------------------------------------------------*/
@@ -640,9 +637,9 @@ static void rndis_open(struct gether *geth)
DBG(cdev, "%s\n", __func__);
- rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3,
+ rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3,
bitrate(cdev->gadget) / 100);
- rndis_signal_connect(rndis->config);
+ rndis_signal_connect(rndis->params);
}
static void rndis_close(struct gether *geth)
@@ -651,8 +648,8 @@ static void rndis_close(struct gether *geth)
DBG(geth->func.config->cdev, "%s\n", __func__);
- rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
- rndis_signal_disconnect(rndis->config);
+ rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3, 0);
+ rndis_signal_disconnect(rndis->params);
}
/*-------------------------------------------------------------------------*/
@@ -745,13 +742,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
rndis->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
if (!ep)
goto fail;
rndis->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
/* NOTE: a status/notification endpoint is, strictly speaking,
* optional. We don't treat it that way though! It's simpler,
@@ -761,7 +756,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
rndis->notify = ep;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -796,11 +790,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->port.open = rndis_open;
rndis->port.close = rndis_close;
- rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0);
- rndis_set_host_mac(rndis->config, rndis->ethaddr);
+ rndis_set_param_medium(rndis->params, RNDIS_MEDIUM_802_3, 0);
+ rndis_set_host_mac(rndis->params, rndis->ethaddr);
if (rndis->manufacturer && rndis->vendorID &&
- rndis_set_param_vendor(rndis->config, rndis->vendorID,
+ rndis_set_param_vendor(rndis->params, rndis->vendorID,
rndis->manufacturer)) {
status = -EINVAL;
goto fail_free_descs;
@@ -829,14 +823,6 @@ fail:
usb_ep_free_request(rndis->notify, rndis->notify_req);
}
- /* we might as well release our claims on endpoints */
- if (rndis->notify)
- rndis->notify->driver_data = NULL;
- if (rndis->port.out_ep)
- rndis->port.out_ep->driver_data = NULL;
- if (rndis->port.in_ep)
- rndis->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -878,10 +864,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
static struct configfs_attribute *rndis_attrs[] = {
- &f_rndis_opts_dev_addr.attr,
- &f_rndis_opts_host_addr.attr,
- &f_rndis_opts_qmult.attr,
- &f_rndis_opts_ifname.attr,
+ &rndis_opts_attr_dev_addr,
+ &rndis_opts_attr_host_addr,
+ &rndis_opts_attr_qmult,
+ &rndis_opts_attr_ifname,
NULL,
};
@@ -944,7 +930,7 @@ static void rndis_free(struct usb_function *f)
struct f_rndis_opts *opts;
rndis = func_to_rndis(f);
- rndis_deregister(rndis->config);
+ rndis_deregister(rndis->params);
opts = container_of(f->fi, struct f_rndis_opts, func_inst);
kfree(rndis);
mutex_lock(&opts->lock);
@@ -968,7 +954,7 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi)
{
struct f_rndis *rndis;
struct f_rndis_opts *opts;
- int status;
+ struct rndis_params *params;
/* allocate and initialize one new instance */
rndis = kzalloc(sizeof(*rndis), GFP_KERNEL);
@@ -1002,36 +988,16 @@ static struct usb_function *rndis_alloc(struct usb_function_instance *fi)
rndis->port.func.disable = rndis_disable;
rndis->port.func.free_func = rndis_free;
- status = rndis_register(rndis_response_available, rndis);
- if (status < 0) {
+ params = rndis_register(rndis_response_available, rndis);
+ if (IS_ERR(params)) {
kfree(rndis);
- return ERR_PTR(status);
+ return ERR_CAST(params);
}
- rndis->config = status;
+ rndis->params = params;
return &rndis->port.func;
}
-DECLARE_USB_FUNCTION(rndis, rndis_alloc_inst, rndis_alloc);
-
-static int __init rndis_mod_init(void)
-{
- int ret;
-
- ret = rndis_init();
- if (ret)
- return ret;
-
- return usb_function_register(&rndisusb_func);
-}
-module_init(rndis_mod_init);
-
-static void __exit rndis_mod_exit(void)
-{
- usb_function_unregister(&rndisusb_func);
- rndis_exit();
-}
-module_exit(rndis_mod_exit);
-
+DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
diff --git a/kernel/drivers/usb/gadget/function/f_serial.c b/kernel/drivers/usb/gadget/function/f_serial.c
index 2e02dfabc..6bb44d613 100644
--- a/kernel/drivers/usb/gadget/function/f_serial.c
+++ b/kernel/drivers/usb/gadget/function/f_serial.c
@@ -16,7 +16,6 @@
#include <linux/device.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/*
@@ -154,7 +153,7 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
- if (gser->port.in->driver_data) {
+ if (gser->port.in->enabled) {
dev_dbg(&cdev->gadget->dev,
"reset generic ttyGS%d\n", gser->port_num);
gserial_disconnect(&gser->port);
@@ -220,13 +219,11 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
gser->port.in = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
if (!ep)
goto fail;
gser->port.out = ep;
- ep->driver_data = cdev; /* claim */
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@@ -250,12 +247,6 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- /* we might as well release our claims on endpoints */
- if (gser->port.out)
- gser->port.out->driver_data = NULL;
- if (gser->port.in)
- gser->port.in->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -267,22 +258,6 @@ static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_serial_opts);
-static ssize_t f_serial_attr_show(struct config_item *item,
- struct configfs_attribute *attr,
- char *page)
-{
- struct f_serial_opts *opts = to_f_serial_opts(item);
- struct f_serial_opts_attribute *f_serial_opts_attr =
- container_of(attr, struct f_serial_opts_attribute, attr);
- ssize_t ret = 0;
-
- if (f_serial_opts_attr->show)
- ret = f_serial_opts_attr->show(opts, page);
-
- return ret;
-}
-
static void serial_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
@@ -292,19 +267,17 @@ static void serial_attr_release(struct config_item *item)
static struct configfs_item_operations serial_item_ops = {
.release = serial_attr_release,
- .show_attribute = f_serial_attr_show,
};
-static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+static ssize_t f_serial_port_num_show(struct config_item *item, char *page)
{
- return sprintf(page, "%u\n", opts->port_num);
+ return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num);
}
-static struct f_serial_opts_attribute f_serial_port_num =
- __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+CONFIGFS_ATTR_RO(f_serial_, port_num);
static struct configfs_attribute *acm_attrs[] = {
- &f_serial_port_num.attr,
+ &f_serial_attr_port_num,
NULL,
};
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,
};
diff --git a/kernel/drivers/usb/gadget/function/f_subset.c b/kernel/drivers/usb/gadget/function/f_subset.c
index e3dfa675f..829c78de9 100644
--- a/kernel/drivers/usb/gadget/function/f_subset.c
+++ b/kernel/drivers/usb/gadget/function/f_subset.c
@@ -262,7 +262,7 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* we know alt == 0, so this is an activation or a reset */
- if (geth->port.in_ep->driver_data) {
+ if (geth->port.in_ep->enabled) {
DBG(cdev, "reset cdc subset\n");
gether_disconnect(&geth->port);
}
@@ -343,13 +343,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
if (!ep)
goto fail;
geth->port.in_ep = ep;
- ep->driver_data = cdev; /* claim */
ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc);
if (!ep)
goto fail;
geth->port.out_ep = ep;
- ep->driver_data = cdev; /* claim */
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
@@ -380,12 +378,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- /* we might as well release our claims on endpoints */
- if (geth->port.out_ep)
- geth->port.out_ep->driver_data = NULL;
- if (geth->port.in_ep)
- geth->port.in_ep->driver_data = NULL;
-
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -413,10 +405,10 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether);
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether);
static struct configfs_attribute *gether_attrs[] = {
- &f_gether_opts_dev_addr.attr,
- &f_gether_opts_host_addr.attr,
- &f_gether_opts_qmult.attr,
- &f_gether_opts_ifname.attr,
+ &gether_opts_attr_dev_addr,
+ &gether_opts_attr_host_addr,
+ &gether_opts_attr_qmult,
+ &gether_opts_attr_ifname,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_uac1.c b/kernel/drivers/usb/gadget/function/f_uac1.c
index 7856b3394..6a2346b99 100644
--- a/kernel/drivers/usb/gadget/function/f_uac1.c
+++ b/kernel/drivers/usb/gadget/function/f_uac1.c
@@ -593,7 +593,6 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
return err;
usb_ep_enable(out_ep);
- out_ep->driver_data = audio;
audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
if (IS_ERR(audio->copy_buf))
return -ENOMEM;
@@ -718,7 +717,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
audio->out_ep = ep;
audio->out_ep->desc = &as_out_ep_desc;
- ep->driver_data = cdev; /* claim */
status = -ENOMEM;
@@ -730,8 +728,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
fail:
gaudio_cleanup(&audio->card);
- if (ep)
- ep->driver_data = NULL;
return status;
}
@@ -773,9 +769,6 @@ static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_uac1_opts);
-CONFIGFS_ATTR_OPS(f_uac1_opts);
-
static void f_uac1_attr_release(struct config_item *item)
{
struct f_uac1_opts *opts = to_f_uac1_opts(item);
@@ -785,14 +778,13 @@ static void f_uac1_attr_release(struct config_item *item)
static struct configfs_item_operations f_uac1_item_ops = {
.release = f_uac1_attr_release,
- .show_attribute = f_uac1_opts_attr_show,
- .store_attribute = f_uac1_opts_attr_store,
};
#define UAC1_INT_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -802,9 +794,10 @@ static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
return result; \
} \
\
-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int ret; \
u32 num; \
\
@@ -826,19 +819,17 @@ end: \
return ret; \
} \
\
-static struct f_uac1_opts_attribute f_uac1_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- f_uac1_opts_##name##_show, \
- f_uac1_opts_##name##_store)
+CONFIGFS_ATTR(f_uac1_opts_, name)
UAC1_INT_ATTRIBUTE(req_buf_size);
UAC1_INT_ATTRIBUTE(req_count);
UAC1_INT_ATTRIBUTE(audio_buf_size);
#define UAC1_STR_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -848,9 +839,10 @@ static ssize_t f_uac1_opts_##name##_show(struct f_uac1_opts *opts, \
return result; \
} \
\
-static ssize_t f_uac1_opts_##name##_store(struct f_uac1_opts *opts, \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int ret = -EBUSY; \
char *tmp; \
\
@@ -874,22 +866,19 @@ end: \
return ret; \
} \
\
-static struct f_uac1_opts_attribute f_uac1_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- f_uac1_opts_##name##_show, \
- f_uac1_opts_##name##_store)
+CONFIGFS_ATTR(f_uac1_opts_, name)
UAC1_STR_ATTRIBUTE(fn_play);
UAC1_STR_ATTRIBUTE(fn_cap);
UAC1_STR_ATTRIBUTE(fn_cntl);
static struct configfs_attribute *f_uac1_attrs[] = {
- &f_uac1_opts_req_buf_size.attr,
- &f_uac1_opts_req_count.attr,
- &f_uac1_opts_audio_buf_size.attr,
- &f_uac1_opts_fn_play.attr,
- &f_uac1_opts_fn_cap.attr,
- &f_uac1_opts_fn_cntl.attr,
+ &f_uac1_opts_attr_req_buf_size,
+ &f_uac1_opts_attr_req_count,
+ &f_uac1_opts_attr_audio_buf_size,
+ &f_uac1_opts_attr_fn_play,
+ &f_uac1_opts_attr_fn_cap,
+ &f_uac1_opts_attr_fn_cntl,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/f_uac2.c b/kernel/drivers/usb/gadget/function/f_uac2.c
index 96d935b00..044ca79d3 100644
--- a/kernel/drivers/usb/gadget/function/f_uac2.c
+++ b/kernel/drivers/usb/gadget/function/f_uac2.c
@@ -994,7 +994,7 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
max_packet_size = num_channels(chmask) * ssize *
DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
- ep_desc->wMaxPacketSize = cpu_to_le16(min(max_packet_size,
+ ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size,
le16_to_cpu(ep_desc->wMaxPacketSize)));
}
@@ -1081,14 +1081,12 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
goto err;
}
- agdev->out_ep->driver_data = agdev;
agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
if (!agdev->in_ep) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
goto err;
}
- agdev->in_ep->driver_data = agdev;
uac2->p_prm.uac2 = uac2;
uac2->c_prm.uac2 = uac2;
@@ -1132,10 +1130,6 @@ err_free_descs:
err:
kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf);
- if (agdev->in_ep)
- agdev->in_ep->driver_data = NULL;
- if (agdev->out_ep)
- agdev->out_ep->driver_data = NULL;
return -EINVAL;
}
@@ -1445,9 +1439,6 @@ static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_uac2_opts);
-CONFIGFS_ATTR_OPS(f_uac2_opts);
-
static void f_uac2_attr_release(struct config_item *item)
{
struct f_uac2_opts *opts = to_f_uac2_opts(item);
@@ -1457,14 +1448,13 @@ static void f_uac2_attr_release(struct config_item *item)
static struct configfs_item_operations f_uac2_item_ops = {
.release = f_uac2_attr_release,
- .show_attribute = f_uac2_opts_attr_show,
- .store_attribute = f_uac2_opts_attr_store,
};
#define UAC2_ATTRIBUTE(name) \
-static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts, \
+static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
+ struct f_uac2_opts *opts = to_f_uac2_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -1474,9 +1464,10 @@ static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts, \
return result; \
} \
\
-static ssize_t f_uac2_opts_##name##_store(struct f_uac2_opts *opts, \
+static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uac2_opts *opts = to_f_uac2_opts(item); \
int ret; \
u32 num; \
\
@@ -1498,10 +1489,7 @@ end: \
return ret; \
} \
\
-static struct f_uac2_opts_attribute f_uac2_opts_##name = \
- __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
- f_uac2_opts_##name##_show, \
- f_uac2_opts_##name##_store)
+CONFIGFS_ATTR(f_uac2_opts_, name)
UAC2_ATTRIBUTE(p_chmask);
UAC2_ATTRIBUTE(p_srate);
@@ -1511,12 +1499,12 @@ UAC2_ATTRIBUTE(c_srate);
UAC2_ATTRIBUTE(c_ssize);
static struct configfs_attribute *f_uac2_attrs[] = {
- &f_uac2_opts_p_chmask.attr,
- &f_uac2_opts_p_srate.attr,
- &f_uac2_opts_p_ssize.attr,
- &f_uac2_opts_c_chmask.attr,
- &f_uac2_opts_c_srate.attr,
- &f_uac2_opts_c_ssize.attr,
+ &f_uac2_opts_attr_p_chmask,
+ &f_uac2_opts_attr_p_srate,
+ &f_uac2_opts_attr_p_ssize,
+ &f_uac2_opts_attr_c_chmask,
+ &f_uac2_opts_attr_c_srate,
+ &f_uac2_opts_attr_c_ssize,
NULL,
};
@@ -1583,11 +1571,6 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
prm = &agdev->uac2.c_prm;
kfree(prm->rbuf);
usb_free_all_descriptors(f);
-
- if (agdev->in_ep)
- agdev->in_ep->driver_data = NULL;
- if (agdev->out_ep)
- agdev->out_ep->driver_data = NULL;
}
static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
diff --git a/kernel/drivers/usb/gadget/function/f_uvc.c b/kernel/drivers/usb/gadget/function/f_uvc.c
index cf0df8fbb..29b41b5de 100644
--- a/kernel/drivers/usb/gadget/function/f_uvc.c
+++ b/kernel/drivers/usb/gadget/function/f_uvc.c
@@ -280,7 +280,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
else if (interface != uvc->streaming_intf)
return -EINVAL;
else
- return uvc->video.ep->driver_data ? 1 : 0;
+ return uvc->video.ep->enabled ? 1 : 0;
}
static int
@@ -298,18 +298,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (alt)
return -EINVAL;
- if (uvc->control_ep->driver_data) {
- INFO(cdev, "reset UVC Control\n");
- usb_ep_disable(uvc->control_ep);
- uvc->control_ep->driver_data = NULL;
- }
+ INFO(cdev, "reset UVC Control\n");
+ usb_ep_disable(uvc->control_ep);
if (!uvc->control_ep->desc)
if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
return -EINVAL;
usb_ep_enable(uvc->control_ep);
- uvc->control_ep->driver_data = uvc;
if (uvc->state == UVC_STATE_DISCONNECTED) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
@@ -336,10 +332,8 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (uvc->state != UVC_STATE_STREAMING)
return 0;
- if (uvc->video.ep) {
+ if (uvc->video.ep)
usb_ep_disable(uvc->video.ep);
- uvc->video.ep->driver_data = NULL;
- }
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMOFF;
@@ -355,18 +349,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (!uvc->video.ep)
return -EINVAL;
- if (uvc->video.ep->driver_data) {
- INFO(cdev, "reset UVC\n");
- usb_ep_disable(uvc->video.ep);
- uvc->video.ep->driver_data = NULL;
- }
+ INFO(cdev, "reset UVC\n");
+ usb_ep_disable(uvc->video.ep);
ret = config_ep_by_speed(f->config->cdev->gadget,
&(uvc->func), uvc->video.ep);
if (ret)
return ret;
usb_ep_enable(uvc->video.ep);
- uvc->video.ep->driver_data = uvc;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
@@ -392,15 +382,8 @@ uvc_function_disable(struct usb_function *f)
uvc->state = UVC_STATE_DISCONNECTED;
- if (uvc->video.ep->driver_data) {
- usb_ep_disable(uvc->video.ep);
- uvc->video.ep->driver_data = NULL;
- }
-
- if (uvc->control_ep->driver_data) {
- usb_ep_disable(uvc->control_ep);
- uvc->control_ep->driver_data = NULL;
- }
+ usb_ep_disable(uvc->video.ep);
+ usb_ep_disable(uvc->control_ep);
}
/* --------------------------------------------------------------------------
@@ -651,7 +634,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
uvc->control_ep = ep;
- ep->driver_data = uvc;
if (gadget_is_superspeed(c->cdev->gadget))
ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
@@ -666,7 +648,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
uvc->video.ep = ep;
- ep->driver_data = uvc;
uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
@@ -733,12 +714,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc->control_req->complete = uvc_function_ep0_complete;
uvc->control_req->context = uvc;
- /* Avoid letting this gadget enumerate until the userspace server is
- * active.
- */
- if ((ret = usb_function_deactivate(f)) < 0)
- goto error;
-
if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) {
printk(KERN_INFO "v4l2_device_register failed\n");
goto error;
@@ -761,11 +736,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
error:
v4l2_device_unregister(&uvc->v4l2_dev);
- if (uvc->control_ep)
- uvc->control_ep->driver_data = NULL;
- if (uvc->video.ep)
- uvc->video.ep->driver_data = NULL;
-
if (uvc->control_req)
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
@@ -892,8 +862,6 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
video_unregister_device(&uvc->vdev);
v4l2_device_unregister(&uvc->v4l2_dev);
- uvc->control_ep->driver_data = NULL;
- uvc->video.ep->driver_data = NULL;
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
@@ -949,6 +917,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
uvc->func.disable = uvc_function_disable;
uvc->func.setup = uvc_function_setup;
uvc->func.free_func = uvc_free;
+ uvc->func.bind_deactivated = true;
return &uvc->func;
}
diff --git a/kernel/drivers/usb/gadget/function/rndis.c b/kernel/drivers/usb/gadget/function/rndis.c
index 95d2324f6..70d3917cc 100644
--- a/kernel/drivers/usb/gadget/function/rndis.c
+++ b/kernel/drivers/usb/gadget/function/rndis.c
@@ -25,6 +25,7 @@
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/idr.h>
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
@@ -57,17 +58,26 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
#define rndis_debug 0
#endif
-#define RNDIS_MAX_CONFIGS 1
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+#define NAME_TEMPLATE "driver/rndis-%03d"
-static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
+static DEFINE_IDA(rndis_ida);
/* Driver Version */
static const __le32 rndis_driver_version = cpu_to_le32(1);
/* Function Prototypes */
-static rndis_resp_t *rndis_add_response(int configNr, u32 length);
+static rndis_resp_t *rndis_add_response(struct rndis_params *params,
+ u32 length);
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static const struct file_operations rndis_proc_fops;
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
/* supported OIDs */
static const u32 oid_supported_list[] =
@@ -160,7 +170,7 @@ static const u32 oid_supported_list[] =
/* NDIS Functions */
-static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
+static int gen_ndis_query_resp(struct rndis_params *params, u32 OID, u8 *buf,
unsigned buf_len, rndis_resp_t *r)
{
int retval = -ENOTSUPP;
@@ -192,7 +202,7 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
outbuf = (__le32 *)&resp[1];
resp->InformationBufferOffset = cpu_to_le32(16);
- net = rndis_per_dev_params[configNr].dev;
+ net = params->dev;
stats = dev_get_stats(net, &temp);
switch (OID) {
@@ -225,7 +235,7 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
/* mandatory */
case RNDIS_OID_GEN_MEDIA_SUPPORTED:
pr_debug("%s: RNDIS_OID_GEN_MEDIA_SUPPORTED\n", __func__);
- *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
+ *outbuf = cpu_to_le32(params->medium);
retval = 0;
break;
@@ -233,16 +243,15 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
case RNDIS_OID_GEN_MEDIA_IN_USE:
pr_debug("%s: RNDIS_OID_GEN_MEDIA_IN_USE\n", __func__);
/* one medium, one transport... (maybe you do it better) */
- *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
+ *outbuf = cpu_to_le32(params->medium);
retval = 0;
break;
/* mandatory */
case RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE:
pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
- if (rndis_per_dev_params[configNr].dev) {
- *outbuf = cpu_to_le32(
- rndis_per_dev_params[configNr].dev->mtu);
+ if (params->dev) {
+ *outbuf = cpu_to_le32(params->dev->mtu);
retval = 0;
}
break;
@@ -251,21 +260,18 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
case RNDIS_OID_GEN_LINK_SPEED:
if (rndis_debug > 1)
pr_debug("%s: RNDIS_OID_GEN_LINK_SPEED\n", __func__);
- if (rndis_per_dev_params[configNr].media_state
- == RNDIS_MEDIA_STATE_DISCONNECTED)
+ if (params->media_state == RNDIS_MEDIA_STATE_DISCONNECTED)
*outbuf = cpu_to_le32(0);
else
- *outbuf = cpu_to_le32(
- rndis_per_dev_params[configNr].speed);
+ *outbuf = cpu_to_le32(params->speed);
retval = 0;
break;
/* mandatory */
case RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE:
pr_debug("%s: RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
- if (rndis_per_dev_params[configNr].dev) {
- *outbuf = cpu_to_le32(
- rndis_per_dev_params[configNr].dev->mtu);
+ if (params->dev) {
+ *outbuf = cpu_to_le32(params->dev->mtu);
retval = 0;
}
break;
@@ -273,9 +279,8 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
/* mandatory */
case RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE:
pr_debug("%s: RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
- if (rndis_per_dev_params[configNr].dev) {
- *outbuf = cpu_to_le32(
- rndis_per_dev_params[configNr].dev->mtu);
+ if (params->dev) {
+ *outbuf = cpu_to_le32(params->dev->mtu);
retval = 0;
}
break;
@@ -283,20 +288,16 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
/* mandatory */
case RNDIS_OID_GEN_VENDOR_ID:
pr_debug("%s: RNDIS_OID_GEN_VENDOR_ID\n", __func__);
- *outbuf = cpu_to_le32(
- rndis_per_dev_params[configNr].vendorID);
+ *outbuf = cpu_to_le32(params->vendorID);
retval = 0;
break;
/* mandatory */
case RNDIS_OID_GEN_VENDOR_DESCRIPTION:
pr_debug("%s: RNDIS_OID_GEN_VENDOR_DESCRIPTION\n", __func__);
- if (rndis_per_dev_params[configNr].vendorDescr) {
- length = strlen(rndis_per_dev_params[configNr].
- vendorDescr);
- memcpy(outbuf,
- rndis_per_dev_params[configNr].vendorDescr,
- length);
+ if (params->vendorDescr) {
+ length = strlen(params->vendorDescr);
+ memcpy(outbuf, params->vendorDescr, length);
} else {
outbuf[0] = 0;
}
@@ -313,7 +314,7 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
/* mandatory */
case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
- *outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter);
+ *outbuf = cpu_to_le32(*params->filter);
retval = 0;
break;
@@ -328,8 +329,7 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
case RNDIS_OID_GEN_MEDIA_CONNECT_STATUS:
if (rndis_debug > 1)
pr_debug("%s: RNDIS_OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
- *outbuf = cpu_to_le32(rndis_per_dev_params[configNr]
- .media_state);
+ *outbuf = cpu_to_le32(params->media_state);
retval = 0;
break;
@@ -409,11 +409,9 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
/* mandatory */
case RNDIS_OID_802_3_PERMANENT_ADDRESS:
pr_debug("%s: RNDIS_OID_802_3_PERMANENT_ADDRESS\n", __func__);
- if (rndis_per_dev_params[configNr].dev) {
+ if (params->dev) {
length = ETH_ALEN;
- memcpy(outbuf,
- rndis_per_dev_params[configNr].host_mac,
- length);
+ memcpy(outbuf, params->host_mac, length);
retval = 0;
}
break;
@@ -421,11 +419,9 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
/* mandatory */
case RNDIS_OID_802_3_CURRENT_ADDRESS:
pr_debug("%s: RNDIS_OID_802_3_CURRENT_ADDRESS\n", __func__);
- if (rndis_per_dev_params[configNr].dev) {
+ if (params->dev) {
length = ETH_ALEN;
- memcpy(outbuf,
- rndis_per_dev_params [configNr].host_mac,
- length);
+ memcpy(outbuf, params->host_mac, length);
retval = 0;
}
break;
@@ -490,12 +486,11 @@ static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
return retval;
}
-static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
- rndis_resp_t *r)
+static int gen_ndis_set_resp(struct rndis_params *params, u32 OID,
+ u8 *buf, u32 buf_len, rndis_resp_t *r)
{
rndis_set_cmplt_type *resp;
int i, retval = -ENOTSUPP;
- struct rndis_params *params;
if (!r)
return -ENOMEM;
@@ -514,7 +509,6 @@ static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
}
}
- params = &rndis_per_dev_params[configNr];
switch (OID) {
case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
@@ -563,16 +557,16 @@ static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* Response Functions
*/
-static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
+static int rndis_init_response(struct rndis_params *params,
+ rndis_init_msg_type *buf)
{
rndis_init_cmplt_type *resp;
rndis_resp_t *r;
- struct rndis_params *params = rndis_per_dev_params + configNr;
if (!params->dev)
return -ENOTSUPP;
- r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
+ r = rndis_add_response(params, sizeof(rndis_init_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_init_cmplt_type *)r->buf;
@@ -599,11 +593,11 @@ static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
return 0;
}
-static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
+static int rndis_query_response(struct rndis_params *params,
+ rndis_query_msg_type *buf)
{
rndis_query_cmplt_type *resp;
rndis_resp_t *r;
- struct rndis_params *params = rndis_per_dev_params + configNr;
/* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
if (!params->dev)
@@ -615,7 +609,7 @@ static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
* rndis_query_cmplt_type followed by data.
* oid_supported_list is the largest data reply
*/
- r = rndis_add_response(configNr,
+ r = rndis_add_response(params,
sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
if (!r)
return -ENOMEM;
@@ -624,7 +618,7 @@ static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
resp->MessageType = cpu_to_le32(RNDIS_MSG_QUERY_C);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
- if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID),
+ if (gen_ndis_query_resp(params, le32_to_cpu(buf->OID),
le32_to_cpu(buf->InformationBufferOffset)
+ 8 + (u8 *)buf,
le32_to_cpu(buf->InformationBufferLength),
@@ -641,14 +635,14 @@ static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
return 0;
}
-static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
+static int rndis_set_response(struct rndis_params *params,
+ rndis_set_msg_type *buf)
{
u32 BufLength, BufOffset;
rndis_set_cmplt_type *resp;
rndis_resp_t *r;
- struct rndis_params *params = rndis_per_dev_params + configNr;
- r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
+ r = rndis_add_response(params, sizeof(rndis_set_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_set_cmplt_type *)r->buf;
@@ -671,7 +665,7 @@ static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
resp->MessageType = cpu_to_le32(RNDIS_MSG_SET_C);
resp->MessageLength = cpu_to_le32(16);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
- if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID),
+ if (gen_ndis_set_resp(params, le32_to_cpu(buf->OID),
((u8 *)buf) + 8 + BufOffset, BufLength, r))
resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
else
@@ -681,13 +675,13 @@ static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
return 0;
}
-static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
+static int rndis_reset_response(struct rndis_params *params,
+ rndis_reset_msg_type *buf)
{
rndis_reset_cmplt_type *resp;
rndis_resp_t *r;
- struct rndis_params *params = rndis_per_dev_params + configNr;
- r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
+ r = rndis_add_response(params, sizeof(rndis_reset_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_reset_cmplt_type *)r->buf;
@@ -702,16 +696,15 @@ static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
return 0;
}
-static int rndis_keepalive_response(int configNr,
+static int rndis_keepalive_response(struct rndis_params *params,
rndis_keepalive_msg_type *buf)
{
rndis_keepalive_cmplt_type *resp;
rndis_resp_t *r;
- struct rndis_params *params = rndis_per_dev_params + configNr;
/* host "should" check only in RNDIS_DATA_INITIALIZED state */
- r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
+ r = rndis_add_response(params, sizeof(rndis_keepalive_cmplt_type));
if (!r)
return -ENOMEM;
resp = (rndis_keepalive_cmplt_type *)r->buf;
@@ -729,17 +722,15 @@ static int rndis_keepalive_response(int configNr,
/*
* Device to Host Comunication
*/
-static int rndis_indicate_status_msg(int configNr, u32 status)
+static int rndis_indicate_status_msg(struct rndis_params *params, u32 status)
{
rndis_indicate_status_msg_type *resp;
rndis_resp_t *r;
- struct rndis_params *params = rndis_per_dev_params + configNr;
if (params->state == RNDIS_UNINITIALIZED)
return -ENOTSUPP;
- r = rndis_add_response(configNr,
- sizeof(rndis_indicate_status_msg_type));
+ r = rndis_add_response(params, sizeof(rndis_indicate_status_msg_type));
if (!r)
return -ENOMEM;
resp = (rndis_indicate_status_msg_type *)r->buf;
@@ -754,53 +745,48 @@ static int rndis_indicate_status_msg(int configNr, u32 status)
return 0;
}
-int rndis_signal_connect(int configNr)
+int rndis_signal_connect(struct rndis_params *params)
{
- rndis_per_dev_params[configNr].media_state
- = RNDIS_MEDIA_STATE_CONNECTED;
- return rndis_indicate_status_msg(configNr,
- RNDIS_STATUS_MEDIA_CONNECT);
+ params->media_state = RNDIS_MEDIA_STATE_CONNECTED;
+ return rndis_indicate_status_msg(params, RNDIS_STATUS_MEDIA_CONNECT);
}
EXPORT_SYMBOL_GPL(rndis_signal_connect);
-int rndis_signal_disconnect(int configNr)
+int rndis_signal_disconnect(struct rndis_params *params)
{
- rndis_per_dev_params[configNr].media_state
- = RNDIS_MEDIA_STATE_DISCONNECTED;
- return rndis_indicate_status_msg(configNr,
- RNDIS_STATUS_MEDIA_DISCONNECT);
+ params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED;
+ return rndis_indicate_status_msg(params, RNDIS_STATUS_MEDIA_DISCONNECT);
}
EXPORT_SYMBOL_GPL(rndis_signal_disconnect);
-void rndis_uninit(int configNr)
+void rndis_uninit(struct rndis_params *params)
{
u8 *buf;
u32 length;
- if (configNr >= RNDIS_MAX_CONFIGS)
+ if (!params)
return;
- rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
+ params->state = RNDIS_UNINITIALIZED;
/* drain the response queue */
- while ((buf = rndis_get_next_response(configNr, &length)))
- rndis_free_response(configNr, buf);
+ while ((buf = rndis_get_next_response(params, &length)))
+ rndis_free_response(params, buf);
}
EXPORT_SYMBOL_GPL(rndis_uninit);
-void rndis_set_host_mac(int configNr, const u8 *addr)
+void rndis_set_host_mac(struct rndis_params *params, const u8 *addr)
{
- rndis_per_dev_params[configNr].host_mac = addr;
+ params->host_mac = addr;
}
EXPORT_SYMBOL_GPL(rndis_set_host_mac);
/*
* Message Parser
*/
-int rndis_msg_parser(u8 configNr, u8 *buf)
+int rndis_msg_parser(struct rndis_params *params, u8 *buf)
{
u32 MsgType, MsgLength;
__le32 *tmp;
- struct rndis_params *params;
if (!buf)
return -ENOMEM;
@@ -809,9 +795,8 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
MsgType = get_unaligned_le32(tmp++);
MsgLength = get_unaligned_le32(tmp++);
- if (configNr >= RNDIS_MAX_CONFIGS)
+ if (!params)
return -ENOTSUPP;
- params = &rndis_per_dev_params[configNr];
/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
* rx/tx statistics and link status, in addition to KEEPALIVE traffic
@@ -824,8 +809,7 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
pr_debug("%s: RNDIS_MSG_INIT\n",
__func__);
params->state = RNDIS_INITIALIZED;
- return rndis_init_response(configNr,
- (rndis_init_msg_type *)buf);
+ return rndis_init_response(params, (rndis_init_msg_type *)buf);
case RNDIS_MSG_HALT:
pr_debug("%s: RNDIS_MSG_HALT\n",
@@ -838,17 +822,16 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
return 0;
case RNDIS_MSG_QUERY:
- return rndis_query_response(configNr,
+ return rndis_query_response(params,
(rndis_query_msg_type *)buf);
case RNDIS_MSG_SET:
- return rndis_set_response(configNr,
- (rndis_set_msg_type *)buf);
+ return rndis_set_response(params, (rndis_set_msg_type *)buf);
case RNDIS_MSG_RESET:
pr_debug("%s: RNDIS_MSG_RESET\n",
__func__);
- return rndis_reset_response(configNr,
+ return rndis_reset_response(params,
(rndis_reset_msg_type *)buf);
case RNDIS_MSG_KEEPALIVE:
@@ -856,7 +839,7 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
if (rndis_debug > 1)
pr_debug("%s: RNDIS_MSG_KEEPALIVE\n",
__func__);
- return rndis_keepalive_response(configNr,
+ return rndis_keepalive_response(params,
(rndis_keepalive_msg_type *)
buf);
@@ -876,71 +859,131 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
}
EXPORT_SYMBOL_GPL(rndis_msg_parser);
-int rndis_register(void (*resp_avail)(void *v), void *v)
+static inline int rndis_get_nr(void)
{
- u8 i;
+ return ida_simple_get(&rndis_ida, 0, 0, GFP_KERNEL);
+}
+
+static inline void rndis_put_nr(int nr)
+{
+ ida_simple_remove(&rndis_ida, nr);
+}
+
+struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v)
+{
+ struct rndis_params *params;
+ int i;
if (!resp_avail)
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
+
+ i = rndis_get_nr();
+ if (i < 0) {
+ pr_debug("failed\n");
+
+ return ERR_PTR(-ENODEV);
+ }
+
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params) {
+ rndis_put_nr(i);
- for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
- if (!rndis_per_dev_params[i].used) {
- rndis_per_dev_params[i].used = 1;
- rndis_per_dev_params[i].resp_avail = resp_avail;
- rndis_per_dev_params[i].v = v;
- pr_debug("%s: configNr = %d\n", __func__, i);
- return i;
+ return ERR_PTR(-ENOMEM);
+ }
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+ {
+ struct proc_dir_entry *proc_entry;
+ char name[20];
+
+ sprintf(name, NAME_TEMPLATE, i);
+ proc_entry = proc_create_data(name, 0660, NULL,
+ &rndis_proc_fops, params);
+ if (!proc_entry) {
+ kfree(params);
+ rndis_put_nr(i);
+
+ return ERR_PTR(-EIO);
}
}
- pr_debug("failed\n");
+#endif
+
+ params->confignr = i;
+ params->used = 1;
+ params->state = RNDIS_UNINITIALIZED;
+ params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED;
+ params->resp_avail = resp_avail;
+ params->v = v;
+ INIT_LIST_HEAD(&(params->resp_queue));
+ pr_debug("%s: configNr = %d\n", __func__, i);
- return -ENODEV;
+ return params;
}
EXPORT_SYMBOL_GPL(rndis_register);
-void rndis_deregister(int configNr)
+void rndis_deregister(struct rndis_params *params)
{
+ int i;
+
pr_debug("%s:\n", __func__);
- if (configNr >= RNDIS_MAX_CONFIGS) return;
- rndis_per_dev_params[configNr].used = 0;
+ if (!params)
+ return;
+
+ i = params->confignr;
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+ {
+ char name[20];
+
+ sprintf(name, NAME_TEMPLATE, i);
+ remove_proc_entry(name, NULL);
+ }
+#endif
+
+ kfree(params);
+ rndis_put_nr(i);
}
EXPORT_SYMBOL_GPL(rndis_deregister);
-
-int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
+int rndis_set_param_dev(struct rndis_params *params, struct net_device *dev,
+ u16 *cdc_filter)
{
pr_debug("%s:\n", __func__);
if (!dev)
return -EINVAL;
- if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+ if (!params)
+ return -1;
- rndis_per_dev_params[configNr].dev = dev;
- rndis_per_dev_params[configNr].filter = cdc_filter;
+ params->dev = dev;
+ params->filter = cdc_filter;
return 0;
}
EXPORT_SYMBOL_GPL(rndis_set_param_dev);
-int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
+int rndis_set_param_vendor(struct rndis_params *params, u32 vendorID,
+ const char *vendorDescr)
{
pr_debug("%s:\n", __func__);
if (!vendorDescr) return -1;
- if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+ if (!params)
+ return -1;
- rndis_per_dev_params[configNr].vendorID = vendorID;
- rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
+ params->vendorID = vendorID;
+ params->vendorDescr = vendorDescr;
return 0;
}
EXPORT_SYMBOL_GPL(rndis_set_param_vendor);
-int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
+int rndis_set_param_medium(struct rndis_params *params, u32 medium, u32 speed)
{
pr_debug("%s: %u %u\n", __func__, medium, speed);
- if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+ if (!params)
+ return -1;
- rndis_per_dev_params[configNr].medium = medium;
- rndis_per_dev_params[configNr].speed = speed;
+ params->medium = medium;
+ params->speed = speed;
return 0;
}
@@ -961,13 +1004,12 @@ void rndis_add_hdr(struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(rndis_add_hdr);
-void rndis_free_response(int configNr, u8 *buf)
+void rndis_free_response(struct rndis_params *params, u8 *buf)
{
rndis_resp_t *r;
struct list_head *act, *tmp;
- list_for_each_safe(act, tmp,
- &(rndis_per_dev_params[configNr].resp_queue))
+ list_for_each_safe(act, tmp, &(params->resp_queue))
{
r = list_entry(act, rndis_resp_t, list);
if (r && r->buf == buf) {
@@ -978,15 +1020,14 @@ void rndis_free_response(int configNr, u8 *buf)
}
EXPORT_SYMBOL_GPL(rndis_free_response);
-u8 *rndis_get_next_response(int configNr, u32 *length)
+u8 *rndis_get_next_response(struct rndis_params *params, u32 *length)
{
rndis_resp_t *r;
struct list_head *act, *tmp;
if (!length) return NULL;
- list_for_each_safe(act, tmp,
- &(rndis_per_dev_params[configNr].resp_queue))
+ list_for_each_safe(act, tmp, &(params->resp_queue))
{
r = list_entry(act, rndis_resp_t, list);
if (!r->send) {
@@ -1000,7 +1041,7 @@ u8 *rndis_get_next_response(int configNr, u32 *length)
}
EXPORT_SYMBOL_GPL(rndis_get_next_response);
-static rndis_resp_t *rndis_add_response(int configNr, u32 length)
+static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length)
{
rndis_resp_t *r;
@@ -1012,8 +1053,7 @@ static rndis_resp_t *rndis_add_response(int configNr, u32 length)
r->length = length;
r->send = 0;
- list_add_tail(&r->list,
- &(rndis_per_dev_params[configNr].resp_queue));
+ list_add_tail(&r->list, &(params->resp_queue));
return r;
}
@@ -1103,11 +1143,11 @@ static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
break;
case 'C':
case 'c':
- rndis_signal_connect(p->confignr);
+ rndis_signal_connect(p);
break;
case 'D':
case 'd':
- rndis_signal_disconnect(p->confignr);
+ rndis_signal_disconnect(p);
break;
default:
if (fl_speed) p->speed = speed;
@@ -1137,54 +1177,4 @@ static const struct file_operations rndis_proc_fops = {
#define NAME_TEMPLATE "driver/rndis-%03d"
-static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
-
#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-
-int rndis_init(void)
-{
- u8 i;
-
- for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- char name [20];
-
- sprintf(name, NAME_TEMPLATE, i);
- rndis_connect_state[i] = proc_create_data(name, 0660, NULL,
- &rndis_proc_fops,
- (void *)(rndis_per_dev_params + i));
- if (!rndis_connect_state[i]) {
- pr_debug("%s: remove entries", __func__);
- while (i) {
- sprintf(name, NAME_TEMPLATE, --i);
- remove_proc_entry(name, NULL);
- }
- pr_debug("\n");
- return -EIO;
- }
-#endif
- rndis_per_dev_params[i].confignr = i;
- rndis_per_dev_params[i].used = 0;
- rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
- rndis_per_dev_params[i].media_state
- = RNDIS_MEDIA_STATE_DISCONNECTED;
- INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
- }
-
- return 0;
-}
-
-void rndis_exit(void)
-{
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- u8 i;
- char name[20];
-
- for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
- sprintf(name, NAME_TEMPLATE, i);
- remove_proc_entry(name, NULL);
- }
-#endif
-}
-
diff --git a/kernel/drivers/usb/gadget/function/rndis.h b/kernel/drivers/usb/gadget/function/rndis.h
index 0f4abb4c3..ef92eb66d 100644
--- a/kernel/drivers/usb/gadget/function/rndis.h
+++ b/kernel/drivers/usb/gadget/function/rndis.h
@@ -177,7 +177,7 @@ typedef struct rndis_resp_t
typedef struct rndis_params
{
- u8 confignr;
+ int confignr;
u8 used;
u16 saved_filter;
enum rndis_state state;
@@ -197,24 +197,25 @@ typedef struct rndis_params
} rndis_params;
/* RNDIS Message parser and other useless functions */
-int rndis_msg_parser (u8 configNr, u8 *buf);
-int rndis_register(void (*resp_avail)(void *v), void *v);
-void rndis_deregister (int configNr);
-int rndis_set_param_dev (u8 configNr, struct net_device *dev,
+int rndis_msg_parser(struct rndis_params *params, u8 *buf);
+struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v);
+void rndis_deregister(struct rndis_params *params);
+int rndis_set_param_dev(struct rndis_params *params, struct net_device *dev,
u16 *cdc_filter);
-int rndis_set_param_vendor (u8 configNr, u32 vendorID,
+int rndis_set_param_vendor(struct rndis_params *params, u32 vendorID,
const char *vendorDescr);
-int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
-void rndis_add_hdr (struct sk_buff *skb);
+int rndis_set_param_medium(struct rndis_params *params, u32 medium,
+ u32 speed);
+void rndis_add_hdr(struct sk_buff *skb);
int rndis_rm_hdr(struct gether *port, struct sk_buff *skb,
struct sk_buff_head *list);
-u8 *rndis_get_next_response (int configNr, u32 *length);
-void rndis_free_response (int configNr, u8 *buf);
-
-void rndis_uninit (int configNr);
-int rndis_signal_connect (int configNr);
-int rndis_signal_disconnect (int configNr);
-int rndis_state (int configNr);
-extern void rndis_set_host_mac (int configNr, const u8 *addr);
+u8 *rndis_get_next_response(struct rndis_params *params, u32 *length);
+void rndis_free_response(struct rndis_params *params, u8 *buf);
+
+void rndis_uninit(struct rndis_params *params);
+int rndis_signal_connect(struct rndis_params *params);
+int rndis_signal_disconnect(struct rndis_params *params);
+int rndis_state(struct rndis_params *params);
+extern void rndis_set_host_mac(struct rndis_params *params, const u8 *addr);
#endif /* _LINUX_RNDIS_H */
diff --git a/kernel/drivers/usb/gadget/function/storage_common.c b/kernel/drivers/usb/gadget/function/storage_common.c
index 648f9e489..d62683017 100644
--- a/kernel/drivers/usb/gadget/function/storage_common.c
+++ b/kernel/drivers/usb/gadget/function/storage_common.c
@@ -341,7 +341,7 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
down_read(filesem);
if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */
- p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1);
+ p = file_path(curlun->filp, buf, PAGE_SIZE - 1);
if (IS_ERR(p))
rc = PTR_ERR(p);
else {
diff --git a/kernel/drivers/usb/gadget/function/storage_common.h b/kernel/drivers/usb/gadget/function/storage_common.h
index 70c891469..c3544e61d 100644
--- a/kernel/drivers/usb/gadget/function/storage_common.h
+++ b/kernel/drivers/usb/gadget/function/storage_common.h
@@ -123,7 +123,7 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
#define FSG_BUFLEN ((u32)16384)
/* Maximal number of LUNs supported in mass storage function */
-#define FSG_MAX_LUNS 8
+#define FSG_MAX_LUNS 16
enum fsg_buffer_state {
BUF_STATE_EMPTY = 0,
diff --git a/kernel/drivers/usb/gadget/function/u_ether.c b/kernel/drivers/usb/gadget/function/u_ether.c
index f1fd777ef..6554322af 100644
--- a/kernel/drivers/usb/gadget/function/u_ether.c
+++ b/kernel/drivers/usb/gadget/function/u_ether.c
@@ -48,6 +48,11 @@
#define UETH__VERSION "29-May-2008"
+/* Experiments show that both Linux and Windows hosts allow up to 16k
+ * frame sizes. Set the max size to 15k+52 to prevent allocating 32k
+ * blocks and still have efficient handling. */
+#define GETHER_MAX_ETH_FRAME_LEN 15412
+
struct eth_dev {
/* lock is held while accessing port_usb
*/
@@ -146,7 +151,7 @@ static int ueth_change_mtu(struct net_device *net, int new_mtu)
spin_lock_irqsave(&dev->lock, flags);
if (dev->port_usb)
status = -EBUSY;
- else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
+ else if (new_mtu <= ETH_HLEN || new_mtu > GETHER_MAX_ETH_FRAME_LEN)
status = -ERANGE;
else
net->mtu = new_mtu;
@@ -294,7 +299,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
while (skb2) {
if (status < 0
|| ETH_HLEN > skb2->len
- || skb2->len > VLAN_ETH_FRAME_LEN) {
+ || skb2->len > GETHER_MAX_ETH_FRAME_LEN) {
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
DBG(dev, "rx length %d\n", skb2->len);
@@ -1144,7 +1149,6 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->req_lock);
}
spin_unlock(&dev->req_lock);
- link->in_ep->driver_data = NULL;
link->in_ep->desc = NULL;
usb_ep_disable(link->out_ep);
@@ -1159,7 +1163,6 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->req_lock);
}
spin_unlock(&dev->req_lock);
- link->out_ep->driver_data = NULL;
link->out_ep->desc = NULL;
/* finish forgetting about this USB link episode */
diff --git a/kernel/drivers/usb/gadget/function/u_ether.h b/kernel/drivers/usb/gadget/function/u_ether.h
index 334b38947..c77145bd6 100644
--- a/kernel/drivers/usb/gadget/function/u_ether.h
+++ b/kernel/drivers/usb/gadget/function/u_ether.h
@@ -20,8 +20,6 @@
#include <linux/usb/cdc.h>
#include <linux/netdevice.h>
-#include "gadget_chips.h"
-
#define QMULT_DEFAULT 5
/*
@@ -259,7 +257,7 @@ void gether_disconnect(struct gether *);
/* Some controllers can't support CDC Ethernet (ECM) ... */
static inline bool can_support_ecm(struct usb_gadget *gadget)
{
- if (!gadget_supports_altsettings(gadget))
+ if (!gadget_is_altset_supported(gadget))
return false;
/* Everything else is *presumably* fine ... but this is a bit
diff --git a/kernel/drivers/usb/gadget/function/u_ether_configfs.h b/kernel/drivers/usb/gadget/function/u_ether_configfs.h
index bcbd30146..4f47289fc 100644
--- a/kernel/drivers/usb/gadget/function/u_ether_configfs.h
+++ b/kernel/drivers/usb/gadget/function/u_ether_configfs.h
@@ -17,9 +17,6 @@
#define __U_ETHER_CONFIGFS_H
#define USB_ETHERNET_CONFIGFS_ITEM(_f_) \
- CONFIGFS_ATTR_STRUCT(f_##_f_##_opts); \
- CONFIGFS_ATTR_OPS(f_##_f_##_opts); \
- \
static void _f_##_attr_release(struct config_item *item) \
{ \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
@@ -29,14 +26,13 @@
\
static struct configfs_item_operations _f_##_item_ops = { \
.release = _f_##_attr_release, \
- .show_attribute = f_##_f_##_opts_attr_show, \
- .store_attribute = f_##_f_##_opts_attr_store, \
}
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \
- static ssize_t _f_##_opts_dev_addr_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -46,9 +42,10 @@
return result; \
} \
\
- static ssize_t _f_##_opts_dev_addr_store(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
@@ -64,15 +61,13 @@
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_dev_addr = \
- __CONFIGFS_ATTR(dev_addr, S_IRUGO | S_IWUSR, \
- _f_##_opts_dev_addr_show, \
- _f_##_opts_dev_addr_store)
+ CONFIGFS_ATTR(_f_##_opts_, dev_addr)
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \
- static ssize_t _f_##_opts_host_addr_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -82,9 +77,10 @@
return result; \
} \
\
- static ssize_t _f_##_opts_host_addr_store(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
@@ -100,15 +96,13 @@
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_host_addr = \
- __CONFIGFS_ATTR(host_addr, S_IRUGO | S_IWUSR, \
- _f_##_opts_host_addr_show, \
- _f_##_opts_host_addr_store)
+ CONFIGFS_ATTR(_f_##_opts_, host_addr)
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \
- static ssize_t _f_##_opts_qmult_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_qmult_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
unsigned qmult; \
\
mutex_lock(&opts->lock); \
@@ -117,9 +111,10 @@
return sprintf(page, "%d", qmult); \
} \
\
- static ssize_t _f_##_opts_qmult_store(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_qmult_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
u8 val; \
int ret; \
\
@@ -140,15 +135,13 @@ out: \
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_qmult = \
- __CONFIGFS_ATTR(qmult, S_IRUGO | S_IWUSR, \
- _f_##_opts_qmult_show, \
- _f_##_opts_qmult_store)
+ CONFIGFS_ATTR(_f_##_opts_, qmult)
#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \
- static ssize_t _f_##_opts_ifname_show(struct f_##_f_##_opts *opts, \
+ static ssize_t _f_##_opts_ifname_show(struct config_item *item, \
char *page) \
{ \
+ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
mutex_lock(&opts->lock); \
@@ -158,7 +151,6 @@ out: \
return ret; \
} \
\
- static struct f_##_f_##_opts_attribute f_##_f_##_opts_ifname = \
- __CONFIGFS_ATTR_RO(ifname, _f_##_opts_ifname_show)
+ CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
#endif /* __U_ETHER_CONFIGFS_H */
diff --git a/kernel/drivers/usb/gadget/function/u_rndis.h b/kernel/drivers/usb/gadget/function/u_rndis.h
index e902aa42a..4eafd5050 100644
--- a/kernel/drivers/usb/gadget/function/u_rndis.h
+++ b/kernel/drivers/usb/gadget/function/u_rndis.h
@@ -39,8 +39,6 @@ struct f_rndis_opts {
int refcnt;
};
-int rndis_init(void);
-void rndis_exit(void);
void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net);
#endif /* U_RNDIS_H */
diff --git a/kernel/drivers/usb/gadget/function/u_serial.c b/kernel/drivers/usb/gadget/function/u_serial.c
index 7ee057930..f7771d86a 100644
--- a/kernel/drivers/usb/gadget/function/u_serial.c
+++ b/kernel/drivers/usb/gadget/function/u_serial.c
@@ -114,6 +114,7 @@ struct gs_port {
struct gs_buf port_write_buf;
wait_queue_head_t drain_wait; /* wait while writes drain */
bool write_busy;
+ wait_queue_head_t close_wait;
/* REVISIT this state ... */
struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
@@ -876,7 +877,6 @@ static void gs_close(struct tty_struct *tty, struct file *file)
else
gs_buf_clear(&port->port_write_buf);
- tty->driver_data = NULL;
port->port.tty = NULL;
port->openclose = false;
@@ -884,7 +884,7 @@ static void gs_close(struct tty_struct *tty, struct file *file)
pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
port->port_num, tty, file);
- wake_up(&port->port.close_wait);
+ wake_up(&port->close_wait);
exit:
spin_unlock_irq(&port->port_lock);
}
@@ -1044,6 +1044,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
tty_port_init(&port->port);
spin_lock_init(&port->port_lock);
init_waitqueue_head(&port->drain_wait);
+ init_waitqueue_head(&port->close_wait);
tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
@@ -1074,7 +1075,7 @@ static void gserial_free_port(struct gs_port *port)
{
tasklet_kill(&port->push);
/* wait for old opens to finish */
- wait_event(port->port.close_wait, gs_closed(port));
+ wait_event(port->close_wait, gs_closed(port));
WARN_ON(port->port_usb != NULL);
tty_port_destroy(&port->port);
kfree(port);
@@ -1224,7 +1225,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
fail_out:
usb_ep_disable(gser->in);
- gser->in->driver_data = NULL;
return status;
}
EXPORT_SYMBOL_GPL(gserial_connect);
@@ -1264,10 +1264,7 @@ void gserial_disconnect(struct gserial *gser)
/* disable endpoints, aborting down any active I/O */
usb_ep_disable(gser->out);
- gser->out->driver_data = NULL;
-
usb_ep_disable(gser->in);
- gser->in->driver_data = NULL;
/* finally, free any unused/unusable I/O buffers */
spin_lock_irqsave(&port->port_lock, flags);
diff --git a/kernel/drivers/usb/gadget/function/u_uac1.h b/kernel/drivers/usb/gadget/function/u_uac1.h
index fe386df6d..5c2ac8e84 100644
--- a/kernel/drivers/usb/gadget/function/u_uac1.h
+++ b/kernel/drivers/usb/gadget/function/u_uac1.h
@@ -21,8 +21,6 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include "gadget_chips.h"
-
#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
#define FILE_CONTROL "/dev/snd/controlC0"
diff --git a/kernel/drivers/usb/gadget/function/uvc.h b/kernel/drivers/usb/gadget/function/uvc.h
index ebe409b9e..7d3bb6272 100644
--- a/kernel/drivers/usb/gadget/function/uvc.h
+++ b/kernel/drivers/usb/gadget/function/uvc.h
@@ -56,7 +56,6 @@ struct uvc_event
#include <linux/usb/composite.h>
#include <linux/usb/gadget.h>
#include <linux/videodev2.h>
-#include <linux/version.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-device.h>
diff --git a/kernel/drivers/usb/gadget/function/uvc_configfs.c b/kernel/drivers/usb/gadget/function/uvc_configfs.c
index 3c0467bcb..ad8c9b055 100644
--- a/kernel/drivers/usb/gadget/function/uvc_configfs.c
+++ b/kernel/drivers/usb/gadget/function/uvc_configfs.c
@@ -17,19 +17,21 @@
#define UVCG_STREAMING_CONTROL_SIZE 1
-#define CONFIGFS_ATTR_OPS_RO(_item) \
-static ssize_t _item##_attr_show(struct config_item *item, \
- struct configfs_attribute *attr, \
- char *page) \
-{ \
- struct _item *_item = to_##_item(item); \
- struct _item##_attribute *_item##_attr = \
- container_of(attr, struct _item##_attribute, attr); \
- ssize_t ret = 0; \
- \
- if (_item##_attr->show) \
- ret = _item##_attr->show(_item, page); \
- return ret; \
+#define UVC_ATTR(prefix, cname, aname) \
+static struct configfs_attribute prefix##attr_##cname = { \
+ .ca_name = __stringify(aname), \
+ .ca_mode = S_IRUGO | S_IWUGO, \
+ .ca_owner = THIS_MODULE, \
+ .show = prefix##cname##_show, \
+ .store = prefix##cname##_store, \
+}
+
+#define UVC_ATTR_RO(prefix, cname, aname) \
+static struct configfs_attribute prefix##attr_##cname = { \
+ .ca_name = __stringify(aname), \
+ .ca_mode = S_IRUGO, \
+ .ca_owner = THIS_MODULE, \
+ .show = prefix##cname##_show, \
}
static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item);
@@ -48,18 +50,11 @@ static struct uvcg_control_header *to_uvcg_control_header(struct config_item *it
return container_of(item, struct uvcg_control_header, item);
}
-CONFIGFS_ATTR_STRUCT(uvcg_control_header);
-CONFIGFS_ATTR_OPS(uvcg_control_header);
-
-static struct configfs_item_operations uvcg_control_header_item_ops = {
- .show_attribute = uvcg_control_header_attr_show,
- .store_attribute = uvcg_control_header_attr_store,
-};
-
#define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
static ssize_t uvcg_control_header_##cname##_show( \
- struct uvcg_control_header *ch, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_control_header *ch = to_uvcg_control_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
@@ -79,9 +74,10 @@ static ssize_t uvcg_control_header_##cname##_show( \
} \
\
static ssize_t \
-uvcg_control_header_##cname##_store(struct uvcg_control_header *ch, \
+uvcg_control_header_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct uvcg_control_header *ch = to_uvcg_control_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
@@ -115,11 +111,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_control_header_attribute \
- uvcg_control_header_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_control_header_##cname##_show, \
- uvcg_control_header_##cname##_store)
+UVC_ATTR(uvcg_control_header_, cname, aname)
UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
0xffff);
@@ -130,13 +122,12 @@ UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32,
#undef UVCG_CTRL_HDR_ATTR
static struct configfs_attribute *uvcg_control_header_attrs[] = {
- &uvcg_control_header_bcd_uvc.attr,
- &uvcg_control_header_dw_clock_frequency.attr,
+ &uvcg_control_header_attr_bcd_uvc,
+ &uvcg_control_header_attr_dw_clock_frequency,
NULL,
};
static struct config_item_type uvcg_control_header_type = {
- .ct_item_ops = &uvcg_control_header_item_ops,
.ct_attrs = uvcg_control_header_attrs,
.ct_owner = THIS_MODULE,
};
@@ -196,17 +187,11 @@ static inline struct uvcg_default_processing
struct uvcg_default_processing, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_processing);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_processing);
-
-static struct configfs_item_operations uvcg_default_processing_item_ops = {
- .show_attribute = uvcg_default_processing_attr_show,
-};
-
#define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_processing_##cname##_show( \
- struct uvcg_default_processing *dp, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
@@ -227,9 +212,7 @@ static ssize_t uvcg_default_processing_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_processing_attribute \
- uvcg_default_processing_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_processing_##cname##_show)
+UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
#define identity_conv(x) (x)
@@ -243,8 +226,9 @@ UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv);
#undef UVCG_DEFAULT_PROCESSING_ATTR
static ssize_t uvcg_default_processing_bm_controls_show(
- struct uvcg_default_processing *dp, char *page)
+ struct config_item *item, char *page)
{
+ struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
@@ -270,22 +254,18 @@ static ssize_t uvcg_default_processing_bm_controls_show(
return result;
}
-static struct uvcg_default_processing_attribute
- uvcg_default_processing_bm_controls =
- __CONFIGFS_ATTR_RO(bmControls,
- uvcg_default_processing_bm_controls_show);
+UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
static struct configfs_attribute *uvcg_default_processing_attrs[] = {
- &uvcg_default_processing_b_unit_id.attr,
- &uvcg_default_processing_b_source_id.attr,
- &uvcg_default_processing_w_max_multiplier.attr,
- &uvcg_default_processing_bm_controls.attr,
- &uvcg_default_processing_i_processing.attr,
+ &uvcg_default_processing_attr_b_unit_id,
+ &uvcg_default_processing_attr_b_source_id,
+ &uvcg_default_processing_attr_w_max_multiplier,
+ &uvcg_default_processing_attr_bm_controls,
+ &uvcg_default_processing_attr_i_processing,
NULL,
};
static struct config_item_type uvcg_default_processing_type = {
- .ct_item_ops = &uvcg_default_processing_item_ops,
.ct_attrs = uvcg_default_processing_attrs,
.ct_owner = THIS_MODULE,
};
@@ -318,17 +298,11 @@ static inline struct uvcg_default_camera
struct uvcg_default_camera, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_camera);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_camera);
-
-static struct configfs_item_operations uvcg_default_camera_item_ops = {
- .show_attribute = uvcg_default_camera_attr_show,
-};
-
#define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_camera_##cname##_show( \
- struct uvcg_default_camera *dc, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
@@ -351,9 +325,7 @@ static ssize_t uvcg_default_camera_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_camera_attribute \
- uvcg_default_camera_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_camera_##cname##_show)
+UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
#define identity_conv(x) (x)
@@ -373,8 +345,9 @@ UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
#undef UVCG_DEFAULT_CAMERA_ATTR
static ssize_t uvcg_default_camera_bm_controls_show(
- struct uvcg_default_camera *dc, char *page)
+ struct config_item *item, char *page)
{
+ struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
@@ -400,24 +373,21 @@ static ssize_t uvcg_default_camera_bm_controls_show(
return result;
}
-static struct uvcg_default_camera_attribute
- uvcg_default_camera_bm_controls =
- __CONFIGFS_ATTR_RO(bmControls, uvcg_default_camera_bm_controls_show);
+UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
static struct configfs_attribute *uvcg_default_camera_attrs[] = {
- &uvcg_default_camera_b_terminal_id.attr,
- &uvcg_default_camera_w_terminal_type.attr,
- &uvcg_default_camera_b_assoc_terminal.attr,
- &uvcg_default_camera_i_terminal.attr,
- &uvcg_default_camera_w_objective_focal_length_min.attr,
- &uvcg_default_camera_w_objective_focal_length_max.attr,
- &uvcg_default_camera_w_ocular_focal_length.attr,
- &uvcg_default_camera_bm_controls.attr,
+ &uvcg_default_camera_attr_b_terminal_id,
+ &uvcg_default_camera_attr_w_terminal_type,
+ &uvcg_default_camera_attr_b_assoc_terminal,
+ &uvcg_default_camera_attr_i_terminal,
+ &uvcg_default_camera_attr_w_objective_focal_length_min,
+ &uvcg_default_camera_attr_w_objective_focal_length_max,
+ &uvcg_default_camera_attr_w_ocular_focal_length,
+ &uvcg_default_camera_attr_bm_controls,
NULL,
};
static struct config_item_type uvcg_default_camera_type = {
- .ct_item_ops = &uvcg_default_camera_item_ops,
.ct_attrs = uvcg_default_camera_attrs,
.ct_owner = THIS_MODULE,
};
@@ -450,17 +420,11 @@ static inline struct uvcg_default_output
struct uvcg_default_output, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_output);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_output);
-
-static struct configfs_item_operations uvcg_default_output_item_ops = {
- .show_attribute = uvcg_default_output_attr_show,
-};
-
#define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_output_##cname##_show( \
- struct uvcg_default_output *dout, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_output *dout = to_uvcg_default_output(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
@@ -483,9 +447,7 @@ static ssize_t uvcg_default_output_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_output_attribute \
- uvcg_default_output_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_output_##cname##_show)
+UVC_ATTR_RO(uvcg_default_output_, cname, aname)
#define identity_conv(x) (x)
@@ -500,16 +462,15 @@ UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv);
#undef UVCG_DEFAULT_OUTPUT_ATTR
static struct configfs_attribute *uvcg_default_output_attrs[] = {
- &uvcg_default_output_b_terminal_id.attr,
- &uvcg_default_output_w_terminal_type.attr,
- &uvcg_default_output_b_assoc_terminal.attr,
- &uvcg_default_output_b_source_id.attr,
- &uvcg_default_output_i_terminal.attr,
+ &uvcg_default_output_attr_b_terminal_id,
+ &uvcg_default_output_attr_w_terminal_type,
+ &uvcg_default_output_attr_b_assoc_terminal,
+ &uvcg_default_output_attr_b_source_id,
+ &uvcg_default_output_attr_i_terminal,
NULL,
};
static struct config_item_type uvcg_default_output_type = {
- .ct_item_ops = &uvcg_default_output_item_ops,
.ct_attrs = uvcg_default_output_attrs,
.ct_owner = THIS_MODULE,
};
@@ -800,9 +761,6 @@ static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item
return container_of(item, struct uvcg_streaming_header, item);
}
-CONFIGFS_ATTR_STRUCT(uvcg_streaming_header);
-CONFIGFS_ATTR_OPS(uvcg_streaming_header);
-
static int uvcg_streaming_header_allow_link(struct config_item *src,
struct config_item *target)
{
@@ -893,16 +851,15 @@ out:
}
static struct configfs_item_operations uvcg_streaming_header_item_ops = {
- .show_attribute = uvcg_streaming_header_attr_show,
- .store_attribute = uvcg_streaming_header_attr_store,
.allow_link = uvcg_streaming_header_allow_link,
.drop_link = uvcg_streaming_header_drop_link,
};
#define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
static ssize_t uvcg_streaming_header_##cname##_show( \
- struct uvcg_streaming_header *sh, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
@@ -921,9 +878,7 @@ static ssize_t uvcg_streaming_header_##cname##_show( \
return result; \
} \
\
-static struct uvcg_streaming_header_attribute \
- uvcg_streaming_header_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_streaming_header_##cname##_show)
+UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
#define identity_conv(x) (x)
@@ -939,11 +894,11 @@ UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv);
#undef UVCG_STREAMING_HEADER_ATTR
static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
- &uvcg_streaming_header_bm_info.attr,
- &uvcg_streaming_header_b_terminal_link.attr,
- &uvcg_streaming_header_b_still_capture_method.attr,
- &uvcg_streaming_header_b_trigger_support.attr,
- &uvcg_streaming_header_b_trigger_usage.attr,
+ &uvcg_streaming_header_attr_bm_info,
+ &uvcg_streaming_header_attr_b_terminal_link,
+ &uvcg_streaming_header_attr_b_still_capture_method,
+ &uvcg_streaming_header_attr_b_trigger_support,
+ &uvcg_streaming_header_attr_b_trigger_usage,
NULL,
};
@@ -1022,17 +977,10 @@ static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
return container_of(item, struct uvcg_frame, item);
}
-CONFIGFS_ATTR_STRUCT(uvcg_frame);
-CONFIGFS_ATTR_OPS(uvcg_frame);
-
-static struct configfs_item_operations uvcg_frame_item_ops = {
- .show_attribute = uvcg_frame_attr_show,
- .store_attribute = uvcg_frame_attr_store,
-};
-
#define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
-static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
+static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
{ \
+ struct uvcg_frame *f = to_uvcg_frame(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
@@ -1051,9 +999,10 @@ static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
return result; \
} \
\
-static ssize_t uvcg_frame_##cname##_store(struct uvcg_frame *f, \
+static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
const char *page, size_t len)\
{ \
+ struct uvcg_frame *f = to_uvcg_frame(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct uvcg_format *fmt; \
@@ -1085,11 +1034,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_frame_attribute \
- uvcg_frame_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_frame_##cname##_show, \
- uvcg_frame_##cname##_store)
+UVC_ATTR(uvcg_frame_, cname, aname);
#define noop_conversion(x) (x)
@@ -1108,9 +1053,10 @@ UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
#undef UVCG_FRAME_ATTR
-static ssize_t uvcg_frame_dw_frame_interval_show(struct uvcg_frame *frm,
+static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
char *page)
{
+ struct uvcg_frame *frm = to_uvcg_frame(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
@@ -1185,9 +1131,10 @@ static int __uvcg_iter_frm_intrv(const char *page, size_t len,
return 0;
}
-static ssize_t uvcg_frame_dw_frame_interval_store(struct uvcg_frame *ch,
+static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
const char *page, size_t len)
{
+ struct uvcg_frame *ch = to_uvcg_frame(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct uvcg_format *fmt;
@@ -1234,26 +1181,21 @@ end:
return ret;
}
-static struct uvcg_frame_attribute
- uvcg_frame_dw_frame_interval =
- __CONFIGFS_ATTR(dwFrameInterval, S_IRUGO | S_IWUSR,
- uvcg_frame_dw_frame_interval_show,
- uvcg_frame_dw_frame_interval_store);
+UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
static struct configfs_attribute *uvcg_frame_attrs[] = {
- &uvcg_frame_bm_capabilities.attr,
- &uvcg_frame_w_width.attr,
- &uvcg_frame_w_height.attr,
- &uvcg_frame_dw_min_bit_rate.attr,
- &uvcg_frame_dw_max_bit_rate.attr,
- &uvcg_frame_dw_max_video_frame_buffer_size.attr,
- &uvcg_frame_dw_default_frame_interval.attr,
- &uvcg_frame_dw_frame_interval.attr,
+ &uvcg_frame_attr_bm_capabilities,
+ &uvcg_frame_attr_w_width,
+ &uvcg_frame_attr_w_height,
+ &uvcg_frame_attr_dw_min_bit_rate,
+ &uvcg_frame_attr_dw_max_bit_rate,
+ &uvcg_frame_attr_dw_max_video_frame_buffer_size,
+ &uvcg_frame_attr_dw_default_frame_interval,
+ &uvcg_frame_attr_dw_frame_interval,
NULL,
};
static struct config_item_type uvcg_frame_type = {
- .ct_item_ops = &uvcg_frame_item_ops,
.ct_attrs = uvcg_frame_attrs,
.ct_owner = THIS_MODULE,
};
@@ -1333,22 +1275,15 @@ static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item)
struct uvcg_uncompressed, fmt);
}
-CONFIGFS_ATTR_STRUCT(uvcg_uncompressed);
-CONFIGFS_ATTR_OPS(uvcg_uncompressed);
-
-static struct configfs_item_operations uvcg_uncompressed_item_ops = {
- .show_attribute = uvcg_uncompressed_attr_show,
- .store_attribute = uvcg_uncompressed_attr_store,
-};
-
static struct configfs_group_operations uvcg_uncompressed_group_ops = {
.make_item = uvcg_frame_make,
.drop_item = uvcg_frame_drop,
};
-static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch,
+static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
char *page)
{
+ struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
@@ -1367,9 +1302,10 @@ static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch,
return sizeof(ch->desc.guidFormat);
}
-static ssize_t uvcg_uncompressed_guid_format_store(struct uvcg_uncompressed *ch,
+static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
const char *page, size_t len)
{
+ struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
struct f_uvc_opts *opts;
struct config_item *opts_item;
struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
@@ -1396,16 +1332,13 @@ end:
return ret;
}
-static struct uvcg_uncompressed_attribute uvcg_uncompressed_guid_format =
- __CONFIGFS_ATTR(guidFormat, S_IRUGO | S_IWUSR,
- uvcg_uncompressed_guid_format_show,
- uvcg_uncompressed_guid_format_store);
-
+UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
static ssize_t uvcg_uncompressed_##cname##_show( \
- struct uvcg_uncompressed *u, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1424,14 +1357,13 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
return result; \
} \
\
-static struct uvcg_uncompressed_attribute \
- uvcg_uncompressed_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_uncompressed_##cname##_show)
+UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
#define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
static ssize_t uvcg_uncompressed_##cname##_show( \
- struct uvcg_uncompressed *u, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1451,9 +1383,10 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
} \
\
static ssize_t \
-uvcg_uncompressed_##cname##_store(struct uvcg_uncompressed *u, \
+uvcg_uncompressed_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1487,11 +1420,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_uncompressed_attribute \
- uvcg_uncompressed_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_uncompressed_##cname##_show, \
- uvcg_uncompressed_##cname##_store)
+UVC_ATTR(uvcg_uncompressed_, cname, aname);
#define identity_conv(x) (x)
@@ -1508,36 +1437,34 @@ UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
#undef UVCG_UNCOMPRESSED_ATTR_RO
static inline ssize_t
-uvcg_uncompressed_bma_controls_show(struct uvcg_uncompressed *unc, char *page)
+uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
{
+ struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
return uvcg_format_bma_controls_show(&unc->fmt, page);
}
static inline ssize_t
-uvcg_uncompressed_bma_controls_store(struct uvcg_uncompressed *ch,
+uvcg_uncompressed_bma_controls_store(struct config_item *item,
const char *page, size_t len)
{
- return uvcg_format_bma_controls_store(&ch->fmt, page, len);
+ struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
+ return uvcg_format_bma_controls_store(&unc->fmt, page, len);
}
-static struct uvcg_uncompressed_attribute uvcg_uncompressed_bma_controls =
- __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR,
- uvcg_uncompressed_bma_controls_show,
- uvcg_uncompressed_bma_controls_store);
+UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
- &uvcg_uncompressed_guid_format.attr,
- &uvcg_uncompressed_b_bits_per_pixel.attr,
- &uvcg_uncompressed_b_default_frame_index.attr,
- &uvcg_uncompressed_b_aspect_ratio_x.attr,
- &uvcg_uncompressed_b_aspect_ratio_y.attr,
- &uvcg_uncompressed_bm_interface_flags.attr,
- &uvcg_uncompressed_bma_controls.attr,
+ &uvcg_uncompressed_attr_guid_format,
+ &uvcg_uncompressed_attr_b_bits_per_pixel,
+ &uvcg_uncompressed_attr_b_default_frame_index,
+ &uvcg_uncompressed_attr_b_aspect_ratio_x,
+ &uvcg_uncompressed_attr_b_aspect_ratio_y,
+ &uvcg_uncompressed_attr_bm_interface_flags,
+ &uvcg_uncompressed_attr_bma_controls,
NULL,
};
static struct config_item_type uvcg_uncompressed_type = {
- .ct_item_ops = &uvcg_uncompressed_item_ops,
.ct_group_ops = &uvcg_uncompressed_group_ops,
.ct_attrs = uvcg_uncompressed_attrs,
.ct_owner = THIS_MODULE,
@@ -1605,22 +1532,15 @@ static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
struct uvcg_mjpeg, fmt);
}
-CONFIGFS_ATTR_STRUCT(uvcg_mjpeg);
-CONFIGFS_ATTR_OPS(uvcg_mjpeg);
-
-static struct configfs_item_operations uvcg_mjpeg_item_ops = {
- .show_attribute = uvcg_mjpeg_attr_show,
- .store_attribute = uvcg_mjpeg_attr_store,
-};
-
static struct configfs_group_operations uvcg_mjpeg_group_ops = {
.make_item = uvcg_frame_make,
.drop_item = uvcg_frame_drop,
};
#define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
-static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
+static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
{ \
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1639,13 +1559,12 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
return result; \
} \
\
-static struct uvcg_mjpeg_attribute \
- uvcg_mjpeg_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_mjpeg_##cname##_show)
+UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
#define UVCG_MJPEG_ATTR(cname, aname, conv) \
-static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
+static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
{ \
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1665,9 +1584,10 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
} \
\
static ssize_t \
-uvcg_mjpeg_##cname##_store(struct uvcg_mjpeg *u, \
+uvcg_mjpeg_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
@@ -1701,11 +1621,7 @@ end: \
return ret; \
} \
\
-static struct uvcg_mjpeg_attribute \
- uvcg_mjpeg_##cname = \
- __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
- uvcg_mjpeg_##cname##_show, \
- uvcg_mjpeg_##cname##_store)
+UVC_ATTR(uvcg_mjpeg_, cname, aname)
#define identity_conv(x) (x)
@@ -1722,35 +1638,33 @@ UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
#undef UVCG_MJPEG_ATTR_RO
static inline ssize_t
-uvcg_mjpeg_bma_controls_show(struct uvcg_mjpeg *unc, char *page)
+uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
{
- return uvcg_format_bma_controls_show(&unc->fmt, page);
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
+ return uvcg_format_bma_controls_show(&u->fmt, page);
}
static inline ssize_t
-uvcg_mjpeg_bma_controls_store(struct uvcg_mjpeg *ch,
+uvcg_mjpeg_bma_controls_store(struct config_item *item,
const char *page, size_t len)
{
- return uvcg_format_bma_controls_store(&ch->fmt, page, len);
+ struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
+ return uvcg_format_bma_controls_store(&u->fmt, page, len);
}
-static struct uvcg_mjpeg_attribute uvcg_mjpeg_bma_controls =
- __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR,
- uvcg_mjpeg_bma_controls_show,
- uvcg_mjpeg_bma_controls_store);
+UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
- &uvcg_mjpeg_b_default_frame_index.attr,
- &uvcg_mjpeg_bm_flags.attr,
- &uvcg_mjpeg_b_aspect_ratio_x.attr,
- &uvcg_mjpeg_b_aspect_ratio_y.attr,
- &uvcg_mjpeg_bm_interface_flags.attr,
- &uvcg_mjpeg_bma_controls.attr,
+ &uvcg_mjpeg_attr_b_default_frame_index,
+ &uvcg_mjpeg_attr_bm_flags,
+ &uvcg_mjpeg_attr_b_aspect_ratio_x,
+ &uvcg_mjpeg_attr_b_aspect_ratio_y,
+ &uvcg_mjpeg_attr_bm_interface_flags,
+ &uvcg_mjpeg_attr_bma_controls,
NULL,
};
static struct config_item_type uvcg_mjpeg_type = {
- .ct_item_ops = &uvcg_mjpeg_item_ops,
.ct_group_ops = &uvcg_mjpeg_group_ops,
.ct_attrs = uvcg_mjpeg_attrs,
.ct_owner = THIS_MODULE,
@@ -1811,17 +1725,12 @@ static inline struct uvcg_default_color_matching
struct uvcg_default_color_matching, group);
}
-CONFIGFS_ATTR_STRUCT(uvcg_default_color_matching);
-CONFIGFS_ATTR_OPS_RO(uvcg_default_color_matching);
-
-static struct configfs_item_operations uvcg_default_color_matching_item_ops = {
- .show_attribute = uvcg_default_color_matching_attr_show,
-};
-
#define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
static ssize_t uvcg_default_color_matching_##cname##_show( \
- struct uvcg_default_color_matching *dc, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct uvcg_default_color_matching *dc = \
+ to_uvcg_default_color_matching(item); \
struct f_uvc_opts *opts; \
struct config_item *opts_item; \
struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
@@ -1842,9 +1751,7 @@ static ssize_t uvcg_default_color_matching_##cname##_show( \
return result; \
} \
\
-static struct uvcg_default_color_matching_attribute \
- uvcg_default_color_matching_##cname = \
- __CONFIGFS_ATTR_RO(aname, uvcg_default_color_matching_##cname##_show)
+UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
#define identity_conv(x) (x)
@@ -1860,14 +1767,13 @@ UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients,
#undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
- &uvcg_default_color_matching_b_color_primaries.attr,
- &uvcg_default_color_matching_b_transfer_characteristics.attr,
- &uvcg_default_color_matching_b_matrix_coefficients.attr,
+ &uvcg_default_color_matching_attr_b_color_primaries,
+ &uvcg_default_color_matching_attr_b_transfer_characteristics,
+ &uvcg_default_color_matching_attr_b_matrix_coefficients,
NULL,
};
static struct config_item_type uvcg_default_color_matching_type = {
- .ct_item_ops = &uvcg_default_color_matching_item_ops,
.ct_attrs = uvcg_default_color_matching_attrs,
.ct_owner = THIS_MODULE,
};
@@ -2285,9 +2191,6 @@ static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
func_inst.group);
}
-CONFIGFS_ATTR_STRUCT(f_uvc_opts);
-CONFIGFS_ATTR_OPS(f_uvc_opts);
-
static void uvc_attr_release(struct config_item *item)
{
struct f_uvc_opts *opts = to_f_uvc_opts(item);
@@ -2297,14 +2200,13 @@ static void uvc_attr_release(struct config_item *item)
static struct configfs_item_operations uvc_item_ops = {
.release = uvc_attr_release,
- .show_attribute = f_uvc_opts_attr_show,
- .store_attribute = f_uvc_opts_attr_store,
};
#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \
static ssize_t f_uvc_opts_##cname##_show( \
- struct f_uvc_opts *opts, char *page) \
+ struct config_item *item, char *page) \
{ \
+ struct f_uvc_opts *opts = to_f_uvc_opts(item); \
int result; \
\
mutex_lock(&opts->lock); \
@@ -2315,9 +2217,10 @@ static ssize_t f_uvc_opts_##cname##_show( \
} \
\
static ssize_t \
-f_uvc_opts_##cname##_store(struct f_uvc_opts *opts, \
+f_uvc_opts_##cname##_store(struct config_item *item, \
const char *page, size_t len) \
{ \
+ struct f_uvc_opts *opts = to_f_uvc_opts(item); \
int ret; \
uxx num; \
\
@@ -2342,11 +2245,7 @@ end: \
return ret; \
} \
\
-static struct f_uvc_opts_attribute \
- f_uvc_opts_attribute_##cname = \
- __CONFIGFS_ATTR(cname, S_IRUGO | S_IWUSR, \
- f_uvc_opts_##cname##_show, \
- f_uvc_opts_##cname##_store)
+UVC_ATTR(f_uvc_opts_, cname, aname)
#define identity_conv(x) (x)
@@ -2362,9 +2261,9 @@ UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv,
#undef UVCG_OPTS_ATTR
static struct configfs_attribute *uvc_attrs[] = {
- &f_uvc_opts_attribute_streaming_interval.attr,
- &f_uvc_opts_attribute_streaming_maxpacket.attr,
- &f_uvc_opts_attribute_streaming_maxburst.attr,
+ &f_uvc_opts_attr_streaming_interval,
+ &f_uvc_opts_attr_streaming_maxpacket,
+ &f_uvc_opts_attr_streaming_maxburst,
NULL,
};
diff --git a/kernel/drivers/usb/gadget/function/uvc_queue.c b/kernel/drivers/usb/gadget/function/uvc_queue.c
index d617c39a0..51d4a1703 100644
--- a/kernel/drivers/usb/gadget/function/uvc_queue.c
+++ b/kernel/drivers/usb/gadget/function/uvc_queue.c
@@ -41,7 +41,7 @@
* videobuf2 queue operations
*/
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
@@ -61,9 +61,10 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
- if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
return -EINVAL;
@@ -75,7 +76,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
buf->state = UVC_BUF_STATE_QUEUED;
buf->mem = vb2_plane_vaddr(vb, 0);
buf->length = vb2_plane_size(vb, 0);
- if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
else
buf->bytesused = vb2_get_plane_payload(vb, 0);
@@ -86,7 +87,8 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
static void uvc_buffer_queue(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
@@ -98,7 +100,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
* directly. The next QBUF call will fail with -ENODEV.
*/
buf->state = UVC_BUF_STATE_ERROR;
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -242,7 +244,7 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
@@ -314,7 +316,7 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->length != buf->bytesused) {
buf->state = UVC_BUF_STATE_QUEUED;
- vb2_set_plane_payload(&buf->buf, 0, 0);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
return buf;
}
@@ -325,12 +327,12 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
else
nextbuf = NULL;
- buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
- buf->buf.v4l2_buf.sequence = queue->sequence++;
- v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
+ buf->buf.field = V4L2_FIELD_NONE;
+ buf->buf.sequence = queue->sequence++;
+ v4l2_get_timestamp(&buf->buf.timestamp);
- vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
- vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+ vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
+ vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
return nextbuf;
}
diff --git a/kernel/drivers/usb/gadget/function/uvc_queue.h b/kernel/drivers/usb/gadget/function/uvc_queue.h
index 01ca9eab3..ac461a9a1 100644
--- a/kernel/drivers/usb/gadget/function/uvc_queue.h
+++ b/kernel/drivers/usb/gadget/function/uvc_queue.h
@@ -6,7 +6,7 @@
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/videodev2.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
/* Maximum frame size in bytes, for sanity checking. */
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
@@ -26,7 +26,7 @@ enum uvc_buffer_state {
};
struct uvc_buffer {
- struct vb2_buffer buf;
+ struct vb2_v4l2_buffer buf;
struct list_head queue;
enum uvc_buffer_state state;
diff --git a/kernel/drivers/usb/gadget/legacy/Kconfig b/kernel/drivers/usb/gadget/legacy/Kconfig
index d5a7102de..4d682ad7b 100644
--- a/kernel/drivers/usb/gadget/legacy/Kconfig
+++ b/kernel/drivers/usb/gadget/legacy/Kconfig
@@ -339,6 +339,7 @@ config USB_CDC_COMPOSITE
config USB_G_NOKIA
tristate "Nokia composite gadget"
depends on PHONET
+ depends on BLOCK
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
@@ -346,6 +347,7 @@ config USB_G_NOKIA
select USB_F_OBEX
select USB_F_PHONET
select USB_F_ECM
+ select USB_F_MASS_STORAGE
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
diff --git a/kernel/drivers/usb/gadget/legacy/acm_ms.c b/kernel/drivers/usb/gadget/legacy/acm_ms.c
index 1194b09ae..4b158e2d1 100644
--- a/kernel/drivers/usb/gadget/legacy/acm_ms.c
+++ b/kernel/drivers/usb/gadget/legacy/acm_ms.c
@@ -58,21 +58,7 @@ static struct usb_device_descriptor device_desc = {
/*.bNumConfigurations = DYNAMIC*/
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -200,10 +186,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
- status = fsg_common_set_nluns(opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@@ -225,10 +207,21 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
if (status < 0)
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -236,11 +229,12 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
return 0;
/* error recovery */
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
- fsg_common_free_luns(opts->common);
-fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@@ -255,6 +249,9 @@ static int acm_ms_unbind(struct usb_composite_dev *cdev)
usb_put_function_instance(fi_msg);
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/audio.c b/kernel/drivers/usb/gadget/legacy/audio.c
index f289caf18..685cf3b4b 100644
--- a/kernel/drivers/usb/gadget/legacy/audio.c
+++ b/kernel/drivers/usb/gadget/legacy/audio.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/usb/composite.h>
-#include "gadget_chips.h"
#define DRIVER_DESC "Linux USB Audio Gadget"
#define DRIVER_VERSION "Feb 2, 2012"
@@ -124,7 +123,7 @@ static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x200),
+ .bcdUSB = cpu_to_le16(0x200),
#ifdef CONFIG_GADGET_UAC1
.bDeviceClass = USB_CLASS_PER_INTERFACE,
@@ -141,8 +140,8 @@ static struct usb_device_descriptor device_desc = {
* we support. (As does bNumConfigurations.) These values can
* also be overridden by module parameters.
*/
- .idVendor = __constant_cpu_to_le16(AUDIO_VENDOR_NUM),
- .idProduct = __constant_cpu_to_le16(AUDIO_PRODUCT_NUM),
+ .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM),
+ .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@@ -150,20 +149,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -259,14 +245,28 @@ static int audio_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto fail;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
if (status < 0)
- goto fail;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION);
return 0;
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
#ifndef CONFIG_GADGET_UAC1
usb_put_function_instance(fi_uac2);
@@ -289,6 +289,9 @@ static int audio_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(fi_uac2))
usb_put_function_instance(fi_uac2);
#endif
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/cdc2.c b/kernel/drivers/usb/gadget/legacy/cdc2.c
index afd3e3792..ecd8c8d62 100644
--- a/kernel/drivers/usb/gadget/legacy/cdc2.c
+++ b/kernel/drivers/usb/gadget/legacy/cdc2.c
@@ -60,21 +60,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -193,10 +179,21 @@ static int cdc_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail1;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -204,6 +201,9 @@ static int cdc_bind(struct usb_composite_dev *cdev)
return 0;
+fail2:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail1:
usb_put_function_instance(fi_serial);
fail:
@@ -219,6 +219,9 @@ static int cdc_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ecm);
if (!IS_ERR_OR_NULL(fi_ecm))
usb_put_function_instance(fi_ecm);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/dbgp.c b/kernel/drivers/usb/gadget/legacy/dbgp.c
index 204b10b1a..99ca3dabc 100644
--- a/kernel/drivers/usb/gadget/legacy/dbgp.c
+++ b/kernel/drivers/usb/gadget/legacy/dbgp.c
@@ -35,10 +35,10 @@ static struct dbgp {
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
- .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
+ .idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
+ .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
.bNumConfigurations = 1,
};
@@ -79,10 +79,7 @@ static int dbgp_consume(char *buf, unsigned len)
static void __disable_ep(struct usb_ep *ep)
{
- if (ep && ep->driver_data == dbgp.gadget) {
- usb_ep_disable(ep);
- ep->driver_data = NULL;
- }
+ usb_ep_disable(ep);
}
static void dbgp_disable_ep(void)
@@ -171,7 +168,6 @@ static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
int err;
ep->desc = desc;
err = usb_ep_enable(ep);
- ep->driver_data = dbgp.gadget;
return err;
}
@@ -229,8 +225,6 @@ static void dbgp_unbind(struct usb_gadget *gadget)
usb_ep_free_request(gadget->ep0, dbgp.req);
dbgp.req = NULL;
}
-
- gadget->ep0->driver_data = NULL;
}
#ifdef CONFIG_USB_G_DBGP_SERIAL
@@ -249,20 +243,17 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
goto fail_1;
}
- dbgp.i_ep->driver_data = gadget;
i_desc.wMaxPacketSize =
- __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+ cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
if (!dbgp.o_ep) {
- dbgp.i_ep->driver_data = NULL;
stp = 2;
- goto fail_2;
+ goto fail_1;
}
- dbgp.o_ep->driver_data = gadget;
o_desc.wMaxPacketSize =
- __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+ cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
@@ -277,8 +268,6 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
return 0;
-fail_2:
- dbgp.i_ep->driver_data = NULL;
fail_1:
dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp);
return -ENODEV;
@@ -306,7 +295,6 @@ static int dbgp_bind(struct usb_gadget *gadget,
}
dbgp.req->length = DBGP_REQ_EP0_LEN;
- gadget->ep0->driver_data = gadget;
#ifdef CONFIG_USB_G_DBGP_SERIAL
dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
@@ -356,8 +344,6 @@ static int dbgp_setup(struct usb_gadget *gadget,
void *data = NULL;
u16 len = 0;
- gadget->ep0->driver_data = gadget;
-
if (request == USB_REQ_GET_DESCRIPTOR) {
switch (value>>8) {
case USB_DT_DEVICE:
diff --git a/kernel/drivers/usb/gadget/legacy/ether.c b/kernel/drivers/usb/gadget/legacy/ether.c
index a3323dca2..31e916022 100644
--- a/kernel/drivers/usb/gadget/legacy/ether.c
+++ b/kernel/drivers/usb/gadget/legacy/ether.c
@@ -171,20 +171,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -416,17 +403,28 @@ static int eth_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail1;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration(s); RNDIS first, if it's used */
if (has_rndis()) {
status = usb_add_config(cdev, &rndis_config_driver,
rndis_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
}
status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -434,6 +432,9 @@ static int eth_bind(struct usb_composite_dev *cdev)
return 0;
+fail2:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail1:
if (has_rndis())
usb_put_function_instance(fi_rndis);
@@ -463,6 +464,9 @@ static int eth_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_geth);
usb_put_function_instance(fi_geth);
}
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/g_ffs.c b/kernel/drivers/usb/gadget/legacy/g_ffs.c
index e821931c9..320a81b2b 100644
--- a/kernel/drivers/usb/gadget/legacy/g_ffs.c
+++ b/kernel/drivers/usb/gadget/legacy/g_ffs.c
@@ -88,21 +88,7 @@ MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
module_param_array_named(functions, func_names, charp, &func_num, 0);
MODULE_PARM_DESC(functions, "USB Functions list");
-static const struct usb_descriptor_header *gfs_otg_desc[] = {
- (const struct usb_descriptor_header *)
- &(const struct usb_otg_descriptor) {
- .bLength = sizeof(struct usb_otg_descriptor),
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
- },
-
- NULL
-};
+static const struct usb_descriptor_header *gfs_otg_desc[2];
/* String IDs are assigned dynamically */
static struct usb_string gfs_strings[] = {
@@ -412,6 +398,17 @@ static int gfs_bind(struct usb_composite_dev *cdev)
goto error_rndis;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto error_rndis;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ gfs_otg_desc[0] = usb_desc;
+ gfs_otg_desc[1] = NULL;
+ }
+
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
@@ -432,6 +429,8 @@ static int gfs_bind(struct usb_composite_dev *cdev)
/* TODO */
error_unbind:
+ kfree(gfs_otg_desc[0]);
+ gfs_otg_desc[0] = NULL;
error_rndis:
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
usb_put_function_instance(fi_rndis);
@@ -473,6 +472,9 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
for (i = 0; i < N_CONF * func_num; ++i)
usb_put_function(*(f_ffs[0] + i));
+ kfree(gfs_otg_desc[0]);
+ gfs_otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/gmidi.c b/kernel/drivers/usb/gadget/legacy/gmidi.c
index da19c486b..8a18348ae 100644
--- a/kernel/drivers/usb/gadget/legacy/gmidi.c
+++ b/kernel/drivers/usb/gadget/legacy/gmidi.c
@@ -35,8 +35,6 @@
#include <linux/usb/audio.h>
#include <linux/usb/midi.h>
-#include "gadget_chips.h"
-
#include "u_midi.h"
/*-------------------------------------------------------------------------*/
@@ -88,10 +86,10 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
- .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
- .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+ .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
+ .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
.bNumConfigurations = 1,
diff --git a/kernel/drivers/usb/gadget/legacy/hid.c b/kernel/drivers/usb/gadget/legacy/hid.c
index 2baa57268..7e5d2c484 100644
--- a/kernel/drivers/usb/gadget/legacy/hid.c
+++ b/kernel/drivers/usb/gadget/legacy/hid.c
@@ -19,7 +19,6 @@
#include <linux/usb/composite.h>
#include <linux/usb/g_hid.h>
-#include "gadget_chips.h"
#define DRIVER_DESC "HID Gadget"
#define DRIVER_VERSION "2010/03/16"
@@ -68,21 +67,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -186,16 +171,30 @@ static int hid_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto put;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &config_driver, do_config);
if (status < 0)
- goto put;
+ goto free_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
return 0;
+free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
put:
list_for_each_entry(m, &hidg_func_list, node) {
if (m == n)
@@ -213,6 +212,10 @@ static int hid_unbind(struct usb_composite_dev *cdev)
usb_put_function(n->f);
usb_put_function_instance(n->fi);
}
+
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/inode.c b/kernel/drivers/usb/gadget/legacy/inode.c
index 7b6da0fde..b20a60343 100644
--- a/kernel/drivers/usb/gadget/legacy/inode.c
+++ b/kernel/drivers/usb/gadget/legacy/inode.c
@@ -769,9 +769,12 @@ ep_config (struct ep_data *data, const char *buf, size_t len)
if (data->dev->state == STATE_DEV_UNBOUND) {
value = -ENOENT;
goto gone;
- } else if ((ep = data->ep) == NULL) {
- value = -ENODEV;
- goto gone;
+ } else {
+ ep = data->ep;
+ if (ep == NULL) {
+ value = -ENODEV;
+ goto gone;
+ }
}
switch (data->dev->gadget->speed) {
case USB_SPEED_LOW:
diff --git a/kernel/drivers/usb/gadget/legacy/mass_storage.c b/kernel/drivers/usb/gadget/legacy/mass_storage.c
index e7bfb081f..bda3c5191 100644
--- a/kernel/drivers/usb/gadget/legacy/mass_storage.c
+++ b/kernel/drivers/usb/gadget/legacy/mass_storage.c
@@ -64,21 +64,7 @@ static struct usb_device_descriptor msg_device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -191,10 +177,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
- status = fsg_common_set_nluns(opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
fsg_common_set_ops(opts->common, &ops);
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
@@ -214,9 +196,20 @@ static int msg_bind(struct usb_composite_dev *cdev)
goto fail_string_ids;
msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
if (status < 0)
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&cdev->gadget->dev,
@@ -224,11 +217,12 @@ static int msg_bind(struct usb_composite_dev *cdev)
set_bit(0, &msg_registered);
return 0;
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
- fsg_common_free_luns(opts->common);
-fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@@ -243,6 +237,9 @@ static int msg_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR(fi_msg))
usb_put_function_instance(fi_msg);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/multi.c b/kernel/drivers/usb/gadget/legacy/multi.c
index b21b51f0c..4fe794ddc 100644
--- a/kernel/drivers/usb/gadget/legacy/multi.c
+++ b/kernel/drivers/usb/gadget/legacy/multi.c
@@ -78,21 +78,7 @@ static struct usb_device_descriptor device_desc = {
.idProduct = cpu_to_le16(MULTI_PRODUCT_NUM),
};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &(struct usb_otg_descriptor){
- .bLength = sizeof(struct usb_otg_descriptor),
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
- },
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
enum {
MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
@@ -407,10 +393,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
if (status)
goto fail2;
- status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@@ -429,14 +411,25 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
goto fail_string_ids;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register configurations */
status = rndis_config_register(cdev);
if (unlikely(status < 0))
- goto fail_string_ids;
+ goto fail_otg_desc;
status = cdc_config_register(cdev);
if (unlikely(status < 0))
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
/* we're done */
@@ -445,11 +438,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
/* error recovery */
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(fsg_opts->common);
fail_set_cdev:
- fsg_common_free_luns(fsg_opts->common);
-fail_set_nluns:
fsg_common_free_buffers(fsg_opts->common);
fail2:
usb_put_function_instance(fi_msg);
@@ -490,6 +484,9 @@ static int multi_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ecm);
usb_put_function_instance(fi_ecm);
#endif
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/ncm.c b/kernel/drivers/usb/gadget/legacy/ncm.c
index 6ce742141..2bae43813 100644
--- a/kernel/drivers/usb/gadget/legacy/ncm.c
+++ b/kernel/drivers/usb/gadget/legacy/ncm.c
@@ -69,20 +69,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -171,16 +158,30 @@ static int gncm_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &ncm_config_driver,
ncm_do_config);
if (status < 0)
- goto fail;
+ goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
return 0;
+fail1:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
usb_put_function_instance(f_ncm_inst);
return status;
@@ -192,6 +193,9 @@ static int gncm_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ncm);
if (!IS_ERR_OR_NULL(f_ncm_inst))
usb_put_function_instance(f_ncm_inst);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/nokia.c b/kernel/drivers/usb/gadget/legacy/nokia.c
index 4bb498a38..8b3f6fb18 100644
--- a/kernel/drivers/usb/gadget/legacy/nokia.c
+++ b/kernel/drivers/usb/gadget/legacy/nokia.c
@@ -23,7 +23,7 @@
#include "u_ether.h"
#include "u_phonet.h"
#include "u_ecm.h"
-#include "gadget_chips.h"
+#include "f_mass_storage.h"
/* Defines */
@@ -34,6 +34,29 @@ USB_GADGET_COMPOSITE_OPTIONS();
USB_ETHERNET_MODULE_PARAMETERS();
+static struct fsg_module_parameters fsg_mod_data = {
+ .stall = 0,
+ .luns = 2,
+ .removable_count = 2,
+ .removable = { 1, 1, },
+};
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
+FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
+
#define NOKIA_VENDOR_ID 0x0421 /* Nokia */
#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */
@@ -66,10 +89,10 @@ static struct usb_gadget_strings *dev_strings[] = {
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_COMM,
- .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
+ .idVendor = cpu_to_le16(NOKIA_VENDOR_ID),
+ .idProduct = cpu_to_le16(NOKIA_PRODUCT_ID),
.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@@ -94,6 +117,8 @@ static struct usb_function *f_obex1_cfg2;
static struct usb_function *f_obex2_cfg2;
static struct usb_function *f_phonet_cfg1;
static struct usb_function *f_phonet_cfg2;
+static struct usb_function *f_msg_cfg1;
+static struct usb_function *f_msg_cfg2;
static struct usb_configuration nokia_config_500ma_driver = {
@@ -117,6 +142,7 @@ static struct usb_function_instance *fi_ecm;
static struct usb_function_instance *fi_obex1;
static struct usb_function_instance *fi_obex2;
static struct usb_function_instance *fi_phonet;
+static struct usb_function_instance *fi_msg;
static int nokia_bind_config(struct usb_configuration *c)
{
@@ -125,6 +151,8 @@ static int nokia_bind_config(struct usb_configuration *c)
struct usb_function *f_obex1 = NULL;
struct usb_function *f_ecm;
struct usb_function *f_obex2 = NULL;
+ struct usb_function *f_msg;
+ struct fsg_opts *fsg_opts;
int status = 0;
int obex1_stat = -1;
int obex2_stat = -1;
@@ -160,6 +188,12 @@ static int nokia_bind_config(struct usb_configuration *c)
goto err_get_ecm;
}
+ f_msg = usb_get_function(fi_msg);
+ if (IS_ERR(f_msg)) {
+ status = PTR_ERR(f_msg);
+ goto err_get_msg;
+ }
+
if (!IS_ERR_OR_NULL(f_phonet)) {
phonet_stat = usb_add_function(c, f_phonet);
if (phonet_stat)
@@ -187,21 +221,36 @@ static int nokia_bind_config(struct usb_configuration *c)
pr_debug("could not bind ecm config %d\n", status);
goto err_ecm;
}
+
+ fsg_opts = fsg_opts_from_func_inst(fi_msg);
+
+ status = fsg_common_run_thread(fsg_opts->common);
+ if (status)
+ goto err_msg;
+
+ status = usb_add_function(c, f_msg);
+ if (status)
+ goto err_msg;
+
if (c == &nokia_config_500ma_driver) {
f_acm_cfg1 = f_acm;
f_ecm_cfg1 = f_ecm;
f_phonet_cfg1 = f_phonet;
f_obex1_cfg1 = f_obex1;
f_obex2_cfg1 = f_obex2;
+ f_msg_cfg1 = f_msg;
} else {
f_acm_cfg2 = f_acm;
f_ecm_cfg2 = f_ecm;
f_phonet_cfg2 = f_phonet;
f_obex1_cfg2 = f_obex1;
f_obex2_cfg2 = f_obex2;
+ f_msg_cfg2 = f_msg;
}
return status;
+err_msg:
+ usb_remove_function(c, f_ecm);
err_ecm:
usb_remove_function(c, f_acm);
err_conf:
@@ -211,6 +260,8 @@ err_conf:
usb_remove_function(c, f_obex1);
if (!phonet_stat)
usb_remove_function(c, f_phonet);
+ usb_put_function(f_msg);
+err_get_msg:
usb_put_function(f_ecm);
err_get_ecm:
usb_put_function(f_acm);
@@ -227,6 +278,8 @@ err_get_acm:
static int nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
+ struct fsg_opts *fsg_opts;
+ struct fsg_config fsg_config;
int status;
status = usb_string_ids_tab(cdev, strings_dev);
@@ -238,7 +291,7 @@ static int nokia_bind(struct usb_composite_dev *cdev)
nokia_config_500ma_driver.iConfiguration = status;
nokia_config_100ma_driver.iConfiguration = status;
- if (!gadget_supports_altsettings(gadget)) {
+ if (!gadget_is_altset_supported(gadget)) {
status = -ENODEV;
goto err_usb;
}
@@ -267,11 +320,42 @@ static int nokia_bind(struct usb_composite_dev *cdev)
goto err_acm_inst;
}
+ fi_msg = usb_get_function_instance("mass_storage");
+ if (IS_ERR(fi_msg)) {
+ status = PTR_ERR(fi_msg);
+ goto err_ecm_inst;
+ }
+
+ /* set up mass storage function */
+ fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers);
+ fsg_config.vendor_name = "Nokia";
+ fsg_config.product_name = "N900";
+
+ fsg_opts = fsg_opts_from_func_inst(fi_msg);
+ fsg_opts->no_configfs = true;
+
+ status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
+ if (status)
+ goto err_msg_inst;
+
+ status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall);
+ if (status)
+ goto err_msg_buf;
+
+ fsg_common_set_sysfs(fsg_opts->common, true);
+
+ status = fsg_common_create_luns(fsg_opts->common, &fsg_config);
+ if (status)
+ goto err_msg_buf;
+
+ fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name,
+ fsg_config.product_name);
+
/* finally register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
- goto err_ecm_inst;
+ goto err_msg_luns;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
@@ -292,6 +376,12 @@ err_put_cfg1:
if (!IS_ERR_OR_NULL(f_phonet_cfg1))
usb_put_function(f_phonet_cfg1);
usb_put_function(f_ecm_cfg1);
+err_msg_luns:
+ fsg_common_remove_luns(fsg_opts->common);
+err_msg_buf:
+ fsg_common_free_buffers(fsg_opts->common);
+err_msg_inst:
+ usb_put_function_instance(fi_msg);
err_ecm_inst:
usb_put_function_instance(fi_ecm);
err_acm_inst:
@@ -325,7 +415,10 @@ static int nokia_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_acm_cfg2);
usb_put_function(f_ecm_cfg1);
usb_put_function(f_ecm_cfg2);
+ usb_put_function(f_msg_cfg1);
+ usb_put_function(f_msg_cfg2);
+ usb_put_function_instance(fi_msg);
usb_put_function_instance(fi_ecm);
if (!IS_ERR(fi_obex2))
usb_put_function_instance(fi_obex2);
diff --git a/kernel/drivers/usb/gadget/legacy/printer.c b/kernel/drivers/usb/gadget/legacy/printer.c
index 1ce7df106..a22d30a4d 100644
--- a/kernel/drivers/usb/gadget/legacy/printer.c
+++ b/kernel/drivers/usb/gadget/legacy/printer.c
@@ -19,8 +19,6 @@
#include <linux/usb/gadget.h>
#include <linux/usb/g_printer.h>
-#include "gadget_chips.h"
-
USB_GADGET_COMPOSITE_OPTIONS();
#define DRIVER_DESC "Printer Gadget"
@@ -82,16 +80,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -136,7 +125,6 @@ static int printer_do_config(struct usb_configuration *c)
usb_gadget_set_selfpowered(gadget);
if (gadget_is_otg(gadget)) {
- otg_descriptor.bmAttributes |= USB_OTG_HNP;
printer_cfg_driver.descriptors = otg_desc;
printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@@ -174,21 +162,39 @@ static int printer_bind(struct usb_composite_dev *cdev)
opts->q_len = QLEN;
ret = usb_string_ids_tab(cdev, strings);
- if (ret < 0) {
- usb_put_function_instance(fi_printer);
- return ret;
- }
+ if (ret < 0)
+ goto fail_put_func_inst;
+
device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
- ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
- if (ret) {
- usb_put_function_instance(fi_printer);
- return ret;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ ret = -ENOMEM;
+ goto fail_put_func_inst;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
}
+
+ ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
+ if (ret)
+ goto fail_free_otg_desc;
+
usb_composite_overwrite_options(cdev, &coverwrite);
return ret;
+
+fail_free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+fail_put_func_inst:
+ usb_put_function_instance(fi_printer);
+ return ret;
}
static int printer_unbind(struct usb_composite_dev *cdev)
@@ -196,6 +202,9 @@ static int printer_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_printer);
usb_put_function_instance(fi_printer);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/serial.c b/kernel/drivers/usb/gadget/legacy/serial.c
index 8b7528f9b..c5d42e034 100644
--- a/kernel/drivers/usb/gadget/legacy/serial.c
+++ b/kernel/drivers/usb/gadget/legacy/serial.c
@@ -17,7 +17,6 @@
#include <linux/tty_flip.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/* Defines */
@@ -79,20 +78,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -191,6 +177,18 @@ static int gs_bind(struct usb_composite_dev *cdev)
serial_config_driver.iConfiguration = status;
if (gadget_is_otg(cdev->gadget)) {
+ if (!otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ status = -ENOMEM;
+ goto fail;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
serial_config_driver.descriptors = otg_desc;
serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@@ -208,13 +206,15 @@ static int gs_bind(struct usb_composite_dev *cdev)
"gser");
}
if (status < 0)
- goto fail;
+ goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s\n", GS_VERSION_NAME);
return 0;
-
+fail1:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
return status;
}
@@ -227,6 +227,10 @@ static int gs_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
}
+
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.c b/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.c
index f9b4882fc..22e56158d 100644
--- a/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.c
+++ b/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.c
@@ -16,21 +16,15 @@
#include <linux/usb/composite.h>
#include <linux/usb/gadget.h>
#include <linux/usb/storage.h>
-#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
-#include <target/target_core_fabric_configfs.h>
-#include <target/target_core_configfs.h>
-#include <target/configfs_macros.h>
#include <asm/unaligned.h>
#include "tcm_usb_gadget.h"
USB_GADGET_COMPOSITE_OPTIONS();
-static const struct target_core_fabric_ops usbg_ops;
-
static inline struct f_uas *to_f_uas(struct usb_function *f)
{
return container_of(f, struct f_uas, function);
@@ -1112,6 +1106,7 @@ static int usbg_submit_command(struct f_uas *fu,
memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
cmd->tag = be16_to_cpup(&cmd_iu->tag);
+ cmd->se_cmd.tag = cmd->tag;
if (fu->flags & USBG_USE_STREAMS) {
if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
goto err;
@@ -1245,6 +1240,7 @@ static int bot_submit_command(struct f_uas *fu,
cmd->unpacked_lun = cbw->Lun;
cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
cmd->data_len = le32_to_cpu(cbw->DataTransferLength);
+ cmd->se_cmd.tag = le32_to_cpu(cmd->bot_tag);
INIT_WORK(&cmd->work, bot_cmd_work);
ret = queue_work(tpg->workqueue, &cmd->work);
@@ -1274,23 +1270,6 @@ static char *usbg_get_fabric_name(void)
return "usb_gadget";
}
-static u8 usbg_get_fabric_proto_ident(struct se_portal_group *se_tpg)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- u8 proto_id;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- proto_id = sas_get_fabric_proto_ident(se_tpg);
- break;
- }
-
- return proto_id;
-}
-
static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg)
{
struct usbg_tpg *tpg = container_of(se_tpg,
@@ -1307,97 +1286,6 @@ static u16 usbg_get_tag(struct se_portal_group *se_tpg)
return tpg->tport_tpgt;
}
-static u32 usbg_get_default_depth(struct se_portal_group *se_tpg)
-{
- return 1;
-}
-
-static u32 usbg_get_pr_transport_id(
- struct se_portal_group *se_tpg,
- struct se_node_acl *se_nacl,
- struct t10_pr_registration *pr_reg,
- int *format_code,
- unsigned char *buf)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- int ret = 0;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- ret = sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg,
- format_code, buf);
- break;
- }
-
- return ret;
-}
-
-static u32 usbg_get_pr_transport_id_len(
- struct se_portal_group *se_tpg,
- struct se_node_acl *se_nacl,
- struct t10_pr_registration *pr_reg,
- int *format_code)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- int ret = 0;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- ret = sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg,
- format_code);
- break;
- }
-
- return ret;
-}
-
-static char *usbg_parse_pr_out_transport_id(
- struct se_portal_group *se_tpg,
- const char *buf,
- u32 *out_tid_len,
- char **port_nexus_ptr)
-{
- struct usbg_tpg *tpg = container_of(se_tpg,
- struct usbg_tpg, se_tpg);
- struct usbg_tport *tport = tpg->tport;
- char *tid = NULL;
-
- switch (tport->tport_proto_id) {
- case SCSI_PROTOCOL_SAS:
- default:
- tid = sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len,
- port_nexus_ptr);
- }
-
- return tid;
-}
-
-static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
-{
- struct usbg_nacl *nacl;
-
- nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
- if (!nacl)
- return NULL;
-
- return &nacl->se_node_acl;
-}
-
-static void usbg_release_fabric_acl(
- struct se_portal_group *se_tpg,
- struct se_node_acl *se_nacl)
-{
- struct usbg_nacl *nacl = container_of(se_nacl,
- struct usbg_nacl, se_node_acl);
- kfree(nacl);
-}
-
static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
{
return 1;
@@ -1448,18 +1336,6 @@ static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
return;
}
-static u32 usbg_get_task_tag(struct se_cmd *se_cmd)
-{
- struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
- se_cmd);
- struct f_uas *fu = cmd->fu;
-
- if (fu->flags & USBG_IS_BOT)
- return le32_to_cpu(cmd->bot_tag);
- else
- return cmd->tag;
-}
-
static int usbg_get_cmd_state(struct se_cmd *se_cmd)
{
return 0;
@@ -1489,50 +1365,11 @@ static const char *usbg_check_wwn(const char *name)
return n;
}
-static struct se_node_acl *usbg_make_nodeacl(
- struct se_portal_group *se_tpg,
- struct config_group *group,
- const char *name)
-{
- struct se_node_acl *se_nacl, *se_nacl_new;
- struct usbg_nacl *nacl;
- u64 wwpn = 0;
- u32 nexus_depth;
- const char *wnn_name;
-
- wnn_name = usbg_check_wwn(name);
- if (!wnn_name)
- return ERR_PTR(-EINVAL);
- se_nacl_new = usbg_alloc_fabric_acl(se_tpg);
- if (!(se_nacl_new))
- return ERR_PTR(-ENOMEM);
-
- nexus_depth = 1;
- /*
- * se_nacl_new may be released by core_tpg_add_initiator_node_acl()
- * when converting a NodeACL from demo mode -> explict
- */
- se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new,
- name, nexus_depth);
- if (IS_ERR(se_nacl)) {
- usbg_release_fabric_acl(se_tpg, se_nacl_new);
- return se_nacl;
- }
- /*
- * Locate our struct usbg_nacl and set the FC Nport WWPN
- */
- nacl = container_of(se_nacl, struct usbg_nacl, se_node_acl);
- nacl->iport_wwpn = wwpn;
- snprintf(nacl->iport_name, sizeof(nacl->iport_name), "%s", name);
- return se_nacl;
-}
-
-static void usbg_drop_nodeacl(struct se_node_acl *se_acl)
+static int usbg_init_nodeacl(struct se_node_acl *se_nacl, const char *name)
{
- struct usbg_nacl *nacl = container_of(se_acl,
- struct usbg_nacl, se_node_acl);
- core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);
- kfree(nacl);
+ if (!usbg_check_wwn(name))
+ return -EINVAL;
+ return 0;
}
struct usbg_tpg *the_only_tpg_I_currently_have;
@@ -1572,8 +1409,11 @@ static struct se_portal_group *usbg_make_tpg(
tpg->tport = tport;
tpg->tport_tpgt = tpgt;
- ret = core_tpg_register(&usbg_ops, wwn, &tpg->se_tpg, tpg,
- TRANSPORT_TPG_TYPE_NORMAL);
+ /*
+ * SPC doesn't assign a protocol identifier for USB-SCSI, so we
+ * pretend to be SAS..
+ */
+ ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);
if (ret < 0) {
destroy_workqueue(tpg->workqueue);
kfree(tpg);
@@ -1625,23 +1465,21 @@ static void usbg_drop_tport(struct se_wwn *wwn)
/*
* If somebody feels like dropping the version property, go ahead.
*/
-static ssize_t usbg_wwn_show_attr_version(
- struct target_fabric_configfs *tf,
- char *page)
+static ssize_t usbg_wwn_version_show(struct config_item *item, char *page)
{
return sprintf(page, "usb-gadget fabric module\n");
}
-TF_WWN_ATTR_RO(usbg, version);
+
+CONFIGFS_ATTR_RO(usbg_wwn_, version);
static struct configfs_attribute *usbg_wwn_attrs[] = {
- &usbg_wwn_version.attr,
+ &usbg_wwn_attr_version,
NULL,
};
-static ssize_t tcm_usbg_tpg_show_enable(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_usbg_tpg_enable_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
@@ -1650,11 +1488,10 @@ static ssize_t tcm_usbg_tpg_show_enable(
static int usbg_attach(struct usbg_tpg *);
static void usbg_detach(struct usbg_tpg *);
-static ssize_t tcm_usbg_tpg_store_enable(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_usbg_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
unsigned long op;
ssize_t ret;
@@ -1681,12 +1518,10 @@ static ssize_t tcm_usbg_tpg_store_enable(
out:
return count;
}
-TF_TPG_BASE_ATTR(tcm_usbg, enable, S_IRUGO | S_IWUSR);
-static ssize_t tcm_usbg_tpg_show_nexus(
- struct se_portal_group *se_tpg,
- char *page)
+static ssize_t tcm_usbg_tpg_nexus_show(struct config_item *item, char *page)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
struct tcm_usbg_nexus *tv_nexus;
ssize_t ret;
@@ -1794,11 +1629,10 @@ out:
return ret;
}
-static ssize_t tcm_usbg_tpg_store_nexus(
- struct se_portal_group *se_tpg,
- const char *page,
- size_t count)
+static ssize_t tcm_usbg_tpg_nexus_store(struct config_item *item,
+ const char *page, size_t count)
{
+ struct se_portal_group *se_tpg = to_tpg(item);
struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
unsigned char i_port[USBG_NAMELEN], *ptr;
int ret;
@@ -1828,11 +1662,13 @@ static ssize_t tcm_usbg_tpg_store_nexus(
return ret;
return count;
}
-TF_TPG_BASE_ATTR(tcm_usbg, nexus, S_IRUGO | S_IWUSR);
+
+CONFIGFS_ATTR(tcm_usbg_tpg_, enable);
+CONFIGFS_ATTR(tcm_usbg_tpg_, nexus);
static struct configfs_attribute *usbg_base_attrs[] = {
- &tcm_usbg_tpg_enable.attr,
- &tcm_usbg_tpg_nexus.attr,
+ &tcm_usbg_tpg_attr_enable,
+ &tcm_usbg_tpg_attr_nexus,
NULL,
};
@@ -1867,19 +1703,12 @@ static const struct target_core_fabric_ops usbg_ops = {
.module = THIS_MODULE,
.name = "usb_gadget",
.get_fabric_name = usbg_get_fabric_name,
- .get_fabric_proto_ident = usbg_get_fabric_proto_ident,
.tpg_get_wwn = usbg_get_fabric_wwn,
.tpg_get_tag = usbg_get_tag,
- .tpg_get_default_depth = usbg_get_default_depth,
- .tpg_get_pr_transport_id = usbg_get_pr_transport_id,
- .tpg_get_pr_transport_id_len = usbg_get_pr_transport_id_len,
- .tpg_parse_pr_out_transport_id = usbg_parse_pr_out_transport_id,
.tpg_check_demo_mode = usbg_check_true,
.tpg_check_demo_mode_cache = usbg_check_false,
.tpg_check_demo_mode_write_protect = usbg_check_false,
.tpg_check_prod_mode_write_protect = usbg_check_false,
- .tpg_alloc_fabric_acl = usbg_alloc_fabric_acl,
- .tpg_release_fabric_acl = usbg_release_fabric_acl,
.tpg_get_inst_index = usbg_tpg_get_inst_index,
.release_cmd = usbg_release_cmd,
.shutdown_session = usbg_shutdown_session,
@@ -1889,7 +1718,6 @@ static const struct target_core_fabric_ops usbg_ops = {
.write_pending = usbg_send_write_request,
.write_pending_status = usbg_write_pending_status,
.set_default_node_attributes = usbg_set_default_node_attrs,
- .get_task_tag = usbg_get_task_tag,
.get_cmd_state = usbg_get_cmd_state,
.queue_data_in = usbg_send_read_response,
.queue_status = usbg_send_status_response,
@@ -1903,10 +1731,7 @@ static const struct target_core_fabric_ops usbg_ops = {
.fabric_drop_tpg = usbg_drop_tpg,
.fabric_post_link = usbg_port_link,
.fabric_pre_unlink = usbg_port_unlink,
- .fabric_make_np = NULL,
- .fabric_drop_np = NULL,
- .fabric_make_nodeacl = usbg_make_nodeacl,
- .fabric_drop_nodeacl = usbg_drop_nodeacl,
+ .fabric_init_nodeacl = usbg_init_nodeacl,
.tfc_wwn_attrs = usbg_wwn_attrs,
.tfc_tpg_base_attrs = usbg_base_attrs,
@@ -2187,14 +2012,6 @@ static struct usb_configuration usbg_config_driver = {
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
};
-static void give_back_ep(struct usb_ep **pep)
-{
- struct usb_ep *ep = *pep;
- if (!ep)
- return;
- ep->driver_data = NULL;
-}
-
static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct f_uas *fu = to_f_uas(f);
@@ -2214,29 +2031,24 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
&uasp_bi_ep_comp_desc);
if (!ep)
goto ep_fail;
-
- ep->driver_data = fu;
fu->ep_in = ep;
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
&uasp_bo_ep_comp_desc);
if (!ep)
goto ep_fail;
- ep->driver_data = fu;
fu->ep_out = ep;
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
&uasp_status_in_ep_comp_desc);
if (!ep)
goto ep_fail;
- ep->driver_data = fu;
fu->ep_status = ep;
ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
&uasp_cmd_comp_desc);
if (!ep)
goto ep_fail;
- ep->driver_data = fu;
fu->ep_cmd = ep;
/* Assume endpoint addresses are the same for both speeds */
@@ -2260,11 +2072,6 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
ep_fail:
pr_err("Can't claim all required eps\n");
-
- give_back_ep(&fu->ep_in);
- give_back_ep(&fu->ep_out);
- give_back_ep(&fu->ep_status);
- give_back_ep(&fu->ep_cmd);
return -ENOTSUPP;
}
diff --git a/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.h b/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.h
index 828921992..0b749e1aa 100644
--- a/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.h
+++ b/kernel/drivers/usb/gadget/legacy/tcm_usb_gadget.h
@@ -6,7 +6,6 @@
#include <linux/usb/composite.h>
#include <linux/usb/uas.h>
#include <linux/usb/storage.h>
-#include <scsi/scsi.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
@@ -25,15 +24,6 @@ enum {
#define USB_G_ALT_INT_BBB 0
#define USB_G_ALT_INT_UAS 1
-struct usbg_nacl {
- /* Binary World Wide unique Port Name for SAS Initiator port */
- u64 iport_wwpn;
- /* ASCII formatted WWPN for Sas Initiator port */
- char iport_name[USBG_NAMELEN];
- /* Returned by usbg_make_nodeacl() */
- struct se_node_acl se_node_acl;
-};
-
struct tcm_usbg_nexus {
struct se_session *tvn_se_sess;
};
@@ -53,8 +43,6 @@ struct usbg_tpg {
};
struct usbg_tport {
- /* SCSI protocol the tport is providing */
- u8 tport_proto_id;
/* Binary World Wide unique Port Name for SAS Target port */
u64 tport_wwpn;
/* ASCII formatted WWPN for SAS Target port */
diff --git a/kernel/drivers/usb/gadget/legacy/zero.c b/kernel/drivers/usb/gadget/legacy/zero.c
index c986e8add..37a410056 100644
--- a/kernel/drivers/usb/gadget/legacy/zero.c
+++ b/kernel/drivers/usb/gadget/legacy/zero.c
@@ -121,24 +121,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 2,
};
-#ifdef CONFIG_USB_OTG
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-#else
-#define otg_desc NULL
-#endif
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
/* default serial number takes at least two packets */
@@ -341,6 +324,18 @@ static int zero_bind(struct usb_composite_dev *cdev)
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
+ if (!otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ status = -ENOMEM;
+ goto err_conf_flb;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
sourcesink_driver.descriptors = otg_desc;
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_driver.descriptors = otg_desc;
@@ -359,12 +354,12 @@ static int zero_bind(struct usb_composite_dev *cdev)
}
status = usb_add_function(&sourcesink_driver, func_ss);
if (status)
- goto err_conf_flb;
+ goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
status = usb_add_function(&loopback_driver, func_lb);
if (status)
- goto err_conf_flb;
+ goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
usb_composite_overwrite_options(cdev, &coverwrite);
@@ -373,6 +368,9 @@ static int zero_bind(struct usb_composite_dev *cdev)
return 0;
+err_free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
err_conf_flb:
usb_put_function(func_lb);
func_lb = NULL;
@@ -397,6 +395,9 @@ static int zero_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(func_lb))
usb_put_function(func_lb);
usb_put_function_instance(func_inst_lb);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/udc/Kconfig b/kernel/drivers/usb/gadget/udc/Kconfig
index 9a3a6b003..cdbff54e0 100644
--- a/kernel/drivers/usb/gadget/udc/Kconfig
+++ b/kernel/drivers/usb/gadget/udc/Kconfig
@@ -55,7 +55,7 @@ config USB_LPC32XX
config USB_ATMEL_USBA
tristate "Atmel USBA"
- depends on AVR32 || ARCH_AT91
+ depends on ((AVR32 && !OF) || ARCH_AT91)
help
USBA is the integrated high-speed USB Device controller on
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
diff --git a/kernel/drivers/usb/gadget/udc/amd5536udc.c b/kernel/drivers/usb/gadget/udc/amd5536udc.c
index de7e5e2cc..cd8764150 100644
--- a/kernel/drivers/usb/gadget/udc/amd5536udc.c
+++ b/kernel/drivers/usb/gadget/udc/amd5536udc.c
@@ -65,18 +65,10 @@
static void udc_tasklet_disconnect(unsigned long);
static void empty_req_queue(struct udc_ep *);
-static int udc_probe(struct udc *dev);
-static void udc_basic_init(struct udc *dev);
static void udc_setup_endpoints(struct udc *dev);
static void udc_soft_reset(struct udc *dev);
static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
-static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
- unsigned long buf_len, gfp_t gfp_flags);
-static int udc_remote_wakeup(struct udc *dev);
-static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void udc_pci_remove(struct pci_dev *pdev);
/* description */
static const char mod_desc[] = UDC_MOD_DESCRIPTION;
@@ -138,15 +130,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
/* endpoint names used for print */
static const char ep0_string[] = "ep0in";
-static const char *const ep_string[] = {
- ep0_string,
- "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
- "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
- "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
- "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
- "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
- "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
- "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO(ep0_string,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep1in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep3in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep5in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep6in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep7in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep8in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep10in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep11in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep12in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep13in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep14in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep15in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep0out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep1out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep5out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep6out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep7out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep8out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep9out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep10out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep11out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep12out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep13out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep14out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep15out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
/* DMA usage flag */
@@ -548,6 +607,30 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
return &req->req;
}
+/* frees pci pool descriptors of a DMA chain */
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
+{
+ int ret_val = 0;
+ struct udc_data_dma *td;
+ struct udc_data_dma *td_last = NULL;
+ unsigned int i;
+
+ DBG(dev, "free chain req = %p\n", req);
+
+ /* do not free first desc., will be done by free for request */
+ td_last = req->td_data;
+ td = phys_to_virt(td_last->next);
+
+ for (i = 1; i < req->chain_len; i++) {
+ pci_pool_free(dev->data_requests, td,
+ (dma_addr_t)td_last->next);
+ td_last = td;
+ td = phys_to_virt(td_last->next);
+ }
+
+ return ret_val;
+}
+
/* Frees request packet, called by gadget driver */
static void
udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -722,6 +805,123 @@ udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
return finished;
}
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+ struct udc_ep *ep,
+ struct udc_request *req,
+ unsigned long buf_len, gfp_t gfp_flags
+)
+{
+ unsigned long bytes = req->req.length;
+ unsigned int i;
+ dma_addr_t dma_addr;
+ struct udc_data_dma *td = NULL;
+ struct udc_data_dma *last = NULL;
+ unsigned long txbytes;
+ unsigned create_new_chain = 0;
+ unsigned len;
+
+ VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
+ bytes, buf_len);
+ dma_addr = DMA_DONT_USE;
+
+ /* unset L bit in first desc for OUT */
+ if (!ep->in)
+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+
+ /* alloc only new desc's if not already available */
+ len = req->req.length / ep->ep.maxpacket;
+ if (req->req.length % ep->ep.maxpacket)
+ len++;
+
+ if (len > req->chain_len) {
+ /* shorter chain already allocated before */
+ if (req->chain_len > 1)
+ udc_free_dma_chain(ep->dev, req);
+ req->chain_len = len;
+ create_new_chain = 1;
+ }
+
+ td = req->td_data;
+ /* gen. required number of descriptors and buffers */
+ for (i = buf_len; i < bytes; i += buf_len) {
+ /* create or determine next desc. */
+ if (create_new_chain) {
+ td = pci_pool_alloc(ep->dev->data_requests,
+ gfp_flags, &dma_addr);
+ if (!td)
+ return -ENOMEM;
+
+ td->status = 0;
+ } else if (i == buf_len) {
+ /* first td */
+ td = (struct udc_data_dma *)phys_to_virt(
+ req->td_data->next);
+ td->status = 0;
+ } else {
+ td = (struct udc_data_dma *)phys_to_virt(last->next);
+ td->status = 0;
+ }
+
+ if (td)
+ td->bufptr = req->req.dma + i; /* assign buffer */
+ else
+ break;
+
+ /* short packet ? */
+ if ((bytes - i) >= buf_len) {
+ txbytes = buf_len;
+ } else {
+ /* short packet */
+ txbytes = bytes - i;
+ }
+
+ /* link td and assign tx bytes */
+ if (i == buf_len) {
+ if (create_new_chain)
+ req->td_data->next = dma_addr;
+ /*
+ * else
+ * req->td_data->next = virt_to_phys(td);
+ */
+ /* write tx bytes */
+ if (ep->in) {
+ /* first desc */
+ req->td_data->status =
+ AMD_ADDBITS(req->td_data->status,
+ ep->ep.maxpacket,
+ UDC_DMA_IN_STS_TXBYTES);
+ /* second desc */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+ } else {
+ if (create_new_chain)
+ last->next = dma_addr;
+ /*
+ * else
+ * last->next = virt_to_phys(td);
+ */
+ if (ep->in) {
+ /* write tx bytes */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+ }
+ last = td;
+ }
+ /* set last bit */
+ if (td) {
+ td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+ /* last desc. points to itself */
+ req->td_data_last = td;
+ }
+
+ return 0;
+}
+
/* create/re-init a DMA descriptor or a DMA descriptor chain */
static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
{
@@ -846,32 +1046,6 @@ __acquires(ep->dev->lock)
ep->halted = halted;
}
-/* frees pci pool descriptors of a DMA chain */
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
-{
-
- int ret_val = 0;
- struct udc_data_dma *td;
- struct udc_data_dma *td_last = NULL;
- unsigned int i;
-
- DBG(dev, "free chain req = %p\n", req);
-
- /* do not free first desc., will be done by free for request */
- td_last = req->td_data;
- td = phys_to_virt(td_last->next);
-
- for (i = 1; i < req->chain_len; i++) {
-
- pci_pool_free(dev->data_requests, td,
- (dma_addr_t) td_last->next);
- td_last = td;
- td = phys_to_virt(td_last->next);
- }
-
- return ret_val;
-}
-
/* Iterates to the end of a DMA chain and returns last descriptor */
static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
{
@@ -908,125 +1082,6 @@ static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
}
-/* Creates or re-inits a DMA chain */
-static int udc_create_dma_chain(
- struct udc_ep *ep,
- struct udc_request *req,
- unsigned long buf_len, gfp_t gfp_flags
-)
-{
- unsigned long bytes = req->req.length;
- unsigned int i;
- dma_addr_t dma_addr;
- struct udc_data_dma *td = NULL;
- struct udc_data_dma *last = NULL;
- unsigned long txbytes;
- unsigned create_new_chain = 0;
- unsigned len;
-
- VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
- bytes, buf_len);
- dma_addr = DMA_DONT_USE;
-
- /* unset L bit in first desc for OUT */
- if (!ep->in)
- req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-
- /* alloc only new desc's if not already available */
- len = req->req.length / ep->ep.maxpacket;
- if (req->req.length % ep->ep.maxpacket)
- len++;
-
- if (len > req->chain_len) {
- /* shorter chain already allocated before */
- if (req->chain_len > 1)
- udc_free_dma_chain(ep->dev, req);
- req->chain_len = len;
- create_new_chain = 1;
- }
-
- td = req->td_data;
- /* gen. required number of descriptors and buffers */
- for (i = buf_len; i < bytes; i += buf_len) {
- /* create or determine next desc. */
- if (create_new_chain) {
-
- td = pci_pool_alloc(ep->dev->data_requests,
- gfp_flags, &dma_addr);
- if (!td)
- return -ENOMEM;
-
- td->status = 0;
- } else if (i == buf_len) {
- /* first td */
- td = (struct udc_data_dma *) phys_to_virt(
- req->td_data->next);
- td->status = 0;
- } else {
- td = (struct udc_data_dma *) phys_to_virt(last->next);
- td->status = 0;
- }
-
-
- if (td)
- td->bufptr = req->req.dma + i; /* assign buffer */
- else
- break;
-
- /* short packet ? */
- if ((bytes - i) >= buf_len) {
- txbytes = buf_len;
- } else {
- /* short packet */
- txbytes = bytes - i;
- }
-
- /* link td and assign tx bytes */
- if (i == buf_len) {
- if (create_new_chain)
- req->td_data->next = dma_addr;
- /*
- else
- req->td_data->next = virt_to_phys(td);
- */
- /* write tx bytes */
- if (ep->in) {
- /* first desc */
- req->td_data->status =
- AMD_ADDBITS(req->td_data->status,
- ep->ep.maxpacket,
- UDC_DMA_IN_STS_TXBYTES);
- /* second desc */
- td->status = AMD_ADDBITS(td->status,
- txbytes,
- UDC_DMA_IN_STS_TXBYTES);
- }
- } else {
- if (create_new_chain)
- last->next = dma_addr;
- /*
- else
- last->next = virt_to_phys(td);
- */
- if (ep->in) {
- /* write tx bytes */
- td->status = AMD_ADDBITS(td->status,
- txbytes,
- UDC_DMA_IN_STS_TXBYTES);
- }
- }
- last = td;
- }
- /* set last bit */
- if (td) {
- td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
- /* last desc. points to itself */
- req->td_data_last = td;
- }
-
- return 0;
-}
-
/* Enabling RX DMA */
static void udc_set_rde(struct udc *dev)
{
@@ -1386,6 +1441,26 @@ static int udc_get_frame(struct usb_gadget *gadget)
return -EOPNOTSUPP;
}
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+ unsigned long flags;
+ u32 tmp;
+
+ DBG(dev, "UDC initiates remote wakeup\n");
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ tmp = readl(&dev->regs->ctl);
+ tmp |= AMD_BIT(UDC_DEVCTL_RES);
+ writel(tmp, &dev->regs->ctl);
+ tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+ writel(tmp, &dev->regs->ctl);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return 0;
+}
+
/* Remote wakeup gadget interface */
static int udc_wakeup(struct usb_gadget *gadget)
{
@@ -1431,33 +1506,6 @@ static void make_ep_lists(struct udc *dev)
dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
}
-/* init registers at driver load time */
-static int startup_registers(struct udc *dev)
-{
- u32 tmp;
-
- /* init controller by soft reset */
- udc_soft_reset(dev);
-
- /* mask not needed interrupts */
- udc_mask_unused_interrupts(dev);
-
- /* put into initial config */
- udc_basic_init(dev);
- /* link up all endpoints */
- udc_setup_endpoints(dev);
-
- /* program speed */
- tmp = readl(&dev->regs->cfg);
- if (use_fullspeed)
- tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
- else
- tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
- writel(tmp, &dev->regs->cfg);
-
- return 0;
-}
-
/* Inits UDC context */
static void udc_basic_init(struct udc *dev)
{
@@ -1496,6 +1544,33 @@ static void udc_basic_init(struct udc *dev)
dev->data_ep_queued = 0;
}
+/* init registers at driver load time */
+static int startup_registers(struct udc *dev)
+{
+ u32 tmp;
+
+ /* init controller by soft reset */
+ udc_soft_reset(dev);
+
+ /* mask not needed interrupts */
+ udc_mask_unused_interrupts(dev);
+
+ /* put into initial config */
+ udc_basic_init(dev);
+ /* link up all endpoints */
+ udc_setup_endpoints(dev);
+
+ /* program speed */
+ tmp = readl(&dev->regs->cfg);
+ if (use_fullspeed)
+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+ else
+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
+ writel(tmp, &dev->regs->cfg);
+
+ return 0;
+}
+
/* Sets initial endpoint parameters */
static void udc_setup_endpoints(struct udc *dev)
{
@@ -1517,7 +1592,8 @@ static void udc_setup_endpoints(struct udc *dev)
for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
ep = &dev->ep[tmp];
ep->dev = dev;
- ep->ep.name = ep_string[tmp];
+ ep->ep.name = ep_info[tmp].name;
+ ep->ep.caps = ep_info[tmp].caps;
ep->num = tmp;
/* txfifo size is calculated at enable time */
ep->txfifo = dev->txfifo;
@@ -2109,7 +2185,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
}
/* DMA */
- } else if (!ep->cancel_transfer && req != NULL) {
+ } else if (!ep->cancel_transfer && req) {
ret_val = IRQ_HANDLED;
/* check for DMA done */
@@ -3039,6 +3115,17 @@ static void udc_remove(struct udc *dev)
udc = NULL;
}
+/* free all the dma pools */
+static void free_dma_pools(struct udc *dev)
+{
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td,
+ dev->ep[UDC_EP0OUT_IX].td_phys);
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+ dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+ dma_pool_destroy(dev->stp_requests);
+ dma_pool_destroy(dev->data_requests);
+}
+
/* Reset all pci context */
static void udc_pci_remove(struct pci_dev *pdev)
{
@@ -3048,35 +3135,19 @@ static void udc_pci_remove(struct pci_dev *pdev)
usb_del_gadget_udc(&udc->gadget);
/* gadget driver must not be registered */
- BUG_ON(dev->driver != NULL);
+ if (WARN_ON(dev->driver))
+ return;
/* dma pool cleanup */
- if (dev->data_requests)
- pci_pool_destroy(dev->data_requests);
-
- if (dev->stp_requests) {
- /* cleanup DMA desc's for ep0in */
- pci_pool_free(dev->stp_requests,
- dev->ep[UDC_EP0OUT_IX].td_stp,
- dev->ep[UDC_EP0OUT_IX].td_stp_dma);
- pci_pool_free(dev->stp_requests,
- dev->ep[UDC_EP0OUT_IX].td,
- dev->ep[UDC_EP0OUT_IX].td_phys);
-
- pci_pool_destroy(dev->stp_requests);
- }
+ free_dma_pools(dev);
/* reset controller */
writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
- if (dev->irq_registered)
- free_irq(pdev->irq, dev);
- if (dev->regs)
- iounmap(dev->regs);
- if (dev->mem_region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- if (dev->active)
- pci_disable_device(pdev);
+ free_irq(pdev->irq, dev);
+ iounmap(dev->virt_addr);
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ pci_disable_device(pdev);
udc_remove(dev);
}
@@ -3101,8 +3172,7 @@ static int init_dma_pools(struct udc *dev)
sizeof(struct udc_data_dma), 0, 0);
if (!dev->data_requests) {
DBG(dev, "can't get request data pool\n");
- retval = -ENOMEM;
- goto finished;
+ return -ENOMEM;
}
/* EP0 in dma regs = dev control regs */
@@ -3114,27 +3184,101 @@ static int init_dma_pools(struct udc *dev)
if (!dev->stp_requests) {
DBG(dev, "can't get stp request pool\n");
retval = -ENOMEM;
- goto finished;
+ goto err_create_dma_pool;
}
/* setup */
td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
&dev->ep[UDC_EP0OUT_IX].td_stp_dma);
- if (td_stp == NULL) {
+ if (!td_stp) {
retval = -ENOMEM;
- goto finished;
+ goto err_alloc_dma;
}
dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
/* data: 0 packets !? */
td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
&dev->ep[UDC_EP0OUT_IX].td_phys);
- if (td_data == NULL) {
+ if (!td_data) {
retval = -ENOMEM;
- goto finished;
+ goto err_alloc_phys;
}
dev->ep[UDC_EP0OUT_IX].td = td_data;
return 0;
+err_alloc_phys:
+ dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+ dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+err_alloc_dma:
+ dma_pool_destroy(dev->stp_requests);
+ dev->stp_requests = NULL;
+err_create_dma_pool:
+ dma_pool_destroy(dev->data_requests);
+ dev->data_requests = NULL;
+ return retval;
+}
+
+/* general probe */
+static int udc_probe(struct udc *dev)
+{
+ char tmp[128];
+ u32 reg;
+ int retval;
+
+ /* mark timer as not initialized */
+ udc_timer.data = 0;
+ udc_pollstall_timer.data = 0;
+
+ /* device struct setup */
+ dev->gadget.ops = &udc_ops;
+
+ dev_set_name(&dev->gadget.dev, "gadget");
+ dev->gadget.name = name;
+ dev->gadget.max_speed = USB_SPEED_HIGH;
+
+ /* init registers, interrupts, ... */
+ startup_registers(dev);
+
+ dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+ snprintf(tmp, sizeof(tmp), "%d", dev->irq);
+ dev_info(&dev->pdev->dev,
+ "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+ tmp, dev->phys_addr, dev->chiprev,
+ (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+ if (dev->chiprev == UDC_HSA0_REV) {
+ dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+ retval = -ENODEV;
+ goto finished;
+ }
+ dev_info(&dev->pdev->dev,
+ "driver version: %s(for Geode5536 B1)\n", tmp);
+ udc = dev;
+
+ retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+ gadget_release);
+ if (retval)
+ goto finished;
+
+ /* timer init */
+ init_timer(&udc_timer);
+ udc_timer.function = udc_timer_function;
+ udc_timer.data = 1;
+ /* timer pollstall init */
+ init_timer(&udc_pollstall_timer);
+ udc_pollstall_timer.function = udc_pollstall_timer_function;
+ udc_pollstall_timer.data = 1;
+
+ /* set SD */
+ reg = readl(&dev->regs->ctl);
+ reg |= AMD_BIT(UDC_DEVCTL_SD);
+ writel(reg, &dev->regs->ctl);
+
+ /* print dev register info */
+ print_regs(dev);
+
+ return 0;
+
finished:
return retval;
}
@@ -3158,19 +3302,14 @@ static int udc_pci_probe(
/* init */
dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
- if (!dev) {
- retval = -ENOMEM;
- goto finished;
- }
+ if (!dev)
+ return -ENOMEM;
/* pci setup */
if (pci_enable_device(pdev) < 0) {
- kfree(dev);
- dev = NULL;
retval = -ENODEV;
- goto finished;
+ goto err_pcidev;
}
- dev->active = 1;
/* PCI resource allocation */
resource = pci_resource_start(pdev, 0);
@@ -3178,28 +3317,21 @@ static int udc_pci_probe(
if (!request_mem_region(resource, len, name)) {
dev_dbg(&pdev->dev, "pci device used already\n");
- kfree(dev);
- dev = NULL;
retval = -EBUSY;
- goto finished;
+ goto err_memreg;
}
- dev->mem_region = 1;
dev->virt_addr = ioremap_nocache(resource, len);
- if (dev->virt_addr == NULL) {
+ if (!dev->virt_addr) {
dev_dbg(&pdev->dev, "start address cannot be mapped\n");
- kfree(dev);
- dev = NULL;
retval = -EFAULT;
- goto finished;
+ goto err_ioremap;
}
if (!pdev->irq) {
dev_err(&pdev->dev, "irq not set\n");
- kfree(dev);
- dev = NULL;
retval = -ENODEV;
- goto finished;
+ goto err_irq;
}
spin_lock_init(&dev->lock);
@@ -3215,12 +3347,9 @@ static int udc_pci_probe(
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
- kfree(dev);
- dev = NULL;
retval = -EBUSY;
- goto finished;
+ goto err_irq;
}
- dev->irq_registered = 1;
pci_set_drvdata(pdev, dev);
@@ -3234,7 +3363,7 @@ static int udc_pci_probe(
if (use_dma) {
retval = init_dma_pools(dev);
if (retval != 0)
- goto finished;
+ goto err_dma;
}
dev->phys_addr = resource;
@@ -3242,101 +3371,28 @@ static int udc_pci_probe(
dev->pdev = pdev;
/* general probing */
- if (udc_probe(dev) == 0)
- return 0;
-
-finished:
- if (dev)
- udc_pci_remove(pdev);
- return retval;
-}
-
-/* general probe */
-static int udc_probe(struct udc *dev)
-{
- char tmp[128];
- u32 reg;
- int retval;
-
- /* mark timer as not initialized */
- udc_timer.data = 0;
- udc_pollstall_timer.data = 0;
-
- /* device struct setup */
- dev->gadget.ops = &udc_ops;
-
- dev_set_name(&dev->gadget.dev, "gadget");
- dev->gadget.name = name;
- dev->gadget.max_speed = USB_SPEED_HIGH;
-
- /* init registers, interrupts, ... */
- startup_registers(dev);
-
- dev_info(&dev->pdev->dev, "%s\n", mod_desc);
-
- snprintf(tmp, sizeof tmp, "%d", dev->irq);
- dev_info(&dev->pdev->dev,
- "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
- tmp, dev->phys_addr, dev->chiprev,
- (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
- strcpy(tmp, UDC_DRIVER_VERSION_STRING);
- if (dev->chiprev == UDC_HSA0_REV) {
- dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+ if (udc_probe(dev)) {
retval = -ENODEV;
- goto finished;
+ goto err_probe;
}
- dev_info(&dev->pdev->dev,
- "driver version: %s(for Geode5536 B1)\n", tmp);
- udc = dev;
-
- retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
- gadget_release);
- if (retval)
- goto finished;
-
- /* timer init */
- init_timer(&udc_timer);
- udc_timer.function = udc_timer_function;
- udc_timer.data = 1;
- /* timer pollstall init */
- init_timer(&udc_pollstall_timer);
- udc_pollstall_timer.function = udc_pollstall_timer_function;
- udc_pollstall_timer.data = 1;
-
- /* set SD */
- reg = readl(&dev->regs->ctl);
- reg |= AMD_BIT(UDC_DEVCTL_SD);
- writel(reg, &dev->regs->ctl);
-
- /* print dev register info */
- print_regs(dev);
-
return 0;
-finished:
+err_probe:
+ if (use_dma)
+ free_dma_pools(dev);
+err_dma:
+ free_irq(pdev->irq, dev);
+err_irq:
+ iounmap(dev->virt_addr);
+err_ioremap:
+ release_mem_region(resource, len);
+err_memreg:
+ pci_disable_device(pdev);
+err_pcidev:
+ kfree(dev);
return retval;
}
-/* Initiates a remote wakeup */
-static int udc_remote_wakeup(struct udc *dev)
-{
- unsigned long flags;
- u32 tmp;
-
- DBG(dev, "UDC initiates remote wakeup\n");
-
- spin_lock_irqsave(&dev->lock, flags);
-
- tmp = readl(&dev->regs->ctl);
- tmp |= AMD_BIT(UDC_DEVCTL_RES);
- writel(tmp, &dev->regs->ctl);
- tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
- writel(tmp, &dev->regs->ctl);
-
- spin_unlock_irqrestore(&dev->lock, flags);
- return 0;
-}
-
/* PCI device parameters */
static const struct pci_device_id pci_id[] = {
{
diff --git a/kernel/drivers/usb/gadget/udc/amd5536udc.h b/kernel/drivers/usb/gadget/udc/amd5536udc.h
index 6744d3b83..4638d707f 100644
--- a/kernel/drivers/usb/gadget/udc/amd5536udc.h
+++ b/kernel/drivers/usb/gadget/udc/amd5536udc.h
@@ -526,14 +526,11 @@ struct udc {
struct udc_ep ep[UDC_EP_NUM];
struct usb_gadget_driver *driver;
/* operational flags */
- unsigned active : 1,
- stall_ep0in : 1,
+ unsigned stall_ep0in : 1,
waiting_zlp_ack_ep0in : 1,
set_cfg_not_acked : 1,
- irq_registered : 1,
data_ep_enabled : 1,
data_ep_queued : 1,
- mem_region : 1,
sys_suspended : 1,
connected;
diff --git a/kernel/drivers/usb/gadget/udc/at91_udc.c b/kernel/drivers/usb/gadget/udc/at91_udc.c
index fc4226462..d0d18947f 100644
--- a/kernel/drivers/usb/gadget/udc/at91_udc.c
+++ b/kernel/drivers/usb/gadget/udc/at91_udc.c
@@ -59,15 +59,34 @@
#define DRIVER_VERSION "3 May 2006"
static const char driver_name [] = "at91_udc";
-static const char * const ep_names[] = {
- "ep0",
- "ep1",
- "ep2",
- "ep3-int",
- "ep4",
- "ep5",
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO("ep0",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep2",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep3-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep4",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep5",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+
+#undef EP_INFO
};
-#define ep0name ep_names[0]
+
+#define ep0name ep_info[0].name
#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
@@ -825,6 +844,7 @@ static void udc_reinit(struct at91_udc *udc)
INIT_LIST_HEAD(&udc->gadget.ep_list);
INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+ udc->gadget.quirk_stall_not_supp = 1;
for (i = 0; i < NUM_ENDPOINTS; i++) {
struct at91_ep *ep = &udc->ep[i];
@@ -1830,7 +1850,8 @@ static int at91udc_probe(struct platform_device *pdev)
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
- ep->ep.name = ep_names[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &at91_ep_ops;
ep->udc = udc;
ep->int_mask = BIT(i);
diff --git a/kernel/drivers/usb/gadget/udc/at91_udc.h b/kernel/drivers/usb/gadget/udc/at91_udc.h
index 2679c8b21..0a433e6b3 100644
--- a/kernel/drivers/usb/gadget/udc/at91_udc.h
+++ b/kernel/drivers/usb/gadget/udc/at91_udc.h
@@ -112,6 +112,14 @@ struct at91_udc_caps {
void (*pullup)(struct at91_udc *udc, int is_on);
};
+struct at91_udc_data {
+ int vbus_pin; /* high == host powering us */
+ u8 vbus_active_low; /* vbus polarity */
+ u8 vbus_polled; /* Use polling, not interrupt */
+ int pullup_pin; /* active == D+ pulled up */
+ u8 pullup_active_low; /* true == pullup_pin is active low */
+};
+
/*
* driver is non-SMP, and just blocks IRQs whenever it needs
* access protection for chip registers or driver state
diff --git a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c
index 351d48550..f9bba26e3 100644
--- a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -17,12 +17,13 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/list.h>
+#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/atmel_usba_udc.h>
#include <linux/delay.h>
-#include <linux/platform_data/atmel.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -704,8 +705,8 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
unsigned long flags;
int ret;
- DBG(DBG_DMA, "%s: req l/%u d/%08x %c%c%c\n",
- ep->ep.name, req->req.length, req->req.dma,
+ DBG(DBG_DMA, "%s: req l/%u d/%pad %c%c%c\n",
+ ep->ep.name, req->req.length, &req->req.dma,
req->req.zero ? 'Z' : 'z',
req->req.short_not_ok ? 'S' : 's',
req->req.no_interrupt ? 'I' : 'i');
@@ -1634,7 +1635,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
spin_lock(&udc->lock);
int_enb = usba_int_enb_get(udc);
- status = usba_readl(udc, INT_STA) & int_enb;
+ status = usba_readl(udc, INT_STA) & (int_enb | USBA_HIGH_SPEED);
DBG(DBG_INT, "irq, status=%#08x\n", status);
if (status & USBA_DET_SUSPEND) {
@@ -1889,20 +1890,15 @@ static int atmel_usba_stop(struct usb_gadget *gadget)
#ifdef CONFIG_OF
static void at91sam9rl_toggle_bias(struct usba_udc *udc, int is_on)
{
- unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
-
- if (is_on)
- at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
- else
- at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN,
+ is_on ? AT91_PMC_BIASEN : 0);
}
static void at91sam9g45_pulse_bias(struct usba_udc *udc)
{
- unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
-
- at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
- at91_pmc_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN, 0);
+ regmap_update_bits(udc->pmc, AT91_CKGR_UCKR, AT91_PMC_BIASEN,
+ AT91_PMC_BIASEN);
}
static const struct usba_udc_errata at91sam9rl_errata = {
@@ -1939,6 +1935,9 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
return ERR_PTR(-EINVAL);
udc->errata = match->data;
+ udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc");
+ if (udc->errata && IS_ERR(udc->pmc))
+ return ERR_CAST(udc->pmc);
udc->num_ep = 0;
@@ -1989,6 +1988,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
ret = of_property_read_string(pp, "name", &name);
+ if (ret) {
+ dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
+ goto err;
+ }
ep->ep.name = name;
ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
@@ -1999,6 +2002,17 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->udc = udc;
INIT_LIST_HEAD(&ep->queue);
+ if (ep->index == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = ep->can_isoc;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
@@ -2063,6 +2077,17 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
ep->can_dma = pdata->ep[i].can_dma;
ep->can_isoc = pdata->ep[i].can_isoc;
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = ep->can_isoc;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
@@ -2203,7 +2228,7 @@ static int usba_udc_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int usba_udc_suspend(struct device *dev)
{
struct usba_udc *udc = dev_get_drvdata(dev);
diff --git a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h
index ea448a344..3e1c9d589 100644
--- a/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h
+++ b/kernel/drivers/usb/gadget/udc/atmel_usba_udc.h
@@ -354,6 +354,8 @@ struct usba_udc {
struct dentry *debugfs_root;
struct dentry *debugfs_regs;
#endif
+
+ struct regmap *pmc;
};
static inline struct usba_ep *to_usba_ep(struct usb_ep *ep)
diff --git a/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c b/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c
index 9db968ba3..8cbb00325 100644
--- a/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/kernel/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -44,9 +44,29 @@
#define DRV_MODULE_NAME "bcm63xx_udc"
static const char bcm63xx_ep0name[] = "ep0";
-static const char *const bcm63xx_ep_name[] = {
- bcm63xx_ep0name,
- "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} bcm63xx_ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO(bcm63xx_ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
static bool use_fullspeed;
@@ -943,7 +963,8 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
for (i = 0; i < BCM63XX_NUM_EP; i++) {
struct bcm63xx_ep *bep = &udc->bep[i];
- bep->ep.name = bcm63xx_ep_name[i];
+ bep->ep.name = bcm63xx_ep_info[i].name;
+ bep->ep.caps = bcm63xx_ep_info[i].caps;
bep->ep_num = i;
bep->ep.ops = &bcm63xx_udc_ep_ops;
list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
diff --git a/kernel/drivers/usb/gadget/udc/bdc/bdc.h b/kernel/drivers/usb/gadget/udc/bdc/bdc.h
index dc18a20bf..916d47135 100644
--- a/kernel/drivers/usb/gadget/udc/bdc/bdc.h
+++ b/kernel/drivers/usb/gadget/udc/bdc/bdc.h
@@ -290,7 +290,7 @@ struct bdc_sr {
__le32 offset[4];
};
-/* bd_table: contigous bd's in a table */
+/* bd_table: contiguous bd's in a table */
struct bd_table {
struct bdc_bd *start_bd;
/* dma address of start bd of table*/
diff --git a/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c b/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c
index 5c8f4effb..ccb9c213c 100644
--- a/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/kernel/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -324,8 +324,7 @@ static void bdc_mem_free(struct bdc *bdc)
bdc->scratchpad.buff, bdc->scratchpad.sp_dma);
/* Destroy the dma pools */
- if (bdc->bd_table_pool)
- dma_pool_destroy(bdc->bd_table_pool);
+ dma_pool_destroy(bdc->bd_table_pool);
/* Free the bdc_ep array */
kfree(bdc->bdc_ep_array);
diff --git a/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c b/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c
index b04980cf6..d6199507f 100644
--- a/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c
+++ b/kernel/drivers/usb/gadget/udc/bdc/bdc_ep.c
@@ -159,8 +159,10 @@ static int ep_bd_list_alloc(struct bdc_ep *ep)
bd_table->start_bd = dma_pool_alloc(bdc->bd_table_pool,
GFP_ATOMIC,
&dma);
- if (!bd_table->start_bd)
+ if (!bd_table->start_bd) {
+ kfree(bd_table);
goto fail;
+ }
bd_table->dma = dma;
@@ -779,7 +781,7 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req)
/* The current hw dequeue pointer */
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0));
deq_ptr_64 = tmp_32;
- tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(1));
+ tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0));
deq_ptr_64 |= ((u64)tmp_32 << 32);
/* we have the dma addr of next bd that will be fetched by hardware */
@@ -1952,12 +1954,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
ep->bdc = bdc;
ep->dir = dir;
+ if (dir)
+ ep->usb_ep.caps.dir_in = true;
+ else
+ ep->usb_ep.caps.dir_out = true;
+
/* ep->ep_num is the index inside bdc_ep */
if (epnum == 1) {
ep->ep_num = 1;
bdc->bdc_ep_array[ep->ep_num] = ep;
snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1);
usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE);
+ ep->usb_ep.caps.type_control = true;
ep->comp_desc = NULL;
bdc->gadget.ep0 = &ep->usb_ep;
} else {
@@ -1971,6 +1979,9 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
dir & 1 ? "in" : "out");
usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024);
+ ep->usb_ep.caps.type_iso = true;
+ ep->usb_ep.caps.type_bulk = true;
+ ep->usb_ep.caps.type_int = true;
ep->usb_ep.max_streams = 0;
list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list);
}
diff --git a/kernel/drivers/usb/gadget/udc/dummy_hcd.c b/kernel/drivers/usb/gadget/udc/dummy_hcd.c
index 181112c88..dde44450d 100644
--- a/kernel/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/kernel/drivers/usb/gadget/udc/dummy_hcd.c
@@ -127,23 +127,87 @@ static inline struct dummy_request *usb_request_to_dummy_request
static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
- ep0name, /* everyone has ep0 */
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+ /* everyone has ep0 */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
/* act like a pxa250: fifteen fixed function endpoints */
- "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
- "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
- "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
- "ep15in-int",
-
+ EP_INFO("ep1in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep5in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep6in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep7out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep8in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep10in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep11in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep12out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep13in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep14out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep15in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
/* or like sa1100: two fixed function endpoints */
- "ep1out-bulk", "ep2in-bulk",
-
+ EP_INFO("ep1out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
/* and now some generic EPs so we have enough in multi config */
- "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
- "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
+ EP_INFO("ep3out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep5out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep6out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep7in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep8out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep9in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep10out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep11out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep12in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep13out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep14in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep15out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
-#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
+
+#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info)
/*-------------------------------------------------------------------------*/
@@ -769,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
/* there are both host and device side versions of this call ... */
static int dummy_g_get_frame(struct usb_gadget *_gadget)
{
- struct timeval tv;
+ struct timespec64 ts64;
- do_gettimeofday(&tv);
- return tv.tv_usec / 1000;
+ ktime_get_ts64(&ts64);
+ return ts64.tv_nsec / NSEC_PER_MSEC;
}
static int dummy_wakeup(struct usb_gadget *_gadget)
@@ -938,9 +1002,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
struct dummy_ep *ep = &dum->ep[i];
- if (!ep_name[i])
+ if (!ep_info[i].name)
break;
- ep->ep.name = ep_name[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &dummy_ep_ops;
list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
ep->halted = ep->wedged = ep->already_seen =
@@ -1283,6 +1348,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
{
struct dummy *dum = dum_hcd->dum;
struct dummy_request *req;
+ int sent = 0;
top:
/* if there's no request queued, the device is NAKing; return */
@@ -1320,12 +1386,15 @@ top:
if (len == 0)
break;
- /* use an extra pass for the final short packet */
- if (len > ep->ep.maxpacket) {
- rescan = 1;
- len -= (len % ep->ep.maxpacket);
+ /* send multiple of maxpacket first, then remainder */
+ if (len >= ep->ep.maxpacket) {
+ is_short = 0;
+ if (len % ep->ep.maxpacket)
+ rescan = 1;
+ len -= len % ep->ep.maxpacket;
+ } else {
+ is_short = 1;
}
- is_short = (len % ep->ep.maxpacket) != 0;
len = dummy_perform_transfer(urb, req, len);
@@ -1334,6 +1403,7 @@ top:
req->req.status = len;
} else {
limit -= len;
+ sent += len;
urb->actual_length += len;
req->req.actual += len;
}
@@ -1356,7 +1426,7 @@ top:
*status = -EOVERFLOW;
else
*status = 0;
- } else if (!to_host) {
+ } else {
*status = 0;
if (host_len > dev_len)
req->req.status = -EOVERFLOW;
@@ -1364,15 +1434,24 @@ top:
req->req.status = 0;
}
- /* many requests terminate without a short packet */
+ /*
+ * many requests terminate without a short packet.
+ * send a zlp if demanded by flags.
+ */
} else {
- if (req->req.length == req->req.actual
- && !req->req.zero)
- req->req.status = 0;
- if (urb->transfer_buffer_length == urb->actual_length
- && !(urb->transfer_flags
- & URB_ZERO_PACKET))
- *status = 0;
+ if (req->req.length == req->req.actual) {
+ if (req->req.zero && to_host)
+ rescan = 1;
+ else
+ req->req.status = 0;
+ }
+ if (urb->transfer_buffer_length == urb->actual_length) {
+ if (urb->transfer_flags & URB_ZERO_PACKET &&
+ !to_host)
+ rescan = 1;
+ else
+ *status = 0;
+ }
}
/* device side completion --> continuable */
@@ -1395,7 +1474,7 @@ top:
if (rescan)
goto top;
}
- return limit;
+ return sent;
}
static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
@@ -1684,7 +1763,7 @@ static void dummy_timer(unsigned long _dum_hcd)
}
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
- if (!ep_name[i])
+ if (!ep_info[i].name)
break;
dum->ep[i].already_seen = 0;
}
@@ -1825,7 +1904,7 @@ restart:
default:
treat_control_like_bulk:
ep->last_io = jiffies;
- total = transfer(dum_hcd, urb, ep, limit, &status);
+ total -= transfer(dum_hcd, urb, ep, limit, &status);
break;
}
diff --git a/kernel/drivers/usb/gadget/udc/fotg210-udc.c b/kernel/drivers/usb/gadget/udc/fotg210-udc.c
index e547ea7f5..6ba122cc7 100644
--- a/kernel/drivers/usb/gadget/udc/fotg210-udc.c
+++ b/kernel/drivers/usb/gadget/udc/fotg210-udc.c
@@ -384,25 +384,15 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep,
return;
}
if (ep->dir_in) { /* if IN */
- if (req->req.length) {
- fotg210_start_dma(ep, req);
- } else {
- pr_err("%s : req->req.length = 0x%x\n",
- __func__, req->req.length);
- }
+ fotg210_start_dma(ep, req);
if ((req->req.length == req->req.actual) ||
(req->req.actual < ep->ep.maxpacket))
fotg210_done(ep, req, 0);
} else { /* OUT */
- if (!req->req.length) {
- fotg210_done(ep, req, 0);
- } else {
- u32 value = ioread32(ep->fotg210->reg +
- FOTG210_DMISGR0);
+ u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0);
- value &= ~DMISGR0_MCX_OUT_INT;
- iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
- }
+ value &= ~DMISGR0_MCX_OUT_INT;
+ iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
}
}
@@ -1153,6 +1143,17 @@ static int fotg210_udc_probe(struct platform_device *pdev)
ep->ep.name = fotg210_ep_name[i];
ep->ep.ops = &fotg210_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
@@ -1171,7 +1172,7 @@ static int fotg210_udc_probe(struct platform_device *pdev)
udc_name, fotg210);
if (ret < 0) {
pr_err("request_irq error (%d)\n", ret);
- goto err_irq;
+ goto err_req;
}
ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget);
@@ -1183,7 +1184,6 @@ static int fotg210_udc_probe(struct platform_device *pdev)
return 0;
err_add_udc:
-err_irq:
free_irq(ires->start, fotg210);
err_req:
diff --git a/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c b/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c
index e0822f1b6..5fb6f8b4f 100644
--- a/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/kernel/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2417,6 +2417,17 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
strcpy(ep->name, ep_name[pipe_num]);
ep->ep.name = ep_name[pipe_num];
+ if (pipe_num == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
ep->ep.ops = &qe_ep_ops;
ep->stopped = 1;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
diff --git a/kernel/drivers/usb/gadget/udc/fsl_udc_core.c b/kernel/drivers/usb/gadget/udc/fsl_udc_core.c
index c60022b46..aab5221d6 100644
--- a/kernel/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/kernel/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
ep->ep.ops = &fsl_ep_ops;
ep->stopped = 0;
+ if (index == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ if (index & 1)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
/* for ep0: maxP defined in desc
* for other eps, maxP is set by epautoconfig() called by gadget layer
*/
diff --git a/kernel/drivers/usb/gadget/udc/fusb300_udc.c b/kernel/drivers/usb/gadget/udc/fusb300_udc.c
index 3970f453d..948845c90 100644
--- a/kernel/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/kernel/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1450,6 +1450,17 @@ static int fusb300_probe(struct platform_device *pdev)
ep->ep.name = fusb300_ep_name[i];
ep->ep.ops = &fusb300_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
fusb300->ep[0]->epnum = 0;
diff --git a/kernel/drivers/usb/gadget/udc/gadget_chips.h b/kernel/drivers/usb/gadget/udc/gadget_chips.h
deleted file mode 100644
index bcd04bc66..000000000
--- a/kernel/drivers/usb/gadget/udc/gadget_chips.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * USB device controllers have lots of quirks. Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- * (And avoiding all runtime comparisons in typical one-choice configs!)
- *
- * NOTE: some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
- */
-
-#ifndef __GADGET_CHIPS_H
-#define __GADGET_CHIPS_H
-
-#include <linux/usb/gadget.h>
-
-/*
- * NOTICE: the entries below are alphabetical and should be kept
- * that way.
- *
- * Always be sure to add new entries to the correct position or
- * accept the bashing later.
- *
- * If you have forgotten the alphabetical order let VIM/EMACS
- * do that for you.
- */
-#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
-#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
-#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
-#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name))
-#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name))
-#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name))
-
-/**
- * gadget_supports_altsettings - return true if altsettings work
- * @gadget: the gadget in question
- */
-static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
-{
- /* PXA 21x/25x/26x has no altsettings at all */
- if (gadget_is_pxa(gadget))
- return false;
-
- /* PXA 27x and 3xx have *broken* altsetting support */
- if (gadget_is_pxa27x(gadget))
- return false;
-
- /* Everything else is *presumably* fine ... */
- return true;
-}
-
-#endif /* __GADGET_CHIPS_H */
diff --git a/kernel/drivers/usb/gadget/udc/goku_udc.c b/kernel/drivers/usb/gadget/udc/goku_udc.c
index 9e8d842e8..1fdfec14a 100644
--- a/kernel/drivers/usb/gadget/udc/goku_udc.c
+++ b/kernel/drivers/usb/gadget/udc/goku_udc.c
@@ -990,6 +990,35 @@ static int goku_get_frame(struct usb_gadget *_gadget)
return -EOPNOTSUPP;
}
+static struct usb_ep *goku_match_ep(struct usb_gadget *g,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ struct goku_udc *dev = to_goku_udc(g);
+ struct usb_ep *ep;
+
+ switch (usb_endpoint_type(desc)) {
+ case USB_ENDPOINT_XFER_INT:
+ /* single buffering is enough */
+ ep = &dev->ep[3].ep;
+ if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (usb_endpoint_dir_in(desc)) {
+ /* DMA may be available */
+ ep = &dev->ep[2].ep;
+ if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+ }
+ break;
+ default:
+ /* nothing */ ;
+ }
+
+ return NULL;
+}
+
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int goku_udc_stop(struct usb_gadget *g);
@@ -998,6 +1027,7 @@ static const struct usb_gadget_ops goku_ops = {
.get_frame = goku_get_frame,
.udc_start = goku_udc_start,
.udc_stop = goku_udc_stop,
+ .match_ep = goku_match_ep,
// no remote wakeup
// not selfpowered
};
@@ -1257,6 +1287,14 @@ static void udc_reinit (struct goku_udc *dev)
INIT_LIST_HEAD (&ep->queue);
ep_reset(NULL, ep);
+
+ if (i == 0)
+ ep->ep.caps.type_control = true;
+ else
+ ep->ep.caps.type_bulk = true;
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
dev->ep[0].reg_mode = NULL;
diff --git a/kernel/drivers/usb/gadget/udc/gr_udc.c b/kernel/drivers/usb/gadget/udc/gr_udc.c
index c8868870e..b9429bc42 100644
--- a/kernel/drivers/usb/gadget/udc/gr_udc.c
+++ b/kernel/drivers/usb/gadget/udc/gr_udc.c
@@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
+
+ ep->ep.caps.type_control = true;
} else {
usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
}
list_add_tail(&ep->ep_list, &dev->ep_list);
+ if (is_in)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit,
&ep->tailbuf_paddr, GFP_ATOMIC);
if (!ep->tailbuf)
@@ -2106,8 +2117,7 @@ static int gr_remove(struct platform_device *pdev)
return -EBUSY;
gr_dfs_delete(dev);
- if (dev->desc_pool)
- dma_pool_destroy(dev->desc_pool);
+ dma_pool_destroy(dev->desc_pool);
platform_set_drvdata(pdev, NULL);
gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
diff --git a/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c b/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c
index 3b6a78528..00b5006ba 100644
--- a/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/kernel/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -2575,6 +2575,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep0",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 0,
@@ -2586,6 +2588,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep1-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 2,
@@ -2597,6 +2601,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep2-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 4,
@@ -2608,6 +2614,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep3-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 6,
@@ -2619,6 +2627,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep4-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 8,
@@ -2630,6 +2640,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep5-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 10,
@@ -2641,6 +2653,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep6-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 12,
@@ -2652,6 +2666,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep7-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 14,
@@ -2663,6 +2679,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep8-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 16,
@@ -2674,6 +2692,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep9-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 18,
@@ -2685,6 +2705,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep10-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 20,
@@ -2696,6 +2718,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep11-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 22,
@@ -2707,6 +2731,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep12-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 24,
@@ -2718,6 +2744,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep13-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 26,
@@ -2729,6 +2757,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep14-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 28,
@@ -2740,6 +2770,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep15-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 30,
diff --git a/kernel/drivers/usb/gadget/udc/m66592-udc.c b/kernel/drivers/usb/gadget/udc/m66592-udc.c
index 9704053df..b1cfa96cc 100644
--- a/kernel/drivers/usb/gadget/udc/m66592-udc.c
+++ b/kernel/drivers/usb/gadget/udc/m66592-udc.c
@@ -1644,6 +1644,17 @@ static int m66592_probe(struct platform_device *pdev)
ep->ep.name = m66592_ep_name[i];
ep->ep.ops = &m66592_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
m66592->ep[0].pipenum = 0;
diff --git a/kernel/drivers/usb/gadget/udc/mv_u3d_core.c b/kernel/drivers/usb/gadget/udc/mv_u3d_core.c
index ea35a248c..dafe74eb9 100644
--- a/kernel/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/kernel/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -1324,6 +1324,9 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
ep->ep.ops = &mv_u3d_ep_ops;
ep->wedge = 0;
usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_u3d_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@@ -1339,14 +1342,20 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
if (i & 1) {
snprintf(name, sizeof(name), "ep%din", i >> 1);
ep->direction = MV_U3D_EP_DIR_IN;
+ ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i >> 1);
ep->direction = MV_U3D_EP_DIR_OUT;
+ ep->ep.caps.dir_out = true;
}
ep->u3d = u3d;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+
ep->ep.ops = &mv_u3d_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep_num = i / 2;
@@ -1758,8 +1767,7 @@ static int mv_u3d_remove(struct platform_device *dev)
usb_del_gadget_udc(&u3d->gadget);
/* free memory allocated in probe */
- if (u3d->trb_pool)
- dma_pool_destroy(u3d->trb_pool);
+ dma_pool_destroy(u3d->trb_pool);
if (u3d->ep_context)
dma_free_coherent(&dev->dev, u3d->ep_context_size,
diff --git a/kernel/drivers/usb/gadget/udc/mv_udc_core.c b/kernel/drivers/usb/gadget/udc/mv_udc_core.c
index 5da37c957..81b6229c7 100644
--- a/kernel/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/kernel/drivers/usb/gadget/udc/mv_udc_core.c
@@ -1257,6 +1257,9 @@ static int eps_init(struct mv_udc *udc)
ep->wedge = 0;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@@ -1269,14 +1272,20 @@ static int eps_init(struct mv_udc *udc)
if (i % 2) {
snprintf(name, sizeof(name), "ep%din", i / 2);
ep->direction = EP_DIR_IN;
+ ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i / 2);
ep->direction = EP_DIR_OUT;
+ ep->ep.caps.dir_out = true;
}
ep->udc = udc;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+
ep->ep.ops = &mv_ep_ops;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
@@ -2091,8 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
}
/* free memory allocated in probe */
- if (udc->dtd_pool)
- dma_pool_destroy(udc->dtd_pool);
+ dma_pool_destroy(udc->dtd_pool);
if (udc->ep_dqh)
dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
diff --git a/kernel/drivers/usb/gadget/udc/net2272.c b/kernel/drivers/usb/gadget/udc/net2272.c
index 195baf3e1..18f5ebd44 100644
--- a/kernel/drivers/usb/gadget/udc/net2272.c
+++ b/kernel/drivers/usb/gadget/udc/net2272.c
@@ -1404,6 +1404,17 @@ net2272_usb_reinit(struct net2272 *dev)
else
ep->fifo_size = 64;
net2272_ep_reset(ep);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
@@ -1826,9 +1837,9 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
if (!e || u.r.wLength > 2)
goto do_stall;
if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
- status = __constant_cpu_to_le16(1);
+ status = cpu_to_le16(1);
else
- status = __constant_cpu_to_le16(0);
+ status = cpu_to_le16(0);
/* don't bother with a request object! */
net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
diff --git a/kernel/drivers/usb/gadget/udc/net2280.c b/kernel/drivers/usb/gadget/udc/net2280.c
index 9871b9019..6706aef90 100644
--- a/kernel/drivers/usb/gadget/udc/net2280.c
+++ b/kernel/drivers/usb/gadget/udc/net2280.c
@@ -74,19 +74,58 @@ static const char driver_desc[] = DRIVER_DESC;
static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
- ep0name,
- "ep-a", "ep-b", "ep-c", "ep-d",
- "ep-e", "ep-f", "ep-g", "ep-h",
-};
-/* Endpoint names for usb3380 advance mode */
-static const char *const ep_name_adv[] = {
- ep0name,
- "ep1in", "ep2out", "ep3in", "ep4out",
- "ep1out", "ep2in", "ep3out", "ep4in",
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info_dft[] = { /* Default endpoint configuration */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-a",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-b",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-c",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-d",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-e",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-f",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-g",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-h",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep1out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep3out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
};
+#undef EP_INFO
+
/* mode 0 == ep-{a,b,c,d} 1K fifo each
* mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
* mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable
@@ -123,6 +162,11 @@ static char *type_string(u8 bmAttributes)
#define valid_bit cpu_to_le32(BIT(VALID_BIT))
#define dma_done_ie cpu_to_le32(BIT(DMA_DONE_INTERRUPT_ENABLE))
+static void ep_clear_seqnum(struct net2280_ep *ep);
+static void stop_activity(struct net2280 *dev,
+ struct usb_gadget_driver *driver);
+static void ep0_start(struct net2280 *dev);
+
/*-------------------------------------------------------------------------*/
static inline void enable_pciirqenb(struct net2280_ep *ep)
{
@@ -142,7 +186,9 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
{
struct net2280 *dev;
struct net2280_ep *ep;
- u32 max, tmp;
+ u32 max;
+ u32 tmp = 0;
+ u32 type;
unsigned long flags;
static const u32 ep_key[9] = { 1, 0, 1, 0, 1, 1, 0, 1, 0 };
int ret = 0;
@@ -198,15 +244,29 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* set type, direction, address; reset fifo counters */
writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
- tmp = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
- if (tmp == USB_ENDPOINT_XFER_INT) {
+
+ if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
+ tmp = readl(&ep->cfg->ep_cfg);
+ /* If USB ep number doesn't match hardware ep number */
+ if ((tmp & 0xf) != usb_endpoint_num(desc)) {
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ goto print_err;
+ }
+ if (ep->is_in)
+ tmp &= ~USB3380_EP_CFG_MASK_IN;
+ else
+ tmp &= ~USB3380_EP_CFG_MASK_OUT;
+ }
+ type = (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+ if (type == USB_ENDPOINT_XFER_INT) {
/* erratum 0105 workaround prevents hs NYET */
if (dev->chiprev == 0100 &&
dev->gadget.speed == USB_SPEED_HIGH &&
!(desc->bEndpointAddress & USB_DIR_IN))
writel(BIT(CLEAR_NAK_OUT_PACKETS_MODE),
&ep->regs->ep_rsp);
- } else if (tmp == USB_ENDPOINT_XFER_BULK) {
+ } else if (type == USB_ENDPOINT_XFER_BULK) {
/* catch some particularly blatant driver bugs */
if ((dev->gadget.speed == USB_SPEED_SUPER && max != 1024) ||
(dev->gadget.speed == USB_SPEED_HIGH && max != 512) ||
@@ -216,10 +276,10 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
goto print_err;
}
}
- ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+ ep->is_iso = (type == USB_ENDPOINT_XFER_ISOC);
/* Enable this endpoint */
if (dev->quirks & PLX_LEGACY) {
- tmp <<= ENDPOINT_TYPE;
+ tmp |= type << ENDPOINT_TYPE;
tmp |= desc->bEndpointAddress;
/* default full fifo lines */
tmp |= (4 << ENDPOINT_BYTE_COUNT);
@@ -228,17 +288,17 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
} else {
/* In Legacy mode, only OUT endpoints are used */
if (dev->enhanced_mode && ep->is_in) {
- tmp <<= IN_ENDPOINT_TYPE;
+ tmp |= type << IN_ENDPOINT_TYPE;
tmp |= BIT(IN_ENDPOINT_ENABLE);
- /* Not applicable to Legacy */
- tmp |= BIT(ENDPOINT_DIRECTION);
} else {
- tmp <<= OUT_ENDPOINT_TYPE;
+ tmp |= type << OUT_ENDPOINT_TYPE;
tmp |= BIT(OUT_ENDPOINT_ENABLE);
tmp |= (ep->is_in << ENDPOINT_DIRECTION);
}
- tmp |= usb_endpoint_num(desc);
+ tmp |= (4 << ENDPOINT_BYTE_COUNT);
+ if (!dev->enhanced_mode)
+ tmp |= usb_endpoint_num(desc);
tmp |= (ep->ep.maxburst << MAX_BURST_SIZE);
}
@@ -256,6 +316,8 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
}
+ if (dev->quirks & PLX_SUPERSPEED)
+ ep_clear_seqnum(ep);
writel(tmp, &ep->cfg->ep_cfg);
/* enable irqs */
@@ -441,6 +503,13 @@ static void ep_reset_338x(struct net2280_regs __iomem *regs,
BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
BIT(DATA_IN_TOKEN_INTERRUPT), &ep->regs->ep_stat);
+
+ tmp = readl(&ep->cfg->ep_cfg);
+ if (ep->is_in)
+ tmp &= ~USB3380_EP_CFG_MASK_IN;
+ else
+ tmp &= ~USB3380_EP_CFG_MASK_OUT;
+ writel(tmp, &ep->cfg->ep_cfg);
}
static void nuke(struct net2280_ep *);
@@ -1468,16 +1537,46 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
spin_lock_irqsave(&dev->lock, flags);
tmp = readl(&dev->usb->usbctl);
dev->softconnect = (is_on != 0);
- if (is_on)
- tmp |= BIT(USB_DETECT_ENABLE);
- else
- tmp &= ~BIT(USB_DETECT_ENABLE);
- writel(tmp, &dev->usb->usbctl);
+ if (is_on) {
+ ep0_start(dev);
+ writel(tmp | BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
+ } else {
+ writel(tmp & ~BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
+ stop_activity(dev, dev->driver);
+ }
+
spin_unlock_irqrestore(&dev->lock, flags);
return 0;
}
+static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ char name[8];
+ struct usb_ep *ep;
+
+ if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) {
+ /* ep-e, ep-f are PIO with only 64 byte fifos */
+ ep = gadget_find_ep_by_name(_gadget, "ep-e");
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+ ep = gadget_find_ep_by_name(_gadget, "ep-f");
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+ }
+
+ /* USB3380: use same address for usb and hardware endpoints */
+ snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
+ usb_endpoint_dir_in(desc) ? "in" : "out");
+ ep = gadget_find_ep_by_name(_gadget, name);
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+
+ return NULL;
+}
+
static int net2280_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
static int net2280_stop(struct usb_gadget *_gadget);
@@ -1489,6 +1588,7 @@ static const struct usb_gadget_ops net2280_ops = {
.pullup = net2280_pullup,
.udc_start = net2280_start,
.udc_stop = net2280_stop,
+ .match_ep = net2280_match_ep,
};
/*-------------------------------------------------------------------------*/
@@ -1813,7 +1913,7 @@ static void defect7374_disable_data_eps(struct net2280 *dev)
for (i = 1; i < 5; i++) {
ep = &dev->ep[i];
- writel(0, &ep->cfg->ep_cfg);
+ writel(i, &ep->cfg->ep_cfg);
}
/* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
@@ -1860,8 +1960,8 @@ static void defect7374_enable_data_eps_zero(struct net2280 *dev)
tmp = ((0 << ENDPOINT_NUMBER) | BIT(ENDPOINT_DIRECTION) |
(2 << OUT_ENDPOINT_TYPE) | (2 << IN_ENDPOINT_TYPE) |
((dev->enhanced_mode) ?
- BIT(OUT_ENDPOINT_ENABLE) : BIT(ENDPOINT_ENABLE)) |
- BIT(IN_ENDPOINT_ENABLE));
+ BIT(OUT_ENDPOINT_ENABLE) | BIT(IN_ENDPOINT_ENABLE) :
+ BIT(ENDPOINT_ENABLE)));
for (i = 1; i < 5; i++)
writel(tmp, &dev->ep[i].cfg->ep_cfg);
@@ -1975,9 +2075,15 @@ static void usb_reset_338x(struct net2280 *dev)
/* clear old dma and irq state */
for (tmp = 0; tmp < 4; tmp++) {
struct net2280_ep *ep = &dev->ep[tmp + 1];
+ struct net2280_dma_regs __iomem *dma;
- if (ep->dma)
+ if (ep->dma) {
abort_dma(ep);
+ } else {
+ dma = &dev->dma[tmp];
+ writel(BIT(DMA_ABORT), &dma->dmastat);
+ writel(0, &dma->dmactl);
+ }
}
writel(~0, &dev->regs->irqstat0), writel(~0, &dev->regs->irqstat1);
@@ -2016,7 +2122,8 @@ static void usb_reinit_228x(struct net2280 *dev)
for (tmp = 0; tmp < 7; tmp++) {
struct net2280_ep *ep = &dev->ep[tmp];
- ep->ep.name = ep_name[tmp];
+ ep->ep.name = ep_info_dft[tmp].name;
+ ep->ep.caps = ep_info_dft[tmp].caps;
ep->dev = dev;
ep->num = tmp;
@@ -2056,7 +2163,10 @@ static void usb_reinit_338x(struct net2280 *dev)
for (i = 0; i < dev->n_ep; i++) {
struct net2280_ep *ep = &dev->ep[i];
- ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i];
+ ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name :
+ ep_info_dft[i].name;
+ ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps :
+ ep_info_dft[i].caps;
ep->dev = dev;
ep->num = i;
@@ -2065,6 +2175,12 @@ static void usb_reinit_338x(struct net2280 *dev)
if (dev->enhanced_mode) {
ep->cfg = &dev->epregs[ne[i]];
+ /*
+ * Set USB endpoint number, hardware allows same number
+ * in both directions.
+ */
+ if (i > 0 && i < 5)
+ writel(ne[i], &ep->cfg->ep_cfg);
ep->regs = (struct net2280_ep_regs __iomem *)
(((void __iomem *)&dev->epregs[ne[i]]) +
ep_reg_addr[i]);
@@ -2874,6 +2990,26 @@ next_endpoints3:
return;
}
+static void usb338x_handle_ep_intr(struct net2280 *dev, u32 stat0)
+{
+ u32 index;
+ u32 bit;
+
+ for (index = 0; index < ARRAY_SIZE(ep_bit); index++) {
+ bit = BIT(ep_bit[index]);
+
+ if (!stat0)
+ break;
+
+ if (!(stat0 & bit))
+ continue;
+
+ stat0 &= ~bit;
+
+ handle_ep_small(&dev->ep[index]);
+ }
+}
+
static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
{
struct net2280_ep *ep;
@@ -3098,20 +3234,31 @@ do_stall:
#undef w_length
next_endpoints:
- /* endpoint data irq ? */
- scratch = stat & 0x7f;
- stat &= ~0x7f;
- for (num = 0; scratch; num++) {
- u32 t;
-
- /* do this endpoint's FIFO and queue need tending? */
- t = BIT(num);
- if ((scratch & t) == 0)
- continue;
- scratch ^= t;
+ if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
+ u32 mask = (BIT(ENDPOINT_0_INTERRUPT) |
+ USB3380_IRQSTAT0_EP_INTR_MASK_IN |
+ USB3380_IRQSTAT0_EP_INTR_MASK_OUT);
+
+ if (stat & mask) {
+ usb338x_handle_ep_intr(dev, stat & mask);
+ stat &= ~mask;
+ }
+ } else {
+ /* endpoint data irq ? */
+ scratch = stat & 0x7f;
+ stat &= ~0x7f;
+ for (num = 0; scratch; num++) {
+ u32 t;
+
+ /* do this endpoint's FIFO and queue need tending? */
+ t = BIT(num);
+ if ((scratch & t) == 0)
+ continue;
+ scratch ^= t;
- ep = &dev->ep[num];
- handle_ep_small(ep);
+ ep = &dev->ep[num];
+ handle_ep_small(ep);
+ }
}
if (stat)
diff --git a/kernel/drivers/usb/gadget/udc/omap_udc.c b/kernel/drivers/usb/gadget/udc/omap_udc.c
index e2fcdb8e5..9b7d39484 100644
--- a/kernel/drivers/usb/gadget/udc/omap_udc.c
+++ b/kernel/drivers/usb/gadget/udc/omap_udc.c
@@ -2579,6 +2579,28 @@ omap_ep_setup(char *name, u8 addr, u8 type,
ep->double_buf = dbuf;
ep->udc = udc;
+ switch (type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ ep->ep.caps.type_iso = true;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ ep->ep.caps.type_bulk = true;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ ep->ep.caps.type_int = true;
+ break;
+ };
+
+ if (addr & USB_DIR_IN)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
ep->maxpacket = maxp;
diff --git a/kernel/drivers/usb/gadget/udc/pch_udc.c b/kernel/drivers/usb/gadget/udc/pch_udc.c
index 613547f07..7a04157ff 100644
--- a/kernel/drivers/usb/gadget/udc/pch_udc.c
+++ b/kernel/drivers/usb/gadget/udc/pch_udc.c
@@ -330,7 +330,7 @@ struct pch_vbus_gpio_data {
* @prot_stall: protcol stall requested
* @irq_registered: irq registered with system
* @mem_region: device memory mapped
- * @registered: driver regsitered with system
+ * @registered: driver registered with system
* @suspended: driver in suspended state
* @connected: gadget driver associated
* @vbus_session: required vbus_session state
@@ -620,9 +620,9 @@ static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
dev->vbus_session = 1;
} else {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
dev->vbus_session = 0;
@@ -1191,9 +1191,9 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
pch_udc_reconnect(dev);
} else {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
}
@@ -1488,11 +1488,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
req->dma_mapped = 0;
}
ep->halted = 1;
- spin_unlock(&dev->lock);
+ spin_lock(&dev->lock);
if (!ep->in)
pch_udc_ep_clear_rrdy(ep);
usb_gadget_giveback_request(&ep->ep, &req->req);
- spin_lock(&dev->lock);
+ spin_unlock(&dev->lock);
ep->halted = halted;
}
@@ -1793,7 +1793,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
}
/* prevent from using desc. - set HOST BUSY */
dma_desc->status |= PCH_UDC_BS_HST_BSY;
- dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+ dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID);
req->td_data = dma_desc;
req->td_data_last = dma_desc;
req->chain_len = 1;
@@ -2414,7 +2414,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
else /* OUT */
dev->gadget.ep0 = &ep->ep;
- spin_unlock(&dev->lock);
+ spin_lock(&dev->lock);
/* If Mass storage Reset */
if ((dev->setup_data.bRequestType == 0x21) &&
(dev->setup_data.bRequest == 0xFF))
@@ -2422,7 +2422,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
/* call gadget with setup data received */
setup_supported = dev->driver->setup(&dev->gadget,
&dev->setup_data);
- spin_lock(&dev->lock);
+ spin_unlock(&dev->lock);
if (dev->setup_data.bRequestType & USB_DIR_IN) {
ep->td_data->status = (ep->td_data->status &
@@ -2594,9 +2594,9 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
empty_req_queue(ep);
}
if (dev->driver) {
- spin_unlock(&dev->lock);
- usb_gadget_udc_reset(&dev->gadget, dev->driver);
spin_lock(&dev->lock);
+ usb_gadget_udc_reset(&dev->gadget, dev->driver);
+ spin_unlock(&dev->lock);
}
}
@@ -2675,9 +2675,9 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
dev->ep[i].halted = 0;
}
dev->stall = 0;
- spin_unlock(&dev->lock);
- ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
+ ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+ spin_unlock(&dev->lock);
}
/**
@@ -2712,9 +2712,9 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
dev->stall = 0;
/* call gadget zero with setup data received */
- spin_unlock(&dev->lock);
- ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
+ ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+ spin_unlock(&dev->lock);
}
/**
@@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
ep->in = ~i & 1;
ep->ep.name = ep_string[i];
ep->ep.ops = &pch_udc_ep_ops;
- if (ep->in)
+ if (ep->in) {
ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
- else
+ ep->ep.caps.dir_in = true;
+ } else {
ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
UDC_EP_REG_SHIFT;
+ ep->ep.caps.dir_out = true;
+ }
+ if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
/* need to set ep->ep.maxpacket and set Default Configuration?*/
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
diff --git a/kernel/drivers/usb/gadget/udc/pxa25x_udc.c b/kernel/drivers/usb/gadget/udc/pxa25x_udc.c
index f6cbe667c..b82cb1485 100644
--- a/kernel/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/kernel/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -1176,6 +1176,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
INIT_LIST_HEAD (&dev->gadget.ep_list);
INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
dev->ep0state = EP0_IDLE;
+ dev->gadget.quirk_altset_not_supp = 1;
/* basic endpoint records init */
for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1821,6 +1822,8 @@ static struct pxa25x_udc memory = {
.name = ep0name,
.ops = &pxa25x_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.reg_udccs = &UDCCS0,
@@ -1833,6 +1836,8 @@ static struct pxa25x_udc memory = {
.name = "ep1in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1846,6 +1851,8 @@ static struct pxa25x_udc memory = {
.name = "ep2out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1861,6 +1868,8 @@ static struct pxa25x_udc memory = {
.name = "ep3in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1874,6 +1883,8 @@ static struct pxa25x_udc memory = {
.name = "ep4out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1888,6 +1899,7 @@ static struct pxa25x_udc memory = {
.name = "ep5in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@@ -1903,6 +1915,8 @@ static struct pxa25x_udc memory = {
.name = "ep6in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1916,6 +1930,8 @@ static struct pxa25x_udc memory = {
.name = "ep7out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1930,6 +1946,8 @@ static struct pxa25x_udc memory = {
.name = "ep8in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1943,6 +1961,8 @@ static struct pxa25x_udc memory = {
.name = "ep9out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1957,6 +1977,7 @@ static struct pxa25x_udc memory = {
.name = "ep10in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@@ -1972,6 +1993,8 @@ static struct pxa25x_udc memory = {
.name = "ep11in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1985,6 +2008,8 @@ static struct pxa25x_udc memory = {
.name = "ep12out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1999,6 +2024,8 @@ static struct pxa25x_udc memory = {
.name = "ep13in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -2012,6 +2039,8 @@ static struct pxa25x_udc memory = {
.name = "ep14out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -2026,6 +2055,7 @@ static struct pxa25x_udc memory = {
.name = "ep15in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
diff --git a/kernel/drivers/usb/gadget/udc/pxa27x_udc.c b/kernel/drivers/usb/gadget/udc/pxa27x_udc.c
index b51226aba..001a3b74a 100644
--- a/kernel/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/kernel/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -1710,6 +1710,7 @@ static void udc_init_data(struct pxa_udc *dev)
INIT_LIST_HEAD(&dev->gadget.ep_list);
INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+ dev->gadget.quirk_altset_not_supp = 1;
ep0_idle(dev);
/* PXA endpoints init */
@@ -2422,7 +2423,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
}
udc->udc_command = mach->udc_command;
} else {
- udc->gpiod = devm_gpiod_get(&pdev->dev, NULL);
+ udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2535,6 +2536,9 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
udc->pullup_resume = udc->pullup_on;
dplus_pullup(udc, 0);
+ if (udc->driver)
+ udc->driver->disconnect(&udc->gadget);
+
return 0;
}
diff --git a/kernel/drivers/usb/gadget/udc/pxa27x_udc.h b/kernel/drivers/usb/gadget/udc/pxa27x_udc.h
index 11e142327..cea2cb79b 100644
--- a/kernel/drivers/usb/gadget/udc/pxa27x_udc.h
+++ b/kernel/drivers/usb/gadget/udc/pxa27x_udc.h
@@ -234,25 +234,35 @@
/*
* Endpoint definition helpers
*/
-#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
-{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \
+{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \
+ .caps = USB_EP_CAPS(ctype, cdir), }, \
.desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
- .bmAttributes = type, \
+ .bmAttributes = USB_ENDPOINT_XFER_ ## type, \
.wMaxPacketSize = maxpkt, }, \
.dev = &memory \
}
-#define USB_EP_BULK(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
-#define USB_EP_ISO(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
-#define USB_EP_INT(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
-#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1)
-#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0)
-#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1)
-#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0)
-#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1)
-#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE)
+#define USB_EP_BULK(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_BULK, cdir)
+#define USB_EP_ISO(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_ISO, cdir)
+#define USB_EP_INT(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_INT, cdir)
+#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0, \
+ USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0, \
+ USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)
#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
{ \
diff --git a/kernel/drivers/usb/gadget/udc/r8a66597-udc.c b/kernel/drivers/usb/gadget/udc/r8a66597-udc.c
index 0293f7169..baa0609a4 100644
--- a/kernel/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/kernel/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1935,6 +1935,16 @@ static int r8a66597_probe(struct platform_device *pdev)
ep->ep.name = r8a66597_ep_name[i];
ep->ep.ops = &r8a66597_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
r8a66597->ep[0].pipenum = 0;
diff --git a/kernel/drivers/usb/gadget/udc/s3c-hsudc.c b/kernel/drivers/usb/gadget/udc/s3c-hsudc.c
index 85a712a03..e9def42ce 100644
--- a/kernel/drivers/usb/gadget/udc/s3c-hsudc.c
+++ b/kernel/drivers/usb/gadget/udc/s3c-hsudc.c
@@ -1005,6 +1005,21 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
hsep->stopped = 0;
hsep->wedge = 0;
+ if (epnum == 0) {
+ hsep->ep.caps.type_control = true;
+ hsep->ep.caps.dir_in = true;
+ hsep->ep.caps.dir_out = true;
+ } else {
+ hsep->ep.caps.type_iso = true;
+ hsep->ep.caps.type_bulk = true;
+ hsep->ep.caps.type_int = true;
+ }
+
+ if (epnum & 1)
+ hsep->ep.caps.dir_in = true;
+ else
+ hsep->ep.caps.dir_out = true;
+
set_index(hsudc, epnum);
writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
}
diff --git a/kernel/drivers/usb/gadget/udc/s3c2410_udc.c b/kernel/drivers/usb/gadget/udc/s3c2410_udc.c
index 99fd9a566..eb3571ee5 100644
--- a/kernel/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/kernel/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -92,40 +92,38 @@ static struct s3c2410_udc_mach_info *udc_info;
static uint32_t s3c2410_ticks = 0;
-static int dprintk(int level, const char *fmt, ...)
+__printf(2, 3)
+static void dprintk(int level, const char *fmt, ...)
{
- static char printk_buf[1024];
static long prevticks;
static int invocation;
+ struct va_format vaf;
va_list args;
- int len;
if (level > USB_S3C2410_DEBUG_LEVEL)
- return 0;
+ return;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
if (s3c2410_ticks != prevticks) {
prevticks = s3c2410_ticks;
invocation = 0;
}
- len = scnprintf(printk_buf,
- sizeof(printk_buf), "%1lu.%02d USB: ",
- prevticks, invocation++);
+ pr_debug("%1lu.%02d USB: %pV", prevticks, invocation++, &vaf);
- va_start(args, fmt);
- len = vscnprintf(printk_buf+len,
- sizeof(printk_buf)-len, fmt, args);
va_end(args);
-
- pr_debug("%s", printk_buf);
- return len;
}
#else
-static int dprintk(int level, const char *fmt, ...)
+__printf(2, 3)
+static void dprintk(int level, const char *fmt, ...)
{
- return 0;
}
#endif
+
static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
{
u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg;
@@ -1693,6 +1691,8 @@ static struct s3c2410_udc memory = {
.name = ep0name,
.ops = &s3c2410_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
},
@@ -1704,6 +1704,8 @@ static struct s3c2410_udc memory = {
.name = "ep1-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1716,6 +1718,8 @@ static struct s3c2410_udc memory = {
.name = "ep2-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1728,6 +1732,8 @@ static struct s3c2410_udc memory = {
.name = "ep3-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1740,6 +1746,8 @@ static struct s3c2410_udc memory = {
.name = "ep4-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
diff --git a/kernel/drivers/usb/gadget/udc/udc-core.c b/kernel/drivers/usb/gadget/udc/udc-core.c
index 7d69931cf..f660afba7 100644
--- a/kernel/drivers/usb/gadget/udc/udc-core.c
+++ b/kernel/drivers/usb/gadget/udc/udc-core.c
@@ -60,13 +60,15 @@ static DEFINE_MUTEX(udc_lock);
int usb_gadget_map_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in)
{
+ struct device *dev = gadget->dev.parent;
+
if (req->length == 0)
return 0;
if (req->num_sgs) {
int mapped;
- mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
+ mapped = dma_map_sg(dev, req->sg, req->num_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (mapped == 0) {
dev_err(&gadget->dev, "failed to map SGs\n");
@@ -75,11 +77,11 @@ int usb_gadget_map_request(struct usb_gadget *gadget,
req->num_mapped_sgs = mapped;
} else {
- req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
+ req->dma = dma_map_single(dev, req->buf, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (dma_mapping_error(&gadget->dev, req->dma)) {
- dev_err(&gadget->dev, "failed to map buffer\n");
+ if (dma_mapping_error(dev, req->dma)) {
+ dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
}
@@ -95,12 +97,12 @@ void usb_gadget_unmap_request(struct usb_gadget *gadget,
return;
if (req->num_mapped_sgs) {
- dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
+ dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
} else {
- dma_unmap_single(&gadget->dev, req->dma, req->length,
+ dma_unmap_single(gadget->dev.parent, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
}
}
@@ -129,6 +131,96 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
/* ------------------------------------------------------------------------- */
+/**
+ * gadget_find_ep_by_name - returns ep whose name is the same as sting passed
+ * in second parameter or NULL if searched endpoint not found
+ * @g: controller to check for quirk
+ * @name: name of searched endpoint
+ */
+struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name)
+{
+ struct usb_ep *ep;
+
+ gadget_for_each_ep(ep, g) {
+ if (!strcmp(ep->name, name))
+ return ep;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gadget_find_ep_by_name);
+
+/* ------------------------------------------------------------------------- */
+
+int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
+ struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ u8 type;
+ u16 max;
+ int num_req_streams = 0;
+
+ /* endpoint already claimed? */
+ if (ep->claimed)
+ return 0;
+
+ type = usb_endpoint_type(desc);
+ max = 0x7ff & usb_endpoint_maxp(desc);
+
+ if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
+ return 0;
+ if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
+ return 0;
+
+ if (max > ep->maxpacket_limit)
+ return 0;
+
+ /* "high bandwidth" works only at high speed */
+ if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
+ return 0;
+
+ switch (type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* only support ep0 for portable CONTROL traffic */
+ return 0;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (!ep->caps.type_iso)
+ return 0;
+ /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
+ if (!gadget_is_dualspeed(gadget) && max > 1023)
+ return 0;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (!ep->caps.type_bulk)
+ return 0;
+ if (ep_comp && gadget_is_superspeed(gadget)) {
+ /* Get the number of required streams from the
+ * EP companion descriptor and see if the EP
+ * matches it
+ */
+ num_req_streams = ep_comp->bmAttributes & 0x1f;
+ if (num_req_streams > ep->max_streams)
+ return 0;
+ }
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ /* Bulk endpoints handle interrupt transfers,
+ * except the toggle-quirky iso-synch kind
+ */
+ if (!ep->caps.type_int && !ep->caps.type_bulk)
+ return 0;
+ /* INT: limit 64 bytes full speed, 1024 high/super speed */
+ if (!gadget_is_dualspeed(gadget) && max > 64)
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
+
+/* ------------------------------------------------------------------------- */
+
static void usb_gadget_state_work(struct work_struct *work)
{
struct usb_gadget *gadget = work_to_gadget(work);
diff --git a/kernel/drivers/usb/gadget/udc/udc-xilinx.c b/kernel/drivers/usb/gadget/udc/udc-xilinx.c
index 1f2427447..1cbb0ac6b 100644
--- a/kernel/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/kernel/drivers/usb/gadget/udc/udc-xilinx.c
@@ -1317,12 +1317,21 @@ static void xudc_eps_init(struct xusb_udc *udc)
snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number);
ep->ep_usb.name = ep->name;
ep->ep_usb.ops = &xusb_ep_ops;
+
+ ep->ep_usb.caps.type_iso = true;
+ ep->ep_usb.caps.type_bulk = true;
+ ep->ep_usb.caps.type_int = true;
} else {
ep->ep_usb.name = ep0name;
usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET);
ep->ep_usb.ops = &xusb_ep0_ops;
+
+ ep->ep_usb.caps.type_control = true;
}
+ ep->ep_usb.caps.dir_in = true;
+ ep->ep_usb.caps.dir_out = true;
+
ep->udc = udc;
ep->epnumber = ep_number;
ep->desc = NULL;