aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/uas.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-01-11 06:42:32 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-02-02 17:51:00 -0500
commitc898add51c7b5b99fcecdeaf4df2ca30949cacb6 (patch)
tree592270c089abd5c93b08ebfe7f85882ab28946f7 /drivers/usb/storage/uas.c
parentb603669842b3b2c66a1fc2e926f35a2143be8b3b (diff)
usb/uas: only bind if the hcd supports SG
The UAS driver requires SG support by the HCD operating the device. This patch stops UAS from operating on a HCD without sg support and prints a message to let him know. The spec says: |For [USB2] backward compatibility, the device shall present [BOT] as |alternate interface zero (primary) and [UAS] as alternate interface one |(secondary). A device which does not need backward compatibility with |[BOT] shall present [UAS] as alternate interface zero. In [USB2] |systems, the [BOT] driver or an associated filter driver may need to |issue a SET INTERFACE request for alternate interface one and then allow |the [UAS] driver to load. If the user used usb_modeswitch to switch to UAS then he can go back to BOT or use a different HCD. In case UAS is the only interface then there is currently no way out. In future usb_sg_wait() should be extended to provide a non-blocking interface so it can work with the UAS driver. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/storage/uas.c')
-rw-r--r--drivers/usb/storage/uas.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index e0133c9ab0bf..e34c75970ed1 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -13,6 +13,7 @@
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/usb.h> 15#include <linux/usb.h>
16#include <linux/usb/hcd.h>
16#include <linux/usb/storage.h> 17#include <linux/usb/storage.h>
17 18
18#include <scsi/scsi.h> 19#include <scsi/scsi.h>
@@ -621,22 +622,34 @@ static int uas_is_interface(struct usb_host_interface *intf)
621 intf->desc.bInterfaceProtocol == USB_PR_UAS); 622 intf->desc.bInterfaceProtocol == USB_PR_UAS);
622} 623}
623 624
625static int uas_isnt_supported(struct usb_device *udev)
626{
627 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
628
629 dev_warn(&udev->dev, "The driver for the USB controller %s does not "
630 "support scatter-gather which is\n",
631 hcd->driver->description);
632 dev_warn(&udev->dev, "required by the UAS driver. Please try an"
633 "alternative USB controller if you wish to use UAS.\n");
634 return -ENODEV;
635}
636
624static int uas_switch_interface(struct usb_device *udev, 637static int uas_switch_interface(struct usb_device *udev,
625 struct usb_interface *intf) 638 struct usb_interface *intf)
626{ 639{
627 int i; 640 int i;
628 641 int sg_supported = udev->bus->sg_tablesize != 0;
629 if (uas_is_interface(intf->cur_altsetting))
630 return 0;
631 642
632 for (i = 0; i < intf->num_altsetting; i++) { 643 for (i = 0; i < intf->num_altsetting; i++) {
633 struct usb_host_interface *alt = &intf->altsetting[i]; 644 struct usb_host_interface *alt = &intf->altsetting[i];
634 if (alt == intf->cur_altsetting) 645
635 continue; 646 if (uas_is_interface(alt)) {
636 if (uas_is_interface(alt)) 647 if (!sg_supported)
648 return uas_isnt_supported(udev);
637 return usb_set_interface(udev, 649 return usb_set_interface(udev,
638 alt->desc.bInterfaceNumber, 650 alt->desc.bInterfaceNumber,
639 alt->desc.bAlternateSetting); 651 alt->desc.bAlternateSetting);
652 }
640 } 653 }
641 654
642 return -ENODEV; 655 return -ENODEV;