Skip to content

Commit c898add

Browse files
Sebastian Andrzej SiewiorSarah Sharp
authored andcommitted
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 <[email protected]> Signed-off-by: Sarah Sharp <[email protected]>
1 parent b603669 commit c898add

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

drivers/usb/storage/uas.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/types.h>
1414
#include <linux/module.h>
1515
#include <linux/usb.h>
16+
#include <linux/usb/hcd.h>
1617
#include <linux/usb/storage.h>
1718

1819
#include <scsi/scsi.h>
@@ -621,22 +622,34 @@ static int uas_is_interface(struct usb_host_interface *intf)
621622
intf->desc.bInterfaceProtocol == USB_PR_UAS);
622623
}
623624

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+
624637
static int uas_switch_interface(struct usb_device *udev,
625638
struct usb_interface *intf)
626639
{
627640
int i;
628-
629-
if (uas_is_interface(intf->cur_altsetting))
630-
return 0;
641+
int sg_supported = udev->bus->sg_tablesize != 0;
631642

632643
for (i = 0; i < intf->num_altsetting; i++) {
633644
struct usb_host_interface *alt = &intf->altsetting[i];
634-
if (alt == intf->cur_altsetting)
635-
continue;
636-
if (uas_is_interface(alt))
645+
646+
if (uas_is_interface(alt)) {
647+
if (!sg_supported)
648+
return uas_isnt_supported(udev);
637649
return usb_set_interface(udev,
638650
alt->desc.bInterfaceNumber,
639651
alt->desc.bAlternateSetting);
652+
}
640653
}
641654

642655
return -ENODEV;

0 commit comments

Comments
 (0)