aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShantur Rathore <i@shantur.com>2024-02-14 09:54:03 +0000
committerMarek Vasut <marex@denx.de>2024-02-19 20:08:41 +0100
commit08e2cd6cd333e0c7dc297ae8ec846f2bc854cd90 (patch)
treec6153968dbe2c4fb7d38e96661dd767d8ed1176f
parent3e6f2a94bfc25f1782ce2d45db27f47ec781feb1 (diff)
downloadu-boot-08e2cd6cd333e0c7dc297ae8ec846f2bc854cd90.zip
u-boot-08e2cd6cd333e0c7dc297ae8ec846f2bc854cd90.tar.gz
u-boot-08e2cd6cd333e0c7dc297ae8ec846f2bc854cd90.tar.bz2
common: usb-hub: Reset USB 3.0 hubs only
Additional testing of the changes introduced in commit 33e06dcbe57a "common: usb-hub: Reset hub port before scanning") revealed that some USB 2.0 and 3.0 flash drives didn't work in U-Boot on some Allwinner SoCs that support USB 2.0 interfaces only. More precisely, some of the tested USB 2.0 and 3.0 flash drives failed to be detected and work on an OrangePi Zero 3, based on the Allwinner H616 SoC that supports USB 2.0 only, while the same USB flash drives worked just fine on a Pine64 H64, based on the Allwinner H6 SoC that supports both USB 2.0 and USB 3.0 interfaces. The USB ID of the above-mentioned USB 3.0 flash drive that failed to work is 1f75:0917 (Innostor Technology Corporation IS917 Mass storage), it is 32 GB in size and sold under the PNY brand. The mentioned USB 2.0 drive is some inexpensive no-name drive with an invalid USB ID. Resetting USB 3.0 hubs only, which this patch introduces to the USB hub resets, has been tested to work as expected, resolving the identified issues on the Allwinner H616, while not introducing any new issues on other tested Allwinner SoCs. Thus, let's fix it that way. According to the USB 3.0 specification, resetting a USB 3.0 port is required when an attached USB device transitions between different states, such as when it resumes from suspend. Though, the Linux kernel performs additional USB 3.0 port resets upon initial USB device attachment, as visible in commit 07194ab7be63 ("USB: Reset USB 3.0 devices on (re)discovery") in the kernel source, to ensure proper state of the USB 3.0 hub port and proper USB mode negotiation during the initial USB device attachment and enumeration. These additional types of USB port resets don't exist for USB 2.0 hubs, according the USB 2.0 specification. The resets seem to be added to the USB 3.0 specification as part of the port and device mode negotiation. The Linux kernel resets USB 3.0 (i.e. SuperSpeed) hubs only, as visible in commit 10d674a82e55 ("USB: When hot reset for USB3 fails, try warm reset.") in the kernel source. The check for SuperSpeed hubs is performed in a way that also applies to newer SuperSpeed Plus (USB 3.1 or 3.2) hubs as well, which hopefully makes it future proof. Fixes: 33e06dcbe57a ("common: usb-hub: Reset hub port before scanning") Link: https://lore.kernel.org/u-boot/20240207102327.35125-1-i@shantur.com/T/#u Link: https://lore.kernel.org/u-boot/20240201164604.13315fa6@donnerap.manchester.arm.com/T/#u Signed-off-by: Shantur Rathore <i@shantur.com> Helped-by: Dragan Simic <dsimic@manjaro.org> Tested-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Dragan Simic <dsimic@manjaro.org> Reviewed-by: Marek Vasut <marex@denx.de>
-rw-r--r--common/usb_hub.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 3fb7e14..2e054eb 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -174,8 +174,10 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
debug("enabling power on all ports\n");
for (i = 0; i < dev->maxchild; i++) {
- usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_RESET);
- debug("Reset : port %d returns %lX\n", i + 1, dev->status);
+ if (usb_hub_is_superspeed(dev)) {
+ usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_RESET);
+ debug("Reset : port %d returns %lX\n", i + 1, dev->status);
+ }
usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
debug("PowerOn : port %d returns %lX\n", i + 1, dev->status);
}