Re: problem with Roseweil eusb3 enclosure

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

 



On Thu, Nov 01, 2012 at 03:46:37PM -0400, Alan Stern wrote:
> On Thu, 1 Nov 2012, Sarah Sharp wrote:
> 
> > Alan, can you take a look at the patch and see what I can do in the case
> > where five warm port resets fail?  I think it's a pretty unlikely
> > scenario, but if you have a good solution, I'm all ears.
> 
> Hmmm.  Overall I'm not really sure about the logic in that routine.
> It would make more sense for the decision about whether to issue a warm 
> vs. a hot reset to be made by the caller.

Are you talking about this bit of code in hub_port_wait_reset?

                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, portstatus)) {
                                int ret;

                                if ((portchange & USB_PORT_STAT_C_CONNECTION))
                                        clear_port_feature(hub->hdev, port1,
                                                        USB_PORT_FEAT_C_CONNECTION);
                                if (portchange & USB_PORT_STAT_C_LINK_STATE)
                                        clear_port_feature(hub->hdev, port1,
                                                        USB_PORT_FEAT_C_PORT_LINK_STATE);
                                if (portchange & USB_PORT_STAT_C_RESET)
                                        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))
                                        clear_port_feature(hub->hdev, port1,
                                                        USB_PORT_FEAT_C_CONNECTION);
                                return ret;
                        }

If so, then yes, I agree that the decision to issue a warm reset should
probably be made in hub_port_reset() instead.

Actually, there's a couple other issues I see with warm reset.

First, under USB 3.0 hubs (and roothubs), a failed hot reset will
automatically move to a warm reset.  That means the warm reset change
bit can be set if we only asked for a hot reset.
hub_port_finish_reset() assumes that only the hot reset change bit needs
to be cleared if warm is false, but it may also need to clear the warm
reset change bit.  This needs to be fixed, or we can lose port status
change events.

Second, this bit of code in hub_port_finish_reset() looks wrong:

        case 0:
                if (!warm) {
                        struct usb_hcd *hcd;
                        /* TRSTRCY = 10 ms; plus some extra */
                        msleep(10 + 40);
                        update_devnum(udev, 0);
                        hcd = bus_to_hcd(udev->bus);
                        if (hcd->driver->reset_device) {
                                *status = hcd->driver->reset_device(hcd, udev);
                                if (*status < 0) {
                                        dev_err(&udev->dev, "Cannot reset "
                                                        "HCD device state\n");
                                        break;
                                }
                        }
                }

Why wouldn't we want to notify the xHCI driver that the device was reset
if we issued a warm reset?  Maybe that's due to the code in
hub_port_wait_reset() that initiates a warm reset when the normal reset
fails?  hub_port_finish_reset() would get called twice with the current
code structure, and I think this code snippet is trying to work around
the fact that we can only notify the xHC once that the device has been
reset.  Once the Reset Device command has completed, the xHC will move
its internal device state to Default, and subsequent Reset Device
commands will fail with a context error until the device is
re-addressed.

I'm actually not sure we even want to break on a Reset Device command
failure.  If we do, we never clear the port reset change bits (warm or
normal), which would cause port status change events to be lost.

> Anyway, if five resets in a row all fail then we should do our best to
> ignore the device.  Let the user unplug it and try again.  Will this
> patch do that?

I think the patch will leave the port in SS.Inactive (the old code would
too).  The port will stay in that state (even when a device is
connected) until either the USB core issues a warm port reset, or the
port is disabled.  But if we disable a SuperSpeed port, we don't get
connect events until we set the link state to RxDetect.  So there's
basically no way to get an automatic notification of a device connect
when the port goes into this state.

Can we set a timer to kick khubd after some amount of time (30 seconds?)
and make hub_events check for ports in SS.Inactive even if none of the
change bits are set?

Sarah Sharp
--
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