Re: USB3: unable to enumerate, device not accepting address

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

 



Well, not everything as good as it seemed - upgrading JMS539 firmware
completely disabled eSATA port on docking station :( So that's another
reason to solve this issue inside Linux kernel.

On Thu, 6 Nov 2014 01:26:07 +0300
parafin <parafin@xxxxxxxx> wrote:

> Update to this issue:
> OS X has problems recognizing these devices as well - 10.9 managed to
> enumerate it after several attempts, but after upgrade to the latest
> release (10.10 Yosemite) OS X only sees these USB devices if they were
> connected before booting up (so same as Linux). Windows, of course, has
> no such problems (tested with Win 7 Pro).
> While googling about possible solutions for OS X, I found out that it
> is possible to upgrade firmware of JMS539 chipset inside these docking
> stations (of course the utility is Windows-only):
> http://www.station-drivers.com/index.php/downloads/Drivers/Jmicron/JMS539-Sata-USB-3.0-Controller/
> Firmware version all previous tests were done with is 255.00.06.00.14,
> I've updated it to the latest 255.31.3.41.22 and it solved enumeration
> problem on both Linux and OS X!
> I left old firmware on one of the devices so I still can test some
> patches. I'm not sure though if it is worth fixing now, in the light of
> what I wrote above, I would still say yes, because: first of all it
> won't be obvious that firmware upgrade is required (or that it's at
> all possible) for anyone else encountering this issue; secondly Windows
> is required to run firmware upgrade and not everyone has readily access
> to it; thirdly there might be other chipsets out there with same quirks
> and no available fixes; and finally it worked before, so it is a
> regression even though most likely it is the device who's doing the
> wrong thing.
> 
> On Wed, 5 Nov 2014 12:50:36 -0800
> Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> wrote:
> 
> > 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 <parafin@xxxxxxxx>
> > > To: <linux-usb@xxxxxxxxxxxxxxx>
> > > 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 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