diff options
author | Johan Hovold <jhovold@gmail.com> | 2011-03-25 06:06:02 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-13 19:18:34 -0400 |
commit | 088c64f812847b3623b03d167ed329f90f3e38a4 (patch) | |
tree | 2c76790cf12fddf227b4ab21d43002713837c948 /drivers/usb/class/cdc-acm.c | |
parent | 74f5e1babde76149c2bb35ca5dbf4d0b9b38f161 (diff) |
USB: cdc-acm: re-write read processing
Kill rx tasklet, which is no longer needed, and re-write read processing.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 295 |
1 files changed, 114 insertions, 181 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 519c7b933508..58754b508a0f 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz> |
8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> | 8 | * Copyright (c) 2004 Oliver Neukum <oliver@neukum.name> |
9 | * Copyright (c) 2005 David Kubicek <dave@awk.cz> | 9 | * Copyright (c) 2005 David Kubicek <dave@awk.cz> |
10 | * Copyright (c) 2011 Johan Hovold <jhovold@gmail.com> | ||
10 | * | 11 | * |
11 | * USB Abstract Control Model driver for USB modems and ISDN adapters | 12 | * USB Abstract Control Model driver for USB modems and ISDN adapters |
12 | * | 13 | * |
@@ -50,7 +51,7 @@ | |||
50 | #include "cdc-acm.h" | 51 | #include "cdc-acm.h" |
51 | 52 | ||
52 | 53 | ||
53 | #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek" | 54 | #define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek, Johan Hovold" |
54 | #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" | 55 | #define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters" |
55 | 56 | ||
56 | static struct usb_driver acm_driver; | 57 | static struct usb_driver acm_driver; |
@@ -323,166 +324,92 @@ exit: | |||
323 | __func__, retval); | 324 | __func__, retval); |
324 | } | 325 | } |
325 | 326 | ||
326 | /* data interface returns incoming bytes, or we got unthrottled */ | 327 | static int acm_submit_read_urb(struct acm *acm, int index, gfp_t mem_flags) |
327 | static void acm_read_bulk(struct urb *urb) | ||
328 | { | 328 | { |
329 | struct acm_rb *buf; | 329 | int res; |
330 | struct acm_ru *rcv = urb->context; | ||
331 | struct acm *acm = rcv->instance; | ||
332 | int status = urb->status; | ||
333 | 330 | ||
334 | dev_vdbg(&acm->data->dev, "%s - status %d\n", __func__, status); | 331 | if (!test_and_clear_bit(index, &acm->read_urbs_free)) |
332 | return 0; | ||
335 | 333 | ||
336 | if (!ACM_READY(acm)) { | 334 | dev_vdbg(&acm->data->dev, "%s - urb %d\n", __func__, index); |
337 | dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); | 335 | |
338 | return; | 336 | res = usb_submit_urb(acm->read_urbs[index], mem_flags); |
337 | if (res) { | ||
338 | if (res != -EPERM) { | ||
339 | dev_err(&acm->data->dev, | ||
340 | "%s - usb_submit_urb failed: %d\n", | ||
341 | __func__, res); | ||
342 | } | ||
343 | set_bit(index, &acm->read_urbs_free); | ||
344 | return res; | ||
339 | } | 345 | } |
340 | usb_mark_last_busy(acm->dev); | ||
341 | 346 | ||
342 | if (status) | 347 | return 0; |
343 | dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", | 348 | } |
344 | __func__, status); | ||
345 | 349 | ||
346 | buf = rcv->buffer; | 350 | static int acm_submit_read_urbs(struct acm *acm, gfp_t mem_flags) |
347 | buf->size = urb->actual_length; | 351 | { |
352 | int res; | ||
353 | int i; | ||
348 | 354 | ||
349 | if (likely(status == 0)) { | 355 | for (i = 0; i < acm->rx_buflimit; ++i) { |
350 | spin_lock(&acm->read_lock); | 356 | res = acm_submit_read_urb(acm, i, mem_flags); |
351 | acm->processing++; | 357 | if (res) |
352 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | 358 | return res; |
353 | list_add_tail(&buf->list, &acm->filled_read_bufs); | ||
354 | spin_unlock(&acm->read_lock); | ||
355 | } else { | ||
356 | /* we drop the buffer due to an error */ | ||
357 | spin_lock(&acm->read_lock); | ||
358 | list_add_tail(&rcv->list, &acm->spare_read_urbs); | ||
359 | list_add(&buf->list, &acm->spare_read_bufs); | ||
360 | spin_unlock(&acm->read_lock); | ||
361 | /* nevertheless the tasklet must be kicked unconditionally | ||
362 | so the queue cannot dry up */ | ||
363 | } | 359 | } |
364 | if (likely(!acm->susp_count)) | 360 | |
365 | tasklet_schedule(&acm->urb_task); | 361 | return 0; |
366 | } | 362 | } |
367 | 363 | ||
368 | static void acm_rx_tasklet(unsigned long _acm) | 364 | static void acm_process_read_urb(struct acm *acm, struct urb *urb) |
369 | { | 365 | { |
370 | struct acm *acm = (void *)_acm; | ||
371 | struct acm_rb *buf; | ||
372 | struct tty_struct *tty; | 366 | struct tty_struct *tty; |
373 | struct acm_ru *rcv; | ||
374 | unsigned long flags; | ||
375 | unsigned char throttled; | ||
376 | |||
377 | dev_vdbg(&acm->data->dev, "%s\n", __func__); | ||
378 | 367 | ||
379 | if (!ACM_READY(acm)) { | 368 | if (!urb->actual_length) |
380 | dev_dbg(&acm->data->dev, "%s - acm not ready\n", __func__); | ||
381 | return; | 369 | return; |
382 | } | ||
383 | |||
384 | spin_lock_irqsave(&acm->throttle_lock, flags); | ||
385 | throttled = acm->throttle; | ||
386 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | ||
387 | if (throttled) { | ||
388 | dev_dbg(&acm->data->dev, "%s - throttled\n", __func__); | ||
389 | return; | ||
390 | } | ||
391 | 370 | ||
392 | tty = tty_port_tty_get(&acm->port); | 371 | tty = tty_port_tty_get(&acm->port); |
372 | if (!tty) | ||
373 | return; | ||
393 | 374 | ||
394 | next_buffer: | 375 | tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); |
395 | spin_lock_irqsave(&acm->read_lock, flags); | 376 | tty_flip_buffer_push(tty); |
396 | if (list_empty(&acm->filled_read_bufs)) { | ||
397 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
398 | goto urbs; | ||
399 | } | ||
400 | buf = list_entry(acm->filled_read_bufs.next, | ||
401 | struct acm_rb, list); | ||
402 | list_del(&buf->list); | ||
403 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
404 | |||
405 | dev_vdbg(&acm->data->dev, "%s - processing buf 0x%p, size = %d\n", | ||
406 | __func__, buf, buf->size); | ||
407 | if (tty) { | ||
408 | spin_lock_irqsave(&acm->throttle_lock, flags); | ||
409 | throttled = acm->throttle; | ||
410 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | ||
411 | if (!throttled) { | ||
412 | tty_insert_flip_string(tty, buf->base, buf->size); | ||
413 | tty_flip_buffer_push(tty); | ||
414 | } else { | ||
415 | tty_kref_put(tty); | ||
416 | dev_dbg(&acm->data->dev, "%s - throttling noticed\n", | ||
417 | __func__); | ||
418 | spin_lock_irqsave(&acm->read_lock, flags); | ||
419 | list_add(&buf->list, &acm->filled_read_bufs); | ||
420 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
421 | return; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | spin_lock_irqsave(&acm->read_lock, flags); | ||
426 | list_add(&buf->list, &acm->spare_read_bufs); | ||
427 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
428 | goto next_buffer; | ||
429 | 377 | ||
430 | urbs: | ||
431 | tty_kref_put(tty); | 378 | tty_kref_put(tty); |
379 | } | ||
432 | 380 | ||
433 | while (!list_empty(&acm->spare_read_bufs)) { | 381 | static void acm_read_bulk_callback(struct urb *urb) |
434 | spin_lock_irqsave(&acm->read_lock, flags); | 382 | { |
435 | if (list_empty(&acm->spare_read_urbs)) { | 383 | struct acm_rb *rb = urb->context; |
436 | acm->processing = 0; | 384 | struct acm *acm = rb->instance; |
437 | spin_unlock_irqrestore(&acm->read_lock, flags); | 385 | unsigned long flags; |
438 | return; | ||
439 | } | ||
440 | rcv = list_entry(acm->spare_read_urbs.next, | ||
441 | struct acm_ru, list); | ||
442 | list_del(&rcv->list); | ||
443 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
444 | 386 | ||
445 | buf = list_entry(acm->spare_read_bufs.next, | 387 | dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__, |
446 | struct acm_rb, list); | 388 | rb->index, urb->actual_length); |
447 | list_del(&buf->list); | 389 | set_bit(rb->index, &acm->read_urbs_free); |
448 | 390 | ||
449 | rcv->buffer = buf; | 391 | if (!acm->dev) { |
392 | dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); | ||
393 | return; | ||
394 | } | ||
395 | usb_mark_last_busy(acm->dev); | ||
450 | 396 | ||
451 | if (acm->is_int_ep) | 397 | if (urb->status) { |
452 | usb_fill_int_urb(rcv->urb, acm->dev, | 398 | dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", |
453 | acm->rx_endpoint, | 399 | __func__, urb->status); |
454 | buf->base, | 400 | return; |
455 | acm->readsize, | ||
456 | acm_read_bulk, rcv, acm->bInterval); | ||
457 | else | ||
458 | usb_fill_bulk_urb(rcv->urb, acm->dev, | ||
459 | acm->rx_endpoint, | ||
460 | buf->base, | ||
461 | acm->readsize, | ||
462 | acm_read_bulk, rcv); | ||
463 | rcv->urb->transfer_dma = buf->dma; | ||
464 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
465 | |||
466 | /* This shouldn't kill the driver as unsuccessful URBs are | ||
467 | returned to the free-urbs-pool and resubmited ASAP */ | ||
468 | spin_lock_irqsave(&acm->read_lock, flags); | ||
469 | if (acm->susp_count || | ||
470 | usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { | ||
471 | list_add(&buf->list, &acm->spare_read_bufs); | ||
472 | list_add(&rcv->list, &acm->spare_read_urbs); | ||
473 | acm->processing = 0; | ||
474 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
475 | return; | ||
476 | } else { | ||
477 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
478 | dev_vdbg(&acm->data->dev, | ||
479 | "%s - sending urb 0x%p, rcv 0x%p, buf 0x%p\n", | ||
480 | __func__, rcv->urb, rcv, buf); | ||
481 | } | ||
482 | } | 401 | } |
402 | acm_process_read_urb(acm, urb); | ||
403 | |||
404 | /* throttle device if requested by tty */ | ||
483 | spin_lock_irqsave(&acm->read_lock, flags); | 405 | spin_lock_irqsave(&acm->read_lock, flags); |
484 | acm->processing = 0; | 406 | acm->throttled = acm->throttle_req; |
485 | spin_unlock_irqrestore(&acm->read_lock, flags); | 407 | if (!acm->throttled && !acm->susp_count) { |
408 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
409 | acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); | ||
410 | } else { | ||
411 | spin_unlock_irqrestore(&acm->read_lock, flags); | ||
412 | } | ||
486 | } | 413 | } |
487 | 414 | ||
488 | /* data interface wrote those outgoing bytes */ | 415 | /* data interface wrote those outgoing bytes */ |
@@ -530,7 +457,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
530 | { | 457 | { |
531 | struct acm *acm; | 458 | struct acm *acm; |
532 | int rv = -ENODEV; | 459 | int rv = -ENODEV; |
533 | int i; | ||
534 | 460 | ||
535 | mutex_lock(&open_mutex); | 461 | mutex_lock(&open_mutex); |
536 | 462 | ||
@@ -572,20 +498,11 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
572 | 498 | ||
573 | usb_autopm_put_interface(acm->control); | 499 | usb_autopm_put_interface(acm->control); |
574 | 500 | ||
575 | INIT_LIST_HEAD(&acm->spare_read_urbs); | 501 | if (acm_submit_read_urbs(acm, GFP_KERNEL)) |
576 | INIT_LIST_HEAD(&acm->spare_read_bufs); | 502 | goto bail_out; |
577 | INIT_LIST_HEAD(&acm->filled_read_bufs); | ||
578 | |||
579 | for (i = 0; i < acm->rx_buflimit; i++) | ||
580 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); | ||
581 | for (i = 0; i < acm->rx_buflimit; i++) | ||
582 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); | ||
583 | |||
584 | acm->throttle = 0; | ||
585 | 503 | ||
586 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); | 504 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); |
587 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | 505 | rv = tty_port_block_til_ready(&acm->port, tty, filp); |
588 | tasklet_schedule(&acm->urb_task); | ||
589 | 506 | ||
590 | mutex_unlock(&acm->mutex); | 507 | mutex_unlock(&acm->mutex); |
591 | out: | 508 | out: |
@@ -613,7 +530,7 @@ static void acm_tty_unregister(struct acm *acm) | |||
613 | for (i = 0; i < ACM_NW; i++) | 530 | for (i = 0; i < ACM_NW; i++) |
614 | usb_free_urb(acm->wb[i].urb); | 531 | usb_free_urb(acm->wb[i].urb); |
615 | for (i = 0; i < acm->rx_buflimit; i++) | 532 | for (i = 0; i < acm->rx_buflimit; i++) |
616 | usb_free_urb(acm->ru[i].urb); | 533 | usb_free_urb(acm->read_urbs[i]); |
617 | kfree(acm->country_codes); | 534 | kfree(acm->country_codes); |
618 | kfree(acm); | 535 | kfree(acm); |
619 | } | 536 | } |
@@ -629,10 +546,8 @@ static void acm_port_down(struct acm *acm) | |||
629 | usb_kill_urb(acm->ctrlurb); | 546 | usb_kill_urb(acm->ctrlurb); |
630 | for (i = 0; i < ACM_NW; i++) | 547 | for (i = 0; i < ACM_NW; i++) |
631 | usb_kill_urb(acm->wb[i].urb); | 548 | usb_kill_urb(acm->wb[i].urb); |
632 | tasklet_disable(&acm->urb_task); | ||
633 | for (i = 0; i < acm->rx_buflimit; i++) | 549 | for (i = 0; i < acm->rx_buflimit; i++) |
634 | usb_kill_urb(acm->ru[i].urb); | 550 | usb_kill_urb(acm->read_urbs[i]); |
635 | tasklet_enable(&acm->urb_task); | ||
636 | acm->control->needs_remote_wakeup = 0; | 551 | acm->control->needs_remote_wakeup = 0; |
637 | usb_autopm_put_interface(acm->control); | 552 | usb_autopm_put_interface(acm->control); |
638 | } | 553 | } |
@@ -731,22 +646,31 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty) | |||
731 | static void acm_tty_throttle(struct tty_struct *tty) | 646 | static void acm_tty_throttle(struct tty_struct *tty) |
732 | { | 647 | { |
733 | struct acm *acm = tty->driver_data; | 648 | struct acm *acm = tty->driver_data; |
649 | |||
734 | if (!ACM_READY(acm)) | 650 | if (!ACM_READY(acm)) |
735 | return; | 651 | return; |
736 | spin_lock_bh(&acm->throttle_lock); | 652 | |
737 | acm->throttle = 1; | 653 | spin_lock_irq(&acm->read_lock); |
738 | spin_unlock_bh(&acm->throttle_lock); | 654 | acm->throttle_req = 1; |
655 | spin_unlock_irq(&acm->read_lock); | ||
739 | } | 656 | } |
740 | 657 | ||
741 | static void acm_tty_unthrottle(struct tty_struct *tty) | 658 | static void acm_tty_unthrottle(struct tty_struct *tty) |
742 | { | 659 | { |
743 | struct acm *acm = tty->driver_data; | 660 | struct acm *acm = tty->driver_data; |
661 | unsigned int was_throttled; | ||
662 | |||
744 | if (!ACM_READY(acm)) | 663 | if (!ACM_READY(acm)) |
745 | return; | 664 | return; |
746 | spin_lock_bh(&acm->throttle_lock); | 665 | |
747 | acm->throttle = 0; | 666 | spin_lock_irq(&acm->read_lock); |
748 | spin_unlock_bh(&acm->throttle_lock); | 667 | was_throttled = acm->throttled; |
749 | tasklet_schedule(&acm->urb_task); | 668 | acm->throttled = 0; |
669 | acm->throttle_req = 0; | ||
670 | spin_unlock_irq(&acm->read_lock); | ||
671 | |||
672 | if (was_throttled) | ||
673 | acm_submit_read_urbs(acm, GFP_KERNEL); | ||
750 | } | 674 | } |
751 | 675 | ||
752 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) | 676 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) |
@@ -884,7 +808,7 @@ static void acm_read_buffers_free(struct acm *acm) | |||
884 | 808 | ||
885 | for (i = 0; i < acm->rx_buflimit; i++) | 809 | for (i = 0; i < acm->rx_buflimit; i++) |
886 | usb_free_coherent(usb_dev, acm->readsize, | 810 | usb_free_coherent(usb_dev, acm->readsize, |
887 | acm->rb[i].base, acm->rb[i].dma); | 811 | acm->read_buffers[i].base, acm->read_buffers[i].dma); |
888 | } | 812 | } |
889 | 813 | ||
890 | /* Little helper: write buffers allocate */ | 814 | /* Little helper: write buffers allocate */ |
@@ -1145,10 +1069,7 @@ made_compressed_probe: | |||
1145 | acm->ctrlsize = ctrlsize; | 1069 | acm->ctrlsize = ctrlsize; |
1146 | acm->readsize = readsize; | 1070 | acm->readsize = readsize; |
1147 | acm->rx_buflimit = num_rx_buf; | 1071 | acm->rx_buflimit = num_rx_buf; |
1148 | acm->urb_task.func = acm_rx_tasklet; | ||
1149 | acm->urb_task.data = (unsigned long) acm; | ||
1150 | INIT_WORK(&acm->work, acm_softint); | 1072 | INIT_WORK(&acm->work, acm_softint); |
1151 | spin_lock_init(&acm->throttle_lock); | ||
1152 | spin_lock_init(&acm->write_lock); | 1073 | spin_lock_init(&acm->write_lock); |
1153 | spin_lock_init(&acm->read_lock); | 1074 | spin_lock_init(&acm->read_lock); |
1154 | mutex_init(&acm->mutex); | 1075 | mutex_init(&acm->mutex); |
@@ -1177,8 +1098,8 @@ made_compressed_probe: | |||
1177 | goto alloc_fail5; | 1098 | goto alloc_fail5; |
1178 | } | 1099 | } |
1179 | for (i = 0; i < num_rx_buf; i++) { | 1100 | for (i = 0; i < num_rx_buf; i++) { |
1180 | struct acm_rb *rb = &(acm->rb[i]); | 1101 | struct acm_rb *rb = &(acm->read_buffers[i]); |
1181 | struct acm_ru *rcv = &(acm->ru[i]); | 1102 | struct urb *urb; |
1182 | 1103 | ||
1183 | rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, | 1104 | rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, |
1184 | &rb->dma); | 1105 | &rb->dma); |
@@ -1187,16 +1108,34 @@ made_compressed_probe: | |||
1187 | "(read bufs usb_alloc_coherent)\n"); | 1108 | "(read bufs usb_alloc_coherent)\n"); |
1188 | goto alloc_fail6; | 1109 | goto alloc_fail6; |
1189 | } | 1110 | } |
1111 | rb->index = i; | ||
1112 | rb->instance = acm; | ||
1190 | 1113 | ||
1191 | rcv->urb = usb_alloc_urb(0, GFP_KERNEL); | 1114 | urb = usb_alloc_urb(0, GFP_KERNEL); |
1192 | if (rcv->urb == NULL) { | 1115 | if (!urb) { |
1193 | dev_err(&intf->dev, | 1116 | dev_err(&intf->dev, |
1194 | "out of memory (read urbs usb_alloc_urb)\n"); | 1117 | "out of memory (read urbs usb_alloc_urb)\n"); |
1195 | goto alloc_fail6; | 1118 | goto alloc_fail6; |
1196 | } | 1119 | } |
1120 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
1121 | urb->transfer_dma = rb->dma; | ||
1122 | if (acm->is_int_ep) { | ||
1123 | usb_fill_int_urb(urb, acm->dev, | ||
1124 | acm->rx_endpoint, | ||
1125 | rb->base, | ||
1126 | acm->readsize, | ||
1127 | acm_read_bulk_callback, rb, | ||
1128 | acm->bInterval); | ||
1129 | } else { | ||
1130 | usb_fill_bulk_urb(urb, acm->dev, | ||
1131 | acm->rx_endpoint, | ||
1132 | rb->base, | ||
1133 | acm->readsize, | ||
1134 | acm_read_bulk_callback, rb); | ||
1135 | } | ||
1197 | 1136 | ||
1198 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1137 | acm->read_urbs[i] = urb; |
1199 | rcv->instance = acm; | 1138 | __set_bit(i, &acm->read_urbs_free); |
1200 | } | 1139 | } |
1201 | for (i = 0; i < ACM_NW; i++) { | 1140 | for (i = 0; i < ACM_NW; i++) { |
1202 | struct acm_wb *snd = &(acm->wb[i]); | 1141 | struct acm_wb *snd = &(acm->wb[i]); |
@@ -1281,7 +1220,7 @@ alloc_fail7: | |||
1281 | usb_free_urb(acm->wb[i].urb); | 1220 | usb_free_urb(acm->wb[i].urb); |
1282 | alloc_fail6: | 1221 | alloc_fail6: |
1283 | for (i = 0; i < num_rx_buf; i++) | 1222 | for (i = 0; i < num_rx_buf; i++) |
1284 | usb_free_urb(acm->ru[i].urb); | 1223 | usb_free_urb(acm->read_urbs[i]); |
1285 | acm_read_buffers_free(acm); | 1224 | acm_read_buffers_free(acm); |
1286 | usb_free_urb(acm->ctrlurb); | 1225 | usb_free_urb(acm->ctrlurb); |
1287 | alloc_fail5: | 1226 | alloc_fail5: |
@@ -1300,15 +1239,11 @@ static void stop_data_traffic(struct acm *acm) | |||
1300 | 1239 | ||
1301 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 1240 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
1302 | 1241 | ||
1303 | tasklet_disable(&acm->urb_task); | ||
1304 | |||
1305 | usb_kill_urb(acm->ctrlurb); | 1242 | usb_kill_urb(acm->ctrlurb); |
1306 | for (i = 0; i < ACM_NW; i++) | 1243 | for (i = 0; i < ACM_NW; i++) |
1307 | usb_kill_urb(acm->wb[i].urb); | 1244 | usb_kill_urb(acm->wb[i].urb); |
1308 | for (i = 0; i < acm->rx_buflimit; i++) | 1245 | for (i = 0; i < acm->rx_buflimit; i++) |
1309 | usb_kill_urb(acm->ru[i].urb); | 1246 | usb_kill_urb(acm->read_urbs[i]); |
1310 | |||
1311 | tasklet_enable(&acm->urb_task); | ||
1312 | 1247 | ||
1313 | cancel_work_sync(&acm->work); | 1248 | cancel_work_sync(&acm->work); |
1314 | } | 1249 | } |
@@ -1369,11 +1304,9 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1369 | if (message.event & PM_EVENT_AUTO) { | 1304 | if (message.event & PM_EVENT_AUTO) { |
1370 | int b; | 1305 | int b; |
1371 | 1306 | ||
1372 | spin_lock_irq(&acm->read_lock); | 1307 | spin_lock_irq(&acm->write_lock); |
1373 | spin_lock(&acm->write_lock); | 1308 | b = acm->transmitting; |
1374 | b = acm->processing + acm->transmitting; | 1309 | spin_unlock_irq(&acm->write_lock); |
1375 | spin_unlock(&acm->write_lock); | ||
1376 | spin_unlock_irq(&acm->read_lock); | ||
1377 | if (b) | 1310 | if (b) |
1378 | return -EBUSY; | 1311 | return -EBUSY; |
1379 | } | 1312 | } |
@@ -1435,7 +1368,7 @@ static int acm_resume(struct usb_interface *intf) | |||
1435 | if (rv < 0) | 1368 | if (rv < 0) |
1436 | goto err_out; | 1369 | goto err_out; |
1437 | 1370 | ||
1438 | tasklet_schedule(&acm->urb_task); | 1371 | rv = acm_submit_read_urbs(acm, GFP_NOIO); |
1439 | } | 1372 | } |
1440 | 1373 | ||
1441 | err_out: | 1374 | err_out: |