diff options
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/atmel_usba_udc.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/composite.c | 18 | ||||
-rw-r--r-- | drivers/usb/gadget/f_fs.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/f_hid.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/goku_udc.h | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/u_ether.c | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/u_serial.c | 54 |
8 files changed, 53 insertions, 29 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index b739ca814651..607d0db4a988 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -158,7 +158,7 @@ config USB_GADGET_FSL_USB2 boolean "Freescale Highspeed USB DR Peripheral Controller" depends on FSL_SOC || ARCH_MXC select USB_GADGET_DUALSPEED - select USB_FSL_MPH_DR_OF + select USB_FSL_MPH_DR_OF if OF help Some of Freescale PowerPC processors have a High Speed Dual-Role(DR) USB controller, which supports device mode. diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index b5e20e873cba..717ff653fa23 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -2017,7 +2017,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) } } else { /* gpio_request fail so use -EINVAL for gpio_is_valid */ - ubc->vbus_pin = -EINVAL; + udc->vbus_pin = -EINVAL; } } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7b5cc16e4a0b..8572dad5ecbb 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1047,9 +1047,9 @@ composite_unbind(struct usb_gadget *gadget) kfree(cdev->req->buf); usb_ep_free_request(gadget->ep0, cdev->req); } + device_remove_file(&gadget->dev, &dev_attr_suspended); kfree(cdev); set_gadget_data(gadget, NULL); - device_remove_file(&gadget->dev, &dev_attr_suspended); composite = NULL; } @@ -1107,14 +1107,6 @@ static int composite_bind(struct usb_gadget *gadget) */ usb_ep_autoconfig_reset(cdev->gadget); - /* standardized runtime overrides for device ID data */ - if (idVendor) - cdev->desc.idVendor = cpu_to_le16(idVendor); - if (idProduct) - cdev->desc.idProduct = cpu_to_le16(idProduct); - if (bcdDevice) - cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); - /* composite gadget needs to assign strings for whole device (like * serial number), register function drivers, potentially update * power state and consumption, etc @@ -1126,6 +1118,14 @@ static int composite_bind(struct usb_gadget *gadget) cdev->desc = *composite->dev; cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket; + /* standardized runtime overrides for device ID data */ + if (idVendor) + cdev->desc.idVendor = cpu_to_le16(idVendor); + if (idProduct) + cdev->desc.idProduct = cpu_to_le16(idProduct); + if (bcdDevice) + cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); + /* stirng overrides */ if (iManufacturer || !cdev->desc.iManufacturer) { if (!iManufacturer && !composite->iManufacturer && diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 4a830df4fc31..484c5ba5450e 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -30,7 +30,6 @@ #include <linux/blkdev.h> #include <linux/pagemap.h> #include <asm/unaligned.h> -#include <linux/smp_lock.h> #include <linux/usb/composite.h> #include <linux/usb/functionfs.h> diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 4f891eddd060..598e7e2ab80c 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -25,7 +25,6 @@ #include <linux/cdev.h> #include <linux/mutex.h> #include <linux/poll.h> -#include <linux/smp_lock.h> #include <linux/uaccess.h> #include <linux/wait.h> #include <linux/usb/g_hid.h> diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index 566cb2319056..e7e0c69d3b1f 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h @@ -251,7 +251,8 @@ struct goku_udc { got_region:1, req_config:1, configured:1, - enabled:1; + enabled:1, + registered:1; /* pci state used to access those endpoints */ struct pci_dev *pdev; diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index cb23355f52d3..fbe86ca95802 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -811,7 +811,6 @@ int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) INFO(dev, "MAC %pM\n", net->dev_addr); INFO(dev, "HOST MAC %pM\n", dev->host_mac); - netif_stop_queue(net); the_dev = dev; } diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 01e5354a4c20..40f7716b31fc 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -105,11 +105,15 @@ struct gs_port { wait_queue_head_t close_wait; /* wait for last close */ struct list_head read_pool; + int read_started; + int read_allocated; struct list_head read_queue; unsigned n_read; struct tasklet_struct push; struct list_head write_pool; + int write_started; + int write_allocated; struct gs_buf port_write_buf; wait_queue_head_t drain_wait; /* wait while writes drain */ @@ -363,6 +367,9 @@ __acquires(&port->port_lock) struct usb_request *req; int len; + if (port->write_started >= QUEUE_SIZE) + break; + req = list_entry(pool->next, struct usb_request, list); len = gs_send_packet(port, req->buf, in->maxpacket); if (len == 0) { @@ -397,6 +404,8 @@ __acquires(&port->port_lock) break; } + port->write_started++; + /* abort immediately after disconnect */ if (!port->port_usb) break; @@ -418,7 +427,6 @@ __acquires(&port->port_lock) { struct list_head *pool = &port->read_pool; struct usb_ep *out = port->port_usb->out; - unsigned started = 0; while (!list_empty(pool)) { struct usb_request *req; @@ -430,6 +438,9 @@ __acquires(&port->port_lock) if (!tty) break; + if (port->read_started >= QUEUE_SIZE) + break; + req = list_entry(pool->next, struct usb_request, list); list_del(&req->list); req->length = out->maxpacket; @@ -447,13 +458,13 @@ __acquires(&port->port_lock) list_add(&req->list, pool); break; } - started++; + port->read_started++; /* abort immediately after disconnect */ if (!port->port_usb) break; } - return started; + return port->read_started; } /* @@ -535,6 +546,7 @@ static void gs_rx_push(unsigned long _port) } recycle: list_move(&req->list, &port->read_pool); + port->read_started--; } /* Push from tty to ldisc; without low_latency set this is handled by @@ -587,6 +599,7 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) spin_lock(&port->port_lock); list_add(&req->list, &port->write_pool); + port->write_started--; switch (req->status) { default: @@ -608,7 +621,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) spin_unlock(&port->port_lock); } -static void gs_free_requests(struct usb_ep *ep, struct list_head *head) +static void gs_free_requests(struct usb_ep *ep, struct list_head *head, + int *allocated) { struct usb_request *req; @@ -616,25 +630,31 @@ static void gs_free_requests(struct usb_ep *ep, struct list_head *head) req = list_entry(head->next, struct usb_request, list); list_del(&req->list); gs_free_req(ep, req); + if (allocated) + (*allocated)--; } } static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head, - void (*fn)(struct usb_ep *, struct usb_request *)) + void (*fn)(struct usb_ep *, struct usb_request *), + int *allocated) { int i; struct usb_request *req; + int n = allocated ? QUEUE_SIZE - *allocated : QUEUE_SIZE; /* Pre-allocate up to QUEUE_SIZE transfers, but if we can't * do quite that many this time, don't fail ... we just won't * be as speedy as we might otherwise be. */ - for (i = 0; i < QUEUE_SIZE; i++) { + for (i = 0; i < n; i++) { req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); if (!req) return list_empty(head) ? -ENOMEM : 0; req->complete = fn; list_add_tail(&req->list, head); + if (allocated) + (*allocated)++; } return 0; } @@ -661,14 +681,15 @@ static int gs_start_io(struct gs_port *port) * configurations may use different endpoints with a given port; * and high speed vs full speed changes packet sizes too. */ - status = gs_alloc_requests(ep, head, gs_read_complete); + status = gs_alloc_requests(ep, head, gs_read_complete, + &port->read_allocated); if (status) return status; status = gs_alloc_requests(port->port_usb->in, &port->write_pool, - gs_write_complete); + gs_write_complete, &port->write_allocated); if (status) { - gs_free_requests(ep, head); + gs_free_requests(ep, head, &port->read_allocated); return status; } @@ -680,8 +701,9 @@ static int gs_start_io(struct gs_port *port) if (started) { tty_wakeup(port->port_tty); } else { - gs_free_requests(ep, head); - gs_free_requests(port->port_usb->in, &port->write_pool); + gs_free_requests(ep, head, &port->read_allocated); + gs_free_requests(port->port_usb->in, &port->write_pool, + &port->write_allocated); status = -EIO; } @@ -1315,8 +1337,12 @@ void gserial_disconnect(struct gserial *gser) spin_lock_irqsave(&port->port_lock, flags); if (port->open_count == 0 && !port->openclose) gs_buf_free(&port->port_write_buf); - gs_free_requests(gser->out, &port->read_pool); - gs_free_requests(gser->out, &port->read_queue); - gs_free_requests(gser->in, &port->write_pool); + gs_free_requests(gser->out, &port->read_pool, NULL); + gs_free_requests(gser->out, &port->read_queue, NULL); + gs_free_requests(gser->in, &port->write_pool, NULL); + + port->read_allocated = port->read_started = + port->write_allocated = port->write_started = 0; + spin_unlock_irqrestore(&port->port_lock, flags); } |