diff options
Diffstat (limited to 'drivers/usb/class')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 143 | ||||
-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 | 59 |
5 files changed, 220 insertions, 142 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e4eca7810bcf..5e1a253b08a0 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,12 +1461,35 @@ 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 */ |
1482 | |||
1483 | #define NOKIA_PCSUITE_ACM_INFO(x) \ | ||
1484 | USB_DEVICE_AND_INTERFACE_INFO(0x0421, x, \ | ||
1485 | USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ | ||
1486 | USB_CDC_ACM_PROTO_VENDOR) | ||
1487 | |||
1464 | /* | 1488 | /* |
1465 | * USB driver structure. | 1489 | * USB driver structure. |
1466 | */ | 1490 | */ |
1467 | 1491 | ||
1468 | static struct usb_device_id acm_ids[] = { | 1492 | static const struct usb_device_id acm_ids[] = { |
1469 | /* quirky and broken devices */ | 1493 | /* quirky and broken devices */ |
1470 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ | 1494 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
1471 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1495 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
@@ -1518,6 +1542,65 @@ static struct usb_device_id acm_ids[] = { | |||
1518 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ | 1542 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ |
1519 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1543 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1520 | }, | 1544 | }, |
1545 | { USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */ | ||
1546 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | ||
1547 | }, | ||
1548 | |||
1549 | /* Nokia S60 phones expose two ACM channels. The first is | ||
1550 | * a modem and is picked up by the standard AT-command | ||
1551 | * information below. The second is 'vendor-specific' but | ||
1552 | * is treated as a serial device at the S60 end, so we want | ||
1553 | * to expose it on Linux too. */ | ||
1554 | { NOKIA_PCSUITE_ACM_INFO(0x042D), }, /* Nokia 3250 */ | ||
1555 | { NOKIA_PCSUITE_ACM_INFO(0x04D8), }, /* Nokia 5500 Sport */ | ||
1556 | { NOKIA_PCSUITE_ACM_INFO(0x04C9), }, /* Nokia E50 */ | ||
1557 | { NOKIA_PCSUITE_ACM_INFO(0x0419), }, /* Nokia E60 */ | ||
1558 | { NOKIA_PCSUITE_ACM_INFO(0x044D), }, /* Nokia E61 */ | ||
1559 | { NOKIA_PCSUITE_ACM_INFO(0x0001), }, /* Nokia E61i */ | ||
1560 | { NOKIA_PCSUITE_ACM_INFO(0x0475), }, /* Nokia E62 */ | ||
1561 | { NOKIA_PCSUITE_ACM_INFO(0x0508), }, /* Nokia E65 */ | ||
1562 | { NOKIA_PCSUITE_ACM_INFO(0x0418), }, /* Nokia E70 */ | ||
1563 | { NOKIA_PCSUITE_ACM_INFO(0x0425), }, /* Nokia N71 */ | ||
1564 | { NOKIA_PCSUITE_ACM_INFO(0x0486), }, /* Nokia N73 */ | ||
1565 | { NOKIA_PCSUITE_ACM_INFO(0x04DF), }, /* Nokia N75 */ | ||
1566 | { NOKIA_PCSUITE_ACM_INFO(0x000e), }, /* Nokia N77 */ | ||
1567 | { NOKIA_PCSUITE_ACM_INFO(0x0445), }, /* Nokia N80 */ | ||
1568 | { NOKIA_PCSUITE_ACM_INFO(0x042F), }, /* Nokia N91 & N91 8GB */ | ||
1569 | { NOKIA_PCSUITE_ACM_INFO(0x048E), }, /* Nokia N92 */ | ||
1570 | { NOKIA_PCSUITE_ACM_INFO(0x0420), }, /* Nokia N93 */ | ||
1571 | { NOKIA_PCSUITE_ACM_INFO(0x04E6), }, /* Nokia N93i */ | ||
1572 | { NOKIA_PCSUITE_ACM_INFO(0x04B2), }, /* Nokia 5700 XpressMusic */ | ||
1573 | { NOKIA_PCSUITE_ACM_INFO(0x0134), }, /* Nokia 6110 Navigator (China) */ | ||
1574 | { NOKIA_PCSUITE_ACM_INFO(0x046E), }, /* Nokia 6110 Navigator */ | ||
1575 | { NOKIA_PCSUITE_ACM_INFO(0x002f), }, /* Nokia 6120 classic & */ | ||
1576 | { NOKIA_PCSUITE_ACM_INFO(0x0088), }, /* Nokia 6121 classic */ | ||
1577 | { NOKIA_PCSUITE_ACM_INFO(0x00fc), }, /* Nokia 6124 classic */ | ||
1578 | { NOKIA_PCSUITE_ACM_INFO(0x0042), }, /* Nokia E51 */ | ||
1579 | { NOKIA_PCSUITE_ACM_INFO(0x00b0), }, /* Nokia E66 */ | ||
1580 | { NOKIA_PCSUITE_ACM_INFO(0x00ab), }, /* Nokia E71 */ | ||
1581 | { NOKIA_PCSUITE_ACM_INFO(0x0481), }, /* Nokia N76 */ | ||
1582 | { NOKIA_PCSUITE_ACM_INFO(0x0007), }, /* Nokia N81 & N81 8GB */ | ||
1583 | { NOKIA_PCSUITE_ACM_INFO(0x0071), }, /* Nokia N82 */ | ||
1584 | { NOKIA_PCSUITE_ACM_INFO(0x04F0), }, /* Nokia N95 & N95-3 NAM */ | ||
1585 | { NOKIA_PCSUITE_ACM_INFO(0x0070), }, /* Nokia N95 8GB */ | ||
1586 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ | ||
1587 | { NOKIA_PCSUITE_ACM_INFO(0x0099), }, /* Nokia 6210 Navigator, RM-367 */ | ||
1588 | { NOKIA_PCSUITE_ACM_INFO(0x0128), }, /* Nokia 6210 Navigator, RM-419 */ | ||
1589 | { NOKIA_PCSUITE_ACM_INFO(0x008f), }, /* Nokia 6220 Classic */ | ||
1590 | { NOKIA_PCSUITE_ACM_INFO(0x00a0), }, /* Nokia 6650 */ | ||
1591 | { NOKIA_PCSUITE_ACM_INFO(0x007b), }, /* Nokia N78 */ | ||
1592 | { NOKIA_PCSUITE_ACM_INFO(0x0094), }, /* Nokia N85 */ | ||
1593 | { NOKIA_PCSUITE_ACM_INFO(0x003a), }, /* Nokia N96 & N96-3 */ | ||
1594 | { NOKIA_PCSUITE_ACM_INFO(0x00e9), }, /* Nokia 5320 XpressMusic */ | ||
1595 | { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ | ||
1596 | { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ | ||
1597 | |||
1598 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ | ||
1599 | |||
1600 | /* Support Lego NXT using pbLua firmware */ | ||
1601 | { USB_DEVICE(0x0694, 0xff00), | ||
1602 | .driver_info = NOT_A_MODEM, | ||
1603 | }, | ||
1521 | 1604 | ||
1522 | /* control interfaces with various AT-command sets */ | 1605 | /* control interfaces with various AT-command sets */ |
1523 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1606 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
@@ -1533,7 +1616,6 @@ static struct usb_device_id acm_ids[] = { | |||
1533 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1616 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
1534 | USB_CDC_ACM_PROTO_AT_CDMA) }, | 1617 | USB_CDC_ACM_PROTO_AT_CDMA) }, |
1535 | 1618 | ||
1536 | /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */ | ||
1537 | { } | 1619 | { } |
1538 | }; | 1620 | }; |
1539 | 1621 | ||
@@ -1546,6 +1628,7 @@ static struct usb_driver acm_driver = { | |||
1546 | #ifdef CONFIG_PM | 1628 | #ifdef CONFIG_PM |
1547 | .suspend = acm_suspend, | 1629 | .suspend = acm_suspend, |
1548 | .resume = acm_resume, | 1630 | .resume = acm_resume, |
1631 | .reset_resume = acm_reset_resume, | ||
1549 | #endif | 1632 | #endif |
1550 | .id_table = acm_ids, | 1633 | .id_table = acm_ids, |
1551 | #ifdef CONFIG_PM | 1634 | #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 2473cf0c6b1d..3e7c1b800ebb 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * drivers/usb/class/usbtmc.c - USB Test & Measurment class driver | 2 | * drivers/usb/class/usbtmc.c - USB Test & Measurement class driver |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany | 4 | * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany |
5 | * Copyright (C) 2008 Novell, Inc. | 5 | * Copyright (C) 2008 Novell, Inc. |
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
27 | #include <linux/kref.h> | 27 | #include <linux/kref.h> |
28 | #include <linux/slab.h> | ||
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
29 | #include <linux/usb.h> | 30 | #include <linux/usb.h> |
30 | #include <linux/usb/tmc.h> | 31 | #include <linux/usb/tmc.h> |
@@ -48,7 +49,7 @@ | |||
48 | */ | 49 | */ |
49 | #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 | 50 | #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100 |
50 | 51 | ||
51 | static struct usb_device_id usbtmc_devices[] = { | 52 | static const struct usb_device_id usbtmc_devices[] = { |
52 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, | 53 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, |
53 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, | 54 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, |
54 | { 0, } /* terminating entry */ | 55 | { 0, } /* terminating entry */ |
@@ -347,13 +348,8 @@ usbtmc_abort_bulk_out_check_status: | |||
347 | goto exit; | 348 | goto exit; |
348 | 349 | ||
349 | usbtmc_abort_bulk_out_clear_halt: | 350 | usbtmc_abort_bulk_out_clear_halt: |
350 | rv = usb_control_msg(data->usb_dev, | 351 | rv = usb_clear_halt(data->usb_dev, |
351 | usb_sndctrlpipe(data->usb_dev, 0), | 352 | usb_sndbulkpipe(data->usb_dev, data->bulk_out)); |
352 | USB_REQ_CLEAR_FEATURE, | ||
353 | USB_DIR_OUT | USB_TYPE_STANDARD | | ||
354 | USB_RECIP_ENDPOINT, | ||
355 | USB_ENDPOINT_HALT, data->bulk_out, buffer, | ||
356 | 0, USBTMC_TIMEOUT); | ||
357 | 353 | ||
358 | if (rv < 0) { | 354 | if (rv < 0) { |
359 | dev_err(dev, "usb_control_msg returned %d\n", rv); | 355 | dev_err(dev, "usb_control_msg returned %d\n", rv); |
@@ -562,10 +558,16 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, | |||
562 | n_bytes = roundup(12 + this_part, 4); | 558 | n_bytes = roundup(12 + this_part, 4); |
563 | memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); | 559 | memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); |
564 | 560 | ||
565 | retval = usb_bulk_msg(data->usb_dev, | 561 | do { |
566 | usb_sndbulkpipe(data->usb_dev, | 562 | retval = usb_bulk_msg(data->usb_dev, |
567 | data->bulk_out), | 563 | usb_sndbulkpipe(data->usb_dev, |
568 | buffer, n_bytes, &actual, USBTMC_TIMEOUT); | 564 | data->bulk_out), |
565 | buffer, n_bytes, | ||
566 | &actual, USBTMC_TIMEOUT); | ||
567 | if (retval != 0) | ||
568 | break; | ||
569 | n_bytes -= actual; | ||
570 | } while (n_bytes); | ||
569 | 571 | ||
570 | data->bTag_last_write = data->bTag; | 572 | data->bTag_last_write = data->bTag; |
571 | data->bTag++; | 573 | data->bTag++; |
@@ -702,14 +704,8 @@ usbtmc_clear_check_status: | |||
702 | 704 | ||
703 | usbtmc_clear_bulk_out_halt: | 705 | usbtmc_clear_bulk_out_halt: |
704 | 706 | ||
705 | rv = usb_control_msg(data->usb_dev, | 707 | rv = usb_clear_halt(data->usb_dev, |
706 | usb_sndctrlpipe(data->usb_dev, 0), | 708 | usb_sndbulkpipe(data->usb_dev, data->bulk_out)); |
707 | USB_REQ_CLEAR_FEATURE, | ||
708 | USB_DIR_OUT | USB_TYPE_STANDARD | | ||
709 | USB_RECIP_ENDPOINT, | ||
710 | USB_ENDPOINT_HALT, | ||
711 | data->bulk_out, buffer, 0, | ||
712 | USBTMC_TIMEOUT); | ||
713 | if (rv < 0) { | 709 | if (rv < 0) { |
714 | dev_err(dev, "usb_control_msg returned %d\n", rv); | 710 | dev_err(dev, "usb_control_msg returned %d\n", rv); |
715 | goto exit; | 711 | goto exit; |
@@ -730,13 +726,8 @@ static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data) | |||
730 | if (!buffer) | 726 | if (!buffer) |
731 | return -ENOMEM; | 727 | return -ENOMEM; |
732 | 728 | ||
733 | rv = usb_control_msg(data->usb_dev, | 729 | rv = usb_clear_halt(data->usb_dev, |
734 | usb_sndctrlpipe(data->usb_dev, 0), | 730 | usb_sndbulkpipe(data->usb_dev, data->bulk_out)); |
735 | USB_REQ_CLEAR_FEATURE, | ||
736 | USB_DIR_OUT | USB_TYPE_STANDARD | | ||
737 | USB_RECIP_ENDPOINT, | ||
738 | USB_ENDPOINT_HALT, data->bulk_out, | ||
739 | buffer, 0, USBTMC_TIMEOUT); | ||
740 | 731 | ||
741 | if (rv < 0) { | 732 | if (rv < 0) { |
742 | dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", | 733 | dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", |
@@ -759,12 +750,8 @@ static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data) | |||
759 | if (!buffer) | 750 | if (!buffer) |
760 | return -ENOMEM; | 751 | return -ENOMEM; |
761 | 752 | ||
762 | rv = usb_control_msg(data->usb_dev, usb_sndctrlpipe(data->usb_dev, 0), | 753 | rv = usb_clear_halt(data->usb_dev, |
763 | USB_REQ_CLEAR_FEATURE, | 754 | usb_rcvbulkpipe(data->usb_dev, data->bulk_in)); |
764 | USB_DIR_OUT | USB_TYPE_STANDARD | | ||
765 | USB_RECIP_ENDPOINT, | ||
766 | USB_ENDPOINT_HALT, data->bulk_in, buffer, 0, | ||
767 | USBTMC_TIMEOUT); | ||
768 | 755 | ||
769 | if (rv < 0) { | 756 | if (rv < 0) { |
770 | dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", | 757 | dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n", |
@@ -1109,13 +1096,13 @@ static void usbtmc_disconnect(struct usb_interface *intf) | |||
1109 | kref_put(&data->kref, usbtmc_delete); | 1096 | kref_put(&data->kref, usbtmc_delete); |
1110 | } | 1097 | } |
1111 | 1098 | ||
1112 | static int usbtmc_suspend (struct usb_interface *intf, pm_message_t message) | 1099 | static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message) |
1113 | { | 1100 | { |
1114 | /* this driver does not have pending URBs */ | 1101 | /* this driver does not have pending URBs */ |
1115 | return 0; | 1102 | return 0; |
1116 | } | 1103 | } |
1117 | 1104 | ||
1118 | static int usbtmc_resume (struct usb_interface *intf) | 1105 | static int usbtmc_resume(struct usb_interface *intf) |
1119 | { | 1106 | { |
1120 | return 0; | 1107 | return 0; |
1121 | } | 1108 | } |