I'm no longer the USB 3.0 driver maintainer. Please work with Mathias Nyman to fix this issue.
Sarah Sharp On Fri, Oct 31, 2014 at 06:01:24PM +0300, parafin wrote: > Hi, > > it was suggested to me that since you are the author of offending > commit I should forward this email to you. Also see this bug: > https://bugzilla.kernel.org/show_bug.cgi?id=41752 > > Begin forwarded message: > > Date: Thu, 30 Oct 2014 22:56:29 +0300 > From: parafin <para...@paraf.in> > To: <linux-usb@vger.kernel.org> > Subject: USB3: unable to enumerate, device not accepting address > > > Hi, > > 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. > --- drivers/usb/core/hub.c.orig 2014-10-30 21:44:50.000746074 +0300 > +++ drivers/usb/core/hub.c 2014-10-30 22:12:01.561256025 +0300 > @@ -2664,56 +2664,95 @@ > if ((portstatus & USB_PORT_STAT_RESET)) > return -EBUSY; > > - if (hub_port_warm_reset_required(hub, port1, portstatus)) > - return -ENOTCONN; > - > - /* Device went away? */ > - if (!(portstatus & USB_PORT_STAT_CONNECTION)) > - return -ENOTCONN; > - > - /* bomb out completely if the connection bounced. A USB 3.0 > - * connection may bounce if multiple warm resets were issued, > - * but the device may have successfully re-connected. Ignore it. > + /* Some buggy devices require a warm reset to be issued even > + * when the port appears not to be connected. > */ > - if (!hub_is_superspeed(hub->hdev) && > - (portchange & USB_PORT_STAT_C_CONNECTION)) > - return -ENOTCONN; > - > - if (!(portstatus & USB_PORT_STAT_ENABLE)) > - return -EBUSY; > + if (!warm) { > + /* > + * Some buggy devices can cause an NEC host controller > + * to transition to the "Error" state after a hot port > + * reset. This will show up as the port state in > + * "Inactive", and the port may also report a > + * disconnect. Forcing a warm port reset seems to > make > + * the device work. > + * > + * See > https://bugzilla.kernel.org/show_bug.cgi?id=41752 > + */ > + if (hub_port_warm_reset_required(hub, port1, > portstatus)) { > + int ret; > + > + if ((portchange & USB_PORT_STAT_C_CONNECTION)) > + usb_clear_port_feature(hub->hdev, > port1, > + > USB_PORT_FEAT_C_CONNECTION); > + if (portchange & USB_PORT_STAT_C_LINK_STATE) > + usb_clear_port_feature(hub->hdev, > port1, > + > USB_PORT_FEAT_C_PORT_LINK_STATE); > + if (portchange & USB_PORT_STAT_C_RESET) > + usb_clear_port_feature(hub->hdev, > port1, > + > USB_PORT_FEAT_C_RESET); > + dev_dbg(hub->intfdev, "hot reset failed, warm > reset port %d\n", > + port1); > + ret = hub_port_reset(hub, port1, > + udev, HUB_BH_RESET_TIME, > + true); > + if ((portchange & USB_PORT_STAT_C_CONNECTION)) > + usb_clear_port_feature(hub->hdev, > port1, > + > USB_PORT_FEAT_C_CONNECTION); > + 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 ((portstatus & USB_PORT_STAT_ENABLE)) { > + if (!udev) > + return 0; > + > + 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; > + } > + } else { > + if (!(portstatus & USB_PORT_STAT_CONNECTION) || > + hub_port_warm_reset_required(hub, > port1, > + portstatus)) > + return -ENOTCONN; > > - if (!udev) > return 0; > - > - 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; > + } > + return -EBUSY; > } > > static void hub_port_finish_reset(struct usb_hub *hub, int port1, > - struct usb_device *udev, int *status) > + struct usb_device *udev, int *status, bool warm) > { > switch (*status) { > case 0: > - /* TRSTRCY = 10 ms; plus some extra */ > - msleep(10 + 40); > - if (udev) { > - struct usb_hcd *hcd = bus_to_hcd(udev->bus); > - > - update_devnum(udev, 0); > - /* The xHC may think the device is already reset, > - * so ignore the status. > - */ > - if (hcd->driver->reset_device) > - hcd->driver->reset_device(hcd, udev); > + if (!warm) { > + struct usb_hcd *hcd; > + /* TRSTRCY = 10 ms; plus some extra */ > + msleep(10 + 40); > + if (udev) { > + update_devnum(udev, 0); > + hcd = bus_to_hcd(udev->bus); > + /* The xHC may think the device is already > + * reset, so ignore the status. > + */ > + if (hcd->driver->reset_device) > + hcd->driver->reset_device(hcd, udev); > + } > } > /* FALL THROUGH */ > case -ENOTCONN: > @@ -2725,10 +2764,8 @@ > USB_PORT_FEAT_C_BH_PORT_RESET); > usb_clear_port_feature(hub->hdev, port1, > USB_PORT_FEAT_C_PORT_LINK_STATE); > - usb_clear_port_feature(hub->hdev, port1, > - USB_PORT_FEAT_C_CONNECTION); > } > - if (udev) > + if (!warm && udev) > usb_set_device_state(udev, *status > ? USB_STATE_NOTATTACHED > : USB_STATE_DEFAULT); > @@ -2789,34 +2826,10 @@ > status); > } > > - /* Check for disconnect or reset */ > + /* return on disconnect or reset */ > if (status == 0 || status == -ENOTCONN || status == -ENODEV) { > - hub_port_finish_reset(hub, port1, udev, &status); > - > - if (!hub_is_superspeed(hub->hdev)) > - goto done; > - > - /* > - * If a USB 3.0 device migrates from reset to an error > - * state, re-issue the warm reset. > - */ > - if (hub_port_status(hub, port1, > - &portstatus, &portchange) < 0) > - goto done; > - > - if (!hub_port_warm_reset_required(hub, port1, > - portstatus)) > - goto done; > - > - /* > - * If the port is in SS.Inactive or Compliance Mode, the > - * hot or warm reset failed. Try another warm reset. > - */ > - if (!warm) { > - dev_dbg(&port_dev->dev, > - "hot reset failed, warm > reset\n"); > - warm = true; > - } > + hub_port_finish_reset(hub, port1, udev, &status, > warm); > + goto done; > } > > dev_dbg(&port_dev->dev, -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html