diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-03-10 15:02:37 +0000 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-03-10 15:02:37 +0000 |
commit | fad837c16cdd856c68ce2e1335ad0fe836ed8ecd (patch) | |
tree | 1a6babdc2ac7e5388c482e93505fdfaf5ff97f61 /drivers/usb/class | |
parent | 51c6ab130642ed975681df843c772dda48a1d2ed (diff) | |
parent | 57d54889cd00db2752994b389ba714138652e60c (diff) |
Merge commit 'v2.6.34-rc1' into for-2.6.35
Diffstat (limited to 'drivers/usb/class')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 82 | ||||
-rw-r--r-- | drivers/usb/class/cdc-acm.h | 2 | ||||
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 2 | ||||
-rw-r--r-- | drivers/usb/class/usblp.c | 22 | ||||
-rw-r--r-- | drivers/usb/class/usbtmc.c | 2 |
5 files changed, 60 insertions, 50 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 34d4eb98829..975d556b478 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -170,6 +170,7 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb) { wb->use = 0; acm->transmitting--; + usb_autopm_put_interface_async(acm->control); } /* @@ -211,9 +212,12 @@ static int acm_write_start(struct acm *acm, int wbn) } dbg("%s susp_count: %d", __func__, acm->susp_count); + usb_autopm_get_interface_async(acm->control); if (acm->susp_count) { - acm->delayed_wb = wb; - schedule_work(&acm->waker); + if (!acm->delayed_wb) + acm->delayed_wb = wb; + else + usb_autopm_put_interface_async(acm->control); spin_unlock_irqrestore(&acm->write_lock, flags); return 0; /* A white lie */ } @@ -424,7 +428,6 @@ next_buffer: throttled = acm->throttle; spin_unlock_irqrestore(&acm->throttle_lock, flags); if (!throttled) { - tty_buffer_request_room(tty, buf->size); tty_insert_flip_string(tty, buf->base, buf->size); tty_flip_buffer_push(tty); } else { @@ -534,23 +537,6 @@ static void acm_softint(struct work_struct *work) tty_kref_put(tty); } -static void acm_waker(struct work_struct *waker) -{ - struct acm *acm = container_of(waker, struct acm, waker); - int rv; - - rv = usb_autopm_get_interface(acm->control); - if (rv < 0) { - dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__); - return; - } - if (acm->delayed_wb) { - acm_start_wb(acm, acm->delayed_wb); - acm->delayed_wb = NULL; - } - usb_autopm_put_interface(acm->control); -} - /* * TTY handlers */ @@ -566,7 +552,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm = acm_table[tty->index]; if (!acm || !acm->dev) - goto err_out; + goto out; else rv = 0; @@ -582,8 +568,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) mutex_lock(&acm->mutex); if (acm->port.count++) { + mutex_unlock(&acm->mutex); usb_autopm_put_interface(acm->control); - goto done; + goto out; } acm->ctrlurb->dev = acm->dev; @@ -612,18 +599,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) set_bit(ASYNCB_INITIALIZED, &acm->port.flags); rv = tty_port_block_til_ready(&acm->port, tty, filp); tasklet_schedule(&acm->urb_task); -done: + mutex_unlock(&acm->mutex); -err_out: +out: mutex_unlock(&open_mutex); return rv; full_bailout: usb_kill_urb(acm->ctrlurb); bail_out: - usb_autopm_put_interface(acm->control); acm->port.count--; mutex_unlock(&acm->mutex); + usb_autopm_put_interface(acm->control); early_bail: mutex_unlock(&open_mutex); tty_port_tty_set(&acm->port, NULL); @@ -1023,7 +1010,7 @@ static int acm_probe(struct usb_interface *intf, case USB_CDC_CALL_MANAGEMENT_TYPE: call_management_function = buffer[3]; call_interface_num = buffer[4]; - if ((call_management_function & 3) != 3) + if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); break; default: @@ -1178,7 +1165,6 @@ made_compressed_probe: acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint); - INIT_WORK(&acm->waker, acm_waker); init_waitqueue_head(&acm->drain_wait); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); @@ -1343,7 +1329,6 @@ static void stop_data_traffic(struct acm *acm) tasklet_enable(&acm->urb_task); cancel_work_sync(&acm->work); - cancel_work_sync(&acm->waker); } static void acm_disconnect(struct usb_interface *intf) @@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); + struct acm_wb *wb; int rv = 0; int cnt; @@ -1449,6 +1435,21 @@ static int acm_resume(struct usb_interface *intf) mutex_lock(&acm->mutex); if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); + + spin_lock_irq(&acm->write_lock); + if (acm->delayed_wb) { + wb = acm->delayed_wb; + acm->delayed_wb = NULL; + spin_unlock_irq(&acm->write_lock); + acm_start_wb(acm, acm->delayed_wb); + } else { + spin_unlock_irq(&acm->write_lock); + } + + /* + * delayed error checking because we must + * do the write path at all cost + */ if (rv < 0) goto err_out; @@ -1460,6 +1461,23 @@ err_out: return rv; } +static int acm_reset_resume(struct usb_interface *intf) +{ + struct acm *acm = usb_get_intfdata(intf); + struct tty_struct *tty; + + mutex_lock(&acm->mutex); + if (acm->port.count) { + tty = tty_port_tty_get(&acm->port); + if (tty) { + tty_hangup(tty); + tty_kref_put(tty); + } + } + mutex_unlock(&acm->mutex); + return acm_resume(intf); +} + #endif /* CONFIG_PM */ #define NOKIA_PCSUITE_ACM_INFO(x) \ @@ -1471,7 +1489,7 @@ err_out: * USB driver structure. */ -static struct usb_device_id acm_ids[] = { +static const struct usb_device_id acm_ids[] = { /* quirky and broken devices */ { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ @@ -1576,6 +1594,11 @@ static struct usb_device_id acm_ids[] = { /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ + /* Support Lego NXT using pbLua firmware */ + { USB_DEVICE(0x0694, 0xff00), + .driver_info = NOT_A_MODEM, + }, + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, @@ -1602,6 +1625,7 @@ static struct usb_driver acm_driver = { #ifdef CONFIG_PM .suspend = acm_suspend, .resume = acm_resume, + .reset_resume = acm_reset_resume, #endif .id_table = acm_ids, #ifdef CONFIG_PM diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index c4a0ee8ffcc..4a8e87ec6ce 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -112,7 +112,6 @@ struct acm { struct mutex mutex; struct usb_cdc_line_coding line; /* bits, stop, parity */ struct work_struct work; /* work queue entry for line discipline waking up */ - struct work_struct waker; wait_queue_head_t drain_wait; /* close processing */ struct tasklet_struct urb_task; /* rx processing */ spinlock_t throttle_lock; /* synchronize throtteling and read callback */ @@ -137,3 +136,4 @@ struct acm { #define NO_UNION_NORMAL 1 #define SINGLE_RX_URB 2 #define NO_CAP_LINE 4 +#define NOT_A_MODEM 8 diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 3e564bfe17d..18aafcb08fc 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -31,7 +31,7 @@ #define DRIVER_AUTHOR "Oliver Neukum" #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" -static struct usb_device_id wdm_ids[] = { +static const struct usb_device_id wdm_ids[] = { { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 9bc112ee780..93b5f85d7ce 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -163,7 +163,6 @@ struct usblp { unsigned char used; /* True if open */ unsigned char present; /* True if not disconnected */ unsigned char bidir; /* interface is bidirectional */ - unsigned char sleeping; /* interface is suspended */ unsigned char no_paper; /* Paper Out happened */ unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ /* first 2 bytes are (big-endian) length */ @@ -191,7 +190,6 @@ static void usblp_dump(struct usblp *usblp) { dbg("quirks=%d", usblp->quirks); dbg("used=%d", usblp->used); dbg("bidir=%d", usblp->bidir); - dbg("sleeping=%d", usblp->sleeping); dbg("device_id_string=\"%s\"", usblp->device_id_string ? usblp->device_id_string + 2 : @@ -376,7 +374,7 @@ static int usblp_check_status(struct usblp *usblp, int err) static int handle_bidir (struct usblp *usblp) { - if (usblp->bidir && usblp->used && !usblp->sleeping) { + if (usblp->bidir && usblp->used) { if (usblp_submit_read(usblp) < 0) return -EIO; } @@ -503,11 +501,6 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto done; } - if (usblp->sleeping) { - retval = -ENODEV; - goto done; - } - dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); @@ -914,8 +907,6 @@ static int usblp_wtest(struct usblp *usblp, int nonblock) return 0; } spin_unlock_irqrestore(&usblp->lock, flags); - if (usblp->sleeping) - return -ENODEV; if (nonblock) return -EAGAIN; return 1; @@ -968,8 +959,6 @@ static int usblp_rtest(struct usblp *usblp, int nonblock) return 0; } spin_unlock_irqrestore(&usblp->lock, flags); - if (usblp->sleeping) - return -ENODEV; if (nonblock) return -EAGAIN; return 1; @@ -1377,12 +1366,10 @@ static void usblp_disconnect(struct usb_interface *intf) mutex_unlock (&usblp_mutex); } -static int usblp_suspend (struct usb_interface *intf, pm_message_t message) +static int usblp_suspend(struct usb_interface *intf, pm_message_t message) { struct usblp *usblp = usb_get_intfdata (intf); - /* we take no more IO */ - usblp->sleeping = 1; usblp_unlink_urbs(usblp); #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ /* not strictly necessary, but just in case */ @@ -1393,18 +1380,17 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message) return 0; } -static int usblp_resume (struct usb_interface *intf) +static int usblp_resume(struct usb_interface *intf) { struct usblp *usblp = usb_get_intfdata (intf); int r; - usblp->sleeping = 0; r = handle_bidir (usblp); return r; } -static struct usb_device_id usblp_ids [] = { +static const struct usb_device_id usblp_ids[] = { { USB_DEVICE_INFO(7, 1, 1) }, { USB_DEVICE_INFO(7, 1, 2) }, { USB_DEVICE_INFO(7, 1, 3) }, diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 7c5f4e32c92..8588c0937a8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -48,7 +48,7 @@ */ #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 -static struct usb_device_id usbtmc_devices[] = { +static const struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, { 0, } /* terminating entry */ |