diff options
| -rw-r--r-- | drivers/usb/class/usbtmc.c | 2 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 35 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.h | 1 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 4 | ||||
| -rw-r--r-- | drivers/usb/core/urb.c | 22 | ||||
| -rw-r--r-- | drivers/usb/storage/unusual_devs.h | 7 |
6 files changed, 67 insertions, 4 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 543811f6e6e8..8e74657f106c 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
| @@ -133,7 +133,7 @@ static int usbtmc_release(struct inode *inode, struct file *file) | |||
| 133 | 133 | ||
| 134 | static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) | 134 | static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) |
| 135 | { | 135 | { |
| 136 | char *buffer; | 136 | u8 *buffer; |
| 137 | struct device *dev; | 137 | struct device *dev; |
| 138 | int rv; | 138 | int rv; |
| 139 | int n; | 139 | int n; |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fc9018e72a09..e1b42626d04d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
| @@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock); | |||
| 106 | /* used when updating an endpoint's URB list */ | 106 | /* used when updating an endpoint's URB list */ |
| 107 | static DEFINE_SPINLOCK(hcd_urb_list_lock); | 107 | static DEFINE_SPINLOCK(hcd_urb_list_lock); |
| 108 | 108 | ||
| 109 | /* used to protect against unlinking URBs after the device is gone */ | ||
| 110 | static DEFINE_SPINLOCK(hcd_urb_unlink_lock); | ||
| 111 | |||
| 109 | /* wait queue for synchronous unlinks */ | 112 | /* wait queue for synchronous unlinks */ |
| 110 | DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); | 113 | DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); |
| 111 | 114 | ||
| @@ -1376,10 +1379,25 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) | |||
| 1376 | int usb_hcd_unlink_urb (struct urb *urb, int status) | 1379 | int usb_hcd_unlink_urb (struct urb *urb, int status) |
| 1377 | { | 1380 | { |
| 1378 | struct usb_hcd *hcd; | 1381 | struct usb_hcd *hcd; |
| 1379 | int retval; | 1382 | int retval = -EIDRM; |
| 1383 | unsigned long flags; | ||
| 1380 | 1384 | ||
| 1381 | hcd = bus_to_hcd(urb->dev->bus); | 1385 | /* Prevent the device and bus from going away while |
| 1382 | retval = unlink1(hcd, urb, status); | 1386 | * the unlink is carried out. If they are already gone |
| 1387 | * then urb->use_count must be 0, since disconnected | ||
| 1388 | * devices can't have any active URBs. | ||
| 1389 | */ | ||
| 1390 | spin_lock_irqsave(&hcd_urb_unlink_lock, flags); | ||
| 1391 | if (atomic_read(&urb->use_count) > 0) { | ||
| 1392 | retval = 0; | ||
| 1393 | usb_get_dev(urb->dev); | ||
| 1394 | } | ||
| 1395 | spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); | ||
| 1396 | if (retval == 0) { | ||
| 1397 | hcd = bus_to_hcd(urb->dev->bus); | ||
| 1398 | retval = unlink1(hcd, urb, status); | ||
| 1399 | usb_put_dev(urb->dev); | ||
| 1400 | } | ||
| 1383 | 1401 | ||
| 1384 | if (retval == 0) | 1402 | if (retval == 0) |
| 1385 | retval = -EINPROGRESS; | 1403 | retval = -EINPROGRESS; |
| @@ -1528,6 +1546,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev, | |||
| 1528 | hcd->driver->endpoint_disable(hcd, ep); | 1546 | hcd->driver->endpoint_disable(hcd, ep); |
| 1529 | } | 1547 | } |
| 1530 | 1548 | ||
| 1549 | /* Protect against drivers that try to unlink URBs after the device | ||
| 1550 | * is gone, by waiting until all unlinks for @udev are finished. | ||
| 1551 | * Since we don't currently track URBs by device, simply wait until | ||
| 1552 | * nothing is running in the locked region of usb_hcd_unlink_urb(). | ||
| 1553 | */ | ||
| 1554 | void usb_hcd_synchronize_unlinks(struct usb_device *udev) | ||
| 1555 | { | ||
| 1556 | spin_lock_irq(&hcd_urb_unlink_lock); | ||
| 1557 | spin_unlock_irq(&hcd_urb_unlink_lock); | ||
| 1558 | } | ||
| 1559 | |||
| 1531 | /*-------------------------------------------------------------------------*/ | 1560 | /*-------------------------------------------------------------------------*/ |
| 1532 | 1561 | ||
| 1533 | /* called in any context */ | 1562 | /* called in any context */ |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 2dcde61c465e..9465e70f4dd0 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev, | |||
| 232 | struct usb_host_endpoint *ep); | 232 | struct usb_host_endpoint *ep); |
| 233 | extern void usb_hcd_disable_endpoint(struct usb_device *udev, | 233 | extern void usb_hcd_disable_endpoint(struct usb_device *udev, |
| 234 | struct usb_host_endpoint *ep); | 234 | struct usb_host_endpoint *ep); |
| 235 | extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); | ||
| 235 | extern int usb_hcd_get_frame_number(struct usb_device *udev); | 236 | extern int usb_hcd_get_frame_number(struct usb_device *udev); |
| 236 | 237 | ||
| 237 | extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, | 238 | extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 9b3f16bd12cb..b19cbfcd51da 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -659,6 +659,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
| 659 | PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); | 659 | PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); |
| 660 | schedule_delayed_work(&hub->init_work, | 660 | schedule_delayed_work(&hub->init_work, |
| 661 | msecs_to_jiffies(delay)); | 661 | msecs_to_jiffies(delay)); |
| 662 | |||
| 663 | /* Suppress autosuspend until init is done */ | ||
| 664 | to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; | ||
| 662 | return; /* Continues at init2: below */ | 665 | return; /* Continues at init2: below */ |
| 663 | } else { | 666 | } else { |
| 664 | hub_power_on(hub, true); | 667 | hub_power_on(hub, true); |
| @@ -1429,6 +1432,7 @@ void usb_disconnect(struct usb_device **pdev) | |||
| 1429 | */ | 1432 | */ |
| 1430 | dev_dbg (&udev->dev, "unregistering device\n"); | 1433 | dev_dbg (&udev->dev, "unregistering device\n"); |
| 1431 | usb_disable_device(udev, 0); | 1434 | usb_disable_device(udev, 0); |
| 1435 | usb_hcd_synchronize_unlinks(udev); | ||
| 1432 | 1436 | ||
| 1433 | usb_unlock_device(udev); | 1437 | usb_unlock_device(udev); |
| 1434 | 1438 | ||
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index f2638009a464..4342bd9c3bb6 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
| @@ -474,6 +474,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb); | |||
| 474 | * indicating that the request has been canceled (rather than any other | 474 | * indicating that the request has been canceled (rather than any other |
| 475 | * code). | 475 | * code). |
| 476 | * | 476 | * |
| 477 | * Drivers should not call this routine or related routines, such as | ||
| 478 | * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect | ||
| 479 | * method has returned. The disconnect function should synchronize with | ||
| 480 | * a driver's I/O routines to insure that all URB-related activity has | ||
| 481 | * completed before it returns. | ||
| 482 | * | ||
| 477 | * This request is always asynchronous. Success is indicated by | 483 | * This request is always asynchronous. Success is indicated by |
| 478 | * returning -EINPROGRESS, at which time the URB will probably not yet | 484 | * returning -EINPROGRESS, at which time the URB will probably not yet |
| 479 | * have been given back to the device driver. When it is eventually | 485 | * have been given back to the device driver. When it is eventually |
| @@ -550,6 +556,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb); | |||
| 550 | * This routine may not be used in an interrupt context (such as a bottom | 556 | * This routine may not be used in an interrupt context (such as a bottom |
| 551 | * half or a completion handler), or when holding a spinlock, or in other | 557 | * half or a completion handler), or when holding a spinlock, or in other |
| 552 | * situations where the caller can't schedule(). | 558 | * situations where the caller can't schedule(). |
| 559 | * | ||
| 560 | * This routine should not be called by a driver after its disconnect | ||
| 561 | * method has returned. | ||
| 553 | */ | 562 | */ |
| 554 | void usb_kill_urb(struct urb *urb) | 563 | void usb_kill_urb(struct urb *urb) |
| 555 | { | 564 | { |
| @@ -588,6 +597,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb); | |||
| 588 | * This routine may not be used in an interrupt context (such as a bottom | 597 | * This routine may not be used in an interrupt context (such as a bottom |
| 589 | * half or a completion handler), or when holding a spinlock, or in other | 598 | * half or a completion handler), or when holding a spinlock, or in other |
| 590 | * situations where the caller can't schedule(). | 599 | * situations where the caller can't schedule(). |
| 600 | * | ||
| 601 | * This routine should not be called by a driver after its disconnect | ||
| 602 | * method has returned. | ||
| 591 | */ | 603 | */ |
| 592 | void usb_poison_urb(struct urb *urb) | 604 | void usb_poison_urb(struct urb *urb) |
| 593 | { | 605 | { |
| @@ -622,6 +634,9 @@ EXPORT_SYMBOL_GPL(usb_unpoison_urb); | |||
| 622 | * | 634 | * |
| 623 | * this allows all outstanding URBs to be killed starting | 635 | * this allows all outstanding URBs to be killed starting |
| 624 | * from the back of the queue | 636 | * from the back of the queue |
| 637 | * | ||
| 638 | * This routine should not be called by a driver after its disconnect | ||
| 639 | * method has returned. | ||
| 625 | */ | 640 | */ |
| 626 | void usb_kill_anchored_urbs(struct usb_anchor *anchor) | 641 | void usb_kill_anchored_urbs(struct usb_anchor *anchor) |
| 627 | { | 642 | { |
| @@ -651,6 +666,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); | |||
| 651 | * this allows all outstanding URBs to be poisoned starting | 666 | * this allows all outstanding URBs to be poisoned starting |
| 652 | * from the back of the queue. Newly added URBs will also be | 667 | * from the back of the queue. Newly added URBs will also be |
| 653 | * poisoned | 668 | * poisoned |
| 669 | * | ||
| 670 | * This routine should not be called by a driver after its disconnect | ||
| 671 | * method has returned. | ||
| 654 | */ | 672 | */ |
| 655 | void usb_poison_anchored_urbs(struct usb_anchor *anchor) | 673 | void usb_poison_anchored_urbs(struct usb_anchor *anchor) |
| 656 | { | 674 | { |
| @@ -672,6 +690,7 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor) | |||
| 672 | spin_unlock_irq(&anchor->lock); | 690 | spin_unlock_irq(&anchor->lock); |
| 673 | } | 691 | } |
| 674 | EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); | 692 | EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); |
| 693 | |||
| 675 | /** | 694 | /** |
| 676 | * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse | 695 | * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse |
| 677 | * @anchor: anchor the requests are bound to | 696 | * @anchor: anchor the requests are bound to |
| @@ -680,6 +699,9 @@ EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); | |||
| 680 | * from the back of the queue. This function is asynchronous. | 699 | * from the back of the queue. This function is asynchronous. |
| 681 | * The unlinking is just tiggered. It may happen after this | 700 | * The unlinking is just tiggered. It may happen after this |
| 682 | * function has returned. | 701 | * function has returned. |
| 702 | * | ||
| 703 | * This routine should not be called by a driver after its disconnect | ||
| 704 | * method has returned. | ||
| 683 | */ | 705 | */ |
| 684 | void usb_unlink_anchored_urbs(struct usb_anchor *anchor) | 706 | void usb_unlink_anchored_urbs(struct usb_anchor *anchor) |
| 685 | { | 707 | { |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a2b9ebbef38e..fb9e20e624c1 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
| @@ -333,6 +333,13 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, | |||
| 333 | "Finecam S5", | 333 | "Finecam S5", |
| 334 | US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), | 334 | US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), |
| 335 | 335 | ||
| 336 | /* Patch submitted by Jens Taprogge <jens.taprogge@taprogge.org> */ | ||
| 337 | UNUSUAL_DEV( 0x0482, 0x0107, 0x0100, 0x0100, | ||
| 338 | "Kyocera", | ||
| 339 | "CONTAX SL300R T*", | ||
| 340 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 341 | US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE), | ||
| 342 | |||
| 336 | /* Reported by Paul Stewart <stewart@wetlogic.net> | 343 | /* Reported by Paul Stewart <stewart@wetlogic.net> |
| 337 | * This entry is needed because the device reports Sub=ff */ | 344 | * This entry is needed because the device reports Sub=ff */ |
| 338 | UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, | 345 | UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, |
