Merge branch 'usb-linus' into usb-next
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Feb 2012 23:10:01 +0000 (15:10 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Feb 2012 23:10:12 +0000 (15:10 -0800)
This is needed so that Sarah can queue up some xhci changes for 3.4

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
49 files changed:
Documentation/ABI/testing/sysfs-bus-usb
drivers/scsi/scsi_scan.c
drivers/scsi/sd.c
drivers/usb/Kconfig
drivers/usb/class/cdc-wdm.c
drivers/usb/core/driver.c
drivers/usb/core/hub.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-fsl.h
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-ls1x.c [new file with mode: 0644]
drivers/usb/host/imx21-dbg.c
drivers/usb/host/uhci-hcd.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/alauda.c
drivers/usb/storage/cypress_atacb.c
drivers/usb/storage/datafab.c
drivers/usb/storage/ene_ub6250.c
drivers/usb/storage/freecom.c
drivers/usb/storage/isd200.c
drivers/usb/storage/jumpshot.c
drivers/usb/storage/karma.c
drivers/usb/storage/onetouch.c
drivers/usb/storage/realtek_cr.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/sddr09.c
drivers/usb/storage/sddr55.c
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/uas.c
drivers/usb/storage/usb.c
include/linux/usb.h
include/linux/usb/serial.h
include/linux/usb/uas.h [new file with mode: 0644]
include/scsi/scsi_device.h

index b4f548792e323f1c07d4472d931dbf941bca708e..7c22a532fdfb8c978a6c3c44b4a86ef88dc66b36 100644 (file)
@@ -182,3 +182,14 @@ Description:
                USB2 hardware LPM is enabled for the device. Developer can
                write y/Y/1 or n/N/0 to the file to enable/disable the
                feature.
+
+What:          /sys/bus/usb/devices/.../removable
+Date:          February 2012
+Contact:       Matthew Garrett <mjg@redhat.com>
+Description:
+               Some information about whether a given USB device is
+               physically fixed to the platform can be inferred from a
+               combination of hub decriptor bits and platform-specific data
+               such as ACPI. This file will read either "removable" or
+               "fixed" if the information is available, and "unknown"
+               otherwise.
\ No newline at end of file
index 89da43f73c00ca209b816ecc68b70a95fbfc0888..fd37bfbfbcdb6788edd59b0198721a8b41e427ab 100644 (file)
@@ -1295,6 +1295,7 @@ EXPORT_SYMBOL(int_to_scsilun);
  *   LUNs even if it's older than SCSI-3.
  *   If BLIST_NOREPORTLUN is set, return 1 always.
  *   If BLIST_NOLUN is set, return 0 always.
+ *   If starget->no_report_luns is set, return 1 always.
  *
  * Return:
  *     0: scan completed (or no memory, so further scanning is futile)
@@ -1321,6 +1322,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
         * Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
         * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
         * support more than 8 LUNs.
+        * Don't attempt if the target doesn't support REPORT LUNS.
         */
        if (bflags & BLIST_NOREPORTLUN)
                return 1;
@@ -1332,6 +1334,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
                return 1;
        if (bflags & BLIST_NOLUN)
                return 0;
+       if (starget->no_report_luns)
+               return 1;
 
        if (!(sdev = scsi_device_lookup_by_target(starget, 0))) {
                sdev = scsi_alloc_sdev(starget, 0, NULL);
index c691fb50e6cbfe75deceddcdf744dc1301cc7d08..d173b90b25e9b67cce85a32f8209206b808c3301 100644 (file)
@@ -2349,7 +2349,7 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp)
         * some USB ones crash on receiving them, and the pages
         * we currently ask for are for SPC-3 and beyond
         */
-       if (sdp->scsi_level > SCSI_SPC_2)
+       if (sdp->scsi_level > SCSI_SPC_2 && !sdp->skip_vpd_pages)
                return 1;
        return 0;
 }
index 75823a1abeb66bebdf58f41de4cecbc7048ce0be..0b0afc81a542ffdfa0c92fe12ca91cd22079a86a 100644 (file)
@@ -76,6 +76,7 @@ config USB_ARCH_HAS_EHCI
        default y if MICROBLAZE
        default y if SPARC_LEON
        default y if ARCH_MMP
+       default y if MACH_LOONGSON1
        default PCI
 
 # some non-PCI HCDs implement xHCI
index d2b3cffca3f786c9eb21c658604419e710a14985..b27bbb957e16aaffe576bf38b79c94faf50f96b3 100644 (file)
@@ -31,6 +31,8 @@
 #define DRIVER_AUTHOR "Oliver Neukum"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 
+#define HUAWEI_VENDOR_ID       0x12D1
+
 static const struct usb_device_id wdm_ids[] = {
        {
                .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
@@ -38,6 +40,20 @@ static const struct usb_device_id wdm_ids[] = {
                .bInterfaceClass = USB_CLASS_COMM,
                .bInterfaceSubClass = USB_CDC_SUBCLASS_DMM
        },
+       {
+               /* 
+                * Huawei E392, E398 and possibly other Qualcomm based modems
+                * embed the Qualcomm QMI protocol inside CDC on CDC ECM like
+                * control interfaces.  Userspace access to this is required
+                * to configure the accompanying data interface
+                */
+               .match_flags        = USB_DEVICE_ID_MATCH_VENDOR |
+                                       USB_DEVICE_ID_MATCH_INT_INFO,
+               .idVendor           = HUAWEI_VENDOR_ID,
+               .bInterfaceClass    = USB_CLASS_VENDOR_SPEC,
+               .bInterfaceSubClass = 1,
+               .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */
+       },
        { }
 };
 
@@ -54,6 +70,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
 #define WDM_POLL_RUNNING       6
 #define WDM_RESPONDING         7
 #define WDM_SUSPENDING         8
+#define WDM_RESETTING          9
 
 #define WDM_MAX                        16
 
@@ -82,7 +99,6 @@ struct wdm_device {
        u16                     bufsize;
        u16                     wMaxCommand;
        u16                     wMaxPacketSize;
-       u16                     bMaxPacketSize0;
        __le16                  inum;
        int                     reslength;
        int                     length;
@@ -162,11 +178,9 @@ static void wdm_int_callback(struct urb *urb)
        int rv = 0;
        int status = urb->status;
        struct wdm_device *desc;
-       struct usb_ctrlrequest *req;
        struct usb_cdc_notification *dr;
 
        desc = urb->context;
-       req = desc->irq;
        dr = (struct usb_cdc_notification *)desc->sbuf;
 
        if (status) {
@@ -213,24 +227,6 @@ static void wdm_int_callback(struct urb *urb)
                goto exit;
        }
 
-       req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
-       req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
-       req->wValue = 0;
-       req->wIndex = desc->inum;
-       req->wLength = cpu_to_le16(desc->wMaxCommand);
-
-       usb_fill_control_urb(
-               desc->response,
-               interface_to_usbdev(desc->intf),
-               /* using common endpoint 0 */
-               usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
-               (unsigned char *)req,
-               desc->inbuf,
-               desc->wMaxCommand,
-               wdm_in_callback,
-               desc
-       );
-       desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
        spin_lock(&desc->iuspin);
        clear_bit(WDM_READ, &desc->flags);
        set_bit(WDM_RESPONDING, &desc->flags);
@@ -279,14 +275,8 @@ static void free_urbs(struct wdm_device *desc)
 
 static void cleanup(struct wdm_device *desc)
 {
-       usb_free_coherent(interface_to_usbdev(desc->intf),
-                         desc->wMaxPacketSize,
-                         desc->sbuf,
-                         desc->validity->transfer_dma);
-       usb_free_coherent(interface_to_usbdev(desc->intf),
-                         desc->bMaxPacketSize0,
-                         desc->inbuf,
-                         desc->response->transfer_dma);
+       kfree(desc->sbuf);
+       kfree(desc->inbuf);
        kfree(desc->orq);
        kfree(desc->irq);
        kfree(desc->ubuf);
@@ -351,6 +341,10 @@ static ssize_t wdm_write
        else
                if (test_bit(WDM_IN_USE, &desc->flags))
                        r = -EAGAIN;
+
+       if (test_bit(WDM_RESETTING, &desc->flags))
+               r = -EIO;
+
        if (r < 0) {
                kfree(buf);
                goto out;
@@ -430,6 +424,10 @@ retry:
                        rv = -ENODEV;
                        goto err;
                }
+               if (test_bit(WDM_RESETTING, &desc->flags)) {
+                       rv = -EIO;
+                       goto err;
+               }
                usb_mark_last_busy(interface_to_usbdev(desc->intf));
                if (rv < 0) {
                        rv = -ERESTARTSYS;
@@ -631,7 +629,6 @@ static void wdm_rxwork(struct work_struct *work)
 static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        int rv = -EINVAL;
-       struct usb_device *udev = interface_to_usbdev(intf);
        struct wdm_device *desc;
        struct usb_host_interface *iface;
        struct usb_endpoint_descriptor *ep;
@@ -692,7 +689,6 @@ next_desc:
                goto err;
 
        desc->wMaxPacketSize = usb_endpoint_maxp(ep);
-       desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
 
        desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
        if (!desc->orq)
@@ -717,19 +713,13 @@ next_desc:
        if (!desc->ubuf)
                goto err;
 
-       desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf),
-                                       desc->wMaxPacketSize,
-                                       GFP_KERNEL,
-                                       &desc->validity->transfer_dma);
+       desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL);
        if (!desc->sbuf)
                goto err;
 
-       desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
-                                        desc->wMaxCommand,
-                                        GFP_KERNEL,
-                                        &desc->response->transfer_dma);
+       desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL);
        if (!desc->inbuf)
-               goto err2;
+               goto err;
 
        usb_fill_int_urb(
                desc->validity,
@@ -741,30 +731,39 @@ next_desc:
                desc,
                ep->bInterval
        );
-       desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
+       desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
+       desc->irq->wValue = 0;
+       desc->irq->wIndex = desc->inum;
+       desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
+
+       usb_fill_control_urb(
+               desc->response,
+               interface_to_usbdev(intf),
+               /* using common endpoint 0 */
+               usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
+               (unsigned char *)desc->irq,
+               desc->inbuf,
+               desc->wMaxCommand,
+               wdm_in_callback,
+               desc
+       );
 
        usb_set_intfdata(intf, desc);
        rv = usb_register_dev(intf, &wdm_class);
        if (rv < 0)
-               goto err3;
+               goto err2;
        else
-               dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
-                       intf->minor - WDM_MINOR_BASE);
+               dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev));
 out:
        return rv;
-err3:
-       usb_set_intfdata(intf, NULL);
-       usb_free_coherent(interface_to_usbdev(desc->intf),
-                         desc->bMaxPacketSize0,
-                       desc->inbuf,
-                       desc->response->transfer_dma);
 err2:
-       usb_free_coherent(interface_to_usbdev(desc->intf),
-                         desc->wMaxPacketSize,
-                         desc->sbuf,
-                         desc->validity->transfer_dma);
+       usb_set_intfdata(intf, NULL);
 err:
        free_urbs(desc);
+       kfree(desc->inbuf);
+       kfree(desc->sbuf);
        kfree(desc->ubuf);
        kfree(desc->orq);
        kfree(desc->irq);
@@ -869,10 +868,6 @@ static int wdm_pre_reset(struct usb_interface *intf)
 {
        struct wdm_device *desc = usb_get_intfdata(intf);
 
-       mutex_lock(&desc->rlock);
-       mutex_lock(&desc->wlock);
-       kill_urbs(desc);
-
        /*
         * we notify everybody using poll of
         * an exceptional situation
@@ -880,9 +875,16 @@ static int wdm_pre_reset(struct usb_interface *intf)
         * message from the device is lost
         */
        spin_lock_irq(&desc->iuspin);
+       set_bit(WDM_RESETTING, &desc->flags);   /* inform read/write */
+       set_bit(WDM_READ, &desc->flags);        /* unblock read */
+       clear_bit(WDM_IN_USE, &desc->flags);    /* unblock write */
        desc->rerr = -EINTR;
        spin_unlock_irq(&desc->iuspin);
        wake_up_all(&desc->wait);
+       mutex_lock(&desc->rlock);
+       mutex_lock(&desc->wlock);
+       kill_urbs(desc);
+       cancel_work_sync(&desc->rxwork);
        return 0;
 }
 
@@ -891,6 +893,7 @@ static int wdm_post_reset(struct usb_interface *intf)
        struct wdm_device *desc = usb_get_intfdata(intf);
        int rv;
 
+       clear_bit(WDM_RESETTING, &desc->flags);
        rv = recover_from_urb_loss(desc);
        mutex_unlock(&desc->wlock);
        mutex_unlock(&desc->rlock);
index d40ff95688135ce82a1c4ccbfac6d129104cd874..d77daf3683da857397dec1c5cff34df7fdd2eb4b 100644 (file)
@@ -958,13 +958,8 @@ void usb_rebind_intf(struct usb_interface *intf)
        int rc;
 
        /* Delayed unbind of an existing driver */
-       if (intf->dev.driver) {
-               struct usb_driver *driver =
-                               to_usb_driver(intf->dev.driver);
-
-               dev_dbg(&intf->dev, "forced unbind\n");
-               usb_driver_release_interface(driver, intf);
-       }
+       if (intf->dev.driver)
+               usb_forced_unbind_intf(intf);
 
        /* Try to rebind the interface */
        if (!intf->dev.power.is_prepared) {
@@ -977,15 +972,13 @@ void usb_rebind_intf(struct usb_interface *intf)
 
 #ifdef CONFIG_PM
 
-#define DO_UNBIND      0
-#define DO_REBIND      1
-
-/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
- * or rebind interfaces that have been unbound, according to @action.
+/* Unbind drivers for @udev's interfaces that don't support suspend/resume
+ * There is no check for reset_resume here because it can be determined
+ * only during resume whether reset_resume is needed.
  *
  * The caller must hold @udev's device lock.
  */
-static void do_unbind_rebind(struct usb_device *udev, int action)
+static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
 {
        struct usb_host_config  *config;
        int                     i;
@@ -996,23 +989,53 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
        if (config) {
                for (i = 0; i < config->desc.bNumInterfaces; ++i) {
                        intf = config->interface[i];
-                       switch (action) {
-                       case DO_UNBIND:
-                               if (intf->dev.driver) {
-                                       drv = to_usb_driver(intf->dev.driver);
-                                       if (!drv->suspend || !drv->resume)
-                                               usb_forced_unbind_intf(intf);
-                               }
-                               break;
-                       case DO_REBIND:
-                               if (intf->needs_binding)
-                                       usb_rebind_intf(intf);
-                               break;
+
+                       if (intf->dev.driver) {
+                               drv = to_usb_driver(intf->dev.driver);
+                               if (!drv->suspend || !drv->resume)
+                                       usb_forced_unbind_intf(intf);
                        }
                }
        }
 }
 
+/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
+ * These interfaces have the needs_binding flag set by usb_resume_interface().
+ *
+ * The caller must hold @udev's device lock.
+ */
+static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
+{
+       struct usb_host_config  *config;
+       int                     i;
+       struct usb_interface    *intf;
+
+       config = udev->actconfig;
+       if (config) {
+               for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+                       intf = config->interface[i];
+                       if (intf->dev.driver && intf->needs_binding)
+                               usb_forced_unbind_intf(intf);
+               }
+       }
+}
+
+static void do_rebind_interfaces(struct usb_device *udev)
+{
+       struct usb_host_config  *config;
+       int                     i;
+       struct usb_interface    *intf;
+
+       config = udev->actconfig;
+       if (config) {
+               for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+                       intf = config->interface[i];
+                       if (intf->needs_binding)
+                               usb_rebind_intf(intf);
+               }
+       }
+}
+
 static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
 {
        struct usb_device_driver        *udriver;
@@ -1302,35 +1325,48 @@ int usb_suspend(struct device *dev, pm_message_t msg)
 {
        struct usb_device       *udev = to_usb_device(dev);
 
-       do_unbind_rebind(udev, DO_UNBIND);
+       unbind_no_pm_drivers_interfaces(udev);
+
+       /* From now on we are sure all drivers support suspend/resume
+        * but not necessarily reset_resume()
+        * so we may still need to unbind and rebind upon resume
+        */
        choose_wakeup(udev, msg);
        return usb_suspend_both(udev, msg);
 }
 
+/* The device lock is held by the PM core */
+int usb_resume_complete(struct device *dev)
+{
+       struct usb_device *udev = to_usb_device(dev);
+
+       /* For PM complete calls, all we do is rebind interfaces
+        * whose needs_binding flag is set
+        */
+       if (udev->state != USB_STATE_NOTATTACHED)
+               do_rebind_interfaces(udev);
+       return 0;
+}
+
 /* The device lock is held by the PM core */
 int usb_resume(struct device *dev, pm_message_t msg)
 {
        struct usb_device       *udev = to_usb_device(dev);
        int                     status;
 
-       /* For PM complete calls, all we do is rebind interfaces */
-       if (msg.event == PM_EVENT_ON) {
-               if (udev->state != USB_STATE_NOTATTACHED)
-                       do_unbind_rebind(udev, DO_REBIND);
-               status = 0;
-
-       /* For all other calls, take the device back to full power and
+       /* For all calls, take the device back to full power and
         * tell the PM core in case it was autosuspended previously.
-        * Unbind the interfaces that will need rebinding later.
+        * Unbind the interfaces that will need rebinding later,
+        * because they fail to support reset_resume.
+        * (This can't be done in usb_resume_interface()
+        * above because it doesn't own the right set of locks.)
         */
-       } else {
-               status = usb_resume_both(udev, msg);
-               if (status == 0) {
-                       pm_runtime_disable(dev);
-                       pm_runtime_set_active(dev);
-                       pm_runtime_enable(dev);
-                       do_unbind_rebind(udev, DO_REBIND);
-               }
+       status = usb_resume_both(udev, msg);
+       if (status == 0) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+               unbind_no_reset_resume_drivers_interfaces(udev);
        }
 
        /* Avoid PM error messages for devices disconnected while suspended
index a0613d8f9be785bf0a52827acf2522b109bce1b2..2d773cbe191cde5c1d3c3f5d68a9f28ed27a1e3a 100644 (file)
@@ -1838,6 +1838,37 @@ fail:
        return err;
 }
 
+static void set_usb_port_removable(struct usb_device *udev)
+{
+       struct usb_device *hdev = udev->parent;
+       struct usb_hub *hub;
+       u8 port = udev->portnum;
+       u16 wHubCharacteristics;
+       bool removable = true;
+
+       if (!hdev)
+               return;
+
+       hub = hdev_to_hub(udev->parent);
+
+       wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+
+       if (!(wHubCharacteristics & HUB_CHAR_COMPOUND))
+               return;
+
+       if (hub_is_superspeed(hdev)) {
+               if (hub->descriptor->u.ss.DeviceRemovable & (1 << port))
+                       removable = false;
+       } else {
+               if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8)))
+                       removable = false;
+       }
+
+       if (removable)
+               udev->removable = USB_DEVICE_REMOVABLE;
+       else
+               udev->removable = USB_DEVICE_FIXED;
+}
 
 /**
  * usb_new_device - perform initial device setup (usbcore-internal)
@@ -1896,6 +1927,15 @@ int usb_new_device(struct usb_device *udev)
        announce_device(udev);
 
        device_enable_async_suspend(&udev->dev);
+
+       /*
+        * check whether the hub marks this port as non-removable. Do it
+        * now so that platform-specific data can override it in
+        * device_add()
+        */
+       if (udev->parent)
+               set_usb_port_removable(udev);
+
        /* Register the device.  The device driver is responsible
         * for configuring the device and invoking the add-device
         * notifier chain (used by usbfs and possibly others).
index 9e491ca2e5c4763016f19e718c2795a3eaeda4ff..566d9f94f735e113ee3a82641388dfb1dc40031f 100644 (file)
@@ -230,6 +230,28 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
 
+static ssize_t
+show_removable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev;
+       char *state;
+
+       udev = to_usb_device(dev);
+
+       switch (udev->removable) {
+       case USB_DEVICE_REMOVABLE:
+               state = "removable";
+               break;
+       case USB_DEVICE_FIXED:
+               state = "fixed";
+               break;
+       default:
+               state = "unknown";
+       }
+
+       return sprintf(buf, "%s\n", state);
+}
+static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL);
 
 #ifdef CONFIG_PM
 
@@ -626,6 +648,7 @@ static struct attribute *dev_attrs[] = {
        &dev_attr_avoid_reset_quirk.attr,
        &dev_attr_authorized.attr,
        &dev_attr_remove.attr,
+       &dev_attr_removable.attr,
        NULL,
 };
 static struct attribute_group dev_attr_grp = {
index 909625b91eb35a3a4096029d3fd46e0a6cb25bb4..f4f20c7b77657a2e88a298bd3ba605c1fa1db12c 100644 (file)
@@ -403,20 +403,17 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
         * cause problems in HCDs if they get it wrong.
         */
        {
-       unsigned int    orig_flags = urb->transfer_flags;
        unsigned int    allowed;
        static int pipetypes[4] = {
                PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
        };
 
        /* Check that the pipe's type matches the endpoint's type */
-       if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
-               dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+       if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+               dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
                        usb_pipetype(urb->pipe), pipetypes[xfertype]);
-               return -EPIPE;          /* The most suitable error code :-) */
-       }
 
-       /* enforce simple/standard policy */
+       /* Check against a simple/standard policy */
        allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
                        URB_FREE_BUFFER);
        switch (xfertype) {
@@ -435,14 +432,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
                allowed |= URB_ISO_ASAP;
                break;
        }
-       urb->transfer_flags &= allowed;
+       allowed &= urb->transfer_flags;
 
-       /* fail if submitter gave bogus flags */
-       if (urb->transfer_flags != orig_flags) {
-               dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n",
-                       orig_flags, urb->transfer_flags);
-               return -EINVAL;
-       }
+       /* warn if submitter gave bogus flags */
+       if (allowed != urb->transfer_flags)
+               dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",
+                       urb->transfer_flags, allowed);
        }
 #endif
        /*
index 8ca9f994a280c625096f8f227d830cb5af6febad..c74ba7bbc7483e7ce106c32129f9aa6d1d693b9c 100644 (file)
@@ -274,7 +274,7 @@ static int usb_dev_prepare(struct device *dev)
 static void usb_dev_complete(struct device *dev)
 {
        /* Currently used only for rebinding interfaces */
-       usb_resume(dev, PMSG_ON);       /* FIXME: change to PMSG_COMPLETE */
+       usb_resume_complete(dev);
 }
 
 static int usb_dev_suspend(struct device *dev)
index 45e8479c377ddb66e4cfd387ad184d8b301b4b4e..71648dcbe4386a98cf5e571516b3186d3b3ba749 100644 (file)
@@ -56,6 +56,7 @@ extern void usb_major_cleanup(void);
 
 extern int usb_suspend(struct device *dev, pm_message_t msg);
 extern int usb_resume(struct device *dev, pm_message_t msg);
+extern int usb_resume_complete(struct device *dev);
 
 extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
 extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
index c26a82e83f6e6d11b78f002dc3982df9a3b0a27b..10e008a730a57b1a004894f5cb4075ab2836d2ad 100644 (file)
@@ -323,7 +323,9 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
        struct fsl_usb2_platform_data *pdata;
+       struct device *dev;
 
+       dev = hcd->self.controller;
        pdata = hcd->self.controller->platform_data;
        ehci->big_endian_desc = pdata->big_endian_desc;
        ehci->big_endian_mmio = pdata->big_endian_mmio;
@@ -353,6 +355,16 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 
        ehci_reset(ehci);
 
+       if (of_device_is_compatible(dev->parent->of_node,
+                                   "fsl,mpc5121-usb2-dr")) {
+               /*
+                * set SBUSCFG:AHBBRST so that control msgs don't
+                * fail when doing heavy PATA writes.
+                */
+               ehci_writel(ehci, SBUSCFG_INCR8,
+                           hcd->regs + FSL_SOC_USB_SBUSCFG);
+       }
+
        retval = ehci_fsl_reinit(ehci);
        return retval;
 }
@@ -476,6 +488,8 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev)
        ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE,
                    hcd->regs + FSL_SOC_USB_ISIPHYCTRL);
 
+       ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG);
+
        /* restore EHCI registers */
        ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
        ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
index bdf43e2adc51a4fdb4f12ca4e70b1e5c42c62f2c..6d5a94e9bb3c739dee61f3f8b64b3d8b9a2398c7 100644 (file)
@@ -19,6 +19,8 @@
 #define _EHCI_FSL_H
 
 /* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_SBUSCFG    0x90
+#define SBUSCFG_INCR8          0x02    /* INCR8, specified */
 #define FSL_SOC_USB_ULPIVP     0x170
 #define FSL_SOC_USB_PORTSC1    0x184
 #define PORT_PTS_MSK           (3<<30)
index a007a9fe0f874a3bbb8ba2c63e37e7d2e0de1ac5..4918b0c59af9fd4461bd856a0092ab8867cc2756 100644 (file)
@@ -1376,6 +1376,11 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_mv_driver
 #endif
 
+#ifdef CONFIG_MACH_LOONGSON1
+#include "ehci-ls1x.c"
+#define PLATFORM_DRIVER                ehci_ls1x_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
new file mode 100644 (file)
index 0000000..a283e59
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ *  Bus Glue for Loongson LS1X built-in EHCI controller.
+ *
+ *  Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+
+#include <linux/platform_device.h>
+
+static int ehci_ls1x_reset(struct usb_hcd *hcd)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       int ret;
+
+       ehci->caps = hcd->regs;
+
+       ret = ehci_setup(hcd);
+       if (ret)
+               return ret;
+
+       ehci_port_power(ehci, 0);
+
+       return 0;
+}
+
+static const struct hc_driver ehci_ls1x_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "LOONGSON1 EHCI",
+       .hcd_priv_size          = sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq                    = ehci_irq,
+       .flags                  = HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset                  = ehci_ls1x_reset,
+       .start                  = ehci_run,
+       .stop                   = ehci_stop,
+       .shutdown               = ehci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue            = ehci_urb_enqueue,
+       .urb_dequeue            = ehci_urb_dequeue,
+       .endpoint_disable       = ehci_endpoint_disable,
+       .endpoint_reset         = ehci_endpoint_reset,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number       = ehci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data        = ehci_hub_status_data,
+       .hub_control            = ehci_hub_control,
+       .relinquish_port        = ehci_relinquish_port,
+       .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd;
+       struct resource *res;
+       int irq;
+       int ret;
+
+       pr_debug("initializing loongson1 ehci USB Controller\n");
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(&pdev->dev,
+                       "Found HC with no IRQ. Check %s setup!\n",
+                       dev_name(&pdev->dev));
+               return -ENODEV;
+       }
+       irq = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev,
+                       "Found HC with no register addr. Check %s setup!\n",
+                       dev_name(&pdev->dev));
+               return -ENODEV;
+       }
+
+       hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
+                               dev_name(&pdev->dev));
+       if (!hcd)
+               return -ENOMEM;
+       hcd->rsrc_start = res->start;
+       hcd->rsrc_len   = resource_size(res);
+
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+               dev_dbg(&pdev->dev, "controller already in use\n");
+               ret = -EBUSY;
+               goto err_put_hcd;
+       }
+
+       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       if (hcd->regs == NULL) {
+               dev_dbg(&pdev->dev, "error mapping memory\n");
+               ret = -EFAULT;
+               goto err_release_region;
+       }
+
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+       if (ret)
+               goto err_iounmap;
+
+       return ret;
+
+err_iounmap:
+       iounmap(hcd->regs);
+err_release_region:
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+       usb_put_hcd(hcd);
+       return ret;
+}
+
+static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_remove_hcd(hcd);
+       iounmap(hcd->regs);
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+
+       return 0;
+}
+
+static struct platform_driver ehci_ls1x_driver = {
+       .probe = ehci_hcd_ls1x_probe,
+       .remove = ehci_hcd_ls1x_remove,
+       .shutdown = usb_hcd_platform_shutdown,
+       .driver = {
+               .name = "ls1x-ehci",
+               .owner  = THIS_MODULE,
+       },
+};
+
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
index 6d7533427163decbce48bc6c6197ef17dd977073..ec98ecee351753774978f0477a86c72bf055f73e 100644 (file)
@@ -239,7 +239,7 @@ static int debug_status_show(struct seq_file *s, void *v)
                "ETDs allocated: %d/%d (max=%d)\n"
                "ETDs in use sw: %d\n"
                "ETDs in use hw: %d\n"
-               "DMEM alocated: %d/%d (max=%d)\n"
+               "DMEM allocated: %d/%d (max=%d)\n"
                "DMEM blocks: %d\n"
                "Queued waiting for ETD: %d\n"
                "Queued waiting for DMEM: %d\n",
index 6b5eb1017e2ca601044e3d1856d87070b0d21328..e37dea87bb5633fe8d88b77f443edb761f1aa584 100644 (file)
@@ -565,6 +565,9 @@ static int uhci_start(struct usb_hcd *hcd)
        struct dentry __maybe_unused *dentry;
 
        hcd->uses_new_polling = 1;
+       /* Accept arbitrarily long scatter-gather lists */
+       if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+               hcd->self.sg_tablesize = ~0;
 
        spin_lock_init(&uhci->lock);
        setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
index 8dbf51a43c45d2fcaf61cf5f6d26d1b65a4e96cf..90721b49eed73c52d2a4f62010140723c5d810ca 100644 (file)
@@ -284,7 +284,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
 
        if (result != size) {
                dbg("%s - Unable to send config request, "
-                               "request=0x%x size=%d result=%d\n",
+                               "request=0x%x size=%d result=%d",
                                __func__, request, size, result);
                if (result > 0)
                        result = -EPROTO;
@@ -338,7 +338,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
 
        if ((size > 2 && result != size) || result < 0) {
                dbg("%s - Unable to send request, "
-                               "request=0x%x size=%d result=%d\n",
+                               "request=0x%x size=%d result=%d",
                                __func__, request, size, result);
                if (result > 0)
                        result = -EPROTO;
@@ -681,13 +681,13 @@ static void cp210x_set_termios(struct tty_struct *tty,
                default:
                        dbg("cp210x driver does not "
                                        "support the number of bits requested,"
-                                       " using 8 bit mode\n");
+                                       " using 8 bit mode");
                                bits |= BITS_DATA_8;
                                break;
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
                        dbg("Number of data bits requested "
-                                       "not supported by device\n");
+                                       "not supported by device");
        }
 
        if ((cflag     & (PARENB|PARODD|CMSPAR)) !=
@@ -714,8 +714,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
                        }
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
-                       dbg("Parity mode not supported "
-                                       "by device\n");
+                       dbg("Parity mode not supported by device");
        }
 
        if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
@@ -730,7 +729,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
                }
                if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
                        dbg("Number of stop bits requested "
-                                       "not supported by device\n");
+                                       "not supported by device");
        }
 
        if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
index 3bdeafa29c24d43c11ac71375c5eb93b6916a18d..5ae86b349cad7871d0e03926c24b81142ef31329 100644 (file)
@@ -800,7 +800,7 @@ send:
                cypress_write_int_callback, port, priv->write_urb_interval);
        result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev,
+               dev_err_console(port,
                                "%s - failed submitting write urb, error %d\n",
                                                        __func__, result);
                priv->write_urb_in_use = 0;
index b23bebd721a1f8e511a386b7667827afc8ebaa3e..2b1da0cc071a042f0754c57449724ce3ede75019 100644 (file)
@@ -995,7 +995,7 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
        /* return length of new data written, or error */
        spin_unlock_irqrestore(&priv->dp_port_lock, flags);
        if (ret < 0)
-               dev_err(&port->dev,
+               dev_err_console(port,
                        "%s: usb_submit_urb failed, ret=%d, port=%d\n",
                        __func__, ret, priv->dp_port_num);
        dbg("digi_write: returning %d", ret);
@@ -1065,7 +1065,7 @@ static void digi_write_bulk_callback(struct urb *urb)
 
        spin_unlock(&priv->dp_port_lock);
        if (ret && ret != -EPERM)
-               dev_err(&port->dev,
+               dev_err_console(port,
                        "%s: usb_submit_urb failed, ret=%d, port=%d\n",
                        __func__, ret, priv->dp_port_num);
 }
index f7403576f99f6d04dfc28b0018875ffc1019a019..2a2fa2d0489ddb9bfb2b156a2d57363550bbe21c 100644 (file)
@@ -217,7 +217,7 @@ retry:
        clear_bit(i, &port->write_urbs_free);
        result = usb_submit_urb(urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - error submitting urb: %d\n",
+               dev_err_console(port, "%s - error submitting urb: %d\n",
                                                __func__, result);
                set_bit(i, &port->write_urbs_free);
                spin_lock_irqsave(&port->lock, flags);
index 0497575e4799fd73fe65903dfea799ffce034518..616b07862771b4718d9ed5d9fe1e34750da2516b 100644 (file)
@@ -1286,7 +1286,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
        count = fifo->count;
        buffer = kmalloc(count+2, GFP_ATOMIC);
        if (buffer == NULL) {
-               dev_err(&edge_port->port->dev,
+               dev_err_console(edge_port->port,
                                "%s - no more kernel memory...\n", __func__);
                edge_port->write_in_progress = false;
                goto exit_send;
@@ -1331,7 +1331,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
                /* something went wrong */
-               dev_err(&edge_port->port->dev,
+               dev_err_console(edge_port->port,
                        "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
                                __func__, status);
                edge_port->write_in_progress = false;
index 5818bfc3261ebb2418a54406e768abbe76245ed9..58a3697246a8f210588a19ed2fec5b511f140864 100644 (file)
@@ -1817,7 +1817,7 @@ static void edge_bulk_out_callback(struct urb *urb)
                    __func__, status);
                return;
        default:
-               dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+               dev_err_console(port, "%s - nonzero write bulk status "
                        "received: %d\n", __func__, status);
        }
 
@@ -2111,7 +2111,7 @@ static void edge_send(struct tty_struct *tty)
        /* send the data out the bulk port */
        result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev,
+               dev_err_console(port,
                        "%s - failed submitting write urb, error %d\n",
                                __func__, result);
                edge_port->ep_write_urb_in_use = 0;
index 4554ee49e635d5d4c3d283caf983555630d1b84c..4fb29b4aaad6f7a5d9d20ef68759f917def20433 100644 (file)
@@ -1294,7 +1294,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
                urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
                                               GFP_KERNEL);
                if (urb->transfer_buffer == NULL) {
-                       dev_err(&port->dev, "%s no more kernel memory...\n",
+                       dev_err_console(port, "%s no more kernel memory...\n",
                                __func__);
                        goto exit;
                }
@@ -1315,7 +1315,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
        /* send it down the pipe */
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
-               dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+               dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
                        "with status = %d\n", __func__, status);
                bytes_sent = status;
                goto exit;
index 03b5e249e95e1620b452cd4a000cc6ab8a8de0a8..19b11cece6baa4fced1743db76987607385f5fff 100644 (file)
@@ -1509,7 +1509,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
                    kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
 
                if (urb->transfer_buffer == NULL) {
-                       dev_err(&port->dev, "%s no more kernel memory...\n",
+                       dev_err_console(port, "%s no more kernel memory...\n",
                                __func__);
                        goto exit;
                }
@@ -1535,7 +1535,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        if (status) {
                mos7840_port->busy[i] = 0;
-               dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+               dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
                        "with status = %d\n", __func__, status);
                bytes_sent = status;
                goto exit;
index 8b8d58a2ac12ad54f3e517298a68e18f9cdb6a24..033e8afa6c778e147994dbaede63349ef1ad0a59 100644 (file)
@@ -254,7 +254,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
        result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
        if (result) {
                set_bit(0, &wport->write_urbs_free);
-               dev_err(&port->dev,
+               dev_err_console(port,
                        "%s - failed submitting write urb, error %d\n",
                        __func__, result);
        } else
index e287fd32682c2794f2ce664d159bdd120db22a9d..343e626a06f89e33df775f1fd908d33c4769d84b 100644 (file)
@@ -302,7 +302,7 @@ static void send_data(struct work_struct *work)
        if (count != 0) {
                allow = kmalloc(1, GFP_KERNEL);
                if (!allow) {
-                       dev_err(&port->dev, "%s(): kmalloc failed\n",
+                       dev_err_console(port, "%s(): kmalloc failed\n",
                                        __func__);
                        return;
                }
@@ -334,7 +334,7 @@ static void send_data(struct work_struct *work)
        port->write_urb->transfer_buffer_length = count;
        result = usb_submit_urb(port->write_urb, GFP_NOIO);
        if (result != 0) {
-               dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+               dev_err_console(port, "%s(): usb_submit_urb() failed"
                               " with error %d\n", __func__, result);
                priv->flags.write_urb_in_use = 0;
        }
@@ -938,7 +938,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
                port->write_urb->transfer_buffer_length = 1;
                result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result) {
-                       dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+                       dev_err_console(port, "%s(): usb_submit_urb() failed,"
                                        " error %d\n", __func__, result);
                } else {
                        return;
index 8468eb769a2919d38316993e670cb2810dfacbd7..91d0dc6403606e9a75cf1b690260f4fda744b542 100644 (file)
@@ -1248,7 +1248,6 @@ static void ti_bulk_out_callback(struct urb *urb)
 {
        struct ti_port *tport = urb->context;
        struct usb_serial_port *port = tport->tp_port;
-       struct device *dev = &urb->dev->dev;
        int status = urb->status;
 
        dbg("%s - port %d", __func__, port->number);
@@ -1266,7 +1265,7 @@ static void ti_bulk_out_callback(struct urb *urb)
                wake_up_interruptible(&tport->tp_write_wait);
                return;
        default:
-               dev_err(dev, "%s - nonzero urb status, %d\n",
+               dev_err_console(port, "%s - nonzero urb status, %d\n",
                        __func__, status);
                tport->tp_tdev->td_urb_error = 1;
                wake_up_interruptible(&tport->tp_write_wait);
@@ -1335,7 +1334,7 @@ static void ti_send(struct ti_port *tport)
 
        result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+               dev_err_console(port, "%s - submit write urb failed, %d\n",
                                                        __func__, result);
                tport->tp_write_urb_in_use = 0;
                /* TODO: reschedule ti_send */
index 7e0acf5c8e38bde7345b3e459f11e352e91739ac..007cf3a2481aa55298785928aff437290990071e 100644 (file)
@@ -740,7 +740,7 @@ static int whiteheat_write(struct tty_struct *tty,
                urb->transfer_buffer_length = bytes;
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result) {
-                       dev_err(&port->dev,
+                       dev_err_console(port,
                                "%s - failed submitting write urb, error %d\n",
                                __func__, result);
                        sent = result;
index 51af2fee2efde3b77b26f0ed301e963cdb9b773e..bab8c8fe8290cfd298e6e4361b9925a1169737e4 100644 (file)
@@ -1276,6 +1276,7 @@ static struct usb_driver alauda_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     alauda_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(alauda_driver);
index 387cbd47acc994aa7e4235c3ee1d0fd7af7538e2..5fe451d16e6870968ec4dbfc084d37e1e055a361 100644 (file)
@@ -272,6 +272,7 @@ static struct usb_driver cypress_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     cypress_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(cypress_driver);
index 15d41f2b3d6fcf25bc9a08edabed1f8f9c5c2ecc..35e9c51e66962af08162b5e07022735f7470a4a4 100644 (file)
@@ -751,6 +751,7 @@ static struct usb_driver datafab_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     datafab_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(datafab_driver);
index a6ade4071a9a115c0cd316bd1779ab958523dac3..30532d93eecc3c1fc9d113df1150c12292ab2840 100644 (file)
@@ -2407,6 +2407,7 @@ static struct usb_driver ene_ub6250_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     ene_ub6250_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(ene_ub6250_driver);
index fa161574847560f90e84549d45fc19856939ff62..042cf9ef3153e194c7474747b8a9aa74986ab0d9 100644 (file)
@@ -553,6 +553,7 @@ static struct usb_driver freecom_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     freecom_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(freecom_driver);
index bd5502700831e0cdf2364ffaf2c63af9606020f8..31fa24e7e68ab5a4a78336fc3be7c4d140e02cb7 100644 (file)
@@ -1566,6 +1566,7 @@ static struct usb_driver isd200_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     isd200_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(isd200_driver);
index a19211b5c2654893ecff3feec45b3c02d75f0e10..e3b97383186ab2f91aaa2df87aeac6304b647259 100644 (file)
@@ -677,6 +677,7 @@ static struct usb_driver jumpshot_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     jumpshot_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(jumpshot_driver);
index e720f8ebdf9fc711ad164468ce9c1fbfd44c44a9..a8708eae9788eb5cd3104a0b50369fb299d3f58a 100644 (file)
@@ -230,6 +230,7 @@ static struct usb_driver karma_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     karma_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(karma_driver);
index d75155c382000c52831d9dfb9553dbc49eccf4e0..886567a3806ddd5d190dfb253dabc6afc44e1ea9 100644 (file)
@@ -312,6 +312,7 @@ static struct usb_driver onetouch_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     onetouch_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(onetouch_driver);
index d32f72061c099ddae5aca09758bed77feddf7319..b1c2fe8b6dcd32f2a161ad3df5df03e2a1a8752a 100644 (file)
@@ -1100,6 +1100,7 @@ static struct usb_driver realtek_cr_driver = {
        .id_table = realtek_cr_ids,
        .soft_unbind = 1,
        .supports_autosuspend = 1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(realtek_cr_driver);
index 13b8bcdf3dbafd675a49501dd532b330beb2ecfa..a324a5d21e99e5ec7d7cba790e804ce003c064c9 100644 (file)
@@ -78,8 +78,6 @@ static const char* host_info(struct Scsi_Host *host)
 
 static int slave_alloc (struct scsi_device *sdev)
 {
-       struct us_data *us = host_to_us(sdev->host);
-
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
         * the extra data and many devices choke if asked for more or
@@ -104,18 +102,6 @@ static int slave_alloc (struct scsi_device *sdev)
         */
        blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
 
-       /*
-        * The UFI spec treates the Peripheral Qualifier bits in an
-        * INQUIRY result as reserved and requires devices to set them
-        * to 0.  However the SCSI spec requires these bits to be set
-        * to 3 to indicate when a LUN is not present.
-        *
-        * Let the scanning code know if this target merely sets
-        * Peripheral Device Type to 0x1f to indicate no LUN.
-        */
-       if (us->subclass == USB_SC_UFI)
-               sdev->sdev_target->pdt_1f_for_no_lun = 1;
-
        return 0;
 }
 
@@ -197,6 +183,9 @@ static int slave_configure(struct scsi_device *sdev)
                 * page x08, so we will skip it. */
                sdev->skip_ms_page_8 = 1;
 
+               /* Some devices don't handle VPD pages correctly */
+               sdev->skip_vpd_pages = 1;
+
                /* Some disks return the total number of blocks in response
                 * to READ CAPACITY rather than the highest block number.
                 * If this device makes that mistake, tell the sd driver. */
@@ -217,16 +206,6 @@ static int slave_configure(struct scsi_device *sdev)
                if (sdev->scsi_level > SCSI_SPC_2)
                        us->fflags |= US_FL_SANE_SENSE;
 
-               /* Some devices report a SCSI revision level above 2 but are
-                * unable to handle the REPORT LUNS command (for which
-                * support is mandatory at level 3).  Since we already have
-                * a Get-Max-LUN request, we won't lose much by setting the
-                * revision level down to 2.  The only devices that would be
-                * affected are those with sparse LUNs. */
-               if (sdev->scsi_level > SCSI_2)
-                       sdev->sdev_target->scsi_level =
-                                       sdev->scsi_level = SCSI_2;
-
                /* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
                 * Hardware Error) when any low-level error occurs,
                 * recoverable or not.  Setting this flag tells the SCSI
@@ -283,6 +262,33 @@ static int slave_configure(struct scsi_device *sdev)
        return 0;
 }
 
+static int target_alloc(struct scsi_target *starget)
+{
+       struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
+
+       /*
+        * Some USB drives don't support REPORT LUNS, even though they
+        * report a SCSI revision level above 2.  Tell the SCSI layer
+        * not to issue that command; it will perform a normal sequential
+        * scan instead.
+        */
+       starget->no_report_luns = 1;
+
+       /*
+        * The UFI spec treats the Peripheral Qualifier bits in an
+        * INQUIRY result as reserved and requires devices to set them
+        * to 0.  However the SCSI spec requires these bits to be set
+        * to 3 to indicate when a LUN is not present.
+        *
+        * Let the scanning code know if this target merely sets
+        * Peripheral Device Type to 0x1f to indicate no LUN.
+        */
+       if (us->subclass == USB_SC_UFI)
+               starget->pdt_1f_for_no_lun = 1;
+
+       return 0;
+}
+
 /* queue a command */
 /* This is always called with scsi_lock(host) held */
 static int queuecommand_lck(struct scsi_cmnd *srb,
@@ -546,6 +552,7 @@ struct scsi_host_template usb_stor_host_template = {
 
        .slave_alloc =                  slave_alloc,
        .slave_configure =              slave_configure,
+       .target_alloc =                 target_alloc,
 
        /* lots of sg segments can be handled */
        .sg_tablesize =                 SCSI_MAX_SG_CHAIN_SEGMENTS,
index 425df7df2e5643089eaaef439f3328a978612d82..3252a62b31bcaeb21824ec80323572fe10d0de28 100644 (file)
@@ -1787,6 +1787,7 @@ static struct usb_driver sddr09_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     sddr09_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(sddr09_driver);
index e4ca5fcb7cc3e995fb339b64ff3b2e9eb0b1c863..c144078065a7f691ce3f1e1c57f2d0244510a724 100644 (file)
@@ -1006,6 +1006,7 @@ static struct usb_driver sddr55_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     sddr55_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(sddr55_driver);
index 1369d259061607ed4d0dda0f12306653ba88b648..fa1ceebc465ce434a28167bb3c5f633a3e48645b 100644 (file)
@@ -1863,6 +1863,7 @@ static struct usb_driver usbat_driver = {
        .post_reset =   usb_stor_post_reset,
        .id_table =     usbat_usb_ids,
        .soft_unbind =  1,
+       .no_dynamic_id = 1,
 };
 
 module_usb_driver(usbat_driver);
index a33ead5dce2045d2abc18779c05c26b20a339bc0..8ec8a6e66f504584c0a85acdfd41fa028fe775bb 100644 (file)
@@ -13,7 +13,9 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/storage.h>
+#include <linux/usb/uas.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-/* Common header for all IUs */
-struct iu {
-       __u8 iu_id;
-       __u8 rsvd1;
-       __be16 tag;
-};
-
-enum {
-       IU_ID_COMMAND           = 0x01,
-       IU_ID_STATUS            = 0x03,
-       IU_ID_RESPONSE          = 0x04,
-       IU_ID_TASK_MGMT         = 0x05,
-       IU_ID_READ_READY        = 0x06,
-       IU_ID_WRITE_READY       = 0x07,
-};
-
-struct command_iu {
-       __u8 iu_id;
-       __u8 rsvd1;
-       __be16 tag;
-       __u8 prio_attr;
-       __u8 rsvd5;
-       __u8 len;
-       __u8 rsvd7;
-       struct scsi_lun lun;
-       __u8 cdb[16];   /* XXX: Overflow-checking tools may misunderstand */
-};
-
-/*
- * Also used for the Read Ready and Write Ready IUs since they have the
- * same first four bytes
- */
-struct sense_iu {
-       __u8 iu_id;
-       __u8 rsvd1;
-       __be16 tag;
-       __be16 status_qual;
-       __u8 status;
-       __u8 rsvd7[7];
-       __be16 len;
-       __u8 sense[SCSI_SENSE_BUFFERSIZE];
-};
-
 /*
  * The r00-r01c specs define this version of the SENSE IU data structure.
  * It's still in use by several different firmware releases.
@@ -79,18 +38,6 @@ struct sense_iu_old {
        __u8 sense[SCSI_SENSE_BUFFERSIZE];
 };
 
-enum {
-       CMD_PIPE_ID             = 1,
-       STATUS_PIPE_ID          = 2,
-       DATA_IN_PIPE_ID         = 3,
-       DATA_OUT_PIPE_ID        = 4,
-
-       UAS_SIMPLE_TAG          = 0,
-       UAS_HEAD_TAG            = 1,
-       UAS_ORDERED_TAG         = 2,
-       UAS_ACA                 = 4,
-};
-
 struct uas_dev_info {
        struct usb_interface *intf;
        struct usb_device *udev;
@@ -98,6 +45,8 @@ struct uas_dev_info {
        unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
        unsigned use_streams:1;
        unsigned uas_sense_old:1;
+       struct scsi_cmnd *cmnd;
+       struct urb *status_urb; /* used only if stream support is available */
 };
 
 enum {
@@ -109,6 +58,9 @@ enum {
        SUBMIT_DATA_OUT_URB     = (1 << 5),
        ALLOC_CMD_URB           = (1 << 6),
        SUBMIT_CMD_URB          = (1 << 7),
+       COMPLETED_DATA_IN       = (1 << 8),
+       COMPLETED_DATA_OUT      = (1 << 9),
+       DATA_COMPLETES_CMD      = (1 << 10),
 };
 
 /* Overrides scsi_pointer */
@@ -116,6 +68,7 @@ struct uas_cmd_info {
        unsigned int state;
        unsigned int stream;
        struct urb *cmd_urb;
+       /* status_urb is used only if stream support isn't available */
        struct urb *status_urb;
        struct urb *data_in_urb;
        struct urb *data_out_urb;
@@ -125,33 +78,43 @@ struct uas_cmd_info {
 /* I hate forward declarations, but I actually have a loop */
 static int uas_submit_urbs(struct scsi_cmnd *cmnd,
                                struct uas_dev_info *devinfo, gfp_t gfp);
+static void uas_do_work(struct work_struct *work);
 
+static DECLARE_WORK(uas_work, uas_do_work);
 static DEFINE_SPINLOCK(uas_work_lock);
 static LIST_HEAD(uas_work_list);
 
 static void uas_do_work(struct work_struct *work)
 {
        struct uas_cmd_info *cmdinfo;
+       struct uas_cmd_info *temp;
        struct list_head list;
+       int err;
 
        spin_lock_irq(&uas_work_lock);
        list_replace_init(&uas_work_list, &list);
        spin_unlock_irq(&uas_work_lock);
 
-       list_for_each_entry(cmdinfo, &list, list) {
+       list_for_each_entry_safe(cmdinfo, temp, &list, list) {
                struct scsi_pointer *scp = (void *)cmdinfo;
                struct scsi_cmnd *cmnd = container_of(scp,
                                                        struct scsi_cmnd, SCp);
-               uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+               err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+               if (err) {
+                       list_del(&cmdinfo->list);
+                       spin_lock_irq(&uas_work_lock);
+                       list_add_tail(&cmdinfo->list, &uas_work_list);
+                       spin_unlock_irq(&uas_work_lock);
+                       schedule_work(&uas_work);
+               }
        }
 }
 
-static DECLARE_WORK(uas_work, uas_do_work);
-
 static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
 {
        struct sense_iu *sense_iu = urb->transfer_buffer;
        struct scsi_device *sdev = cmnd->device;
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
        if (urb->actual_length > 16) {
                unsigned len = be16_to_cpup(&sense_iu->len);
@@ -169,16 +132,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
        }
 
        cmnd->result = sense_iu->status;
-       if (sdev->current_cmnd)
-               sdev->current_cmnd = NULL;
-       cmnd->scsi_done(cmnd);
-       usb_free_urb(urb);
+       if (!(cmdinfo->state & DATA_COMPLETES_CMD))
+               cmnd->scsi_done(cmnd);
 }
 
 static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
 {
        struct sense_iu_old *sense_iu = urb->transfer_buffer;
        struct scsi_device *sdev = cmnd->device;
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
        if (urb->actual_length > 8) {
                unsigned len = be16_to_cpup(&sense_iu->len) - 2;
@@ -196,10 +158,8 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
        }
 
        cmnd->result = sense_iu->status;
-       if (sdev->current_cmnd)
-               sdev->current_cmnd = NULL;
-       cmnd->scsi_done(cmnd);
-       usb_free_urb(urb);
+       if (!(cmdinfo->state & DATA_COMPLETES_CMD))
+               cmnd->scsi_done(cmnd);
 }
 
 static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
@@ -208,7 +168,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
        struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
        int err;
 
-       cmdinfo->state = direction | SUBMIT_STATUS_URB;
+       cmdinfo->state = direction;
        err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
        if (err) {
                spin_lock(&uas_work_lock);
@@ -221,27 +181,61 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
 static void uas_stat_cmplt(struct urb *urb)
 {
        struct iu *iu = urb->transfer_buffer;
-       struct scsi_device *sdev = urb->context;
-       struct uas_dev_info *devinfo = sdev->hostdata;
+       struct Scsi_Host *shost = urb->context;
+       struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
        struct scsi_cmnd *cmnd;
+       struct uas_cmd_info *cmdinfo;
        u16 tag;
+       int ret;
 
        if (urb->status) {
                dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
-               usb_free_urb(urb);
+               if (devinfo->use_streams)
+                       usb_free_urb(urb);
                return;
        }
 
        tag = be16_to_cpup(&iu->tag) - 1;
-       if (sdev->current_cmnd)
-               cmnd = sdev->current_cmnd;
+       if (tag == 0)
+               cmnd = devinfo->cmnd;
        else
-               cmnd = scsi_find_tag(sdev, tag);
-       if (!cmnd)
+               cmnd = scsi_host_find_tag(shost, tag - 1);
+       if (!cmnd) {
+               if (devinfo->use_streams) {
+                       usb_free_urb(urb);
+                       return;
+               }
+               ret = usb_submit_urb(urb, GFP_ATOMIC);
+               if (ret)
+                       dev_err(&urb->dev->dev, "failed submit status urb\n");
                return;
+       }
+       cmdinfo = (void *)&cmnd->SCp;
 
        switch (iu->iu_id) {
        case IU_ID_STATUS:
+               if (devinfo->cmnd == cmnd)
+                       devinfo->cmnd = NULL;
+
+               if (!(cmdinfo->state & COMPLETED_DATA_IN) &&
+                               cmdinfo->data_in_urb) {
+                      if (devinfo->use_streams) {
+                              cmdinfo->state |= DATA_COMPLETES_CMD;
+                              usb_unlink_urb(cmdinfo->data_in_urb);
+                      } else {
+                              usb_free_urb(cmdinfo->data_in_urb);
+                      }
+               }
+               if (!(cmdinfo->state & COMPLETED_DATA_OUT) &&
+                               cmdinfo->data_out_urb) {
+                       if (devinfo->use_streams) {
+                               cmdinfo->state |= DATA_COMPLETES_CMD;
+                               usb_unlink_urb(cmdinfo->data_in_urb);
+                       } else {
+                               usb_free_urb(cmdinfo->data_out_urb);
+                       }
+               }
+
                if (urb->actual_length < 16)
                        devinfo->uas_sense_old = 1;
                if (devinfo->uas_sense_old)
@@ -259,29 +253,70 @@ static void uas_stat_cmplt(struct urb *urb)
                scmd_printk(KERN_ERR, cmnd,
                        "Bogus IU (%d) received on status pipe\n", iu->iu_id);
        }
+
+       if (devinfo->use_streams) {
+               usb_free_urb(urb);
+               return;
+       }
+
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret)
+               dev_err(&urb->dev->dev, "failed submit status urb\n");
 }
 
-static void uas_data_cmplt(struct urb *urb)
+static void uas_data_out_cmplt(struct urb *urb)
 {
-       struct scsi_data_buffer *sdb = urb->context;
+       struct scsi_cmnd *cmnd = urb->context;
+       struct scsi_data_buffer *sdb = scsi_out(cmnd);
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+       cmdinfo->state |= COMPLETED_DATA_OUT;
+
        sdb->resid = sdb->length - urb->actual_length;
        usb_free_urb(urb);
+
+       if (cmdinfo->state & DATA_COMPLETES_CMD)
+               cmnd->scsi_done(cmnd);
+}
+
+static void uas_data_in_cmplt(struct urb *urb)
+{
+       struct scsi_cmnd *cmnd = urb->context;
+       struct scsi_data_buffer *sdb = scsi_in(cmnd);
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+       cmdinfo->state |= COMPLETED_DATA_IN;
+
+       sdb->resid = sdb->length - urb->actual_length;
+       usb_free_urb(urb);
+
+       if (cmdinfo->state & DATA_COMPLETES_CMD)
+               cmnd->scsi_done(cmnd);
 }
 
 static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-                               unsigned int pipe, u16 stream_id,
-                               struct scsi_data_buffer *sdb,
-                               enum dma_data_direction dir)
+               unsigned int pipe, struct scsi_cmnd *cmnd,
+               enum dma_data_direction dir)
 {
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
        struct usb_device *udev = devinfo->udev;
        struct urb *urb = usb_alloc_urb(0, gfp);
+       struct scsi_data_buffer *sdb;
+       usb_complete_t complete_fn;
+       u16 stream_id = cmdinfo->stream;
 
        if (!urb)
                goto out;
-       usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
-                                                                       sdb);
-       if (devinfo->use_streams)
-               urb->stream_id = stream_id;
+       if (dir == DMA_FROM_DEVICE) {
+               sdb = scsi_in(cmnd);
+               complete_fn = uas_data_in_cmplt;
+       } else {
+               sdb = scsi_out(cmnd);
+               complete_fn = uas_data_out_cmplt;
+       }
+       usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
+                       complete_fn, cmnd);
+       urb->stream_id = stream_id;
        urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
        urb->sg = sdb->table.sgl;
  out:
@@ -289,7 +324,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
 }
 
 static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-                                       struct scsi_cmnd *cmnd, u16 stream_id)
+               struct Scsi_Host *shost, u16 stream_id)
 {
        struct usb_device *udev = devinfo->udev;
        struct urb *urb = usb_alloc_urb(0, gfp);
@@ -303,7 +338,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
                goto free;
 
        usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
-                                               uas_stat_cmplt, cmnd->device);
+                                               uas_stat_cmplt, shost);
        urb->stream_id = stream_id;
        urb->transfer_flags |= URB_FREE_BUFFER;
  out:
@@ -334,7 +369,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
                goto free;
 
        iu->iu_id = IU_ID_COMMAND;
-       iu->tag = cpu_to_be16(stream_id);
+       if (blk_rq_tagged(cmnd->request))
+               iu->tag = cpu_to_be16(cmnd->request->tag + 2);
+       else
+               iu->tag = cpu_to_be16(1);
        iu->prio_attr = UAS_SIMPLE_TAG;
        iu->len = len;
        int_to_scsilun(sdev->lun, &iu->lun);
@@ -362,8 +400,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
        struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
 
        if (cmdinfo->state & ALLOC_STATUS_URB) {
-               cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
-                                                         cmdinfo->stream);
+               cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp,
+                               cmnd->device->host, cmdinfo->stream);
                if (!cmdinfo->status_urb)
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                cmdinfo->state &= ~ALLOC_STATUS_URB;
@@ -380,8 +418,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 
        if (cmdinfo->state & ALLOC_DATA_IN_URB) {
                cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
-                                       devinfo->data_in_pipe, cmdinfo->stream,
-                                       scsi_in(cmnd), DMA_FROM_DEVICE);
+                                       devinfo->data_in_pipe, cmnd,
+                                       DMA_FROM_DEVICE);
                if (!cmdinfo->data_in_urb)
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                cmdinfo->state &= ~ALLOC_DATA_IN_URB;
@@ -398,8 +436,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 
        if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
                cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
-                                       devinfo->data_out_pipe, cmdinfo->stream,
-                                       scsi_out(cmnd), DMA_TO_DEVICE);
+                                       devinfo->data_out_pipe, cmnd,
+                                       DMA_TO_DEVICE);
                if (!cmdinfo->data_out_urb)
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
@@ -444,13 +482,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
 
        BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
-       if (!cmdinfo->status_urb && sdev->current_cmnd)
+       if (devinfo->cmnd)
                return SCSI_MLQUEUE_DEVICE_BUSY;
 
        if (blk_rq_tagged(cmnd->request)) {
-               cmdinfo->stream = cmnd->request->tag + 1;
+               cmdinfo->stream = cmnd->request->tag + 2;
        } else {
-               sdev->current_cmnd = cmnd;
+               devinfo->cmnd = cmnd;
                cmdinfo->stream = 1;
        }
 
@@ -472,7 +510,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
        }
 
        if (!devinfo->use_streams) {
-               cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
+               cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB |
+                               ALLOC_STATUS_URB | SUBMIT_STATUS_URB);
                cmdinfo->stream = 0;
        }
 
@@ -551,7 +590,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
 {
        struct uas_dev_info *devinfo = sdev->hostdata;
        scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
-       scsi_activate_tcq(sdev, devinfo->qdepth - 1);
+       scsi_activate_tcq(sdev, devinfo->qdepth - 2);
        return 0;
 }
 
@@ -589,22 +628,34 @@ static int uas_is_interface(struct usb_host_interface *intf)
                intf->desc.bInterfaceProtocol == USB_PR_UAS);
 }
 
+static int uas_isnt_supported(struct usb_device *udev)
+{
+       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+       dev_warn(&udev->dev, "The driver for the USB controller %s does not "
+                       "support scatter-gather which is\n",
+                       hcd->driver->description);
+       dev_warn(&udev->dev, "required by the UAS driver. Please try an"
+                       "alternative USB controller if you wish to use UAS.\n");
+       return -ENODEV;
+}
+
 static int uas_switch_interface(struct usb_device *udev,
                                                struct usb_interface *intf)
 {
        int i;
-
-       if (uas_is_interface(intf->cur_altsetting))
-               return 0;
+       int sg_supported = udev->bus->sg_tablesize != 0;
 
        for (i = 0; i < intf->num_altsetting; i++) {
                struct usb_host_interface *alt = &intf->altsetting[i];
-               if (alt == intf->cur_altsetting)
-                       continue;
-               if (uas_is_interface(alt))
+
+               if (uas_is_interface(alt)) {
+                       if (!sg_supported)
+                               return uas_isnt_supported(udev);
                        return usb_set_interface(udev,
                                                alt->desc.bInterfaceNumber,
                                                alt->desc.bAlternateSetting);
+               }
        }
 
        return -ENODEV;
@@ -619,6 +670,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
        unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
 
        devinfo->uas_sense_old = 0;
+       devinfo->cmnd = NULL;
 
        for (i = 0; i < n_endpoints; i++) {
                unsigned char *extra = endpoint[i].extra;
@@ -670,6 +722,40 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
        }
 }
 
+static int uas_alloc_status_urb(struct uas_dev_info *devinfo,
+               struct Scsi_Host *shost)
+{
+       if (devinfo->use_streams) {
+               devinfo->status_urb = NULL;
+               return 0;
+       }
+
+       devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL,
+                       shost, 0);
+       if (!devinfo->status_urb)
+               goto err_s_urb;
+
+       if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL))
+               goto err_submit_urb;
+
+       return 0;
+err_submit_urb:
+       usb_free_urb(devinfo->status_urb);
+err_s_urb:
+       return -ENOMEM;
+}
+
+static void uas_free_streams(struct uas_dev_info *devinfo)
+{
+       struct usb_device *udev = devinfo->udev;
+       struct usb_host_endpoint *eps[3];
+
+       eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+       eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+       eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+       usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
+}
+
 /*
  * XXX: What I'd like to do here is register a SCSI host for each USB host in
  * the system.  Follow usb-storage's design of registering a SCSI host for
@@ -699,18 +785,33 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        shost->max_id = 1;
        shost->sg_tablesize = udev->bus->sg_tablesize;
 
-       result = scsi_add_host(shost, &intf->dev);
+       devinfo->intf = intf;
+       devinfo->udev = udev;
+       uas_configure_endpoints(devinfo);
+
+       result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
        if (result)
                goto free;
+
+       result = scsi_add_host(shost, &intf->dev);
+       if (result)
+               goto deconfig_eps;
+
        shost->hostdata[0] = (unsigned long)devinfo;
 
-       devinfo->intf = intf;
-       devinfo->udev = udev;
-       uas_configure_endpoints(devinfo);
+       result = uas_alloc_status_urb(devinfo, shost);
+       if (result)
+               goto err_alloc_status;
 
        scsi_scan_host(shost);
        usb_set_intfdata(intf, shost);
        return result;
+
+err_alloc_status:
+       scsi_remove_host(shost);
+       shost = NULL;
+deconfig_eps:
+       uas_free_streams(devinfo);
  free:
        kfree(devinfo);
        if (shost)
@@ -732,18 +833,13 @@ static int uas_post_reset(struct usb_interface *intf)
 
 static void uas_disconnect(struct usb_interface *intf)
 {
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct usb_host_endpoint *eps[3];
        struct Scsi_Host *shost = usb_get_intfdata(intf);
        struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
 
        scsi_remove_host(shost);
-
-       eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
-       eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
-       eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
-       usb_free_streams(intf, eps, 3, GFP_KERNEL);
-
+       usb_kill_urb(devinfo->status_urb);
+       usb_free_urb(devinfo->status_urb);
+       uas_free_streams(devinfo);
        kfree(devinfo);
 }
 
index 3dd7da9fd5043cad98a00e552ba8c11ebe9ff581..58f56775ecde5910862aab47a76846d9c86cebcd 100644 (file)
@@ -125,6 +125,9 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
        { }             /* Terminating entry */
 };
 
+static struct us_unusual_dev for_dynamic_ids =
+               USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0);
+
 #undef UNUSUAL_DEV
 #undef COMPLIANT_DEV
 #undef USUAL_DEV
@@ -1027,8 +1030,10 @@ EXPORT_SYMBOL_GPL(usb_stor_disconnect);
 static int storage_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
+       struct us_unusual_dev *unusual_dev;
        struct us_data *us;
        int result;
+       int size;
 
        /*
         * If libusual is configured, let it decide whether a standard
@@ -1047,8 +1052,19 @@ static int storage_probe(struct usb_interface *intf,
         * table, so we use the index of the id entry to find the
         * corresponding unusual_devs entry.
         */
-       result = usb_stor_probe1(&us, intf, id,
-                       (id - usb_storage_usb_ids) + us_unusual_dev_list);
+
+       size = ARRAY_SIZE(us_unusual_dev_list);
+       if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) {
+               unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list;
+       } else {
+               unusual_dev = &for_dynamic_ids;
+
+               US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport",
+                       "with the Transparent SCSI protocol for dynamic id:",
+                       id->idVendor, id->idProduct);
+       }
+
+       result = usb_stor_probe1(&us, intf, id, unusual_dev);
        if (result)
                return result;
 
@@ -1074,7 +1090,6 @@ static struct usb_driver usb_storage_driver = {
        .id_table =     usb_storage_usb_ids,
        .supports_autosuspend = 1,
        .soft_unbind =  1,
-       .no_dynamic_id = 1,
 };
 
 static int __init usb_stor_init(void)
index 69d845739bc2304ff52bfac2f9e18f87b1002d8e..0c51663f2733bc98452edeed37cb77cbd6bfd26c 100644 (file)
@@ -376,6 +376,12 @@ struct usb_bus {
 
 struct usb_tt;
 
+enum usb_device_removable {
+       USB_DEVICE_REMOVABLE_UNKNOWN = 0,
+       USB_DEVICE_REMOVABLE,
+       USB_DEVICE_FIXED,
+};
+
 /**
  * struct usb_device - kernel's representation of a USB device
  * @devnum: device number; address on a USB bus
@@ -432,6 +438,7 @@ struct usb_tt;
  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
  *     specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
+ * @removable: Device can be physically removed from this port
  *
  * Notes:
  * Usbcore drivers should not set usbdev->state directly.  Instead use
@@ -509,6 +516,7 @@ struct usb_device {
 #endif
        struct wusb_dev *wusb_dev;
        int slot_id;
+       enum usb_device_removable removable;
 };
 #define        to_usb_device(d) container_of(d, struct usb_device, dev)
 
index 4267a9c717baac379045ad953746e2b0569b9b95..10cb74d2ad1d75ba983f46e843eecb286cbc1a4c 100644 (file)
@@ -389,5 +389,20 @@ do {                                                                       \
                printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \
 } while (0)
 
+/*
+ * Macro for reporting errors in write path to avoid inifinite loop
+ * when port is used as a console.
+ */
+#define dev_err_console(usport, fmt, ...)                              \
+do {                                                                   \
+       static bool __print_once;                                       \
+       struct usb_serial_port *__port = (usport);                      \
+                                                                       \
+       if (!__port->port.console || !__print_once) {                   \
+               __print_once = true;                                    \
+               dev_err(&__port->dev, fmt, ##__VA_ARGS__);              \
+       }                                                               \
+} while (0)
+
 #endif /* __LINUX_USB_SERIAL_H */
 
diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h
new file mode 100644 (file)
index 0000000..9a988e4
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __USB_UAS_H__
+#define __USB_UAS_H__
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+/* Common header for all IUs */
+struct iu {
+       __u8 iu_id;
+       __u8 rsvd1;
+       __be16 tag;
+};
+
+enum {
+       IU_ID_COMMAND           = 0x01,
+       IU_ID_STATUS            = 0x03,
+       IU_ID_RESPONSE          = 0x04,
+       IU_ID_TASK_MGMT         = 0x05,
+       IU_ID_READ_READY        = 0x06,
+       IU_ID_WRITE_READY       = 0x07,
+};
+
+struct command_iu {
+       __u8 iu_id;
+       __u8 rsvd1;
+       __be16 tag;
+       __u8 prio_attr;
+       __u8 rsvd5;
+       __u8 len;
+       __u8 rsvd7;
+       struct scsi_lun lun;
+       __u8 cdb[16];   /* XXX: Overflow-checking tools may misunderstand */
+};
+
+/*
+ * Also used for the Read Ready and Write Ready IUs since they have the
+ * same first four bytes
+ */
+struct sense_iu {
+       __u8 iu_id;
+       __u8 rsvd1;
+       __be16 tag;
+       __be16 status_qual;
+       __u8 status;
+       __u8 rsvd7[7];
+       __be16 len;
+       __u8 sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+struct usb_pipe_usage_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bPipeID;
+       __u8  Reserved;
+} __attribute__((__packed__));
+
+enum {
+       CMD_PIPE_ID             = 1,
+       STATUS_PIPE_ID          = 2,
+       DATA_IN_PIPE_ID         = 3,
+       DATA_OUT_PIPE_ID        = 4,
+
+       UAS_SIMPLE_TAG          = 0,
+       UAS_HEAD_TAG            = 1,
+       UAS_ORDERED_TAG         = 2,
+       UAS_ACA                 = 4,
+};
+#endif
index 77273f2fdd8020939e35a4e4f3d567d013eadc63..b3a1c2daf6cca49e94503279e3fbbabbb5ff6302 100644 (file)
@@ -136,6 +136,7 @@ struct scsi_device {
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
        unsigned skip_ms_page_8:1;      /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;     /* do not use MODE SENSE page 0x3f */
+       unsigned skip_vpd_pages:1;      /* do not read VPD pages */
        unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
        unsigned no_start_on_add:1;     /* do not issue start on add */
        unsigned allow_restart:1; /* issue START_UNIT in error handler */
@@ -246,8 +247,10 @@ struct scsi_target {
        unsigned int            single_lun:1;   /* Indicates we should only
                                                 * allow I/O to one of the luns
                                                 * for the device at a time. */
-       unsigned int            pdt_1f_for_no_lun;      /* PDT = 0x1f */
-                                               /* means no lun present */
+       unsigned int            pdt_1f_for_no_lun:1;    /* PDT = 0x1f
+                                                * means no lun present. */
+       unsigned int            no_report_luns:1;       /* Don't use
+                                                * REPORT LUNS for scanning. */
        /* commands actually active on LLD. protected by host lock. */
        unsigned int            target_busy;
        /*