summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/function
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-04 18:03:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-04 18:03:51 -0700
commit8f28472a739e8e39adc6e64ee5b460df039f0e4f (patch)
tree979e35f3d1d2be94c06c942bcdc9ee68cbebaacb /drivers/usb/gadget/function
parent4ac4d584886a4f47f8ff3bca0f32ff9a2987d3e5 (diff)
parentc034a43e72dda58e4a184d71f5502ef356e04453 (diff)
Merge tag 'usb-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH: "Here is the big USB patchset for 4.12-rc1. Lots of good stuff here, after many many many attempts, the kernel finally has a working typeC interface, many thanks to Heikki and Guenter and others who have taken the time to get this merged. It wasn't an easy path for them at all. There's also a staging driver that uses this new api, which is why it's coming in through this tree. Along with that, there's the usual huge number of changes for gadget drivers, xhci, and other stuff. Johan also finally refactored pretty much every driver that was looking at USB endpoints to do it in a common way, which will help prevent any "badly-formed" devices from causing problems in drivers. That too wasn't a simple task. All of these have been in linux-next for a while with no reported issues" * tag 'usb-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (263 commits) staging: typec: Fairchild FUSB302 Type-c chip driver staging: typec: Type-C Port Controller Interface driver (tcpci) staging: typec: USB Type-C Port Manager (tcpm) usb: host: xhci: remove #ifdef around PM functions usb: musb: don't mark of_dev_auxdata as initdata usb: misc: legousbtower: Fix buffers on stack USB: Revert "cdc-wdm: fix "out-of-sync" due to missing notifications" usb: Make sure usb/phy/of gets built-in USB: storage: e-mail update in drivers/usb/storage/unusual_devs.h usb: host: xhci: print correct command ring address usb: host: xhci: delete sp_dma_buffers for scratchpad usb: host: xhci: using correct specification chapter reference for DCBAAP xhci: switch to pci_alloc_irq_vectors usb: host: xhci-plat: set resume_quirk() for R-Car controllers usb: host: xhci-plat: add resume_quirk() usb: host: xhci-plat: enable clk in resume timing usb: host: plat: Enable xHCI plat runtime PM USB: serial: ftdi_sio: add device ID for Microsemi/Arrow SF2PLUS Dev Kit USB: serial: constify static arrays usb: fix some references for /proc/bus/usb ...
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r--drivers/usb/gadget/function/f_fs.c80
-rw-r--r--drivers/usb/gadget/function/u_ether.c24
-rw-r--r--drivers/usb/gadget/function/u_fs.h14
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c16
4 files changed, 45 insertions, 89 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index a0085571824d..71dd27c0d7f2 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -246,7 +246,6 @@ EXPORT_SYMBOL_GPL(ffs_lock);
static struct ffs_dev *_ffs_find_dev(const char *name);
static struct ffs_dev *_ffs_alloc_dev(void);
-static int _ffs_name_dev(struct ffs_dev *dev, const char *name);
static void _ffs_free_dev(struct ffs_dev *dev);
static void *ffs_acquire_dev(const char *dev_name);
static void ffs_release_dev(struct ffs_data *ffs_data);
@@ -1571,14 +1570,14 @@ static void ffs_data_get(struct ffs_data *ffs)
{
ENTER();
- atomic_inc(&ffs->ref);
+ refcount_inc(&ffs->ref);
}
static void ffs_data_opened(struct ffs_data *ffs)
{
ENTER();
- atomic_inc(&ffs->ref);
+ refcount_inc(&ffs->ref);
if (atomic_add_return(1, &ffs->opened) == 1 &&
ffs->state == FFS_DEACTIVATED) {
ffs->state = FFS_CLOSING;
@@ -1590,7 +1589,7 @@ static void ffs_data_put(struct ffs_data *ffs)
{
ENTER();
- if (unlikely(atomic_dec_and_test(&ffs->ref))) {
+ if (unlikely(refcount_dec_and_test(&ffs->ref))) {
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
@@ -1635,7 +1634,7 @@ static struct ffs_data *ffs_data_new(void)
ENTER();
- atomic_set(&ffs->ref, 1);
+ refcount_set(&ffs->ref, 1);
atomic_set(&ffs->opened, 0);
ffs->state = FFS_READ_DESCRIPTORS;
mutex_init(&ffs->mutex);
@@ -3302,9 +3301,10 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name)
{
struct ffs_dev *dev;
+ if (!name)
+ return NULL;
+
list_for_each_entry(dev, &ffs_devices, entry) {
- if (!dev->name || !name)
- continue;
if (strcmp(dev->name, name) == 0)
return dev;
}
@@ -3380,42 +3380,11 @@ static void ffs_free_inst(struct usb_function_instance *f)
kfree(opts);
}
-#define MAX_INST_NAME_LEN 40
-
static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name)
{
- struct f_fs_opts *opts;
- char *ptr;
- const char *tmp;
- int name_len, ret;
-
- name_len = strlen(name) + 1;
- if (name_len > MAX_INST_NAME_LEN)
+ if (strlen(name) >= FIELD_SIZEOF(struct ffs_dev, name))
return -ENAMETOOLONG;
-
- ptr = kstrndup(name, name_len, GFP_KERNEL);
- if (!ptr)
- return -ENOMEM;
-
- opts = to_f_fs_opts(fi);
- tmp = NULL;
-
- ffs_dev_lock();
-
- tmp = opts->dev->name_allocated ? opts->dev->name : NULL;
- ret = _ffs_name_dev(opts->dev, ptr);
- if (ret) {
- kfree(ptr);
- ffs_dev_unlock();
- return ret;
- }
- opts->dev->name_allocated = true;
-
- ffs_dev_unlock();
-
- kfree(tmp);
-
- return 0;
+ return ffs_name_dev(to_f_fs_opts(fi)->dev, name);
}
static struct usb_function_instance *ffs_alloc_inst(void)
@@ -3545,32 +3514,19 @@ static struct ffs_dev *_ffs_alloc_dev(void)
return dev;
}
-/*
- * ffs_lock must be taken by the caller of this function
- * The caller is responsible for "name" being available whenever f_fs needs it
- */
-static int _ffs_name_dev(struct ffs_dev *dev, const char *name)
+int ffs_name_dev(struct ffs_dev *dev, const char *name)
{
struct ffs_dev *existing;
+ int ret = 0;
- existing = _ffs_do_find_dev(name);
- if (existing)
- return -EBUSY;
-
- dev->name = name;
-
- return 0;
-}
+ ffs_dev_lock();
-/*
- * The caller is responsible for "name" being available whenever f_fs needs it
- */
-int ffs_name_dev(struct ffs_dev *dev, const char *name)
-{
- int ret;
+ existing = _ffs_do_find_dev(name);
+ if (!existing)
+ strlcpy(dev->name, name, ARRAY_SIZE(dev->name));
+ else if (existing != dev)
+ ret = -EBUSY;
- ffs_dev_lock();
- ret = _ffs_name_dev(dev, name);
ffs_dev_unlock();
return ret;
@@ -3600,8 +3556,6 @@ EXPORT_SYMBOL_GPL(ffs_single_dev);
static void _ffs_free_dev(struct ffs_dev *dev)
{
list_del(&dev->entry);
- if (dev->name_allocated)
- kfree(dev->name);
/* Clear the private_data pointer to stop incorrect dev access */
if (dev->ffs_data)
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index c3cab77181d4..a8b40d07e927 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -178,6 +178,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req);
static int
rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
{
+ struct usb_gadget *g = dev->gadget;
struct sk_buff *skb;
int retval = -ENOMEM;
size_t size = 0;
@@ -209,8 +210,11 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
*/
size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA;
size += dev->port_usb->header_len;
- size += out->maxpacket - 1;
- size -= size % out->maxpacket;
+
+ if (g->quirk_ep_out_aligned_size) {
+ size += out->maxpacket - 1;
+ size -= size % out->maxpacket;
+ }
if (dev->port_usb->is_fixed)
size = max_t(size_t, size, dev->port_usb->fixed_out_len);
@@ -401,13 +405,12 @@ done:
static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
{
struct usb_request *req;
+ struct usb_request *tmp;
unsigned long flags;
/* fill unused rxq slots with some skb */
spin_lock_irqsave(&dev->req_lock, flags);
- while (!list_empty(&dev->rx_reqs)) {
- req = container_of(dev->rx_reqs.next,
- struct usb_request, list);
+ list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
list_del_init(&req->list);
spin_unlock_irqrestore(&dev->req_lock, flags);
@@ -527,7 +530,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- req = container_of(dev->tx_reqs.next, struct usb_request, list);
+ req = list_first_entry(&dev->tx_reqs, struct usb_request, list);
list_del(&req->list);
/* temporarily stop TX queue when the freelist empties */
@@ -1122,6 +1125,7 @@ void gether_disconnect(struct gether *link)
{
struct eth_dev *dev = link->ioport;
struct usb_request *req;
+ struct usb_request *tmp;
WARN_ON(!dev);
if (!dev)
@@ -1138,9 +1142,7 @@ void gether_disconnect(struct gether *link)
*/
usb_ep_disable(link->in_ep);
spin_lock(&dev->req_lock);
- while (!list_empty(&dev->tx_reqs)) {
- req = container_of(dev->tx_reqs.next,
- struct usb_request, list);
+ list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) {
list_del(&req->list);
spin_unlock(&dev->req_lock);
@@ -1152,9 +1154,7 @@ void gether_disconnect(struct gether *link)
usb_ep_disable(link->out_ep);
spin_lock(&dev->req_lock);
- while (!list_empty(&dev->rx_reqs)) {
- req = container_of(dev->rx_reqs.next,
- struct usb_request, list);
+ list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
list_del(&req->list);
spin_unlock(&dev->req_lock);
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h
index 4b6969451cdc..4378cc2fcac3 100644
--- a/drivers/usb/gadget/function/u_fs.h
+++ b/drivers/usb/gadget/function/u_fs.h
@@ -20,6 +20,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
+#include <linux/refcount.h>
#ifdef VERBOSE_DEBUG
#ifndef pr_vdebug
@@ -39,15 +40,16 @@
struct f_fs_opts;
struct ffs_dev {
- const char *name;
- bool name_allocated;
- bool mounted;
- bool desc_ready;
- bool single;
struct ffs_data *ffs_data;
struct f_fs_opts *opts;
struct list_head entry;
+ char name[41];
+
+ bool mounted;
+ bool desc_ready;
+ bool single;
+
int (*ffs_ready_callback)(struct ffs_data *ffs);
void (*ffs_closed_callback)(struct ffs_data *ffs);
void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev);
@@ -177,7 +179,7 @@ struct ffs_data {
struct completion ep0req_completion; /* P: mutex */
/* reference counter */
- atomic_t ref;
+ refcount_t ref;
/* how many files are opened (EP0 and others) */
atomic_t opened;
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 4e037d2a7a60..844cb738bafd 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -2125,7 +2125,7 @@ static struct configfs_item_operations uvc_item_ops = {
.release = uvc_attr_release,
};
-#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \
+#define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
static ssize_t f_uvc_opts_##cname##_show( \
struct config_item *item, char *page) \
{ \
@@ -2168,16 +2168,16 @@ end: \
return ret; \
} \
\
-UVC_ATTR(f_uvc_opts_, cname, aname)
+UVC_ATTR(f_uvc_opts_, cname, cname)
#define identity_conv(x) (x)
-UVCG_OPTS_ATTR(streaming_interval, identity_conv, kstrtou8, u8, identity_conv,
- 16);
-UVCG_OPTS_ATTR(streaming_maxpacket, le16_to_cpu, kstrtou16, u16, le16_to_cpu,
- 3072);
-UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv,
- 15);
+UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv,
+ kstrtou8, u8, identity_conv, 16);
+UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu,
+ kstrtou16, u16, le16_to_cpu, 3072);
+UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv,
+ kstrtou8, u8, identity_conv, 15);
#undef identity_conv