Commit 11ea859d64b69a747d6b060b9ed1520eab1161fe

Authored by Oliver Neukum
Committed by Greg Kroah-Hartman
1 parent 188d636027

USB: additional power savings for cdc-acm devices that support remote wakeup

this patch saves power for cdc-acm devices that support remote wakeup
while the device is connected.

- request needs_remote_wakeup when needed
- delayed write while a device is autoresumed
- the device is marked busy when appropriate

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 2 changed files with 126 additions and 21 deletions Side-by-side Diff

drivers/usb/class/cdc-acm.c
... ... @@ -159,12 +159,34 @@
159 159 spin_lock_irqsave(&acm->write_lock, flags);
160 160 acm->write_ready = 1;
161 161 wb->use = 0;
  162 + acm->transmitting--;
162 163 spin_unlock_irqrestore(&acm->write_lock, flags);
163 164 }
164 165  
165 166 /*
166 167 * Poke write.
  168 + *
  169 + * the caller is responsible for locking
167 170 */
  171 +
  172 +static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
  173 +{
  174 + int rc;
  175 +
  176 + acm->transmitting++;
  177 +
  178 + wb->urb->transfer_buffer = wb->buf;
  179 + wb->urb->transfer_dma = wb->dmah;
  180 + wb->urb->transfer_buffer_length = wb->len;
  181 + wb->urb->dev = acm->dev;
  182 +
  183 + if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
  184 + dbg("usb_submit_urb(write bulk) failed: %d", rc);
  185 + acm_write_done(acm, wb);
  186 + }
  187 + return rc;
  188 +}
  189 +
168 190 static int acm_write_start(struct acm *acm, int wbn)
169 191 {
170 192 unsigned long flags;
171 193  
172 194  
173 195  
174 196  
... ... @@ -182,26 +204,31 @@
182 204 return 0; /* A white lie */
183 205 }
184 206  
  207 + wb = &acm->wb[wbn];
  208 + if(acm_wb_is_avail(acm) <= 1)
  209 + acm->write_ready = 0;
  210 +
  211 + dbg("%s susp_count: %d", __func__, acm->susp_count);
  212 + if (acm->susp_count) {
  213 + acm->old_ready = acm->write_ready;
  214 + acm->delayed_wb = wb;
  215 + acm->write_ready = 0;
  216 + schedule_work(&acm->waker);
  217 + spin_unlock_irqrestore(&acm->write_lock, flags);
  218 + return 0; /* A white lie */
  219 + }
  220 + usb_mark_last_busy(acm->dev);
  221 +
185 222 if (!acm_wb_is_used(acm, wbn)) {
186 223 spin_unlock_irqrestore(&acm->write_lock, flags);
187 224 return 0;
188 225 }
189   - wb = &acm->wb[wbn];
190 226  
191   - if(acm_wb_is_avail(acm) <= 1)
192   - acm->write_ready = 0;
  227 + rc = acm_start_wb(acm, wb);
193 228 spin_unlock_irqrestore(&acm->write_lock, flags);
194 229  
195   - wb->urb->transfer_buffer = wb->buf;
196   - wb->urb->transfer_dma = wb->dmah;
197   - wb->urb->transfer_buffer_length = wb->len;
198   - wb->urb->dev = acm->dev;
199   -
200   - if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
201   - dbg("usb_submit_urb(write bulk) failed: %d", rc);
202   - acm_write_done(acm, wb);
203   - }
204 230 return rc;
  231 +
205 232 }
206 233 /*
207 234 * attributes exported through sysfs
... ... @@ -304,6 +331,7 @@
304 331 break;
305 332 }
306 333 exit:
  334 + usb_mark_last_busy(acm->dev);
307 335 retval = usb_submit_urb (urb, GFP_ATOMIC);
308 336 if (retval)
309 337 err ("%s - usb_submit_urb failed with result %d",
310 338  
... ... @@ -320,8 +348,11 @@
320 348  
321 349 dbg("Entering acm_read_bulk with status %d", status);
322 350  
323   - if (!ACM_READY(acm))
  351 + if (!ACM_READY(acm)) {
  352 + dev_dbg(&acm->data->dev, "Aborting, acm not ready");
324 353 return;
  354 + }
  355 + usb_mark_last_busy(acm->dev);
325 356  
326 357 if (status)
327 358 dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
... ... @@ -331,6 +362,7 @@
331 362  
332 363 if (likely(status == 0)) {
333 364 spin_lock(&acm->read_lock);
  365 + acm->processing++;
334 366 list_add_tail(&rcv->list, &acm->spare_read_urbs);
335 367 list_add_tail(&buf->list, &acm->filled_read_bufs);
336 368 spin_unlock(&acm->read_lock);
... ... @@ -343,7 +375,8 @@
343 375 /* nevertheless the tasklet must be kicked unconditionally
344 376 so the queue cannot dry up */
345 377 }
346   - tasklet_schedule(&acm->urb_task);
  378 + if (likely(!acm->susp_count))
  379 + tasklet_schedule(&acm->urb_task);
347 380 }
348 381  
349 382 static void acm_rx_tasklet(unsigned long _acm)
350 383  
351 384  
352 385  
353 386  
... ... @@ -354,16 +387,23 @@
354 387 struct acm_ru *rcv;
355 388 unsigned long flags;
356 389 unsigned char throttled;
  390 +
357 391 dbg("Entering acm_rx_tasklet");
358 392  
359 393 if (!ACM_READY(acm))
  394 + {
  395 + dbg("acm_rx_tasklet: ACM not ready");
360 396 return;
  397 + }
361 398  
362 399 spin_lock_irqsave(&acm->throttle_lock, flags);
363 400 throttled = acm->throttle;
364 401 spin_unlock_irqrestore(&acm->throttle_lock, flags);
365 402 if (throttled)
  403 + {
  404 + dbg("acm_rx_tasklet: throttled");
366 405 return;
  406 + }
367 407  
368 408 next_buffer:
369 409 spin_lock_irqsave(&acm->read_lock, flags);
... ... @@ -403,6 +443,7 @@
403 443 while (!list_empty(&acm->spare_read_bufs)) {
404 444 spin_lock_irqsave(&acm->read_lock, flags);
405 445 if (list_empty(&acm->spare_read_urbs)) {
  446 + acm->processing = 0;
406 447 spin_unlock_irqrestore(&acm->read_lock, flags);
407 448 return;
408 449 }
409 450  
410 451  
411 452  
412 453  
413 454  
... ... @@ -425,18 +466,23 @@
425 466 rcv->urb->transfer_dma = buf->dma;
426 467 rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
427 468  
428   - dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
429   -
430 469 /* This shouldn't kill the driver as unsuccessful URBs are returned to the
431 470 free-urbs-pool and resubmited ASAP */
432   - if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
  471 + spin_lock_irqsave(&acm->read_lock, flags);
  472 + if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
433 473 list_add(&buf->list, &acm->spare_read_bufs);
434   - spin_lock_irqsave(&acm->read_lock, flags);
435 474 list_add(&rcv->list, &acm->spare_read_urbs);
  475 + acm->processing = 0;
436 476 spin_unlock_irqrestore(&acm->read_lock, flags);
437 477 return;
  478 + } else {
  479 + spin_unlock_irqrestore(&acm->read_lock, flags);
  480 + dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
438 481 }
439 482 }
  483 + spin_lock_irqsave(&acm->read_lock, flags);
  484 + acm->processing = 0;
  485 + spin_unlock_irqrestore(&acm->read_lock, flags);
440 486 }
441 487  
442 488 /* data interface wrote those outgoing bytes */
... ... @@ -463,6 +509,27 @@
463 509 tty_wakeup(acm->tty);
464 510 }
465 511  
  512 +static void acm_waker(struct work_struct *waker)
  513 +{
  514 + struct acm *acm = container_of(waker, struct acm, waker);
  515 + long flags;
  516 + int rv;
  517 +
  518 + rv = usb_autopm_get_interface(acm->control);
  519 + if (rv < 0) {
  520 + err("Autopm failure in %s", __func__);
  521 + return;
  522 + }
  523 + if (acm->delayed_wb) {
  524 + acm_start_wb(acm, acm->delayed_wb);
  525 + acm->delayed_wb = NULL;
  526 + }
  527 + spin_lock_irqsave(&acm->write_lock, flags);
  528 + acm->write_ready = acm->old_ready;
  529 + spin_unlock_irqrestore(&acm->write_lock, flags);
  530 + usb_autopm_put_interface(acm->control);
  531 +}
  532 +
466 533 /*
467 534 * TTY handlers
468 535 */
... ... @@ -492,6 +559,8 @@
492 559  
493 560 if (usb_autopm_get_interface(acm->control) < 0)
494 561 goto early_bail;
  562 + else
  563 + acm->control->needs_remote_wakeup = 1;
495 564  
496 565 mutex_lock(&acm->mutex);
497 566 if (acm->used++) {
... ... @@ -509,6 +578,7 @@
509 578 if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
510 579 (acm->ctrl_caps & USB_CDC_CAP_LINE))
511 580 goto full_bailout;
  581 + usb_autopm_put_interface(acm->control);
512 582  
513 583 INIT_LIST_HEAD(&acm->spare_read_urbs);
514 584 INIT_LIST_HEAD(&acm->spare_read_bufs);
515 585  
... ... @@ -570,12 +640,14 @@
570 640 mutex_lock(&open_mutex);
571 641 if (!--acm->used) {
572 642 if (acm->dev) {
  643 + usb_autopm_get_interface(acm->control);
573 644 acm_set_control(acm, acm->ctrlout = 0);
574 645 usb_kill_urb(acm->ctrlurb);
575 646 for (i = 0; i < ACM_NW; i++)
576 647 usb_kill_urb(acm->wb[i].urb);
577 648 for (i = 0; i < nr; i++)
578 649 usb_kill_urb(acm->ru[i].urb);
  650 + acm->control->needs_remote_wakeup = 0;
579 651 usb_autopm_put_interface(acm->control);
580 652 } else
581 653 acm_tty_unregister(acm);
... ... @@ -987,6 +1059,7 @@
987 1059 acm->urb_task.func = acm_rx_tasklet;
988 1060 acm->urb_task.data = (unsigned long) acm;
989 1061 INIT_WORK(&acm->work, acm_softint);
  1062 + INIT_WORK(&acm->waker, acm_waker);
990 1063 spin_lock_init(&acm->throttle_lock);
991 1064 spin_lock_init(&acm->write_lock);
992 1065 spin_lock_init(&acm->read_lock);
... ... @@ -1116,6 +1189,7 @@
1116 1189 static void stop_data_traffic(struct acm *acm)
1117 1190 {
1118 1191 int i;
  1192 + dbg("Entering stop_data_traffic");
1119 1193  
1120 1194 tasklet_disable(&acm->urb_task);
1121 1195  
... ... @@ -1128,6 +1202,7 @@
1128 1202 tasklet_enable(&acm->urb_task);
1129 1203  
1130 1204 cancel_work_sync(&acm->work);
  1205 + cancel_work_sync(&acm->waker);
1131 1206 }
1132 1207  
1133 1208 static void acm_disconnect(struct usb_interface *intf)
1134 1209  
... ... @@ -1181,8 +1256,27 @@
1181 1256 static int acm_suspend(struct usb_interface *intf, pm_message_t message)
1182 1257 {
1183 1258 struct acm *acm = usb_get_intfdata(intf);
  1259 + int cnt;
1184 1260  
1185   - if (acm->susp_count++)
  1261 + if (acm->dev->auto_pm) {
  1262 + int b;
  1263 +
  1264 + spin_lock_irq(&acm->read_lock);
  1265 + spin_lock(&acm->write_lock);
  1266 + b = acm->processing + acm->transmitting;
  1267 + spin_unlock(&acm->write_lock);
  1268 + spin_unlock_irq(&acm->read_lock);
  1269 + if (b)
  1270 + return -EBUSY;
  1271 + }
  1272 +
  1273 + spin_lock_irq(&acm->read_lock);
  1274 + spin_lock(&acm->write_lock);
  1275 + cnt = acm->susp_count++;
  1276 + spin_unlock(&acm->write_lock);
  1277 + spin_unlock_irq(&acm->read_lock);
  1278 +
  1279 + if (cnt)
1186 1280 return 0;
1187 1281 /*
1188 1282 we treat opened interfaces differently,
1189 1283  
1190 1284  
... ... @@ -1201,15 +1295,21 @@
1201 1295 {
1202 1296 struct acm *acm = usb_get_intfdata(intf);
1203 1297 int rv = 0;
  1298 + int cnt;
1204 1299  
1205   - if (--acm->susp_count)
  1300 + spin_lock_irq(&acm->read_lock);
  1301 + acm->susp_count -= 1;
  1302 + cnt = acm->susp_count;
  1303 + spin_unlock_irq(&acm->read_lock);
  1304 +
  1305 + if (cnt)
1206 1306 return 0;
1207 1307  
1208 1308 mutex_lock(&acm->mutex);
1209 1309 if (acm->used) {
1210 1310 rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
1211 1311 if (rv < 0)
1212   - goto err_out;
  1312 + goto err_out;
1213 1313  
1214 1314 tasklet_schedule(&acm->urb_task);
1215 1315 }
drivers/usb/class/cdc-acm.h
... ... @@ -107,10 +107,14 @@
107 107 struct list_head filled_read_bufs;
108 108 int write_used; /* number of non-empty write buffers */
109 109 int write_ready; /* write urb is not running */
  110 + int old_ready;
  111 + int processing;
  112 + int transmitting;
110 113 spinlock_t write_lock;
111 114 struct mutex mutex;
112 115 struct usb_cdc_line_coding line; /* bits, stop, parity */
113 116 struct work_struct work; /* work queue entry for line discipline waking up */
  117 + struct work_struct waker;
114 118 struct tasklet_struct urb_task; /* rx processing */
115 119 spinlock_t throttle_lock; /* synchronize throtteling and read callback */
116 120 unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
... ... @@ -123,6 +127,7 @@
123 127 unsigned char clocal; /* termios CLOCAL */
124 128 unsigned int ctrl_caps; /* control capabilities from the class specific header */
125 129 unsigned int susp_count; /* number of suspended interfaces */
  130 + struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
126 131 };
127 132  
128 133 #define CDC_DATA_INTERFACE_TYPE 0x0a