aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index e78720b59d67..3e15add665e2 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -360,7 +360,7 @@ static void acm_ctrl_irq(struct urb *urb)
360 } 360 }
361exit: 361exit:
362 retval = usb_submit_urb(urb, GFP_ATOMIC); 362 retval = usb_submit_urb(urb, GFP_ATOMIC);
363 if (retval) 363 if (retval && retval != -EPERM)
364 dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n", 364 dev_err(&acm->control->dev, "%s - usb_submit_urb failed: %d\n",
365 __func__, retval); 365 __func__, retval);
366} 366}
@@ -417,25 +417,33 @@ static void acm_read_bulk_callback(struct urb *urb)
417 struct acm_rb *rb = urb->context; 417 struct acm_rb *rb = urb->context;
418 struct acm *acm = rb->instance; 418 struct acm *acm = rb->instance;
419 unsigned long flags; 419 unsigned long flags;
420 int status = urb->status;
420 421
421 dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__, 422 dev_vdbg(&acm->data->dev, "%s - urb %d, len %d\n", __func__,
422 rb->index, urb->actual_length); 423 rb->index, urb->actual_length);
423 set_bit(rb->index, &acm->read_urbs_free);
424 424
425 if (!acm->dev) { 425 if (!acm->dev) {
426 set_bit(rb->index, &acm->read_urbs_free);
426 dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); 427 dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
427 return; 428 return;
428 } 429 }
429 430
430 if (urb->status) { 431 if (status) {
432 set_bit(rb->index, &acm->read_urbs_free);
431 dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n", 433 dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
432 __func__, urb->status); 434 __func__, status);
433 return; 435 return;
434 } 436 }
435 437
436 usb_mark_last_busy(acm->dev); 438 usb_mark_last_busy(acm->dev);
437 439
438 acm_process_read_urb(acm, urb); 440 acm_process_read_urb(acm, urb);
441 /*
442 * Unthrottle may run on another CPU which needs to see events
443 * in the same order. Submission has an implict barrier
444 */
445 smp_mb__before_atomic();
446 set_bit(rb->index, &acm->read_urbs_free);
439 447
440 /* throttle device if requested by tty */ 448 /* throttle device if requested by tty */
441 spin_lock_irqsave(&acm->read_lock, flags); 449 spin_lock_irqsave(&acm->read_lock, flags);
@@ -454,13 +462,14 @@ static void acm_write_bulk(struct urb *urb)
454 struct acm_wb *wb = urb->context; 462 struct acm_wb *wb = urb->context;
455 struct acm *acm = wb->instance; 463 struct acm *acm = wb->instance;
456 unsigned long flags; 464 unsigned long flags;
465 int status = urb->status;
457 466
458 if (urb->status || (urb->actual_length != urb->transfer_buffer_length)) 467 if (status || (urb->actual_length != urb->transfer_buffer_length))
459 dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n", 468 dev_vdbg(&acm->data->dev, "%s - len %d/%d, status %d\n",
460 __func__, 469 __func__,
461 urb->actual_length, 470 urb->actual_length,
462 urb->transfer_buffer_length, 471 urb->transfer_buffer_length,
463 urb->status); 472 status);
464 473
465 spin_lock_irqsave(&acm->write_lock, flags); 474 spin_lock_irqsave(&acm->write_lock, flags);
466 acm_write_done(acm, wb); 475 acm_write_done(acm, wb);
@@ -1650,6 +1659,8 @@ static int acm_reset_resume(struct usb_interface *intf)
1650 1659
1651static const struct usb_device_id acm_ids[] = { 1660static const struct usb_device_id acm_ids[] = {
1652 /* quirky and broken devices */ 1661 /* quirky and broken devices */
1662 { USB_DEVICE(0x076d, 0x0006), /* Denso Cradle CU-321 */
1663 .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
1653 { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */ 1664 { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */
1654 .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */ 1665 .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */
1655 { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ 1666 { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */