diff options
Diffstat (limited to 'drivers/usb/class')
| -rw-r--r-- | drivers/usb/class/cdc-acm.c | 82 | ||||
| -rw-r--r-- | drivers/usb/class/cdc-acm.h | 2 | ||||
| -rw-r--r-- | drivers/usb/class/cdc-wdm.c | 136 | ||||
| -rw-r--r-- | drivers/usb/class/usblp.c | 22 | ||||
| -rw-r--r-- | drivers/usb/class/usbtmc.c | 2 |
5 files changed, 138 insertions, 106 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 34d4eb98829e..be6331e2c276 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 | } |
| @@ -424,7 +428,6 @@ next_buffer: | |||
| 424 | throttled = acm->throttle; | 428 | throttled = acm->throttle; |
| 425 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | 429 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
| 426 | if (!throttled) { | 430 | if (!throttled) { |
| 427 | tty_buffer_request_room(tty, buf->size); | ||
| 428 | tty_insert_flip_string(tty, buf->base, buf->size); | 431 | tty_insert_flip_string(tty, buf->base, buf->size); |
| 429 | tty_flip_buffer_push(tty); | 432 | tty_flip_buffer_push(tty); |
| 430 | } else { | 433 | } else { |
| @@ -534,23 +537,6 @@ static void acm_softint(struct work_struct *work) | |||
| 534 | tty_kref_put(tty); | 537 | tty_kref_put(tty); |
| 535 | } | 538 | } |
| 536 | 539 | ||
| 537 | static 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 | /* | 540 | /* |
| 555 | * TTY handlers | 541 | * TTY handlers |
| 556 | */ | 542 | */ |
| @@ -566,7 +552,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 566 | 552 | ||
| 567 | acm = acm_table[tty->index]; | 553 | acm = acm_table[tty->index]; |
| 568 | if (!acm || !acm->dev) | 554 | if (!acm || !acm->dev) |
| 569 | goto err_out; | 555 | goto out; |
| 570 | else | 556 | else |
| 571 | rv = 0; | 557 | rv = 0; |
| 572 | 558 | ||
| @@ -582,8 +568,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 582 | 568 | ||
| 583 | mutex_lock(&acm->mutex); | 569 | mutex_lock(&acm->mutex); |
| 584 | if (acm->port.count++) { | 570 | if (acm->port.count++) { |
| 571 | mutex_unlock(&acm->mutex); | ||
| 585 | usb_autopm_put_interface(acm->control); | 572 | usb_autopm_put_interface(acm->control); |
| 586 | goto done; | 573 | goto out; |
| 587 | } | 574 | } |
| 588 | 575 | ||
| 589 | acm->ctrlurb->dev = acm->dev; | 576 | acm->ctrlurb->dev = acm->dev; |
| @@ -612,18 +599,18 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 612 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); | 599 | set_bit(ASYNCB_INITIALIZED, &acm->port.flags); |
| 613 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | 600 | rv = tty_port_block_til_ready(&acm->port, tty, filp); |
| 614 | tasklet_schedule(&acm->urb_task); | 601 | tasklet_schedule(&acm->urb_task); |
| 615 | done: | 602 | |
| 616 | mutex_unlock(&acm->mutex); | 603 | mutex_unlock(&acm->mutex); |
| 617 | err_out: | 604 | out: |
| 618 | mutex_unlock(&open_mutex); | 605 | mutex_unlock(&open_mutex); |
| 619 | return rv; | 606 | return rv; |
| 620 | 607 | ||
| 621 | full_bailout: | 608 | full_bailout: |
| 622 | usb_kill_urb(acm->ctrlurb); | 609 | usb_kill_urb(acm->ctrlurb); |
| 623 | bail_out: | 610 | bail_out: |
| 624 | usb_autopm_put_interface(acm->control); | ||
| 625 | acm->port.count--; | 611 | acm->port.count--; |
| 626 | mutex_unlock(&acm->mutex); | 612 | mutex_unlock(&acm->mutex); |
| 613 | usb_autopm_put_interface(acm->control); | ||
| 627 | early_bail: | 614 | early_bail: |
| 628 | mutex_unlock(&open_mutex); | 615 | mutex_unlock(&open_mutex); |
| 629 | tty_port_tty_set(&acm->port, NULL); | 616 | tty_port_tty_set(&acm->port, NULL); |
| @@ -1023,7 +1010,7 @@ static int acm_probe(struct usb_interface *intf, | |||
| 1023 | case USB_CDC_CALL_MANAGEMENT_TYPE: | 1010 | case USB_CDC_CALL_MANAGEMENT_TYPE: |
| 1024 | call_management_function = buffer[3]; | 1011 | call_management_function = buffer[3]; |
| 1025 | call_interface_num = buffer[4]; | 1012 | call_interface_num = buffer[4]; |
| 1026 | if ((call_management_function & 3) != 3) | 1013 | if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3) |
| 1027 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); | 1014 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); |
| 1028 | break; | 1015 | break; |
| 1029 | default: | 1016 | default: |
| @@ -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 | ||
| 1349 | static void acm_disconnect(struct usb_interface *intf) | 1334 | static void acm_disconnect(struct usb_interface *intf) |
| @@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1435 | static int acm_resume(struct usb_interface *intf) | 1420 | static 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, 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 | ||
| @@ -1460,6 +1461,23 @@ err_out: | |||
| 1460 | return rv; | 1461 | return rv; |
| 1461 | } | 1462 | } |
| 1462 | 1463 | ||
| 1464 | static int acm_reset_resume(struct usb_interface *intf) | ||
| 1465 | { | ||
| 1466 | struct acm *acm = usb_get_intfdata(intf); | ||
| 1467 | struct tty_struct *tty; | ||
| 1468 | |||
| 1469 | mutex_lock(&acm->mutex); | ||
| 1470 | if (acm->port.count) { | ||
| 1471 | tty = tty_port_tty_get(&acm->port); | ||
| 1472 | if (tty) { | ||
| 1473 | tty_hangup(tty); | ||
| 1474 | tty_kref_put(tty); | ||
| 1475 | } | ||
| 1476 | } | ||
| 1477 | mutex_unlock(&acm->mutex); | ||
| 1478 | return acm_resume(intf); | ||
| 1479 | } | ||
| 1480 | |||
| 1463 | #endif /* CONFIG_PM */ | 1481 | #endif /* CONFIG_PM */ |
| 1464 | 1482 | ||
| 1465 | #define NOKIA_PCSUITE_ACM_INFO(x) \ | 1483 | #define NOKIA_PCSUITE_ACM_INFO(x) \ |
| @@ -1471,7 +1489,7 @@ err_out: | |||
| 1471 | * USB driver structure. | 1489 | * USB driver structure. |
| 1472 | */ | 1490 | */ |
| 1473 | 1491 | ||
| 1474 | static struct usb_device_id acm_ids[] = { | 1492 | static const struct usb_device_id acm_ids[] = { |
| 1475 | /* quirky and broken devices */ | 1493 | /* quirky and broken devices */ |
| 1476 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ | 1494 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
| 1477 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1495 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| @@ -1576,6 +1594,11 @@ static struct usb_device_id acm_ids[] = { | |||
| 1576 | 1594 | ||
| 1577 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ | 1595 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ |
| 1578 | 1596 | ||
| 1597 | /* Support Lego NXT using pbLua firmware */ | ||
| 1598 | { USB_DEVICE(0x0694, 0xff00), | ||
| 1599 | .driver_info = NOT_A_MODEM, | ||
| 1600 | }, | ||
| 1601 | |||
| 1579 | /* control interfaces with various AT-command sets */ | 1602 | /* control interfaces with various AT-command sets */ |
| 1580 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1603 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
| 1581 | USB_CDC_ACM_PROTO_AT_V25TER) }, | 1604 | USB_CDC_ACM_PROTO_AT_V25TER) }, |
| @@ -1602,6 +1625,7 @@ static struct usb_driver acm_driver = { | |||
| 1602 | #ifdef CONFIG_PM | 1625 | #ifdef CONFIG_PM |
| 1603 | .suspend = acm_suspend, | 1626 | .suspend = acm_suspend, |
| 1604 | .resume = acm_resume, | 1627 | .resume = acm_resume, |
| 1628 | .reset_resume = acm_reset_resume, | ||
| 1605 | #endif | 1629 | #endif |
| 1606 | .id_table = acm_ids, | 1630 | .id_table = acm_ids, |
| 1607 | #ifdef CONFIG_PM | 1631 | #ifdef CONFIG_PM |
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index c4a0ee8ffccf..4a8e87ec6ce9 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 */ |
| @@ -137,3 +136,4 @@ struct acm { | |||
| 137 | #define NO_UNION_NORMAL 1 | 136 | #define NO_UNION_NORMAL 1 |
| 138 | #define SINGLE_RX_URB 2 | 137 | #define SINGLE_RX_URB 2 |
| 139 | #define NO_CAP_LINE 4 | 138 | #define NO_CAP_LINE 4 |
| 139 | #define NOT_A_MODEM 8 | ||
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 3e564bfe17d1..189141ca4e05 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #define DRIVER_AUTHOR "Oliver Neukum" | 31 | #define DRIVER_AUTHOR "Oliver Neukum" |
| 32 | #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" | 32 | #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management" |
| 33 | 33 | ||
| 34 | static struct usb_device_id wdm_ids[] = { | 34 | static const struct usb_device_id wdm_ids[] = { |
| 35 | { | 35 | { |
| 36 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | | 36 | .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | |
| 37 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | 37 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, |
| @@ -52,7 +52,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
| 52 | #define WDM_READ 4 | 52 | #define WDM_READ 4 |
| 53 | #define WDM_INT_STALL 5 | 53 | #define WDM_INT_STALL 5 |
| 54 | #define WDM_POLL_RUNNING 6 | 54 | #define WDM_POLL_RUNNING 6 |
| 55 | 55 | #define WDM_RESPONDING 7 | |
| 56 | #define WDM_SUSPENDING 8 | ||
| 56 | 57 | ||
| 57 | #define WDM_MAX 16 | 58 | #define WDM_MAX 16 |
| 58 | 59 | ||
| @@ -87,9 +88,7 @@ struct wdm_device { | |||
| 87 | int count; | 88 | int count; |
| 88 | dma_addr_t shandle; | 89 | dma_addr_t shandle; |
| 89 | dma_addr_t ihandle; | 90 | dma_addr_t ihandle; |
| 90 | struct mutex wlock; | 91 | struct mutex lock; |
| 91 | struct mutex rlock; | ||
| 92 | struct mutex plock; | ||
| 93 | wait_queue_head_t wait; | 92 | wait_queue_head_t wait; |
| 94 | struct work_struct rxwork; | 93 | struct work_struct rxwork; |
| 95 | int werr; | 94 | int werr; |
| @@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb) | |||
| 117 | int status = urb->status; | 116 | int status = urb->status; |
| 118 | 117 | ||
| 119 | spin_lock(&desc->iuspin); | 118 | spin_lock(&desc->iuspin); |
| 119 | clear_bit(WDM_RESPONDING, &desc->flags); | ||
| 120 | 120 | ||
| 121 | if (status) { | 121 | if (status) { |
| 122 | switch (status) { | 122 | switch (status) { |
| 123 | case -ENOENT: | 123 | case -ENOENT: |
| 124 | dev_dbg(&desc->intf->dev, | 124 | dev_dbg(&desc->intf->dev, |
| 125 | "nonzero urb status received: -ENOENT"); | 125 | "nonzero urb status received: -ENOENT"); |
| 126 | break; | 126 | goto skip_error; |
| 127 | case -ECONNRESET: | 127 | case -ECONNRESET: |
| 128 | dev_dbg(&desc->intf->dev, | 128 | dev_dbg(&desc->intf->dev, |
| 129 | "nonzero urb status received: -ECONNRESET"); | 129 | "nonzero urb status received: -ECONNRESET"); |
| 130 | break; | 130 | goto skip_error; |
| 131 | case -ESHUTDOWN: | 131 | case -ESHUTDOWN: |
| 132 | dev_dbg(&desc->intf->dev, | 132 | dev_dbg(&desc->intf->dev, |
| 133 | "nonzero urb status received: -ESHUTDOWN"); | 133 | "nonzero urb status received: -ESHUTDOWN"); |
| 134 | break; | 134 | goto skip_error; |
| 135 | case -EPIPE: | 135 | case -EPIPE: |
| 136 | dev_err(&desc->intf->dev, | 136 | dev_err(&desc->intf->dev, |
| 137 | "nonzero urb status received: -EPIPE\n"); | 137 | "nonzero urb status received: -EPIPE\n"); |
| @@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb) | |||
| 147 | desc->reslength = urb->actual_length; | 147 | desc->reslength = urb->actual_length; |
| 148 | memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); | 148 | memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); |
| 149 | desc->length += desc->reslength; | 149 | desc->length += desc->reslength; |
| 150 | skip_error: | ||
| 150 | wake_up(&desc->wait); | 151 | wake_up(&desc->wait); |
| 151 | 152 | ||
| 152 | set_bit(WDM_READ, &desc->flags); | 153 | set_bit(WDM_READ, &desc->flags); |
| @@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb) | |||
| 229 | desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 230 | desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 230 | spin_lock(&desc->iuspin); | 231 | spin_lock(&desc->iuspin); |
| 231 | clear_bit(WDM_READ, &desc->flags); | 232 | clear_bit(WDM_READ, &desc->flags); |
| 232 | if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { | 233 | set_bit(WDM_RESPONDING, &desc->flags); |
| 234 | if (!test_bit(WDM_DISCONNECTING, &desc->flags) | ||
| 235 | && !test_bit(WDM_SUSPENDING, &desc->flags)) { | ||
| 233 | rv = usb_submit_urb(desc->response, GFP_ATOMIC); | 236 | rv = usb_submit_urb(desc->response, GFP_ATOMIC); |
| 234 | dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d", | 237 | dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d", |
| 235 | __func__, rv); | 238 | __func__, rv); |
| 236 | } | 239 | } |
| 237 | spin_unlock(&desc->iuspin); | 240 | spin_unlock(&desc->iuspin); |
| 238 | if (rv < 0) { | 241 | if (rv < 0) { |
| 242 | clear_bit(WDM_RESPONDING, &desc->flags); | ||
| 239 | if (rv == -EPERM) | 243 | if (rv == -EPERM) |
| 240 | return; | 244 | return; |
| 241 | if (rv == -ENOMEM) { | 245 | if (rv == -ENOMEM) { |
| @@ -305,14 +309,38 @@ static ssize_t wdm_write | |||
| 305 | if (we < 0) | 309 | if (we < 0) |
| 306 | return -EIO; | 310 | return -EIO; |
| 307 | 311 | ||
| 308 | r = mutex_lock_interruptible(&desc->wlock); /* concurrent writes */ | 312 | desc->outbuf = buf = kmalloc(count, GFP_KERNEL); |
| 313 | if (!buf) { | ||
| 314 | rv = -ENOMEM; | ||
| 315 | goto outnl; | ||
| 316 | } | ||
| 317 | |||
| 318 | r = copy_from_user(buf, buffer, count); | ||
| 319 | if (r > 0) { | ||
| 320 | kfree(buf); | ||
| 321 | rv = -EFAULT; | ||
| 322 | goto outnl; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* concurrent writes and disconnect */ | ||
| 326 | r = mutex_lock_interruptible(&desc->lock); | ||
| 309 | rv = -ERESTARTSYS; | 327 | rv = -ERESTARTSYS; |
| 310 | if (r) | 328 | if (r) { |
| 329 | kfree(buf); | ||
| 311 | goto outnl; | 330 | goto outnl; |
| 331 | } | ||
| 332 | |||
| 333 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) { | ||
| 334 | kfree(buf); | ||
| 335 | rv = -ENODEV; | ||
| 336 | goto outnp; | ||
| 337 | } | ||
| 312 | 338 | ||
| 313 | r = usb_autopm_get_interface(desc->intf); | 339 | r = usb_autopm_get_interface(desc->intf); |
| 314 | if (r < 0) | 340 | if (r < 0) { |
| 341 | kfree(buf); | ||
| 315 | goto outnp; | 342 | goto outnp; |
| 343 | } | ||
| 316 | 344 | ||
| 317 | if (!file->f_flags && O_NONBLOCK) | 345 | if (!file->f_flags && O_NONBLOCK) |
| 318 | r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, | 346 | r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, |
| @@ -320,24 +348,8 @@ static ssize_t wdm_write | |||
| 320 | else | 348 | else |
| 321 | if (test_bit(WDM_IN_USE, &desc->flags)) | 349 | if (test_bit(WDM_IN_USE, &desc->flags)) |
| 322 | r = -EAGAIN; | 350 | r = -EAGAIN; |
| 323 | if (r < 0) | 351 | if (r < 0) { |
| 324 | goto out; | ||
| 325 | |||
| 326 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) { | ||
| 327 | rv = -ENODEV; | ||
| 328 | goto out; | ||
| 329 | } | ||
| 330 | |||
| 331 | desc->outbuf = buf = kmalloc(count, GFP_KERNEL); | ||
| 332 | if (!buf) { | ||
| 333 | rv = -ENOMEM; | ||
| 334 | goto out; | ||
| 335 | } | ||
| 336 | |||
| 337 | r = copy_from_user(buf, buffer, count); | ||
| 338 | if (r > 0) { | ||
| 339 | kfree(buf); | 352 | kfree(buf); |
| 340 | rv = -EFAULT; | ||
| 341 | goto out; | 353 | goto out; |
| 342 | } | 354 | } |
| 343 | 355 | ||
| @@ -374,7 +386,7 @@ static ssize_t wdm_write | |||
| 374 | out: | 386 | out: |
| 375 | usb_autopm_put_interface(desc->intf); | 387 | usb_autopm_put_interface(desc->intf); |
| 376 | outnp: | 388 | outnp: |
| 377 | mutex_unlock(&desc->wlock); | 389 | mutex_unlock(&desc->lock); |
| 378 | outnl: | 390 | outnl: |
| 379 | return rv < 0 ? rv : count; | 391 | return rv < 0 ? rv : count; |
| 380 | } | 392 | } |
| @@ -387,7 +399,7 @@ static ssize_t wdm_read | |||
| 387 | struct wdm_device *desc = file->private_data; | 399 | struct wdm_device *desc = file->private_data; |
| 388 | 400 | ||
| 389 | 401 | ||
| 390 | rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ | 402 | rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */ |
| 391 | if (rv < 0) | 403 | if (rv < 0) |
| 392 | return -ERESTARTSYS; | 404 | return -ERESTARTSYS; |
| 393 | 405 | ||
| @@ -424,11 +436,8 @@ retry: | |||
| 424 | spin_lock_irq(&desc->iuspin); | 436 | spin_lock_irq(&desc->iuspin); |
| 425 | 437 | ||
| 426 | if (desc->rerr) { /* read completed, error happened */ | 438 | if (desc->rerr) { /* read completed, error happened */ |
| 427 | int t = desc->rerr; | ||
| 428 | desc->rerr = 0; | 439 | desc->rerr = 0; |
| 429 | spin_unlock_irq(&desc->iuspin); | 440 | spin_unlock_irq(&desc->iuspin); |
| 430 | dev_err(&desc->intf->dev, | ||
| 431 | "reading had resulted in %d\n", t); | ||
| 432 | rv = -EIO; | 441 | rv = -EIO; |
| 433 | goto err; | 442 | goto err; |
| 434 | } | 443 | } |
| @@ -465,9 +474,7 @@ retry: | |||
| 465 | rv = cntr; | 474 | rv = cntr; |
| 466 | 475 | ||
| 467 | err: | 476 | err: |
| 468 | mutex_unlock(&desc->rlock); | 477 | mutex_unlock(&desc->lock); |
| 469 | if (rv < 0 && rv != -EAGAIN) | ||
| 470 | dev_err(&desc->intf->dev, "wdm_read: exit error\n"); | ||
| 471 | return rv; | 478 | return rv; |
| 472 | } | 479 | } |
| 473 | 480 | ||
| @@ -533,7 +540,7 @@ static int wdm_open(struct inode *inode, struct file *file) | |||
| 533 | } | 540 | } |
| 534 | intf->needs_remote_wakeup = 1; | 541 | intf->needs_remote_wakeup = 1; |
| 535 | 542 | ||
| 536 | mutex_lock(&desc->plock); | 543 | mutex_lock(&desc->lock); |
| 537 | if (!desc->count++) { | 544 | if (!desc->count++) { |
| 538 | rv = usb_submit_urb(desc->validity, GFP_KERNEL); | 545 | rv = usb_submit_urb(desc->validity, GFP_KERNEL); |
| 539 | if (rv < 0) { | 546 | if (rv < 0) { |
| @@ -544,7 +551,7 @@ static int wdm_open(struct inode *inode, struct file *file) | |||
| 544 | } else { | 551 | } else { |
| 545 | rv = 0; | 552 | rv = 0; |
| 546 | } | 553 | } |
| 547 | mutex_unlock(&desc->plock); | 554 | mutex_unlock(&desc->lock); |
| 548 | usb_autopm_put_interface(desc->intf); | 555 | usb_autopm_put_interface(desc->intf); |
| 549 | out: | 556 | out: |
| 550 | mutex_unlock(&wdm_mutex); | 557 | mutex_unlock(&wdm_mutex); |
| @@ -556,9 +563,9 @@ static int wdm_release(struct inode *inode, struct file *file) | |||
| 556 | struct wdm_device *desc = file->private_data; | 563 | struct wdm_device *desc = file->private_data; |
| 557 | 564 | ||
| 558 | mutex_lock(&wdm_mutex); | 565 | mutex_lock(&wdm_mutex); |
| 559 | mutex_lock(&desc->plock); | 566 | mutex_lock(&desc->lock); |
| 560 | desc->count--; | 567 | desc->count--; |
| 561 | mutex_unlock(&desc->plock); | 568 | mutex_unlock(&desc->lock); |
| 562 | 569 | ||
| 563 | if (!desc->count) { | 570 | if (!desc->count) { |
| 564 | dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); | 571 | dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); |
| @@ -655,9 +662,7 @@ next_desc: | |||
| 655 | desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); | 662 | desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); |
| 656 | if (!desc) | 663 | if (!desc) |
| 657 | goto out; | 664 | goto out; |
| 658 | mutex_init(&desc->wlock); | 665 | mutex_init(&desc->lock); |
| 659 | mutex_init(&desc->rlock); | ||
| 660 | mutex_init(&desc->plock); | ||
| 661 | spin_lock_init(&desc->iuspin); | 666 | spin_lock_init(&desc->iuspin); |
| 662 | init_waitqueue_head(&desc->wait); | 667 | init_waitqueue_head(&desc->wait); |
| 663 | desc->wMaxCommand = maxcom; | 668 | desc->wMaxCommand = maxcom; |
| @@ -771,14 +776,17 @@ static void wdm_disconnect(struct usb_interface *intf) | |||
| 771 | /* to terminate pending flushes */ | 776 | /* to terminate pending flushes */ |
| 772 | clear_bit(WDM_IN_USE, &desc->flags); | 777 | clear_bit(WDM_IN_USE, &desc->flags); |
| 773 | spin_unlock_irqrestore(&desc->iuspin, flags); | 778 | spin_unlock_irqrestore(&desc->iuspin, flags); |
| 774 | cancel_work_sync(&desc->rxwork); | 779 | mutex_lock(&desc->lock); |
| 775 | kill_urbs(desc); | 780 | kill_urbs(desc); |
| 781 | cancel_work_sync(&desc->rxwork); | ||
| 782 | mutex_unlock(&desc->lock); | ||
| 776 | wake_up_all(&desc->wait); | 783 | wake_up_all(&desc->wait); |
| 777 | if (!desc->count) | 784 | if (!desc->count) |
| 778 | cleanup(desc); | 785 | cleanup(desc); |
| 779 | mutex_unlock(&wdm_mutex); | 786 | mutex_unlock(&wdm_mutex); |
| 780 | } | 787 | } |
| 781 | 788 | ||
| 789 | #ifdef CONFIG_PM | ||
| 782 | static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | 790 | static int wdm_suspend(struct usb_interface *intf, pm_message_t message) |
| 783 | { | 791 | { |
| 784 | struct wdm_device *desc = usb_get_intfdata(intf); | 792 | struct wdm_device *desc = usb_get_intfdata(intf); |
| @@ -786,22 +794,30 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 786 | 794 | ||
| 787 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); | 795 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); |
| 788 | 796 | ||
| 789 | mutex_lock(&desc->plock); | 797 | /* if this is an autosuspend the caller does the locking */ |
| 790 | #ifdef CONFIG_PM | 798 | if (!(message.event & PM_EVENT_AUTO)) |
| 799 | mutex_lock(&desc->lock); | ||
| 800 | spin_lock_irq(&desc->iuspin); | ||
| 801 | |||
| 791 | if ((message.event & PM_EVENT_AUTO) && | 802 | if ((message.event & PM_EVENT_AUTO) && |
| 792 | test_bit(WDM_IN_USE, &desc->flags)) { | 803 | (test_bit(WDM_IN_USE, &desc->flags) |
| 804 | || test_bit(WDM_RESPONDING, &desc->flags))) { | ||
| 805 | spin_unlock_irq(&desc->iuspin); | ||
| 793 | rv = -EBUSY; | 806 | rv = -EBUSY; |
| 794 | } else { | 807 | } else { |
| 795 | #endif | 808 | |
| 796 | cancel_work_sync(&desc->rxwork); | 809 | set_bit(WDM_SUSPENDING, &desc->flags); |
| 810 | spin_unlock_irq(&desc->iuspin); | ||
| 811 | /* callback submits work - order is essential */ | ||
| 797 | kill_urbs(desc); | 812 | kill_urbs(desc); |
| 798 | #ifdef CONFIG_PM | 813 | cancel_work_sync(&desc->rxwork); |
| 799 | } | 814 | } |
| 800 | #endif | 815 | if (!(message.event & PM_EVENT_AUTO)) |
| 801 | mutex_unlock(&desc->plock); | 816 | mutex_unlock(&desc->lock); |
| 802 | 817 | ||
| 803 | return rv; | 818 | return rv; |
| 804 | } | 819 | } |
| 820 | #endif | ||
| 805 | 821 | ||
| 806 | static int recover_from_urb_loss(struct wdm_device *desc) | 822 | static int recover_from_urb_loss(struct wdm_device *desc) |
| 807 | { | 823 | { |
| @@ -815,23 +831,27 @@ static int recover_from_urb_loss(struct wdm_device *desc) | |||
| 815 | } | 831 | } |
| 816 | return rv; | 832 | return rv; |
| 817 | } | 833 | } |
| 834 | |||
| 835 | #ifdef CONFIG_PM | ||
| 818 | static int wdm_resume(struct usb_interface *intf) | 836 | static int wdm_resume(struct usb_interface *intf) |
| 819 | { | 837 | { |
| 820 | struct wdm_device *desc = usb_get_intfdata(intf); | 838 | struct wdm_device *desc = usb_get_intfdata(intf); |
| 821 | int rv; | 839 | int rv; |
| 822 | 840 | ||
| 823 | dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); | 841 | dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); |
| 824 | mutex_lock(&desc->plock); | 842 | |
| 843 | clear_bit(WDM_SUSPENDING, &desc->flags); | ||
| 825 | rv = recover_from_urb_loss(desc); | 844 | rv = recover_from_urb_loss(desc); |
| 826 | mutex_unlock(&desc->plock); | 845 | |
| 827 | return rv; | 846 | return rv; |
| 828 | } | 847 | } |
| 848 | #endif | ||
| 829 | 849 | ||
| 830 | static int wdm_pre_reset(struct usb_interface *intf) | 850 | static int wdm_pre_reset(struct usb_interface *intf) |
| 831 | { | 851 | { |
| 832 | struct wdm_device *desc = usb_get_intfdata(intf); | 852 | struct wdm_device *desc = usb_get_intfdata(intf); |
| 833 | 853 | ||
| 834 | mutex_lock(&desc->plock); | 854 | mutex_lock(&desc->lock); |
| 835 | return 0; | 855 | return 0; |
| 836 | } | 856 | } |
| 837 | 857 | ||
| @@ -841,7 +861,7 @@ static int wdm_post_reset(struct usb_interface *intf) | |||
| 841 | int rv; | 861 | int rv; |
| 842 | 862 | ||
| 843 | rv = recover_from_urb_loss(desc); | 863 | rv = recover_from_urb_loss(desc); |
| 844 | mutex_unlock(&desc->plock); | 864 | mutex_unlock(&desc->lock); |
| 845 | return 0; | 865 | return 0; |
| 846 | } | 866 | } |
| 847 | 867 | ||
| @@ -849,9 +869,11 @@ static struct usb_driver wdm_driver = { | |||
| 849 | .name = "cdc_wdm", | 869 | .name = "cdc_wdm", |
| 850 | .probe = wdm_probe, | 870 | .probe = wdm_probe, |
| 851 | .disconnect = wdm_disconnect, | 871 | .disconnect = wdm_disconnect, |
| 872 | #ifdef CONFIG_PM | ||
| 852 | .suspend = wdm_suspend, | 873 | .suspend = wdm_suspend, |
| 853 | .resume = wdm_resume, | 874 | .resume = wdm_resume, |
| 854 | .reset_resume = wdm_resume, | 875 | .reset_resume = wdm_resume, |
| 876 | #endif | ||
| 855 | .pre_reset = wdm_pre_reset, | 877 | .pre_reset = wdm_pre_reset, |
| 856 | .post_reset = wdm_post_reset, | 878 | .post_reset = wdm_post_reset, |
| 857 | .id_table = wdm_ids, | 879 | .id_table = wdm_ids, |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 9bc112ee7803..93b5f85d7ceb 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
| @@ -163,7 +163,6 @@ struct usblp { | |||
| 163 | unsigned char used; /* True if open */ | 163 | unsigned char used; /* True if open */ |
| 164 | unsigned char present; /* True if not disconnected */ | 164 | unsigned char present; /* True if not disconnected */ |
| 165 | unsigned char bidir; /* interface is bidirectional */ | 165 | unsigned char bidir; /* interface is bidirectional */ |
| 166 | unsigned char sleeping; /* interface is suspended */ | ||
| 167 | unsigned char no_paper; /* Paper Out happened */ | 166 | unsigned char no_paper; /* Paper Out happened */ |
| 168 | unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ | 167 | unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ |
| 169 | /* first 2 bytes are (big-endian) length */ | 168 | /* first 2 bytes are (big-endian) length */ |
| @@ -191,7 +190,6 @@ static void usblp_dump(struct usblp *usblp) { | |||
| 191 | dbg("quirks=%d", usblp->quirks); | 190 | dbg("quirks=%d", usblp->quirks); |
| 192 | dbg("used=%d", usblp->used); | 191 | dbg("used=%d", usblp->used); |
| 193 | dbg("bidir=%d", usblp->bidir); | 192 | dbg("bidir=%d", usblp->bidir); |
| 194 | dbg("sleeping=%d", usblp->sleeping); | ||
| 195 | dbg("device_id_string=\"%s\"", | 193 | dbg("device_id_string=\"%s\"", |
| 196 | usblp->device_id_string ? | 194 | usblp->device_id_string ? |
| 197 | usblp->device_id_string + 2 : | 195 | usblp->device_id_string + 2 : |
| @@ -376,7 +374,7 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
| 376 | 374 | ||
| 377 | static int handle_bidir (struct usblp *usblp) | 375 | static int handle_bidir (struct usblp *usblp) |
| 378 | { | 376 | { |
| 379 | if (usblp->bidir && usblp->used && !usblp->sleeping) { | 377 | if (usblp->bidir && usblp->used) { |
| 380 | if (usblp_submit_read(usblp) < 0) | 378 | if (usblp_submit_read(usblp) < 0) |
| 381 | return -EIO; | 379 | return -EIO; |
| 382 | } | 380 | } |
| @@ -503,11 +501,6 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 503 | goto done; | 501 | goto done; |
| 504 | } | 502 | } |
| 505 | 503 | ||
| 506 | if (usblp->sleeping) { | ||
| 507 | retval = -ENODEV; | ||
| 508 | goto done; | ||
| 509 | } | ||
| 510 | |||
| 511 | dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), | 504 | dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), |
| 512 | _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); | 505 | _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); |
| 513 | 506 | ||
| @@ -914,8 +907,6 @@ static int usblp_wtest(struct usblp *usblp, int nonblock) | |||
| 914 | return 0; | 907 | return 0; |
| 915 | } | 908 | } |
| 916 | spin_unlock_irqrestore(&usblp->lock, flags); | 909 | spin_unlock_irqrestore(&usblp->lock, flags); |
| 917 | if (usblp->sleeping) | ||
| 918 | return -ENODEV; | ||
| 919 | if (nonblock) | 910 | if (nonblock) |
| 920 | return -EAGAIN; | 911 | return -EAGAIN; |
| 921 | return 1; | 912 | return 1; |
| @@ -968,8 +959,6 @@ static int usblp_rtest(struct usblp *usblp, int nonblock) | |||
| 968 | return 0; | 959 | return 0; |
| 969 | } | 960 | } |
| 970 | spin_unlock_irqrestore(&usblp->lock, flags); | 961 | spin_unlock_irqrestore(&usblp->lock, flags); |
| 971 | if (usblp->sleeping) | ||
| 972 | return -ENODEV; | ||
| 973 | if (nonblock) | 962 | if (nonblock) |
| 974 | return -EAGAIN; | 963 | return -EAGAIN; |
| 975 | return 1; | 964 | return 1; |
| @@ -1377,12 +1366,10 @@ static void usblp_disconnect(struct usb_interface *intf) | |||
| 1377 | mutex_unlock (&usblp_mutex); | 1366 | mutex_unlock (&usblp_mutex); |
| 1378 | } | 1367 | } |
| 1379 | 1368 | ||
| 1380 | static int usblp_suspend (struct usb_interface *intf, pm_message_t message) | 1369 | static int usblp_suspend(struct usb_interface *intf, pm_message_t message) |
| 1381 | { | 1370 | { |
| 1382 | struct usblp *usblp = usb_get_intfdata (intf); | 1371 | struct usblp *usblp = usb_get_intfdata (intf); |
| 1383 | 1372 | ||
| 1384 | /* we take no more IO */ | ||
| 1385 | usblp->sleeping = 1; | ||
| 1386 | usblp_unlink_urbs(usblp); | 1373 | usblp_unlink_urbs(usblp); |
| 1387 | #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ | 1374 | #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ |
| 1388 | /* not strictly necessary, but just in case */ | 1375 | /* not strictly necessary, but just in case */ |
| @@ -1393,18 +1380,17 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message) | |||
| 1393 | return 0; | 1380 | return 0; |
| 1394 | } | 1381 | } |
| 1395 | 1382 | ||
| 1396 | static int usblp_resume (struct usb_interface *intf) | 1383 | static int usblp_resume(struct usb_interface *intf) |
| 1397 | { | 1384 | { |
| 1398 | struct usblp *usblp = usb_get_intfdata (intf); | 1385 | struct usblp *usblp = usb_get_intfdata (intf); |
| 1399 | int r; | 1386 | int r; |
| 1400 | 1387 | ||
| 1401 | usblp->sleeping = 0; | ||
| 1402 | r = handle_bidir (usblp); | 1388 | r = handle_bidir (usblp); |
| 1403 | 1389 | ||
| 1404 | return r; | 1390 | return r; |
| 1405 | } | 1391 | } |
| 1406 | 1392 | ||
| 1407 | static struct usb_device_id usblp_ids [] = { | 1393 | static const struct usb_device_id usblp_ids[] = { |
| 1408 | { USB_DEVICE_INFO(7, 1, 1) }, | 1394 | { USB_DEVICE_INFO(7, 1, 1) }, |
| 1409 | { USB_DEVICE_INFO(7, 1, 2) }, | 1395 | { USB_DEVICE_INFO(7, 1, 2) }, |
| 1410 | { USB_DEVICE_INFO(7, 1, 3) }, | 1396 | { USB_DEVICE_INFO(7, 1, 3) }, |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 7c5f4e32c920..8588c0937a89 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
| @@ -48,7 +48,7 @@ | |||
| 48 | */ | 48 | */ |
| 49 | #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 | 49 | #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 |
| 50 | 50 | ||
| 51 | static struct usb_device_id usbtmc_devices[] = { | 51 | static const struct usb_device_id usbtmc_devices[] = { |
| 52 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, | 52 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, |
| 53 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, | 53 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, |
| 54 | { 0, } /* terminating entry */ | 54 | { 0, } /* terminating entry */ |
