From a91b0c502285fd0c569fae1222fdd945ef739233 Mon Sep 17 00:00:00 2001 From: Francesco Lavra Date: Tue, 8 Dec 2009 09:54:11 +0100 Subject: cdc_acm: add reset_resume method Add reset resume logic to the cdc acm driver Signed-off-by: Francesco Lavra Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 34d4eb98829..ef2e6f9c890 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1460,6 +1460,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) \ @@ -1602,6 +1619,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 -- cgit v1.2.3-70-g09d2 From 97d35f95552c9a0ee4777a7f04431a9fd1260478 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 16 Dec 2009 17:05:57 +0100 Subject: USB: cdc-acm: Update to new autopm API Update cdc-acm to the async methods eliminating the workqueue Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 43 ++++++++++++++++++++++--------------------- drivers/usb/class/cdc-acm.h | 1 - 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ef2e6f9c890..6ae7ccaff07 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 */ } @@ -534,23 +538,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 */ @@ -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; diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index c4a0ee8ffcc..519eb638b6e 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 */ -- cgit v1.2.3-70-g09d2 From 7c5d8c394a077a686cfa646cd85dc159a2a940cc Mon Sep 17 00:00:00 2001 From: Julian Calaby Date: Tue, 5 Jan 2010 23:57:46 +1100 Subject: USB: cdc_acm: Add support for pbLua console port The pbLua firmware (http://pblua.com/) for the Lego Mindstorms NXT provides a CDC ACM port for it's serial console. This used to be detected automatically, but this support has been dropped, probably for sensible reasons. Explicitly add support for this device by adding an item to the device ID table. Signed-off-by: Julian Calaby Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6ae7ccaff07..d071da96e07 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1594,6 +1594,9 @@ 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), }, + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, -- cgit v1.2.3-70-g09d2 From ce126644aa10bf1d8f1c1929b65adab026095761 Mon Sep 17 00:00:00 2001 From: Julian Calaby Date: Tue, 5 Jan 2010 23:58:20 +1100 Subject: USB: cdc_acm: Silence "It is not a modem." error for pbLua devices The pbLua console port is known to not be a modem, so it is unnecessary to be told this when it is plugged in. Add NOT_A_MODEM quirk to tell the driver that we know this already and hence not to warn us, and mark the pbLua console port. Signed-off-by: Julian Calaby Cc: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 ++++-- drivers/usb/class/cdc-acm.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d071da96e07..95f29a29304 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1010,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: @@ -1595,7 +1595,9 @@ 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), }, + { 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, diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 519eb638b6e..4a8e87ec6ce 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -136,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 -- cgit v1.2.3-70-g09d2 From 6ef4852b1326301f6e9657e99b2c3221be1a3a44 Mon Sep 17 00:00:00 2001 From: Németh Márton Date: Sun, 10 Jan 2010 15:33:45 +0100 Subject: USB class: make USB device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct usb_device_id is constant in so it is worth to make the initialization data also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Németh Márton Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- drivers/usb/class/cdc-wdm.c | 2 +- drivers/usb/class/usblp.c | 2 +- drivers/usb/class/usbtmc.c | 2 +- drivers/usb/wusbcore/cbaf.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 95f29a29304..5155ff2b228 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1489,7 +1489,7 @@ static int acm_reset_resume(struct usb_interface *intf) * 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 */ 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 9d8ec729c26..93b5f85d7ce 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1390,7 +1390,7 @@ static int usblp_resume(struct usb_interface *intf) 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 */ diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index 25eae405f62..51a8e0d5789 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c @@ -641,7 +641,7 @@ static void cbaf_disconnect(struct usb_interface *iface) kzfree(cbaf); } -static struct usb_device_id cbaf_id_table[] = { +static const struct usb_device_id cbaf_id_table[] = { { USB_INTERFACE_INFO(0xef, 0x03, 0x01), }, { }, }; -- cgit v1.2.3-70-g09d2 From 2b626dc134d38d0001b98acf8c7293b6bc5ee86d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 3 Feb 2010 17:10:22 +0100 Subject: USB: cdc-acm: fix possible deadlock with multiple openers The lock must be dropped before usb_autopm_interface_put() is called Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5155ff2b228..b97f9309c82 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -553,7 +553,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; @@ -569,8 +569,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; @@ -599,18 +600,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); -- cgit v1.2.3-70-g09d2 From b6a2f10ca045c9b0a4732c38485ad6ca1b663bf4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 17 Feb 2010 13:07:05 +0000 Subject: USB: tty: kill request_room for USB ACM class Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b97f9309c82..975d556b478 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -428,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 { -- cgit v1.2.3-70-g09d2 From f0730924e9e32bb8935c60040a26d94179355088 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 3 Mar 2010 00:37:56 +0100 Subject: USB: cdc-acm: Fix stupid NULL pointer in resume() Stupid logic bug passing a just nulled pointer Signed-off-by: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/class/cdc-acm.c') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 975d556b478..be6331e2c27 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf) wb = acm->delayed_wb; acm->delayed_wb = NULL; spin_unlock_irq(&acm->write_lock); - acm_start_wb(acm, acm->delayed_wb); + acm_start_wb(acm, wb); } else { spin_unlock_irq(&acm->write_lock); } -- cgit v1.2.3-70-g09d2