Commit 52e8e19b authored by Linus Torvalds's avatar Linus Torvalds

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
parents 908c3d8c 61fbeba1
...@@ -133,7 +133,7 @@ static int usbtmc_release(struct inode *inode, struct file *file) ...@@ -133,7 +133,7 @@ static int usbtmc_release(struct inode *inode, struct file *file)
static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
{ {
char *buffer; u8 *buffer;
struct device *dev; struct device *dev;
int rv; int rv;
int n; int n;
......
...@@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock); ...@@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock);
/* used when updating an endpoint's URB list */ /* used when updating an endpoint's URB list */
static DEFINE_SPINLOCK(hcd_urb_list_lock); static DEFINE_SPINLOCK(hcd_urb_list_lock);
/* used to protect against unlinking URBs after the device is gone */
static DEFINE_SPINLOCK(hcd_urb_unlink_lock);
/* wait queue for synchronous unlinks */ /* wait queue for synchronous unlinks */
DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
...@@ -1376,10 +1379,25 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -1376,10 +1379,25 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status)
int usb_hcd_unlink_urb (struct urb *urb, int status) int usb_hcd_unlink_urb (struct urb *urb, int status)
{ {
struct usb_hcd *hcd; struct usb_hcd *hcd;
int retval; int retval = -EIDRM;
unsigned long flags;
hcd = bus_to_hcd(urb->dev->bus); /* Prevent the device and bus from going away while
retval = unlink1(hcd, urb, status); * the unlink is carried out. If they are already gone
* then urb->use_count must be 0, since disconnected
* devices can't have any active URBs.
*/
spin_lock_irqsave(&hcd_urb_unlink_lock, flags);
if (atomic_read(&urb->use_count) > 0) {
retval = 0;
usb_get_dev(urb->dev);
}
spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags);
if (retval == 0) {
hcd = bus_to_hcd(urb->dev->bus);
retval = unlink1(hcd, urb, status);
usb_put_dev(urb->dev);
}
if (retval == 0) if (retval == 0)
retval = -EINPROGRESS; retval = -EINPROGRESS;
...@@ -1528,6 +1546,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev, ...@@ -1528,6 +1546,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev,
hcd->driver->endpoint_disable(hcd, ep); hcd->driver->endpoint_disable(hcd, ep);
} }
/* Protect against drivers that try to unlink URBs after the device
* is gone, by waiting until all unlinks for @udev are finished.
* Since we don't currently track URBs by device, simply wait until
* nothing is running in the locked region of usb_hcd_unlink_urb().
*/
void usb_hcd_synchronize_unlinks(struct usb_device *udev)
{
spin_lock_irq(&hcd_urb_unlink_lock);
spin_unlock_irq(&hcd_urb_unlink_lock);
}
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* called in any context */ /* called in any context */
......
...@@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev, ...@@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep); struct usb_host_endpoint *ep);
extern void usb_hcd_disable_endpoint(struct usb_device *udev, extern void usb_hcd_disable_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep); struct usb_host_endpoint *ep);
extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
extern int usb_hcd_get_frame_number(struct usb_device *udev); extern int usb_hcd_get_frame_number(struct usb_device *udev);
extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
......
...@@ -659,6 +659,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) ...@@ -659,6 +659,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2);
schedule_delayed_work(&hub->init_work, schedule_delayed_work(&hub->init_work,
msecs_to_jiffies(delay)); msecs_to_jiffies(delay));
/* Suppress autosuspend until init is done */
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
return; /* Continues at init2: below */ return; /* Continues at init2: below */
} else { } else {
hub_power_on(hub, true); hub_power_on(hub, true);
...@@ -1429,6 +1432,7 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -1429,6 +1432,7 @@ void usb_disconnect(struct usb_device **pdev)
*/ */
dev_dbg (&udev->dev, "unregistering device\n"); dev_dbg (&udev->dev, "unregistering device\n");
usb_disable_device(udev, 0); usb_disable_device(udev, 0);
usb_hcd_synchronize_unlinks(udev);
usb_unlock_device(udev); usb_unlock_device(udev);
......
...@@ -474,6 +474,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb); ...@@ -474,6 +474,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb);
* indicating that the request has been canceled (rather than any other * indicating that the request has been canceled (rather than any other
* code). * code).
* *
* Drivers should not call this routine or related routines, such as
* usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect
* method has returned. The disconnect function should synchronize with
* a driver's I/O routines to insure that all URB-related activity has
* completed before it returns.
*
* This request is always asynchronous. Success is indicated by * This request is always asynchronous. Success is indicated by
* returning -EINPROGRESS, at which time the URB will probably not yet * returning -EINPROGRESS, at which time the URB will probably not yet
* have been given back to the device driver. When it is eventually * have been given back to the device driver. When it is eventually
...@@ -550,6 +556,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb); ...@@ -550,6 +556,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb);
* This routine may not be used in an interrupt context (such as a bottom * This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other * half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule(). * situations where the caller can't schedule().
*
* This routine should not be called by a driver after its disconnect
* method has returned.
*/ */
void usb_kill_urb(struct urb *urb) void usb_kill_urb(struct urb *urb)
{ {
...@@ -588,6 +597,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb); ...@@ -588,6 +597,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
* This routine may not be used in an interrupt context (such as a bottom * This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other * half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule(). * situations where the caller can't schedule().
*
* This routine should not be called by a driver after its disconnect
* method has returned.
*/ */
void usb_poison_urb(struct urb *urb) void usb_poison_urb(struct urb *urb)
{ {
...@@ -622,6 +634,9 @@ EXPORT_SYMBOL_GPL(usb_unpoison_urb); ...@@ -622,6 +634,9 @@ EXPORT_SYMBOL_GPL(usb_unpoison_urb);
* *
* this allows all outstanding URBs to be killed starting * this allows all outstanding URBs to be killed starting
* from the back of the queue * from the back of the queue
*
* This routine should not be called by a driver after its disconnect
* method has returned.
*/ */
void usb_kill_anchored_urbs(struct usb_anchor *anchor) void usb_kill_anchored_urbs(struct usb_anchor *anchor)
{ {
...@@ -651,6 +666,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); ...@@ -651,6 +666,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
* this allows all outstanding URBs to be poisoned starting * this allows all outstanding URBs to be poisoned starting
* from the back of the queue. Newly added URBs will also be * from the back of the queue. Newly added URBs will also be
* poisoned * poisoned
*
* This routine should not be called by a driver after its disconnect
* method has returned.
*/ */
void usb_poison_anchored_urbs(struct usb_anchor *anchor) void usb_poison_anchored_urbs(struct usb_anchor *anchor)
{ {
...@@ -672,6 +690,7 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor) ...@@ -672,6 +690,7 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor)
spin_unlock_irq(&anchor->lock); spin_unlock_irq(&anchor->lock);
} }
EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
/** /**
* usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
* @anchor: anchor the requests are bound to * @anchor: anchor the requests are bound to
...@@ -680,6 +699,9 @@ EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); ...@@ -680,6 +699,9 @@ EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
* from the back of the queue. This function is asynchronous. * from the back of the queue. This function is asynchronous.
* The unlinking is just tiggered. It may happen after this * The unlinking is just tiggered. It may happen after this
* function has returned. * function has returned.
*
* This routine should not be called by a driver after its disconnect
* method has returned.
*/ */
void usb_unlink_anchored_urbs(struct usb_anchor *anchor) void usb_unlink_anchored_urbs(struct usb_anchor *anchor)
{ {
......
...@@ -333,6 +333,13 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, ...@@ -333,6 +333,13 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100,
"Finecam S5", "Finecam S5",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
/* Patch submitted by Jens Taprogge <jens.taprogge@taprogge.org> */
UNUSUAL_DEV( 0x0482, 0x0107, 0x0100, 0x0100,
"Kyocera",
"CONTAX SL300R T*",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE),
/* Reported by Paul Stewart <stewart@wetlogic.net> /* Reported by Paul Stewart <stewart@wetlogic.net>
* This entry is needed because the device reports Sub=ff */ * This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment