diff options
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/f_eem.c | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/f_fs.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 194 | ||||
-rw-r--r-- | drivers/usb/gadget/f_uvc.c | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/g_ffs.c | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/printer.c | 32 | ||||
-rw-r--r-- | drivers/usb/gadget/s3c2410_udc.c | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/u_serial.c | 16 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc.h | 10 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc_queue.c | 153 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc_queue.h | 20 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc_v4l2.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc_video.c | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/webcam.c | 4 |
14 files changed, 199 insertions, 264 deletions
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 38226e9..95dd466 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port, crc = get_unaligned_le32(skb->data + len - ETH_FCS_LEN); crc2 = ~crc32_le(~0, - skb->data, - skb->len - ETH_FCS_LEN); + skb->data, len - ETH_FCS_LEN); } else { crc = get_unaligned_be32(skb->data + len - ETH_FCS_LEN); diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index d69eccf..2aaa0f7 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -136,7 +136,7 @@ struct ffs_data { * handling setup requests immidiatelly user space may be so * slow that another setup will be sent to the gadget but this * time not to us but another function and then there could be - * a race. Is taht the case? Or maybe we can use cdev->req + * a race. Is that the case? Or maybe we can use cdev->req * after all, maybe we just need some spinlock for that? */ struct usb_request *ep0req; /* P: mutex */ struct completion ep0req_completion; /* P: mutex */ diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 7d05a0b..4ce899c 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -321,8 +321,8 @@ struct fsg_dev; /* Data shared by all the FSG instances. */ struct fsg_common { struct usb_gadget *gadget; - struct fsg_dev *fsg; - struct fsg_dev *prev_fsg; + struct fsg_dev *fsg, *new_fsg; + wait_queue_head_t fsg_wait; /* filesem protects: backing files in use */ struct rw_semaphore filesem; @@ -351,7 +351,6 @@ struct fsg_common { enum fsg_state state; /* For exception handling */ unsigned int exception_req_tag; - u8 config, new_config; enum data_direction data_dir; u32 data_size; u32 data_size_from_cmnd; @@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f, u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); - if (!fsg->common->config) + if (!fsg_is_set(fsg->common)) return -EOPNOTSUPP; switch (ctrl->bRequest) { @@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep, return -ENOMEM; } -/* - * Reset interface setting and re-init endpoint state (toggle etc). - * Call with altsetting < 0 to disable the interface. The only other - * available altsetting is 0, which enables the interface. - */ -static int do_set_interface(struct fsg_common *common, int altsetting) +/* Reset interface setting and re-init endpoint state (toggle etc). */ +static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) { - int rc = 0; - int i; - const struct usb_endpoint_descriptor *d; + const struct usb_endpoint_descriptor *d; + struct fsg_dev *fsg; + int i, rc = 0; if (common->running) DBG(common, "reset interface\n"); reset: /* Deallocate the requests */ - if (common->prev_fsg) { - struct fsg_dev *fsg = common->prev_fsg; + if (common->fsg) { + fsg = common->fsg; for (i = 0; i < FSG_NUM_BUFFERS; ++i) { struct fsg_buffhd *bh = &common->buffhds[i]; @@ -2345,88 +2340,53 @@ reset: fsg->bulk_out_enabled = 0; } - common->prev_fsg = 0; + common->fsg = NULL; + wake_up(&common->fsg_wait); } common->running = 0; - if (altsetting < 0 || rc != 0) + if (!new_fsg || rc) return rc; - DBG(common, "set interface %d\n", altsetting); + common->fsg = new_fsg; + fsg = common->fsg; - if (fsg_is_set(common)) { - struct fsg_dev *fsg = common->fsg; - common->prev_fsg = common->fsg; + /* Enable the endpoints */ + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); + rc = enable_endpoint(common, fsg->bulk_in, d); + if (rc) + goto reset; + fsg->bulk_in_enabled = 1; + + d = fsg_ep_desc(common->gadget, + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); + rc = enable_endpoint(common, fsg->bulk_out, d); + if (rc) + goto reset; + fsg->bulk_out_enabled = 1; + common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - /* Enable the endpoints */ - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); - rc = enable_endpoint(common, fsg->bulk_in, d); + /* Allocate the requests */ + for (i = 0; i < FSG_NUM_BUFFERS; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + rc = alloc_request(common, fsg->bulk_in, &bh->inreq); if (rc) goto reset; - fsg->bulk_in_enabled = 1; - - d = fsg_ep_desc(common->gadget, - &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); - rc = enable_endpoint(common, fsg->bulk_out, d); + rc = alloc_request(common, fsg->bulk_out, &bh->outreq); if (rc) goto reset; - fsg->bulk_out_enabled = 1; - common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); - clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); - - /* Allocate the requests */ - for (i = 0; i < FSG_NUM_BUFFERS; ++i) { - struct fsg_buffhd *bh = &common->buffhds[i]; - - rc = alloc_request(common, fsg->bulk_in, &bh->inreq); - if (rc) - goto reset; - rc = alloc_request(common, fsg->bulk_out, &bh->outreq); - if (rc) - goto reset; - bh->inreq->buf = bh->outreq->buf = bh->buf; - bh->inreq->context = bh->outreq->context = bh; - bh->inreq->complete = bulk_in_complete; - bh->outreq->complete = bulk_out_complete; - } - - common->running = 1; - for (i = 0; i < common->nluns; ++i) - common->luns[i].unit_attention_data = SS_RESET_OCCURRED; - return rc; - } else { - return -EIO; - } -} - - -/* - * Change our operational configuration. This code must agree with the code - * that returns config descriptors, and with interface altsetting code. - * - * It's also responsible for power management interactions. Some - * configurations might not work with our current power sources. - * For now we just assume the gadget is always self-powered. - */ -static int do_set_config(struct fsg_common *common, u8 new_config) -{ - int rc = 0; - - /* Disable the single interface */ - if (common->config != 0) { - DBG(common, "reset config\n"); - common->config = 0; - rc = do_set_interface(common, -1); + bh->inreq->buf = bh->outreq->buf = bh->buf; + bh->inreq->context = bh->outreq->context = bh; + bh->inreq->complete = bulk_in_complete; + bh->outreq->complete = bulk_out_complete; } - /* Enable the interface */ - if (new_config != 0) { - common->config = new_config; - rc = do_set_interface(common, 0); - if (rc != 0) - common->config = 0; /* Reset on errors */ - } + common->running = 1; + for (i = 0; i < common->nluns; ++i) + common->luns[i].unit_attention_data = SS_RESET_OCCURRED; return rc; } @@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config) static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->prev_fsg = fsg->common->fsg; - fsg->common->fsg = fsg; - fsg->common->new_config = 1; + fsg->common->new_fsg = fsg; raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); return 0; } @@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) static void fsg_disable(struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); - fsg->common->prev_fsg = fsg->common->fsg; - fsg->common->fsg = fsg; - fsg->common->new_config = 0; + fsg->common->new_fsg = NULL; raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); } @@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f) static void handle_exception(struct fsg_common *common) { siginfo_t info; - int sig; int i; struct fsg_buffhd *bh; enum fsg_state old_state; - u8 new_config; struct fsg_lun *curlun; unsigned int exception_req_tag; - int rc; /* Clear the existing signals. Anything but SIGUSR1 is converted * into a high-priority EXIT exception. */ for (;;) { - sig = dequeue_signal_lock(current, ¤t->blocked, &info); + int sig = + dequeue_signal_lock(current, ¤t->blocked, &info); if (!sig) break; if (sig != SIGUSR1) { @@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common) } /* Cancel all the pending transfers */ - if (fsg_is_set(common)) { + if (likely(common->fsg)) { for (i = 0; i < FSG_NUM_BUFFERS; ++i) { bh = &common->buffhds[i]; if (bh->inreq_busy) @@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common) common->next_buffhd_to_fill = &common->buffhds[0]; common->next_buffhd_to_drain = &common->buffhds[0]; exception_req_tag = common->exception_req_tag; - new_config = common->new_config; old_state = common->state; if (old_state == FSG_STATE_ABORT_BULK_OUT) @@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common) break; case FSG_STATE_CONFIG_CHANGE: - rc = do_set_config(common, new_config); + do_set_interface(common, common->new_fsg); break; case FSG_STATE_EXIT: case FSG_STATE_TERMINATED: - do_set_config(common, 0); /* Free resources */ + do_set_interface(common, NULL); /* Free resources */ spin_lock_irq(&common->lock); common->state = FSG_STATE_TERMINATED; /* Stop the thread */ spin_unlock_irq(&common->lock); @@ -2863,6 +2816,7 @@ buffhds_first_it: goto error_release; } init_completion(&common->thread_notifier); + init_waitqueue_head(&common->fsg_wait); #undef OR @@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref) static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); + struct fsg_common *common = fsg->common; DBG(fsg, "unbind\n"); - fsg_common_put(fsg->common); + if (fsg->common->fsg == fsg) { + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + /* FIXME: make interruptible or killable somehow? */ + wait_event(common->fsg_wait, common->fsg != fsg); + } + + fsg_common_put(common); usb_free_descriptors(fsg->function.descriptors); usb_free_descriptors(fsg->function.hs_descriptors); kfree(fsg); @@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); struct usb_gadget *gadget = c->cdev->gadget; - int rc; int i; struct usb_ep *ep; @@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ep->driver_data = fsg->common; /* claim the endpoint */ fsg->bulk_out = ep; + /* Copy descriptors */ + f->descriptors = usb_copy_descriptors(fsg_fs_function); + if (unlikely(!f->descriptors)) + return -ENOMEM; + if (gadget_is_dualspeed(gadget)) { /* Assume endpoint addresses are the same for both speeds */ fsg_hs_bulk_in_desc.bEndpointAddress = @@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg_hs_bulk_out_desc.bEndpointAddress = fsg_fs_bulk_out_desc.bEndpointAddress; f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); - if (unlikely(!f->hs_descriptors)) + if (unlikely(!f->hs_descriptors)) { + usb_free_descriptors(f->descriptors); return -ENOMEM; + } } return 0; autoconf_fail: ERROR(fsg, "unable to autoconfigure all endpoints\n"); - rc = -ENOTSUPP; - return rc; + return -ENOTSUPP; } @@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev, fsg->function.name = FSG_DRIVER_DESC; fsg->function.strings = fsg_strings_array; - fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function); - if (unlikely(!fsg->function.descriptors)) { - rc = -ENOMEM; - goto error_free_fsg; - } fsg->function.bind = fsg_bind; fsg->function.unbind = fsg_unbind; fsg->function.setup = fsg_setup; @@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev, rc = usb_add_function(c, &fsg->function); if (unlikely(rc)) - goto error_free_all; - - fsg_common_get(fsg->common); - return 0; - -error_free_all: - usb_free_descriptors(fsg->function.descriptors); - /* fsg_bind() might have copied those; or maybe not? who cares - * -- free it just in case. */ - usb_free_descriptors(fsg->function.hs_descriptors); -error_free_fsg: - kfree(fsg); - + kfree(fsg); + else + fsg_common_get(fsg->common); return rc; } diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index fc2611f..dbe6db0 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -28,7 +28,7 @@ #include "uvc.h" -unsigned int uvc_trace_param; +unsigned int uvc_gadget_trace_param; /* -------------------------------------------------------------------------- * Function descriptors @@ -656,6 +656,6 @@ error: return ret; } -module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); +module_param_named(trace, uvc_gadget_trace_param, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(trace, "Trace level bitmask"); diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 4b0e4a0..d1af253 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c, if (unlikely(ret < 0)) return ret; + /* After previous do_configs there may be some invalid + * pointers in c->interface array. This happens every time + * a user space function with fewer interfaces than a user + * space function that was run before the new one is run. The + * compasit's set_config() assumes that if there is no more + * then MAX_CONFIG_INTERFACES interfaces in a configuration + * then there is a NULL pointer after the last interface in + * c->interface array. We need to make sure this is true. */ + if (c->next_interface_id < ARRAY_SIZE(c->interface)) + c->interface[c->next_interface_id] = NULL; + return 0; } diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 43abf55..4c3ac5c 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -82,7 +82,7 @@ static struct class *usb_gadget_class; struct printer_dev { spinlock_t lock; /* lock this structure */ /* lock buffer lists during read/write calls */ - spinlock_t lock_printer_io; + struct mutex lock_printer_io; struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ u8 config; @@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) DBG(dev, "printer_read trying to read %d bytes\n", (int)len); - spin_lock(&dev->lock_printer_io); + mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); /* We will use this flag later to check if a printer reset happened @@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) * call or not. */ if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) if (dev->reset_printer) { list_add(¤t_rx_req->list, &dev->rx_reqs); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) dev->current_rx_buf = current_rx_buf; spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied); @@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (len == 0) return -EINVAL; - spin_lock(&dev->lock_printer_io); + mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); /* Check if a printer reset happens while we have interrupts on */ @@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) * a NON-Blocking call or not. */ if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (copy_from_user(req->buf, buf, size)) { list_add(&req->list, &dev->tx_reqs); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return bytes_copied; } @@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (dev->reset_printer) { list_add(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) { list_add(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } @@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) } spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied); @@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait) unsigned long flags; int status = 0; - spin_lock(&dev->lock_printer_io); + mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); setup_rx_reqs(dev); spin_unlock_irqrestore(&dev->lock, flags); - spin_unlock(&dev->lock_printer_io); + mutex_unlock(&dev->lock_printer_io); poll_wait(fd, &dev->rx_wait, wait); poll_wait(fd, &dev->tx_wait, wait); @@ -1461,7 +1461,7 @@ autoconf_fail: } spin_lock_init(&dev->lock); - spin_lock_init(&dev->lock_printer_io); + mutex_init(&dev->lock_printer_io); INIT_LIST_HEAD(&dev->tx_reqs); INIT_LIST_HEAD(&dev->tx_reqs_active); INIT_LIST_HEAD(&dev->rx_reqs); @@ -1594,7 +1594,7 @@ cleanup(void) { int status; - spin_lock(&usb_printer_gadget.lock_printer_io); + mutex_lock(&usb_printer_gadget.lock_printer_io); class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 2); @@ -1602,6 +1602,6 @@ cleanup(void) if (status) ERROR(dev, "usb_gadget_unregister_driver %x\n", status); - spin_unlock(&usb_printer_gadget.lock_printer_io); + mutex_unlock(&usb_printer_gadget.lock_printer_io); } module_exit(cleanup); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index d5f4c1d..e724a05 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1700,9 +1700,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!driver || driver != udc->driver || !driver->unbind) return -EINVAL; - dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n", + dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n", driver->driver.name); + /* report disconnect */ + if (driver->disconnect) + driver->disconnect(&udc->gadget); + driver->unbind(&udc->gadget); device_del(&udc->gadget.dev); diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 16bdf77..3e8dcb5 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -536,17 +536,11 @@ recycle: list_move(&req->list, &port->read_pool); } - /* Push from tty to ldisc; this is immediate with low_latency, and - * may trigger callbacks to this driver ... so drop the spinlock. + /* Push from tty to ldisc; without low_latency set this is handled by + * a workqueue, so we won't get callbacks and can hold port_lock */ if (tty && do_push) { - spin_unlock_irq(&port->port_lock); tty_flip_buffer_push(tty); - wake_up_interruptible(&tty->read_wait); - spin_lock_irq(&port->port_lock); - - /* tty may have been closed */ - tty = port->port_tty; } @@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file) port->open_count = 1; port->openclose = false; - /* low_latency means ldiscs work in tasklet context, without - * needing a workqueue schedule ... easier to keep up. - */ - tty->low_latency = 1; - /* if connected, start the I/O stream */ if (port->port_usb) { struct gserial *gser = port->port_usb; @@ -1195,6 +1184,7 @@ void gserial_cleanup(void) n_ports = 0; tty_unregister_driver(gs_tty_driver); + put_tty_driver(gs_tty_driver); gs_tty_driver = NULL; pr_debug("%s: cleaned up ttyGS* support\n", __func__); diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 0a705e6..e92454c 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -107,11 +107,11 @@ struct uvc_streaming_control { #define UVC_WARN_MINMAX 0 #define UVC_WARN_PROBE_DEF 1 -extern unsigned int uvc_trace_param; +extern unsigned int uvc_gadget_trace_param; #define uvc_trace(flag, msg...) \ do { \ - if (uvc_trace_param & flag) \ + if (uvc_gadget_trace_param & flag) \ printk(KERN_DEBUG "uvcvideo: " msg); \ } while (0) @@ -220,16 +220,10 @@ struct uvc_file_handle #define to_uvc_file_handle(handle) \ container_of(handle, struct uvc_file_handle, vfh) -extern struct v4l2_file_operations uvc_v4l2_fops; - /* ------------------------------------------------------------------------ * Functions */ -extern int uvc_video_enable(struct uvc_video *video, int enable); -extern int uvc_video_init(struct uvc_video *video); -extern int uvc_video_pump(struct uvc_video *video); - extern void uvc_endpoint_stream(struct uvc_device *dev); extern void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index 4389199..f7395ac 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -78,7 +78,8 @@ * */ -void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) +static void +uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) { mutex_init(&queue->mutex); spin_lock_init(&queue->irqlock); @@ -88,6 +89,28 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) } /* + * Free the video buffers. + * + * This function must be called with the queue lock held. + */ +static int uvc_free_buffers(struct uvc_video_queue *queue) +{ + unsigned int i; + + for (i = 0; i < queue->count; ++i) { + if (queue->buffer[i].vma_use_count != 0) + return -EBUSY; + } + + if (queue->count) { + vfree(queue->mem); + queue->count = 0; + } + + return 0; +} + +/* * Allocate the video buffers. * * Pages are reserved to make sure they will not be swapped, as they will be @@ -95,8 +118,9 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) * * Buffers will be individually mapped, so they must all be page aligned. */ -int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, - unsigned int buflength) +static int +uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, + unsigned int buflength) { unsigned int bufsize = PAGE_ALIGN(buflength); unsigned int i; @@ -150,28 +174,6 @@ done: return ret; } -/* - * Free the video buffers. - * - * This function must be called with the queue lock held. - */ -int uvc_free_buffers(struct uvc_video_queue *queue) -{ - unsigned int i; - - for (i = 0; i < queue->count; ++i) { - if (queue->buffer[i].vma_use_count != 0) - return -EBUSY; - } - - if (queue->count) { - vfree(queue->mem); - queue->count = 0; - } - - return 0; -} - static void __uvc_query_buffer(struct uvc_buffer *buf, struct v4l2_buffer *v4l2_buf) { @@ -195,8 +197,8 @@ static void __uvc_query_buffer(struct uvc_buffer *buf, } } -int uvc_query_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf) +static int +uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) { int ret = 0; @@ -217,8 +219,8 @@ done: * Queue a video buffer. Attempting to queue a buffer that has already been * queued will return -EINVAL. */ -int uvc_queue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf) +static int +uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) { struct uvc_buffer *buf; unsigned long flags; @@ -298,8 +300,9 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) * Dequeue a video buffer. If nonblocking is false, block until a buffer is * available. */ -int uvc_dequeue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf, int nonblocking) +static int +uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf, + int nonblocking) { struct uvc_buffer *buf; int ret = 0; @@ -359,8 +362,9 @@ done: * This function implements video queue polling and is intended to be used by * the device poll handler. */ -unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, - poll_table *wait) +static unsigned int +uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, + poll_table *wait) { struct uvc_buffer *buf; unsigned int mask = 0; @@ -407,7 +411,8 @@ static struct vm_operations_struct uvc_vm_ops = { * This function implements video buffer memory mapping and is intended to be * used by the device mmap handler. */ -int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) +static int +uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) { struct uvc_buffer *uninitialized_var(buffer); struct page *page; @@ -458,6 +463,42 @@ done: } /* + * Cancel the video buffers queue. + * + * Cancelling the queue marks all buffers on the irq queue as erroneous, + * wakes them up and removes them from the queue. + * + * If the disconnect parameter is set, further calls to uvc_queue_buffer will + * fail with -ENODEV. + * + * This function acquires the irq spinlock and can be called from interrupt + * context. + */ +static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) +{ + struct uvc_buffer *buf; + unsigned long flags; + + spin_lock_irqsave(&queue->irqlock, flags); + while (!list_empty(&queue->irqqueue)) { + buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, + queue); + list_del(&buf->queue); + buf->state = UVC_BUF_STATE_ERROR; + wake_up(&buf->wait); + } + /* This must be protected by the irqlock spinlock to avoid race + * conditions between uvc_queue_buffer and the disconnection event that + * could result in an interruptible wait in uvc_dequeue_buffer. Do not + * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED + * state outside the queue code. + */ + if (disconnect) + queue->flags |= UVC_QUEUE_DISCONNECTED; + spin_unlock_irqrestore(&queue->irqlock, flags); +} + +/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be @@ -474,7 +515,7 @@ done: * This function can't be called from interrupt context. Use * uvc_queue_cancel() instead. */ -int uvc_queue_enable(struct uvc_video_queue *queue, int enable) +static int uvc_queue_enable(struct uvc_video_queue *queue, int enable) { unsigned int i; int ret = 0; @@ -503,44 +544,8 @@ done: return ret; } -/* - * Cancel the video buffers queue. - * - * Cancelling the queue marks all buffers on the irq queue as erroneous, - * wakes them up and removes them from the queue. - * - * If the disconnect parameter is set, further calls to uvc_queue_buffer will - * fail with -ENODEV. - * - * This function acquires the irq spinlock and can be called from interrupt - * context. - */ -void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) -{ - struct uvc_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&queue->irqlock, flags); - while (!list_empty(&queue->irqqueue)) { - buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, - queue); - list_del(&buf->queue); - buf->state = UVC_BUF_STATE_ERROR; - wake_up(&buf->wait); - } - /* This must be protected by the irqlock spinlock to avoid race - * conditions between uvc_queue_buffer and the disconnection event that - * could result in an interruptible wait in uvc_dequeue_buffer. Do not - * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED - * state outside the queue code. - */ - if (disconnect) - queue->flags |= UVC_QUEUE_DISCONNECTED; - spin_unlock_irqrestore(&queue->irqlock, flags); -} - -struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, - struct uvc_buffer *buf) +static struct uvc_buffer * +uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { struct uvc_buffer *nextbuf; unsigned long flags; @@ -568,7 +573,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, return nextbuf; } -struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue) +static struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue) { struct uvc_buffer *buf = NULL; diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h index 7f5a33f..1812a8e 100644 --- a/drivers/usb/gadget/uvc_queue.h +++ b/drivers/usb/gadget/uvc_queue.h @@ -58,30 +58,10 @@ struct uvc_video_queue { struct list_head irqqueue; }; -extern void uvc_queue_init(struct uvc_video_queue *queue, - enum v4l2_buf_type type); -extern int uvc_alloc_buffers(struct uvc_video_queue *queue, - unsigned int nbuffers, unsigned int buflength); -extern int uvc_free_buffers(struct uvc_video_queue *queue); -extern int uvc_query_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf); -extern int uvc_queue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf); -extern int uvc_dequeue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf, int nonblocking); -extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable); -extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); -extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, - struct uvc_buffer *buf); -extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, - struct file *file, poll_table *wait); -extern int uvc_queue_mmap(struct uvc_video_queue *queue, - struct vm_area_struct *vma); static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { return queue->flags & UVC_QUEUE_STREAMING; } -extern struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue); #endif /* __KERNEL__ */ diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index a7989f2..2dcffda 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -363,7 +363,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait) return mask; } -struct v4l2_file_operations uvc_v4l2_fops = { +static struct v4l2_file_operations uvc_v4l2_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index de8cbc4..b08f354 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -271,7 +271,7 @@ error: * This function fills the available USB requests (listed in req_free) with * video data from the queued buffers. */ -int +static int uvc_video_pump(struct uvc_video *video) { struct usb_request *req; @@ -328,7 +328,7 @@ uvc_video_pump(struct uvc_video *video) /* * Enable or disable the video stream. */ -int +static int uvc_video_enable(struct uvc_video *video, int enable) { unsigned int i; @@ -367,7 +367,7 @@ uvc_video_enable(struct uvc_video *video, int enable) /* * Initialize the UVC video stream. */ -int +static int uvc_video_init(struct uvc_video *video) { INIT_LIST_HEAD(&video->req_free); diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 417fd68..f5f3030 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -28,10 +28,10 @@ #include "config.c" #include "epautoconf.c" -#include "f_uvc.c" #include "uvc_queue.c" -#include "uvc_v4l2.c" #include "uvc_video.c" +#include "uvc_v4l2.c" +#include "f_uvc.c" /* -------------------------------------------------------------------------- * Device descriptor |