[PATCH 3/3] usb/storage: don't bind the device if there is UAS alt interface available

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux