Commit 45196cee authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-3.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

USB bugfixes for 3.3-rc4

A number of new device ids, and a cleanup/fix for some of the option
device ids that shouldn't have been added in the first place.

There's also a few USB 3 fixes for problems that people have reported,
and a usb-storage bugfix to round it out.
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>

* tag 'usb-3.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: Added Kamstrup VID/PIDs to cp210x serial driver.
  USB: Serial: ti_usb_3410_5052: Add Abbot Diabetes Care cable id
  usb-storage: fix freezing of the scanning thread
  xhci: Fix encoding for HS bulk/control NAK rate.
  USB: Set hub depth after USB3 hub reset
  USB: Fix handoff when BIOS disables host PCI device.
  USB: option: cleanup zte 3g-dongle's pid in option.c
  USB: Don't fail USB3 probe on missing legacy PCI IRQ.
  xhci: Fix oops caused by more USB2 ports than USB3 ports.
  USB: Remove duplicate USB 3.0 hub feature #defines.
parents e2d4370b c6c1e449
...@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV; return -ENODEV;
dev->current_state = PCI_D0; dev->current_state = PCI_D0;
if (!dev->irq) { /* The xHCI driver supports MSI and MSI-X,
* so don't fail if the BIOS doesn't provide a legacy IRQ.
*/
if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
dev_err(&dev->dev, dev_err(&dev->dev,
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n", "Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
pci_name(dev)); pci_name(dev));
......
...@@ -2447,8 +2447,10 @@ int usb_add_hcd(struct usb_hcd *hcd, ...@@ -2447,8 +2447,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
&& device_can_wakeup(&hcd->self.root_hub->dev)) && device_can_wakeup(&hcd->self.root_hub->dev))
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n"); dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
/* enable irqs just before we start the controller */ /* enable irqs just before we start the controller,
if (usb_hcd_is_primary_hcd(hcd)) { * if the BIOS provides legacy PCI irqs.
*/
if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
retval = usb_hcd_request_irqs(hcd, irqnum, irqflags); retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
if (retval) if (retval)
goto err_request_irq; goto err_request_irq;
......
...@@ -705,10 +705,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) ...@@ -705,10 +705,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
if (type == HUB_INIT3) if (type == HUB_INIT3)
goto init3; goto init3;
/* After a resume, port power should still be on. /* The superspeed hub except for root hub has to use Hub Depth
* value as an offset into the route string to locate the bits
* it uses to determine the downstream port number. So hub driver
* should send a set hub depth request to superspeed hub after
* the superspeed hub is set configuration in initialization or
* reset procedure.
*
* After a resume, port power should still be on.
* For any other type of activation, turn it on. * For any other type of activation, turn it on.
*/ */
if (type != HUB_RESUME) { if (type != HUB_RESUME) {
if (hdev->parent && hub_is_superspeed(hdev)) {
ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
HUB_SET_DEPTH, USB_RT_HUB,
hdev->level - 1, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
if (ret < 0)
dev_err(hub->intfdev,
"set hub depth failed\n");
}
/* Speed up system boot by using a delayed_work for the /* Speed up system boot by using a delayed_work for the
* hub's initial power-up delays. This is pretty awkward * hub's initial power-up delays. This is pretty awkward
...@@ -987,18 +1003,6 @@ static int hub_configure(struct usb_hub *hub, ...@@ -987,18 +1003,6 @@ static int hub_configure(struct usb_hub *hub,
goto fail; goto fail;
} }
if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) {
ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
HUB_SET_DEPTH, USB_RT_HUB,
hdev->level - 1, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
if (ret < 0) {
message = "can't set hub depth";
goto fail;
}
}
/* Request the entire hub descriptor. /* Request the entire hub descriptor.
* hub->descriptor can handle USB_MAXCHILDREN ports, * hub->descriptor can handle USB_MAXCHILDREN ports,
* but the hub can/will return fewer bytes here. * but the hub can/will return fewer bytes here.
......
...@@ -872,7 +872,17 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) ...@@ -872,7 +872,17 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
*/ */
if (pdev->vendor == 0x184e) /* vendor Netlogic */ if (pdev->vendor == 0x184e) /* vendor Netlogic */
return; return;
if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_OHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_EHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_XHCI)
return;
if (pci_enable_device(pdev) < 0) {
dev_warn(&pdev->dev, "Can't enable PCI device, "
"BIOS handoff failed.\n");
return;
}
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev); quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
...@@ -881,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) ...@@ -881,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
quirk_usb_disable_ehci(pdev); quirk_usb_disable_ehci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
quirk_usb_handoff_xhci(pdev); quirk_usb_handoff_xhci(pdev);
pci_disable_device(pdev);
} }
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
...@@ -93,7 +93,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, ...@@ -93,7 +93,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
*/ */
memset(port_removable, 0, sizeof(port_removable)); memset(port_removable, 0, sizeof(port_removable));
for (i = 0; i < ports; i++) { for (i = 0; i < ports; i++) {
portsc = xhci_readl(xhci, xhci->usb3_ports[i]); portsc = xhci_readl(xhci, xhci->usb2_ports[i]);
/* If a device is removable, PORTSC reports a 0, same as in the /* If a device is removable, PORTSC reports a 0, same as in the
* hub descriptor DeviceRemovable bits. * hub descriptor DeviceRemovable bits.
*/ */
......
...@@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, ...@@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
} }
/* /*
* Convert bInterval expressed in frames (in 1-255 range) to exponent of * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
* microframes, rounded down to nearest power of 2. * microframes, rounded down to nearest power of 2.
*/ */
static unsigned int xhci_parse_frame_interval(struct usb_device *udev, static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
struct usb_host_endpoint *ep) struct usb_host_endpoint *ep, unsigned int desc_interval,
unsigned int min_exponent, unsigned int max_exponent)
{ {
unsigned int interval; unsigned int interval;
interval = fls(8 * ep->desc.bInterval) - 1; interval = fls(desc_interval) - 1;
interval = clamp_val(interval, 3, 10); interval = clamp_val(interval, min_exponent, max_exponent);
if ((1 << interval) != 8 * ep->desc.bInterval) if ((1 << interval) != desc_interval)
dev_warn(&udev->dev, dev_warn(&udev->dev,
"ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
ep->desc.bEndpointAddress, ep->desc.bEndpointAddress,
1 << interval, 1 << interval,
8 * ep->desc.bInterval); desc_interval);
return interval; return interval;
} }
static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
return xhci_microframes_to_exponent(udev, ep,
ep->desc.bInterval, 0, 15);
}
static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
return xhci_microframes_to_exponent(udev, ep,
ep->desc.bInterval * 8, 3, 10);
}
/* Return the polling or NAK interval. /* Return the polling or NAK interval.
* *
* The polling interval is expressed in "microframes". If xHCI's Interval field * The polling interval is expressed in "microframes". If xHCI's Interval field
...@@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, ...@@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
/* Max NAK rate */ /* Max NAK rate */
if (usb_endpoint_xfer_control(&ep->desc) || if (usb_endpoint_xfer_control(&ep->desc) ||
usb_endpoint_xfer_bulk(&ep->desc)) { usb_endpoint_xfer_bulk(&ep->desc)) {
interval = ep->desc.bInterval; interval = xhci_parse_microframe_interval(udev, ep);
break; break;
} }
/* Fall through - SS and HS isoc/int have same decoding */ /* Fall through - SS and HS isoc/int have same decoding */
......
...@@ -352,6 +352,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) ...@@ -352,6 +352,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
/* hcd->irq is -1, we have MSI */ /* hcd->irq is -1, we have MSI */
return 0; return 0;
if (!pdev->irq) {
xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
return -EINVAL;
}
/* fall back to legacy interrupt*/ /* fall back to legacy interrupt*/
ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
hcd->irq_descr, hcd); hcd->irq_descr, hcd);
......
...@@ -136,6 +136,8 @@ static const struct usb_device_id id_table[] = { ...@@ -136,6 +136,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
{ USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
{ USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
......
This diff is collapsed.
...@@ -165,7 +165,7 @@ static unsigned int product_5052_count; ...@@ -165,7 +165,7 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */ /* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ /* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */ /* null entry */
static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = { static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
...@@ -179,6 +179,7 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = { ...@@ -179,6 +179,7 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
}; };
static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
...@@ -188,7 +189,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { ...@@ -188,7 +189,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
}; };
static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] = { static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
...@@ -206,6 +207,7 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] ...@@ -206,6 +207,7 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1]
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
{ } { }
}; };
......
...@@ -49,6 +49,10 @@ ...@@ -49,6 +49,10 @@
#define MTS_MT9234ZBA_PRODUCT_ID 0xF115 #define MTS_MT9234ZBA_PRODUCT_ID 0xF115
#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319 #define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
/* Abbott Diabetics vendor and product ids */
#define ABBOTT_VENDOR_ID 0x1a61
#define ABBOTT_PRODUCT_ID 0x3410
/* Commands */ /* Commands */
#define TI_GET_VERSION 0x01 #define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02 #define TI_GET_PORT_STATUS 0x02
......
...@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(struct us_data *us) ...@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(struct us_data *us)
struct Scsi_Host *host = us_to_host(us); struct Scsi_Host *host = us_to_host(us);
/* If the device is really gone, cut short reset delays */ /* If the device is really gone, cut short reset delays */
if (us->pusb_dev->state == USB_STATE_NOTATTACHED) if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
set_bit(US_FLIDX_DISCONNECTING, &us->dflags); set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
wake_up(&us->delay_wait);
}
/* Prevent SCSI-scanning (if it hasn't started yet) /* Prevent SCSI scanning (if it hasn't started yet)
* and wait for the SCSI-scanning thread to stop. * or wait for the SCSI-scanning routine to stop.
*/ */
set_bit(US_FLIDX_DONT_SCAN, &us->dflags); cancel_delayed_work_sync(&us->scan_dwork);
wake_up(&us->delay_wait);
wait_for_completion(&us->scanning_done); /* Balance autopm calls if scanning was cancelled */
if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
usb_autopm_put_interface_no_suspend(us->pusb_intf);
/* Removing the host will perform an orderly shutdown: caches /* Removing the host will perform an orderly shutdown: caches
* synchronized, disks spun down, etc. * synchronized, disks spun down, etc.
...@@ -823,41 +827,17 @@ static void release_everything(struct us_data *us) ...@@ -823,41 +827,17 @@ static void release_everything(struct us_data *us)
scsi_host_put(us_to_host(us)); scsi_host_put(us_to_host(us));
} }
/* Thread to carry out delayed SCSI-device scanning */ /* Delayed-work routine to carry out SCSI-device scanning */
static int usb_stor_scan_thread(void * __us) static void usb_stor_scan_dwork(struct work_struct *work)
{ {
struct us_data *us = (struct us_data *)__us; struct us_data *us = container_of(work, struct us_data,
scan_dwork.work);
struct device *dev = &us->pusb_intf->dev; struct device *dev = &us->pusb_intf->dev;
dev_dbg(dev, "device found\n"); dev_dbg(dev, "starting scan\n");
set_freezable();
/*
* Wait for the timeout to expire or for a disconnect
*
* We can't freeze in this thread or we risk causing khubd to
* fail to freeze, but we can't be non-freezable either. Nor can
* khubd freeze while waiting for scanning to complete as it may
* hold the device lock, causing a hang when suspending devices.
* So instead of using wait_event_freezable(), explicitly test
* for (DONT_SCAN || freezing) in interruptible wait and proceed
* if any of DONT_SCAN, freezing or timeout has happened.
*/
if (delay_use > 0) {
dev_dbg(dev, "waiting for device to settle "
"before scanning\n");
wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DONT_SCAN, &us->dflags) ||
freezing(current), delay_use * HZ);
}
/* If the device is still connected, perform the scanning */
if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
/* For bulk-only devices, determine the max LUN value */ /* For bulk-only devices, determine the max LUN value */
if (us->protocol == USB_PR_BULK && if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
!(us->fflags & US_FL_SINGLE_LUN)) {
mutex_lock(&us->dev_mutex); mutex_lock(&us->dev_mutex);
us->max_lun = usb_stor_Bulk_max_lun(us); us->max_lun = usb_stor_Bulk_max_lun(us);
mutex_unlock(&us->dev_mutex); mutex_unlock(&us->dev_mutex);
...@@ -866,10 +846,9 @@ static int usb_stor_scan_thread(void * __us) ...@@ -866,10 +846,9 @@ static int usb_stor_scan_thread(void * __us)
dev_dbg(dev, "scan complete\n"); dev_dbg(dev, "scan complete\n");
/* Should we unbind if no devices were detected? */ /* Should we unbind if no devices were detected? */
}
usb_autopm_put_interface(us->pusb_intf); usb_autopm_put_interface(us->pusb_intf);
complete_and_exit(&us->scanning_done, 0); clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
} }
static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf) static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
...@@ -916,7 +895,7 @@ int usb_stor_probe1(struct us_data **pus, ...@@ -916,7 +895,7 @@ int usb_stor_probe1(struct us_data **pus,
init_completion(&us->cmnd_ready); init_completion(&us->cmnd_ready);
init_completion(&(us->notify)); init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait); init_waitqueue_head(&us->delay_wait);
init_completion(&us->scanning_done); INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
/* Associate the us_data structure with the USB device */ /* Associate the us_data structure with the USB device */
result = associate_dev(us, intf); result = associate_dev(us, intf);
...@@ -947,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1); ...@@ -947,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
/* Second part of general USB mass-storage probing */ /* Second part of general USB mass-storage probing */
int usb_stor_probe2(struct us_data *us) int usb_stor_probe2(struct us_data *us)
{ {
struct task_struct *th;
int result; int result;
struct device *dev = &us->pusb_intf->dev; struct device *dev = &us->pusb_intf->dev;
...@@ -988,20 +966,14 @@ int usb_stor_probe2(struct us_data *us) ...@@ -988,20 +966,14 @@ int usb_stor_probe2(struct us_data *us)
goto BadDevice; goto BadDevice;
} }
/* Start up the thread for delayed SCSI-device scanning */ /* Submit the delayed_work for SCSI-device scanning */
th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
if (IS_ERR(th)) {
dev_warn(dev,
"Unable to start the device-scanning thread\n");
complete(&us->scanning_done);
quiesce_and_remove_host(us);
result = PTR_ERR(th);
goto BadDevice;
}
usb_autopm_get_interface_no_resume(us->pusb_intf); usb_autopm_get_interface_no_resume(us->pusb_intf);
wake_up_process(th); set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
if (delay_use > 0)
dev_dbg(dev, "waiting for device to settle before scanning\n");
queue_delayed_work(system_freezable_wq, &us->scan_dwork,
delay_use * HZ);
return 0; return 0;
/* We come here if there are any problems */ /* We come here if there are any problems */
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/workqueue.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
struct us_data; struct us_data;
...@@ -72,7 +73,7 @@ struct us_unusual_dev { ...@@ -72,7 +73,7 @@ struct us_unusual_dev {
#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */ #define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */
#define US_FLIDX_RESETTING 4 /* device reset in progress */ #define US_FLIDX_RESETTING 4 /* device reset in progress */
#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ #define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ #define US_FLIDX_SCAN_PENDING 6 /* scanning not yet done */
#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */ #define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */ #define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
...@@ -147,8 +148,8 @@ struct us_data { ...@@ -147,8 +148,8 @@ struct us_data {
/* mutual exclusion and synchronization structures */ /* mutual exclusion and synchronization structures */
struct completion cmnd_ready; /* to sleep thread on */ struct completion cmnd_ready; /* to sleep thread on */
struct completion notify; /* thread begin/end */ struct completion notify; /* thread begin/end */
wait_queue_head_t delay_wait; /* wait during scan, reset */ wait_queue_head_t delay_wait; /* wait during reset */
struct completion scanning_done; /* wait for scan thread */ struct delayed_work scan_dwork; /* for async scanning */
/* subdriver information */ /* subdriver information */
void *extra; /* Any extra data */ void *extra; /* Any extra data */
......
...@@ -61,12 +61,6 @@ ...@@ -61,12 +61,6 @@
#define USB_PORT_FEAT_TEST 21 #define USB_PORT_FEAT_TEST 21
#define USB_PORT_FEAT_INDICATOR 22 #define USB_PORT_FEAT_INDICATOR 22
#define USB_PORT_FEAT_C_PORT_L1 23 #define USB_PORT_FEAT_C_PORT_L1 23
#define USB_PORT_FEAT_C_PORT_LINK_STATE 25
#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26
#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27
#define USB_PORT_FEAT_BH_PORT_RESET 28
#define USB_PORT_FEAT_C_BH_PORT_RESET 29
#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30
/* /*
* Port feature selectors added by USB 3.0 spec. * Port feature selectors added by USB 3.0 spec.
...@@ -75,8 +69,8 @@ ...@@ -75,8 +69,8 @@
#define USB_PORT_FEAT_LINK_STATE 5 #define USB_PORT_FEAT_LINK_STATE 5
#define USB_PORT_FEAT_U1_TIMEOUT 23 #define USB_PORT_FEAT_U1_TIMEOUT 23
#define USB_PORT_FEAT_U2_TIMEOUT 24 #define USB_PORT_FEAT_U2_TIMEOUT 24
#define USB_PORT_FEAT_C_LINK_STATE 25 #define USB_PORT_FEAT_C_PORT_LINK_STATE 25
#define USB_PORT_FEAT_C_CONFIG_ERR 26 #define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26
#define USB_PORT_FEAT_REMOTE_WAKE_MASK 27 #define USB_PORT_FEAT_REMOTE_WAKE_MASK 27
#define USB_PORT_FEAT_BH_PORT_RESET 28 #define USB_PORT_FEAT_BH_PORT_RESET 28
#define USB_PORT_FEAT_C_BH_PORT_RESET 29 #define USB_PORT_FEAT_C_BH_PORT_RESET 29
......
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