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 <para...@paraf.in> 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.sh...@linux.intel.com> 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 <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

Reply via email to