summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/usb/gadget/function
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/usb/gadget/function')
-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
34 files changed, 956 insertions, 1403 deletions
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;