forked from luck/tmp_suning_uos_patched
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:
commit
52e8e19b01
@ -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)
|
||||
{
|
||||
char *buffer;
|
||||
u8 *buffer;
|
||||
struct device *dev;
|
||||
int rv;
|
||||
int n;
|
||||
|
@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock);
|
||||
/* used when updating an endpoint's URB list */
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
int retval = -EIDRM;
|
||||
unsigned long flags;
|
||||
|
||||
hcd = bus_to_hcd(urb->dev->bus);
|
||||
retval = unlink1(hcd, urb, status);
|
||||
/* Prevent the device and bus from going away while
|
||||
* 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)
|
||||
retval = -EINPROGRESS;
|
||||
@ -1528,6 +1546,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev,
|
||||
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 */
|
||||
|
@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep);
|
||||
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
|
||||
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 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);
|
||||
schedule_delayed_work(&hub->init_work,
|
||||
msecs_to_jiffies(delay));
|
||||
|
||||
/* Suppress autosuspend until init is done */
|
||||
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
|
||||
return; /* Continues at init2: below */
|
||||
} else {
|
||||
hub_power_on(hub, true);
|
||||
@ -1429,6 +1432,7 @@ void usb_disconnect(struct usb_device **pdev)
|
||||
*/
|
||||
dev_dbg (&udev->dev, "unregistering device\n");
|
||||
usb_disable_device(udev, 0);
|
||||
usb_hcd_synchronize_unlinks(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
|
||||
* 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
|
||||
* returning -EINPROGRESS, at which time the URB will probably not yet
|
||||
* 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
|
||||
* half or a completion handler), or when holding a spinlock, or in other
|
||||
* 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)
|
||||
{
|
||||
@ -588,6 +597,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
@ -622,6 +634,9 @@ EXPORT_SYMBOL_GPL(usb_unpoison_urb);
|
||||
*
|
||||
* this allows all outstanding URBs to be killed starting
|
||||
* 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)
|
||||
{
|
||||
@ -651,6 +666,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
|
||||
* this allows all outstanding URBs to be poisoned starting
|
||||
* from the back of the queue. Newly added URBs will also be
|
||||
* 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)
|
||||
{
|
||||
@ -672,6 +690,7 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor)
|
||||
spin_unlock_irq(&anchor->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs);
|
||||
|
||||
/**
|
||||
* usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse
|
||||
* @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.
|
||||
* The unlinking is just tiggered. It may happen after this
|
||||
* 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)
|
||||
{
|
||||
|
@ -333,6 +333,13 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100,
|
||||
"Finecam S5",
|
||||
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>
|
||||
* This entry is needed because the device reports Sub=ff */
|
||||
UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001,
|
||||
|
Loading…
Reference in New Issue
Block a user