[RFC v3] USB: Warn about USB3 devices plugged into USB2 hub.

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

 



When a SuperSpeed device is plugged into non-SuperSpeed host or hub, it
will show up as a high speed or full speed device with a BCD USB version
number of 0x0201 or 0x210.  It will also contain a SuperSpeed
Capabilities BOS descriptor.

If we see such a device, warn the user that they should plug their
device into a USB 3.0 hub or xHCI root port.  Only warn the user if
there is at least one SuperSpeed roothub available.

Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
Cc: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Cc: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
---

v3:
 - Remove redundant speed checking.
 - Warn about full or low speed devices that could run at SuperSpeed.
 - Change description to remove false assumption about what BCD USB
   shows up as under a UHCI/OHCI host.


 drivers/usb/core/hub.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d4f0624..2553bcf 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1272,6 +1272,7 @@ static void hub_release(struct kref *kref)
 }
 
 static unsigned highspeed_hubs;
+static unsigned superspeed_hubs;
 
 static void hub_disconnect(struct usb_interface *intf)
 {
@@ -1295,6 +1296,8 @@ static void hub_disconnect(struct usb_interface *intf)
 
 	if (hub->hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs--;
+	if (hub->hdev->speed == USB_SPEED_SUPER)
+		superspeed_hubs--;
 
 	usb_free_urb(hub->urb);
 	kfree(hub->port_owners);
@@ -1372,6 +1375,8 @@ descriptor_error:
 
 	if (hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs++;
+	if (hub->hdev->speed == USB_SPEED_SUPER)
+		superspeed_hubs++;
 
 	if (hub_configure(hub, endpoint) >= 0)
 		return 0;
@@ -3230,6 +3235,15 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
 	kfree(qual);
 }
 
+static void check_superspeed(struct usb_hub *hub, struct usb_device *udev,
+		int port1)
+{
+	if (udev->bos && udev->bos->ss_cap) {
+		dev_info(&udev->dev, "not running at top speed; "
+			"connect to a SuperSpeed port\n");
+	}
+}
+
 static unsigned
 hub_power_remaining (struct usb_hub *hub)
 {
@@ -3449,6 +3463,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 				&& udev->speed == USB_SPEED_FULL
 				&& highspeed_hubs != 0)
 			check_highspeed (hub, udev, port1);
+		if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201 &&
+				udev->speed < USB_SPEED_SUPER &&
+				superspeed_hubs != 0)
+			check_superspeed(hub, udev, port1);
 
 		/* Store the parent's children[] pointer.  At this point
 		 * udev becomes globally accessible, although presumably
-- 
1.7.9

--
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