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
This commit is contained in:
@@ -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);
|
|||||||
/* 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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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);
|
|||||||
* 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);
|
|||||||
* 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);
|
|||||||
* 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);
|
|||||||
*
|
*
|
||||||
* 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);
|
|||||||
* 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)
|
|||||||
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);
|
|||||||
* 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,
|
|||||||
"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,
|
||||||
|
Reference in New Issue
Block a user