For UAS we use an alternative driver. A device might show as USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK on alt setting 0. and have USB_PR_UAS on alt setting 1. In that case we do not want to bind to the device and let the UAS driver to pick it up. There is one requirement by the UAS driver: sg support in HCD. If this is not possible then we keep the device and inform the user. Cc: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> Cc: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxxxx> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> --- drivers/usb/storage/usb.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 48 insertions(+), 0 deletions(-) diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 9e069ef..4216869 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -1022,6 +1022,50 @@ void usb_stor_disconnect(struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usb_stor_disconnect); +#if defined(CONFIG_USB_UAS) || defined(CONFIG_USB_UAS_MODULE) +static int uas_is_interface(struct usb_host_interface *intf) +{ + return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE && + intf->desc.bInterfaceSubClass == USB_SC_SCSI && + intf->desc.bInterfaceProtocol == USB_PR_UAS); +} + +static int stor_check_for_uas(struct usb_interface *intf) +{ + struct usb_device *udev = interface_to_usbdev(intf); + int sg_supported = udev->bus->sg_tablesize != 0; + int i; + + for (i = 0; i < intf->num_altsetting; i++) { + struct usb_host_interface *alt = &intf->altsetting[i]; + + if (uas_is_interface(alt)) { + if (!sg_supported) { + dev_warn(&udev->dev, + "Device provides UAS function which can not be used " + "because this USB controller does not support\n"); + dev_warn(&udev->dev, + "scatter-gather. Using legacy interface.\n"); + return 0; + } else { + dev_warn(&udev->dev, + "Releasing the device in favour of the UAS driver\n"); + return 1; + } + } + } + return 0; +} + +#else + +static inline int stor_check_for_uas(struct usb_interface *intf) +{ + return 0; +} + +#endif + /* The main probe routine for standard devices */ static int storage_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1039,6 +1083,10 @@ static int storage_probe(struct usb_interface *intf, usb_usual_ignore_device(intf)) return -ENXIO; + result = stor_check_for_uas(intf); + if (result) + return -ENXIO; + /* * Call the general probe procedures. * -- 1.7.8.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html