aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-acm.c43
-rw-r--r--drivers/usb/class/cdc-acm.h1
2 files changed, 22 insertions, 22 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index ef2e6f9c8906..6ae7ccaff07f 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)
170{ 170{
171 wb->use = 0; 171 wb->use = 0;
172 acm->transmitting--; 172 acm->transmitting--;
173 usb_autopm_put_interface_async(acm->control);
173} 174}
174 175
175/* 176/*
@@ -211,9 +212,12 @@ static int acm_write_start(struct acm *acm, int wbn)
211 } 212 }
212 213
213 dbg("%s susp_count: %d", __func__, acm->susp_count); 214 dbg("%s susp_count: %d", __func__, acm->susp_count);
215 usb_autopm_get_interface_async(acm->control);
214 if (acm->susp_count) { 216 if (acm->susp_count) {
215 acm->delayed_wb = wb; 217 if (!acm->delayed_wb)
216 schedule_work(&acm->waker); 218 acm->delayed_wb = wb;
219 else
220 usb_autopm_put_interface_async(acm->control);
217 spin_unlock_irqrestore(&acm->write_lock, flags); 221 spin_unlock_irqrestore(&acm->write_lock, flags);
218 return 0; /* A white lie */ 222 return 0; /* A white lie */
219 } 223 }
@@ -534,23 +538,6 @@ static void acm_softint(struct work_struct *work)
534 tty_kref_put(tty); 538 tty_kref_put(tty);
535} 539}
536 540
537static void acm_waker(struct work_struct *waker)
538{
539 struct acm *acm = container_of(waker, struct acm, waker);
540 int rv;
541
542 rv = usb_autopm_get_interface(acm->control);
543 if (rv < 0) {
544 dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
545 return;
546 }
547 if (acm->delayed_wb) {
548 acm_start_wb(acm, acm->delayed_wb);
549 acm->delayed_wb = NULL;
550 }
551 usb_autopm_put_interface(acm->control);
552}
553
554/* 541/*
555 * TTY handlers 542 * TTY handlers
556 */ 543 */
@@ -1178,7 +1165,6 @@ made_compressed_probe:
1178 acm->urb_task.func = acm_rx_tasklet; 1165 acm->urb_task.func = acm_rx_tasklet;
1179 acm->urb_task.data = (unsigned long) acm; 1166 acm->urb_task.data = (unsigned long) acm;
1180 INIT_WORK(&acm->work, acm_softint); 1167 INIT_WORK(&acm->work, acm_softint);
1181 INIT_WORK(&acm->waker, acm_waker);
1182 init_waitqueue_head(&acm->drain_wait); 1168 init_waitqueue_head(&acm->drain_wait);
1183 spin_lock_init(&acm->throttle_lock); 1169 spin_lock_init(&acm->throttle_lock);
1184 spin_lock_init(&acm->write_lock); 1170 spin_lock_init(&acm->write_lock);
@@ -1343,7 +1329,6 @@ static void stop_data_traffic(struct acm *acm)
1343 tasklet_enable(&acm->urb_task); 1329 tasklet_enable(&acm->urb_task);
1344 1330
1345 cancel_work_sync(&acm->work); 1331 cancel_work_sync(&acm->work);
1346 cancel_work_sync(&acm->waker);
1347} 1332}
1348 1333
1349static void acm_disconnect(struct usb_interface *intf) 1334static void acm_disconnect(struct usb_interface *intf)
@@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
1435static int acm_resume(struct usb_interface *intf) 1420static int acm_resume(struct usb_interface *intf)
1436{ 1421{
1437 struct acm *acm = usb_get_intfdata(intf); 1422 struct acm *acm = usb_get_intfdata(intf);
1423 struct acm_wb *wb;
1438 int rv = 0; 1424 int rv = 0;
1439 int cnt; 1425 int cnt;
1440 1426
@@ -1449,6 +1435,21 @@ static int acm_resume(struct usb_interface *intf)
1449 mutex_lock(&acm->mutex); 1435 mutex_lock(&acm->mutex);
1450 if (acm->port.count) { 1436 if (acm->port.count) {
1451 rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); 1437 rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
1438
1439 spin_lock_irq(&acm->write_lock);
1440 if (acm->delayed_wb) {
1441 wb = acm->delayed_wb;
1442 acm->delayed_wb = NULL;
1443 spin_unlock_irq(&acm->write_lock);
1444 acm_start_wb(acm, acm->delayed_wb);
1445 } else {
1446 spin_unlock_irq(&acm->write_lock);
1447 }
1448
1449 /*
1450 * delayed error checking because we must
1451 * do the write path at all cost
1452 */
1452 if (rv < 0) 1453 if (rv < 0)
1453 goto err_out; 1454 goto err_out;
1454 1455
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index c4a0ee8ffccf..519eb638b6e9 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -112,7 +112,6 @@ struct acm {
112 struct mutex mutex; 112 struct mutex mutex;
113 struct usb_cdc_line_coding line; /* bits, stop, parity */ 113 struct usb_cdc_line_coding line; /* bits, stop, parity */
114 struct work_struct work; /* work queue entry for line discipline waking up */ 114 struct work_struct work; /* work queue entry for line discipline waking up */
115 struct work_struct waker;
116 wait_queue_head_t drain_wait; /* close processing */ 115 wait_queue_head_t drain_wait; /* close processing */
117 struct tasklet_struct urb_task; /* rx processing */ 116 struct tasklet_struct urb_task; /* rx processing */
118 spinlock_t throttle_lock; /* synchronize throtteling and read callback */ 117 spinlock_t throttle_lock; /* synchronize throtteling and read callback */