diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-01-11 06:42:32 -0500 |
---|---|---|
committer | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2012-02-02 17:51:00 -0500 |
commit | c898add51c7b5b99fcecdeaf4df2ca30949cacb6 (patch) | |
tree | 592270c089abd5c93b08ebfe7f85882ab28946f7 /drivers/usb/storage/uas.c | |
parent | b603669842b3b2c66a1fc2e926f35a2143be8b3b (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.c | 25 |
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 | ||
625 | static 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 | |||
624 | static int uas_switch_interface(struct usb_device *udev, | 637 | static 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; |