Bug 41752
Summary: | [PATCH]USB 3.0 port does not recognize external disk | ||
---|---|---|---|
Product: | Drivers | Reporter: | Harald Brennich (harald.brennich) |
Component: | USB | Assignee: | XHCI bugs virtual user (xhci) |
Status: | REOPENED --- | ||
Severity: | normal | CC: | alan, florian, greg, help, szg00000 |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
URL: | http://download.opensuse.org/repositories/Kernel:/vanilla/standard/x86_64/ | ||
Kernel Version: | 3.1.0-rc3-1-vanilla | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
dmesg when trying to connect the disk
The original dmesg unzipped Patch to try warm reset if USB3 port reports a disconnect & inactive link state. /var/log/messages when the patch is applied (gzipped) Make USB 3.0 work on L755D notebook 0002-USB-When-hot-reset-for-USB3-fails-try-warm-reset.patch Make_USB3.0_port_work_with_L755D_notebook.patch revert of beabe20445c60322719d8f58e9eb9dd4660c1b3e for 3.17.1 |
After adding some trace statements to the source (linux-3.1.0-rc3-1-vanilla/drivers/usb/core/hub.c) I found the reason for the failure in function hub_port_reset. Either the Logilink USB 3.0 to SATA HDD Adapter or the NEC Corporation uPD720200 USB 3.0 Host Controller responds to this request by changing the pair status/status change from 0x203/0x1 to 0x2c0/0x51. To this the function hub_port_wait_reset responds with the error code -ENOTCONN. By modifying function hub_port_wait_reset from /* Device went away? */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; /* bomb out completely if the connection bounced */ if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; to if (hub->hdev->descriptor.bcdUSB != 0x300) { /* Device went away? */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; /* bomb out completely if the connection bounced */ if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; } else { if (!(portstatus & USB_PORT_STAT_CONNECTION) && !(portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; } I got the disk to run. Timing measured with hdparm is as following: The internal disk: Timing buffered disk reads: 228 MB in 3.04 seconds = 75.02 MB/sec The external disk connected via USB 3.0: Timing buffered disk reads: 172 MB in 3.02 seconds = 56.93 MB/sec The external disk connected via USB 2.0: Timing buffered disk reads: 94 MB in 3.01 seconds = 31.24 MB/sec So the hack seems to work at least partially. There remain two open points: Firstly, I do not know whether there is a firmware bug or a programming bug, though the problem probably is with the firmware. Secondly, when the disk is disconnected from the USB 3.0 port, the entry in /dev remains. When the disk is disconnected from the USB 2.0 port, the corresponding /dev/entry disappears. That's not a feasible fix, because it won't ever allow your device to disconnect (as you noticed when the /dev entry didn't go away). Can you please try updating the firmware on your NEC host controller first? We've had some issues with devices not being able to connect (or at least not connect at high speed) that were fixed with a firmware upgrade. I'll have a look at your dmesg output in the mean time. Your dmesg is completely garbled (lots of unicode characters? Did you upload an executable?). Can you re-upload it? Created attachment 71522 [details]
The original dmesg unzipped
Do not consider the code modification as a fix, but as a hack. I am simply trying to find out why the USB 3.0 port does not work with Linux. With Windows 7, the disk is detected (and shown in the Windows Explorer) on connecting to the port and removed from the Windows Explorer when disconnecting from the port, so the USB 3.0 port seems to conform to USB 3.0 specs to a certain degree. As to updating the firmware: I do not even find the controller on the NEC site. Also, Windows gives the controller another product name (I took the name from lspci). Lastly, I don't even know how to upgrade controller firmware :(. Finally, the hack may prevent the external disk from properly disconnecting. However, I think some trace of a disconnecting event should be found in dmesg. But there is nada - no call to hub_irq, no call of hub_events .. simply nothing. Hello Sarah, the current implementation of function hub_port_wait_reset returns -ENOTCONN even during the ongoing reset. I propose to ignore changes of connection state during reset. So instead of static int hub_port_wait_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay) { int delay_time, ret; u16 portstatus; u16 portchange; for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay) { /* wait to give the device a chance to reset */ msleep(delay); /* read and decode port status */ ret = hub_port_status(hub, port1, &portstatus, &portchange); if (ret < 0) return ret; /* Device went away? */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; /* bomb out completely if the connection bounced */ if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; /* if we`ve finished resetting, then break out of the loop */ if (!(portstatus & USB_PORT_STAT_RESET) && (portstatus & USB_PORT_STAT_ENABLE)) { if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; else if (hub_is_superspeed(hub->hdev)) udev->speed = USB_SPEED_SUPER; else if (portstatus & USB_PORT_STAT_HIGH_SPEED) udev->speed = USB_SPEED_HIGH; else if (portstatus & USB_PORT_STAT_LOW_SPEED) udev->speed = USB_SPEED_LOW; else udev->speed = USB_SPEED_FULL; return 0; } /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; dev_dbg (hub->intfdev, "port %d not reset yet, waiting %dms\n", port1, delay); } return -EBUSY; } the following implementation: static int hub_port_wait_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay) { int delay_time, ret; u16 portstatus; u16 portchange; for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay) { /* wait to give the device a chance to reset */ msleep(delay); /* read and decode port status */ ret = hub_port_status(hub, port1, &portstatus, &portchange); if (ret < 0) return ret; /* if we`ve finished resetting, then break out of the loop */ if (!(portstatus & USB_PORT_STAT_RESET) && (portstatus & USB_PORT_STAT_ENABLE)) { /* Device went away? */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; else if (hub_is_superspeed(hub->hdev)) udev->speed = USB_SPEED_SUPER; else if (portstatus & USB_PORT_STAT_HIGH_SPEED) udev->speed = USB_SPEED_HIGH; else if (portstatus & USB_PORT_STAT_LOW_SPEED) udev->speed = USB_SPEED_LOW; else udev->speed = USB_SPEED_FULL; return 0; } /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; dev_dbg (hub->intfdev, "port %d not reset yet, waiting %dms\n", port1, delay); } /* Device went away? */ if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; /* bomb out completely if the connection bounced */ if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; return -EBUSY; } This allows devices to report a disconnect during reset. Or is there something in the USB specs that prohibits this handling of feature RESET? Here's what I think is happening: [ 681.859162] xhci_hcd 0000:08:00.0: Port Status Change Event for port 1 ... [ 681.978459] xhci_hcd 0000:08:00.0: get port status, actual port 0 status = 0x1203 # The SuperSpeed device shows up fine, port status = enabled, CSC, U0 state, powered, superspeed # slot ID is allocated [ 681.978690] xhci_hcd 0000:08:00.0: set port reset, actual port 0 status = 0x1311 # port status = CSC, disabled, port in reset, recovery, powered, superspeed # (Not sure why the port is disabled here.) [ 681.978700] xhci_hcd 0000:08:00.0: Port Status Change Event for port 1 [ 682.034421] xhci_hcd 0000:08:00.0: get port status, actual port 0 status = 0x6202c0 # status = disconnected, disabled, no reset in progress, inactive link state, powered, unknown speed, connect status change I think the hot port reset failed here, and we need to do a warm port reset. This is what usually needs to be done when the port link state is in the inactive state. The host controller is supposed to try warm port reset if hot reset fails, but it's possible your host controller does not, or it's possible your host controller is in the middle of an automatic warm port reset when we read the port status register. In any case, I'll whip up a patch to start a warm port reset when the SuperSpeed device state is in inactive and the device is disconnected. Created attachment 71772 [details]
Patch to try warm reset if USB3 port reports a disconnect & inactive link state.
Harald, please try out this patch.
Created attachment 71782 [details]
/var/log/messages when the patch is applied (gzipped)
Hello Sarah, The suggested patch does not work for my USB 3.0. hub_port_wait_reset does not return an error, but the hub still doesn't work. The disk was plugged in at 20:18:26. Maybe the problem is now Sep 6 20:18:27 HATOSH kernel: [ 88.503250] usb 4-1: Device not responding to set address. Sep 6 20:18:27 HATOSH kernel: [ 88.706747] usb 4-1: device not accepting address 4, error -71 A patch referencing this bug report has been merged in Linux v3.2-rc1: commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 Author: Sarah Sharp <sarah.a.sharp@linux.intel.com> Date: Wed Sep 14 14:24:52 2011 -0700 USB: When hot reset for USB3 fails, try warm reset. My USB3.0 port with kernel 3.2.0-rc1-286-gd291ffb-1-vanilla and later now works out of the box. Status can be set to resolved. A patch referencing a commit referencing this bug report has been merged in Linux v3.5-rc7: commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 Author: Stanislaw Ledwon <staszek.ledwon@linux.jf.intel.com> Date: Mon Jun 18 15:20:00 2012 +0200 usb: Add support for root hub port status CAS A patch referencing a commit referencing this bug report has been merged in Linux v3.6-rc6: commit 71c731a296f1b08a3724bd1b514b64f1bda87a23 Author: Alexis R. Cortes <alexis.cortes@ti.com> Date: Fri Aug 3 14:00:27 2012 -0500 usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware A patch referencing a commit referencing this bug report has been merged in Linux v3.7-rc1: commit 457a73d346187c2cc5d599072f38676f18f130e0 Author: Vivek Gautam <gautam.vivek@samsung.com> Date: Sat Sep 22 18:11:19 2012 +0530 usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems A patch referencing a commit referencing this bug report has been merged in Linux v3.8-rc1: commit b0e4e606ff6ff26da0f60826e75577b56ba4e463 Author: Alexis R. Cortes <alexis.cortes@ti.com> Date: Thu Nov 8 16:59:27 2012 -0600 usb: host: xhci: Stricter conditional for Z1 system models for Compliance Mode Patch Created attachment 117161 [details]
Make USB 3.0 work on L755D notebook
For the newer kernels supplied by openSuse, my USB 3.0 device again is not recognised.
Tested kernel versions are
3.4.63-2.44-desktop
3.7.10-1.16-desktop
3.11.6-4-desktop
3.13.0-rc2-1-gaf91706-1-vanilla
Taking the patch
"USB: When hot reset for USB3 fails, try warm reset." from Date: Tue, 6 Sep 2011 09:53:01 -0700 with some modification to take account of changes in the hub.c source code, I made a patch that makes my USB 3.0 portwork again.
It has been tested with openSuse3.11.6-4-vanilla.
Please note that I do not know
- what I am really doing
- why the patch is working
- whether the code in the patch ever was part of hub.c, and if so why it was dropped
- what side effects the code may have
All that I know is that it works.
Harald: The upstream kernel has the commit you mentioned (commit 10d674a82e55 "USB: When hot reset for USB3 fails, try warm reset."). When you tested 3.13.0-rc2-1-gaf91706-1-vanilla, the kernel should have had that patch. Did 3.13-rc2 fail as well? Can you point me to a URL for the patch you modified? And post the modified patch that fixes your system? Created attachment 117201 [details] 0002-USB-When-hot-reset-for-USB3-fails-try-warm-reset.patch Sarah, I think You mailed me the original patch (attachment 0002-USB-When-hot-reset....). My modification is in attachment Make_USB3.0_port_work... I have not tried 3.13-rc2 from kernel.org, only the version openSuse offers (3.13.0-rc2-1-gaf91706-1-vanilla). However I also tried a 3.12 kernel direct from kernel.org, that did not work either. To me it looks like your patch got lost somewhere in the later 3.4.x versions, maybe in 3.4.63. Am 02.12.2013, 19:10 Uhr, schrieb <bugzilla-daemon@bugzilla.kernel.org>: > https://bugzilla.kernel.org/show_bug.cgi?id=41752 > > --- Comment #18 from Sarah Sharp <sarah.a.sharp@linux.intel.com> --- > Harald: > > The upstream kernel has the commit you mentioned (commit 10d674a82e55 > "USB: > When hot reset for USB3 fails, try warm reset."). When you tested > 3.13.0-rc2-1-gaf91706-1-vanilla, the kernel should have had that patch. > Did > 3.13-rc2 fail as well? > > Can you point me to a URL for the patch you modified? And post the > modified > patch that fixes your system? > Created attachment 117211 [details]
Make_USB3.0_port_work_with_L755D_notebook.patch
I have diffed drivers/usb/core/hub.c for versions 3.12 and 3.13-rc2 from kernel.org and 3.11.6-4-vanilla from openSuse and none of these have the special treatment for (!warm) in hub_port_warm_reset_required that was in the patch from Sarah. Created attachment 155891 [details] revert of beabe20445c60322719d8f58e9eb9dd4660c1b3e for 3.17.1 I just posted to linux-usb mailing list about the issue which I think is the same as this one, I'm gonna copy it here: I have 2 very similar USB3 devices that stopped working sometime after kernel version 3.3 - they fail to enumerate unless I reload xhci_hcd driver. These are the devices: http://www.agestar.com/en/Products/Docking-Station/USB3-0/974-usb30esata-to-2535-sata-hdd-docking-station.html http://www.agestar.com/en/Products/Docking-Station/USB3-0/980-usb30esata-to-2535-sata-hdd-docking-station.html Basically it's some eSATA->USB3 bridge JMicron chip (I'm guessing it's the same one in both devices): Bus 009 Device 002: ID 152d:2509 JMicron Technology Corp. / JMicron USA Technology Corp. JMS539 SuperSpeed SATA II 3.0G Bridge This is USB controller I am testing them with: 01:00.0 USB controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 03) I even tried upgrading firmware, with no result It appears in system as 2 buses (lsusb -t output): /: Bus 09.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M /: Bus 08.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M One for SuperSpeed devices, another for slower. So here's dmesg for when it fails: [ 195.207408] hub 8-0:1.0: unable to enumerate USB device on port 1 [ 196.016556] usb 9-1: device not accepting address 2, error -22 [ 196.520572] hub 9-0:1.0: unable to enumerate USB device on port 1 And here how it should look (when it works): [ 61.686218] hub 8-0:1.0: unable to enumerate USB device on port 1 [ 63.620211] usb 9-1: new SuperSpeed USB device number 2 using xhci_hcd [ 63.636918] usb 9-1: New USB device found, idVendor=152d, idProduct=2509 [ 63.636932] usb 9-1: New USB device strings: Mfr=1, Product=11, SerialNumber=3 [ 63.636942] usb 9-1: Product: Usb production [ 63.636950] usb 9-1: Manufacturer: JMicron [ 63.636956] usb 9-1: SerialNumber: 00A1234578EA [ 63.638549] scsi5 : usb-storage 9-1:1.0 [ 64.926983] scsi 5:0:0:0: Direct-Access Jmicron Corp. 0000 PQ: 0 ANSI: 5 [ 64.927925] sd 5:0:0:0: Attached scsi generic sg6 type 0 [ 64.929912] sd 5:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16). [ 64.930353] sd 5:0:0:0: [sdg] 5860533168 512-byte logical blocks: (3.00 TB/2.72 TiB) [ 64.931031] sd 5:0:0:0: [sdg] Write Protect is off [ 64.931042] sd 5:0:0:0: [sdg] Mode Sense: 28 00 00 00 [ 64.931764] sd 5:0:0:0: [sdg] No Caching mode page present [ 64.931772] sd 5:0:0:0: [sdg] Assuming drive cache: write through [ 64.932486] sd 5:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16). [ 64.933992] sd 5:0:0:0: [sdg] No Caching mode page present [ 64.933997] sd 5:0:0:0: [sdg] Assuming drive cache: write through [ 64.989015] sdg: sdg1 sdg2 sdg3 sdg4 [ 64.992112] sd 5:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16). [ 64.993885] sd 5:0:0:0: [sdg] No Caching mode page present [ 64.993898] sd 5:0:0:0: [sdg] Assuming drive cache: write through [ 64.993909] sd 5:0:0:0: [sdg] Attached SCSI disk First line doesn't always appear, might depend on kernel version, I'm not sure. I managed to bisect this down to this commit: beabe20445c60322719d8f58e9eb9dd4660c1b3e (it's from 3.4 branch, included in 3.4.36 release, upstream commit id from commit message seems to be invalid, at least it's missing one character). I backported reverse of this commit to 3.17.1 (I can't run 3.4 kernel due to different issues) and it helps with this issue. Patch attached in case it is helpful, sorry though for whitespace mess, I used nano:) I doubt that just reverting is acceptable solution for mainstream kernel, so I'm willing to test some other patches (on top of 3.17.1 would be best) or provide additional information so that this issue could be fixed in next releases. Kernel 3.16.6 still has this bug. The patch Make_USB3.0_port_work_with_L755D_notebook.patch still fixes this bug. Some new resultsfor USB 3.0 and suspend/resume with openSuse 13.2 : Kernel 3.16.7-32-desktop: USB 3.0 and suspend/resume work out of the box Kernel 3.16.7-32-vanilla: USB 3.0 doesn't work, external monitor connected via HDMI stays black after resume from suspend (see https://bugzilla.kernel.org/show_bug.cgi?id=88541) |
Created attachment 70272 [details] dmesg when trying to connect the disk Hardware: Toshiba Satellite L755 USB: 08:00.0 USB Controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 04) Peripherals: Logilink USB 3.0 to SATA HDD Adapter with Western Digital WD2500JS When the external disk is connected to a USB 2.0 port, it is detected and can be mounted. When it is connected to the USB 3.0 port, the drive starts spinning and there are entries in dmesg, but the external disk cannot be mounted.