diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-30 14:49:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-30 14:49:12 -0400 |
commit | 52e8e19b019ca7ad6951d7a39b78d24b198238bc (patch) | |
tree | 5bc9dd4f4df1630aea1e0d7b42ba1673cdf810c7 /drivers | |
parent | 908c3d8c005f19f807c67105cede0bd2c352a8e6 (diff) | |
parent | 61fbeba11c553c489ba5284c0ed67067dc7b7c0f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
USB: prevent autosuspend during hub initialization
USB: Unusual dev for the "Kyocera / Contax SL300R T*" digital camera.
USB: usbtmc: Use explicit unsigned type for input buffer instead of char*
USB: fix crash when URBs are unlinked after the device is gone
Diffstat (limited to 'drivers')
-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, |