summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/composite.c78
-rw-r--r--drivers/usb/gadget/function/f_ncm.c59
-rw-r--r--drivers/usb/gadget/function/f_printer.c16
-rw-r--r--drivers/usb/gadget/function/f_tcm.c7
-rw-r--r--drivers/usb/gadget/function/f_uac1_legacy.c2
-rw-r--r--drivers/usb/gadget/function/f_uac2.c7
-rw-r--r--drivers/usb/gadget/function/u_ether.c2
-rw-r--r--drivers/usb/gadget/u_f.h38
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c13
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_ep.c16
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c7
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c11
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c2
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c3
-rw-r--r--drivers/usb/gadget/udc/net2280.c4
-rw-r--r--drivers/usb/gadget/udc/s3c2410_udc.c4
17 files changed, 196 insertions, 75 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index d98ca1566e95..f75ff1a75dc4 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -96,40 +96,43 @@ function_descriptors(struct usb_function *f,
}
/**
- * next_ep_desc() - advance to the next EP descriptor
+ * next_desc() - advance to the next desc_type descriptor
* @t: currect pointer within descriptor array
+ * @desc_type: descriptor type
*
- * Return: next EP descriptor or NULL
+ * Return: next desc_type descriptor or NULL
*
- * Iterate over @t until either EP descriptor found or
+ * Iterate over @t until either desc_type descriptor found or
* NULL (that indicates end of list) encountered
*/
static struct usb_descriptor_header**
-next_ep_desc(struct usb_descriptor_header **t)
+next_desc(struct usb_descriptor_header **t, u8 desc_type)
{
for (; *t; t++) {
- if ((*t)->bDescriptorType == USB_DT_ENDPOINT)
+ if ((*t)->bDescriptorType == desc_type)
return t;
}
return NULL;
}
/*
- * for_each_ep_desc()- iterate over endpoint descriptors in the
- * descriptors list
- * @start: pointer within descriptor array.
- * @ep_desc: endpoint descriptor to use as the loop cursor
+ * for_each_desc() - iterate over desc_type descriptors in the
+ * descriptors list
+ * @start: pointer within descriptor array.
+ * @iter_desc: desc_type descriptor to use as the loop cursor
+ * @desc_type: wanted descriptr type
*/
-#define for_each_ep_desc(start, ep_desc) \
- for (ep_desc = next_ep_desc(start); \
- ep_desc; ep_desc = next_ep_desc(ep_desc+1))
+#define for_each_desc(start, iter_desc, desc_type) \
+ for (iter_desc = next_desc(start, desc_type); \
+ iter_desc; iter_desc = next_desc(iter_desc + 1, desc_type))
/**
- * config_ep_by_speed() - configures the given endpoint
+ * config_ep_by_speed_and_alt() - configures the given endpoint
* according to gadget speed.
* @g: pointer to the gadget
* @f: usb function
* @_ep: the endpoint to configure
+ * @alt: alternate setting number
*
* Return: error code, 0 on success
*
@@ -142,11 +145,13 @@ next_ep_desc(struct usb_descriptor_header **t)
* Note: the supplied function should hold all the descriptors
* for supported speeds
*/
-int config_ep_by_speed(struct usb_gadget *g,
- struct usb_function *f,
- struct usb_ep *_ep)
+int config_ep_by_speed_and_alt(struct usb_gadget *g,
+ struct usb_function *f,
+ struct usb_ep *_ep,
+ u8 alt)
{
struct usb_endpoint_descriptor *chosen_desc = NULL;
+ struct usb_interface_descriptor *int_desc = NULL;
struct usb_descriptor_header **speed_desc = NULL;
struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
@@ -182,8 +187,21 @@ int config_ep_by_speed(struct usb_gadget *g,
default:
speed_desc = f->fs_descriptors;
}
+
+ /* find correct alternate setting descriptor */
+ for_each_desc(speed_desc, d_spd, USB_DT_INTERFACE) {
+ int_desc = (struct usb_interface_descriptor *)*d_spd;
+
+ if (int_desc->bAlternateSetting == alt) {
+ speed_desc = d_spd;
+ goto intf_found;
+ }
+ }
+ return -EIO;
+
+intf_found:
/* find descriptors */
- for_each_ep_desc(speed_desc, d_spd) {
+ for_each_desc(speed_desc, d_spd, USB_DT_ENDPOINT) {
chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;
if (chosen_desc->bEndpointAddress == _ep->address)
goto ep_found;
@@ -237,6 +255,32 @@ ep_found:
}
return 0;
}
+EXPORT_SYMBOL_GPL(config_ep_by_speed_and_alt);
+
+/**
+ * config_ep_by_speed() - configures the given endpoint
+ * according to gadget speed.
+ * @g: pointer to the gadget
+ * @f: usb function
+ * @_ep: the endpoint to configure
+ *
+ * Return: error code, 0 on success
+ *
+ * This function chooses the right descriptors for a given
+ * endpoint according to gadget speed and saves it in the
+ * endpoint desc field. If the endpoint already has a descriptor
+ * assigned to it - overwrites it with currently corresponding
+ * descriptor. The endpoint maxpacket field is updated according
+ * to the chosen descriptor.
+ * Note: the supplied function should hold all the descriptors
+ * for supported speeds
+ */
+int config_ep_by_speed(struct usb_gadget *g,
+ struct usb_function *f,
+ struct usb_ep *_ep)
+{
+ return config_ep_by_speed_and_alt(g, f, _ep, 0);
+}
EXPORT_SYMBOL_GPL(config_ep_by_speed);
/**
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 1d900081b1f0..92a7c3a83945 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -85,8 +85,10 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f)
/* peak (theoretical) bulk transfer rate in bits-per-second */
static inline unsigned ncm_bitrate(struct usb_gadget *g)
{
- if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
- return 13 * 1024 * 8 * 1000 * 8;
+ if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS)
+ return 4250000000U;
+ else if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
+ return 3750000000U;
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
return 13 * 512 * 8 * 1000 * 8;
else
@@ -1181,9 +1183,11 @@ static int ncm_unwrap_ntb(struct gether *port,
int ndp_index;
unsigned dg_len, dg_len2;
unsigned ndp_len;
+ unsigned block_len;
struct sk_buff *skb2;
int ret = -EINVAL;
- unsigned max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
+ unsigned ntb_max = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize);
+ unsigned frame_max = le16_to_cpu(ecm_desc.wMaxSegmentSize);
const struct ndp_parser_opts *opts = ncm->parser_opts;
unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
int dgram_counter;
@@ -1205,8 +1209,9 @@ static int ncm_unwrap_ntb(struct gether *port,
}
tmp++; /* skip wSequence */
+ block_len = get_ncm(&tmp, opts->block_length);
/* (d)wBlockLength */
- if (get_ncm(&tmp, opts->block_length) > max_size) {
+ if (block_len > ntb_max) {
INFO(port->func.config->cdev, "OUT size exceeded\n");
goto err;
}
@@ -1215,15 +1220,23 @@ static int ncm_unwrap_ntb(struct gether *port,
/* Run through all the NDP's in the NTB */
do {
- /* NCM 3.2 */
- if (((ndp_index % 4) != 0) &&
- (ndp_index < opts->nth_size)) {
+ /*
+ * NCM 3.2
+ * dwNdpIndex
+ */
+ if (((ndp_index % 4) != 0) ||
+ (ndp_index < opts->nth_size) ||
+ (ndp_index > (block_len -
+ opts->ndp_size))) {
INFO(port->func.config->cdev, "Bad index: %#X\n",
ndp_index);
goto err;
}
- /* walk through NDP */
+ /*
+ * walk through NDP
+ * dwSignature
+ */
tmp = (void *)(skb->data + ndp_index);
if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
@@ -1234,14 +1247,15 @@ static int ncm_unwrap_ntb(struct gether *port,
ndp_len = get_unaligned_le16(tmp++);
/*
* NCM 3.3.1
+ * wLength
* entry is 2 items
* item size is 16/32 bits, opts->dgram_item_len * 2 bytes
* minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry
* Each entry is a dgram index and a dgram length.
*/
if ((ndp_len < opts->ndp_size
- + 2 * 2 * (opts->dgram_item_len * 2))
- || (ndp_len % opts->ndplen_align != 0)) {
+ + 2 * 2 * (opts->dgram_item_len * 2)) ||
+ (ndp_len % opts->ndplen_align != 0)) {
INFO(port->func.config->cdev, "Bad NDP length: %#X\n",
ndp_len);
goto err;
@@ -1258,8 +1272,21 @@ static int ncm_unwrap_ntb(struct gether *port,
do {
index = index2;
+ /* wDatagramIndex[0] */
+ if ((index < opts->nth_size) ||
+ (index > block_len - opts->dpe_size)) {
+ INFO(port->func.config->cdev,
+ "Bad index: %#X\n", index);
+ goto err;
+ }
+
dg_len = dg_len2;
- if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */
+ /*
+ * wDatagramLength[0]
+ * ethernet hdr + crc or larger than max frame size
+ */
+ if ((dg_len < 14 + crc_len) ||
+ (dg_len > frame_max)) {
INFO(port->func.config->cdev,
"Bad dgram length: %#X\n", dg_len);
goto err;
@@ -1283,6 +1310,13 @@ static int ncm_unwrap_ntb(struct gether *port,
index2 = get_ncm(&tmp, opts->dgram_item_len);
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
+ /* wDatagramIndex[1] */
+ if (index2 > block_len - opts->dpe_size) {
+ INFO(port->func.config->cdev,
+ "Bad index: %#X\n", index2);
+ goto err;
+ }
+
/*
* Copy the data into a new skb.
* This ensures the truesize is correct
@@ -1299,7 +1333,6 @@ static int ncm_unwrap_ntb(struct gether *port,
ndp_len -= 2 * (opts->dgram_item_len * 2);
dgram_counter++;
-
if (index2 == 0 || dg_len2 == 0)
break;
} while (ndp_len > 2 * (opts->dgram_item_len * 2));
@@ -1503,7 +1536,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
fs_ncm_notify_desc.bEndpointAddress;
status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
- ncm_ss_function, NULL);
+ ncm_ss_function, ncm_ss_function);
if (status)
goto fail;
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 9c7ed2539ff7..8ed1295d7e35 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -31,6 +31,7 @@
#include <linux/types.h>
#include <linux/ctype.h>
#include <linux/cdev.h>
+#include <linux/kref.h>
#include <asm/byteorder.h>
#include <linux/io.h>
@@ -64,7 +65,7 @@ struct printer_dev {
struct usb_gadget *gadget;
s8 interface;
struct usb_ep *in_ep, *out_ep;
-
+ struct kref kref;
struct list_head rx_reqs; /* List of free RX structs */
struct list_head rx_reqs_active; /* List of Active RX xfers */
struct list_head rx_buffers; /* List of completed xfers */
@@ -218,6 +219,13 @@ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget,
/*-------------------------------------------------------------------------*/
+static void printer_dev_free(struct kref *kref)
+{
+ struct printer_dev *dev = container_of(kref, struct printer_dev, kref);
+
+ kfree(dev);
+}
+
static struct usb_request *
printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags)
{
@@ -348,6 +356,7 @@ printer_open(struct inode *inode, struct file *fd)
spin_unlock_irqrestore(&dev->lock, flags);
+ kref_get(&dev->kref);
DBG(dev, "printer_open returned %x\n", ret);
return ret;
}
@@ -365,6 +374,7 @@ printer_close(struct inode *inode, struct file *fd)
dev->printer_status &= ~PRINTER_SELECTED;
spin_unlock_irqrestore(&dev->lock, flags);
+ kref_put(&dev->kref, printer_dev_free);
DBG(dev, "printer_close\n");
return 0;
@@ -1350,7 +1360,8 @@ static void gprinter_free(struct usb_function *f)
struct f_printer_opts *opts;
opts = container_of(f->fi, struct f_printer_opts, func_inst);
- kfree(dev);
+
+ kref_put(&dev->kref, printer_dev_free);
mutex_lock(&opts->lock);
--opts->refcnt;
mutex_unlock(&opts->lock);
@@ -1419,6 +1430,7 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi)
return ERR_PTR(-ENOMEM);
}
+ kref_init(&dev->kref);
++opts->refcnt;
dev->minor = opts->minor;
dev->pnp_string = opts->pnp_string;
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 7f01f78b1d23..f6d203fec495 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -751,12 +751,13 @@ static int uasp_alloc_stream_res(struct f_uas *fu, struct uas_stream *stream)
goto err_sts;
return 0;
+
err_sts:
- usb_ep_free_request(fu->ep_status, stream->req_status);
- stream->req_status = NULL;
-err_out:
usb_ep_free_request(fu->ep_out, stream->req_out);
stream->req_out = NULL;
+err_out:
+ usb_ep_free_request(fu->ep_in, stream->req_in);
+ stream->req_in = NULL;
out:
return -ENOMEM;
}
diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c
index 6677ae932de0..06ee6e901808 100644
--- a/drivers/usb/gadget/function/f_uac1_legacy.c
+++ b/drivers/usb/gadget/function/f_uac1_legacy.c
@@ -336,7 +336,9 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
/* Copy buffer is full, add it to the play_queue */
if (audio_buf_size - copy_buf->actual < req->actual) {
+ spin_lock_irq(&audio->lock);
list_add_tail(&copy_buf->list, &audio->play_queue);
+ spin_unlock_irq(&audio->lock);
schedule_work(&audio->playback_work);
copy_buf = f_audio_buffer_alloc(audio_buf_size);
if (IS_ERR(copy_buf))
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index db2d4980cb35..3633df6d7610 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -215,10 +215,7 @@ static struct uac2_ac_header_descriptor ac_hdr_desc = {
.bDescriptorSubtype = UAC_MS_HEADER,
.bcdADC = cpu_to_le16(0x200),
.bCategory = UAC2_FUNCTION_IO_BOX,
- .wTotalLength = cpu_to_le16(sizeof in_clk_src_desc
- + sizeof out_clk_src_desc + sizeof usb_out_it_desc
- + sizeof io_in_it_desc + sizeof usb_in_ot_desc
- + sizeof io_out_ot_desc),
+ /* .wTotalLength = DYNAMIC */
.bmControls = 0,
};
@@ -501,7 +498,7 @@ static void setup_descriptor(struct f_uac2_opts *opts)
as_in_hdr_desc.bTerminalLink = usb_in_ot_desc.bTerminalID;
iad_desc.bInterfaceCount = 1;
- ac_hdr_desc.wTotalLength = 0;
+ ac_hdr_desc.wTotalLength = cpu_to_le16(sizeof(ac_hdr_desc));
if (EPIN_EN(opts)) {
u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index fbe96ef1ac7a..891e9f7f40d5 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -93,7 +93,7 @@ struct eth_dev {
static inline int qlen(struct usb_gadget *gadget, unsigned qmult)
{
if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH ||
- gadget->speed == USB_SPEED_SUPER))
+ gadget->speed >= USB_SPEED_SUPER))
return qmult * DEFAULT_QLEN;
else
return DEFAULT_QLEN;
diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h
index eaa13fd3dc7f..e313c3b8dcb1 100644
--- a/drivers/usb/gadget/u_f.h
+++ b/drivers/usb/gadget/u_f.h
@@ -14,6 +14,7 @@
#define __U_F_H__
#include <linux/usb/gadget.h>
+#include <linux/overflow.h>
/* Variable Length Array Macros **********************************************/
#define vla_group(groupname) size_t groupname##__next = 0
@@ -21,21 +22,36 @@
#define vla_item(groupname, type, name, n) \
size_t groupname##_##name##__offset = ({ \
- size_t align_mask = __alignof__(type) - 1; \
- size_t offset = (groupname##__next + align_mask) & ~align_mask;\
- size_t size = (n) * sizeof(type); \
- groupname##__next = offset + size; \
+ size_t offset = 0; \
+ if (groupname##__next != SIZE_MAX) { \
+ size_t align_mask = __alignof__(type) - 1; \
+ size_t size = array_size(n, sizeof(type)); \
+ offset = (groupname##__next + align_mask) & \
+ ~align_mask; \
+ if (check_add_overflow(offset, size, \
+ &groupname##__next)) { \
+ groupname##__next = SIZE_MAX; \
+ offset = 0; \
+ } \
+ } \
offset; \
})
#define vla_item_with_sz(groupname, type, name, n) \
- size_t groupname##_##name##__sz = (n) * sizeof(type); \
- size_t groupname##_##name##__offset = ({ \
- size_t align_mask = __alignof__(type) - 1; \
- size_t offset = (groupname##__next + align_mask) & ~align_mask;\
- size_t size = groupname##_##name##__sz; \
- groupname##__next = offset + size; \
- offset; \
+ size_t groupname##_##name##__sz = array_size(n, sizeof(type)); \
+ size_t groupname##_##name##__offset = ({ \
+ size_t offset = 0; \
+ if (groupname##__next != SIZE_MAX) { \
+ size_t align_mask = __alignof__(type) - 1; \
+ offset = (groupname##__next + align_mask) & \
+ ~align_mask; \
+ if (check_add_overflow(offset, groupname##_##name##__sz,\
+ &groupname##__next)) { \
+ groupname##__next = SIZE_MAX; \
+ offset = 0; \
+ } \
+ } \
+ offset; \
})
#define vla_ptr(ptr, groupname, name) \
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 58e5b015d40e..bebe814f55e6 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -870,7 +870,7 @@ static int usba_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
u32 status;
DBG(DBG_GADGET | DBG_QUEUE, "ep_dequeue: %s, req %p\n",
- ep->ep.name, req);
+ ep->ep.name, _req);
spin_lock_irqsave(&udc->lock, flags);
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index cc4a16e253ac..3d33499db50b 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -282,6 +282,7 @@ static void bdc_mem_init(struct bdc *bdc, bool reinit)
* in that case reinit is passed as 1
*/
if (reinit) {
+ int i;
/* Enable interrupts */
temp = bdc_readl(bdc->regs, BDC_BDCSC);
temp |= BDC_GIE;
@@ -291,6 +292,9 @@ static void bdc_mem_init(struct bdc *bdc, bool reinit)
/* Initialize SRR to 0 */
memset(bdc->srr.sr_bds, 0,
NUM_SR_ENTRIES * sizeof(struct bdc_bd));
+ /* clear ep flags to avoid post disconnect stops/deconfigs */
+ for (i = 1; i < bdc->num_eps; ++i)
+ bdc->bdc_ep_array[i]->flags = 0;
} else {
/* One time initiaization only */
/* Enable status report function pointers */
@@ -601,9 +605,14 @@ static int bdc_remove(struct platform_device *pdev)
static int bdc_suspend(struct device *dev)
{
struct bdc *bdc = dev_get_drvdata(dev);
+ int ret;
- clk_disable_unprepare(bdc->clk);
- return 0;
+ /* Halt the controller */
+ ret = bdc_stop(bdc);
+ if (!ret)
+ clk_disable_unprepare(bdc->clk);
+
+ return ret;
}
static int bdc_resume(struct device *dev)
diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c
index d49c6dc1082d..9ddc0b4e92c9 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_ep.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c
@@ -615,7 +615,6 @@ int bdc_ep_enable(struct bdc_ep *ep)
}
bdc_dbg_bd_list(bdc, ep);
/* only for ep0: config ep is called for ep0 from connect event */
- ep->flags |= BDC_EP_ENABLED;
if (ep->ep_num == 1)
return ret;
@@ -759,10 +758,13 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req)
__func__, ep->name, start_bdi, end_bdi);
dev_dbg(bdc->dev, "ep_dequeue ep=%p ep->desc=%p\n",
ep, (void *)ep->usb_ep.desc);
- /* Stop the ep to see where the HW is ? */
- ret = bdc_stop_ep(bdc, ep->ep_num);
- /* if there is an issue with stopping ep, then no need to go further */
- if (ret)
+ /* if still connected, stop the ep to see where the HW is ? */
+ if (!(bdc_readl(bdc->regs, BDC_USPC) & BDC_PST_MASK)) {
+ ret = bdc_stop_ep(bdc, ep->ep_num);
+ /* if there is an issue, then no need to go further */
+ if (ret)
+ return 0;
+ } else
return 0;
/*
@@ -1911,7 +1913,9 @@ static int bdc_gadget_ep_disable(struct usb_ep *_ep)
__func__, ep->name, ep->flags);
if (!(ep->flags & BDC_EP_ENABLED)) {
- dev_warn(bdc->dev, "%s is already disabled\n", ep->name);
+ if (bdc->gadget.speed != USB_SPEED_UNKNOWN)
+ dev_warn(bdc->dev, "%s is already disabled\n",
+ ep->name);
return 0;
}
spin_lock_irqsave(&bdc->lock, flags);
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index 116d386472ef..da73a06c20a3 100644
--- a/drivers/usb/gadget/udc/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -1980,9 +1980,12 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
if (num == 0) {
_req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
+ if (!_req)
+ return -ENOMEM;
+
buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
- if (!_req || !buf) {
- /* possible _req freed by gr_probe via gr_remove */
+ if (!buf) {
+ gr_free_request(&ep->ep, _req);
return -ENOMEM;
}
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index bf6c81e2f8cc..6d2f1f98f13d 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -1614,17 +1614,17 @@ static int lpc32xx_ep_enable(struct usb_ep *_ep,
const struct usb_endpoint_descriptor *desc)
{
struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
- struct lpc32xx_udc *udc = ep->udc;
+ struct lpc32xx_udc *udc;
u16 maxpacket;
u32 tmp;
unsigned long flags;
/* Verify EP data */
if ((!_ep) || (!ep) || (!desc) ||
- (desc->bDescriptorType != USB_DT_ENDPOINT)) {
- dev_dbg(udc->dev, "bad ep or descriptor\n");
+ (desc->bDescriptorType != USB_DT_ENDPOINT))
return -EINVAL;
- }
+
+ udc = ep->udc;
maxpacket = usb_endpoint_maxp(desc);
if ((maxpacket == 0) || (maxpacket > ep->maxpacket)) {
dev_dbg(udc->dev, "bad ep descriptor's packet size\n");
@@ -1872,7 +1872,7 @@ static int lpc32xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
{
struct lpc32xx_ep *ep = container_of(_ep, struct lpc32xx_ep, ep);
- struct lpc32xx_udc *udc = ep->udc;
+ struct lpc32xx_udc *udc;
unsigned long flags;
if ((!ep) || (ep->hwep_num <= 1))
@@ -1882,6 +1882,7 @@ static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
if (ep->is_in)
return -EAGAIN;
+ udc = ep->udc;
spin_lock_irqsave(&udc->lock, flags);
if (value == 1) {
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index a8288df6aadf..ea59b56e5402 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1667,7 +1667,7 @@ static int m66592_probe(struct platform_device *pdev)
err_add_udc:
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
-
+ m66592->ep0_req = NULL;
clean_up3:
if (m66592->pdata->on_chip) {
clk_disable(m66592->clk);
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index cafde053788b..80a1b52c656e 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -2313,7 +2313,8 @@ static int mv_udc_probe(struct platform_device *pdev)
return 0;
err_create_workqueue:
- destroy_workqueue(udc->qwork);
+ if (udc->qwork)
+ destroy_workqueue(udc->qwork);
err_destroy_dma:
dma_pool_destroy(udc->dtd_pool);
err_free_dma:
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index 51efee21915f..7c616d7641c6 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -3782,8 +3782,10 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
done:
- if (dev)
+ if (dev) {
net2280_remove(pdev);
+ kfree(dev);
+ }
return retval;
}
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
index f82208fbc249..5dcc0692b95c 100644
--- a/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -251,10 +251,6 @@ static void s3c2410_udc_done(struct s3c2410_ep *ep,
static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
struct s3c2410_ep *ep, int status)
{
- /* Sanity check */
- if (&ep->queue == NULL)
- return;
-
while (!list_empty(&ep->queue)) {
struct s3c2410_request *req;
req = list_entry(ep->queue.next, struct s3c2410_request,