Re: [PATCH v3 00/10] Just the essential port power control fixes for 3.14

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

 



On Tue, 2014-01-14 at 15:22 -0800, Sarah Sharp wrote:
> On Tue, Jan 07, 2014 at 12:29:28PM -0800, Dan Williams wrote:
> > Alan, Sarah,
> > 
> > This revision boils down the port power control fixes to the
> > bare minimum to get the implementation functional and reliable.
> > Data structure changes are constrained to struct usb_port and
> > gone are the clumsier attempts at wider reworks from v1 [1] and
> > v2 [2].  No device model changes to consider or changes to the
> > meaning of 'runtime_status' for port devices.  Three disconnect
> > bugs are fixed:
> > 
> > 1/ Superspeed devices downgrade to their hi-speed connection: fix this by
> >    preventing superspeed poweroff until the peer port is suspended.  See
> >    patch 5.
> 
> I've been testing these a bit, and run into some unexpected behavior.
> 
> First, just checking: what do you expect to happen if a USB 2.0 port has
> port power off enabled, but its peer USB 3.0 port has power off
> disabled?  I had expected that the port would remained powered on, but
> this does not seem to be what the code actually does.
> 
> Say I have one xHCI host that registers bus 1 (USB 2.0) and bus 2 (USB
> 3.0).  Port 1 on both buses are peer ports, and both ports have power
> off disabled.  Then I do the following:
> 
> 1. Plug in a USB mouse into the USB 2.0 port.
> 2. Enable port power off for the USB 2.0 port.
> 4. Enable suspend for the mouse.  Port should be prevented from being
>    powered off, since usbhid enables remote wakeup for the device, and
>    the port's runtime_status does reflect that it's active.
> 3. Unbind usbhid.
> 5. Check that the USB 2.0 port's runtime_status is 'suspended' while the
>    USB 3.0 port's runtime_status is 'active'.  (Note, at this point,
>    according to my assumption, the port should still be powered, but
>    it's not.)
> 6. Unplug the USB mouse.  No disconnect event observed.
> 7. Disable port power off for the USB 2.0 port.  Still no disconnect.
> 8. Run `sudo lsusb` and note that the mouse is still listed in lsusb
>    output.  Further, the sysfs directories are still there.  The device
>    remains even after running `sudo lsusb -v` (which should trigger a
>    get port status for the roothub, where the disconnect should be
>    noticed.
> 
> A command line history of that procedure is attached.
> 
> It seems like there needs to be a way to detect whether a USB device is
> really disconnected after the port is powered back on.  ISTR asking
> Tianyu to fix this, but I'm not sure if it ever did get fixed.

Actually, this appears to be behaving as intended.  The bug is in the
test, here:

    echo "1-1" >  usb1/1-0\:1.0/port1/device/driver/unbind

That unbinds the usb_device from the usb_generic_driver and removes the
ability of the usb core to resume the device.  Without that ability we
will never notice the disconnect since usb_resume() will hit:

        /* Can't resume it if it doesn't have a driver. */
        if (udev->dev.driver == NULL) {
                status = -ENOTCONN;
                goto done;
        }      

The documentation does cover this, but I think it can be more explicit
about the pitfalls and consequences.  I have folded in the following
change:

diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index 94230439fe9c..2ceea37d8fbc 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -587,7 +587,14 @@ suspended.
               
 Note, some interface devices/drivers do not support autosuspend.  Userspace may
 need to unbind the interface drivers before the usb_device will suspend.  An
-unbound interface device is suspended by default.
+unbound interface device is suspended by default.  When unbinding, be careful
+to unbind interface drivers, not the driver of the parent usb device.  Also,
+leave hub interface drivers bound.  If the driver for the usb device (not
+interface) is unbound the kernel is no longer able to resume the device.  If a
+hub interface driver is unbound, control of its child ports is lost and all
+attached child-devices will disconnect.  A good rule of thumb is that if the
+'driver/module' link for a device points to /sys/module/usbcore then unbinding
+it will interfere with port power control.
 
 Example of the relevant files for port power control.
 
@@ -599,7 +606,10 @@ Example of the relevant files for port power control.
 
      /sys/bus/devices/usb2/2-0:1.0/port1/power/pm_qos_no_power_off
      /sys/bus/devices/usb2/2-0:1.0/port1/device/power/control
-     /sys/bus/devices/usb2/2-0:1.0/port1/device/<intf>/driver/unbind
+     /sys/bus/devices/usb2/2-0:1.0/port1/device/2-1:<intf0>/driver/unbind
+     /sys/bus/devices/usb2/2-0:1.0/port1/device/2-1:<intf1>/driver/unbind
+     ...      
+     /sys/bus/devices/usb2/2-0:1.0/port1/device/2-1:<intfN>/driver/unbind
 
 In addition to these files some ports may have a 'peer' link to a port on
 another hub.  The expectation is that all superspeed ports have a

---

When the usb_device stays bound we do attempt recovery, fail, and
properly trigger a disconnect of the device as expected.

Question for Alan:  I'm thinking we need a hub_port_logical_disconnect()
when the usb_device becomes unbound.  Otherwise the port state will
remain stale until the next khubd event on that port.  I'll give it some
more thought, but curious what is the expected recovery from that state.

--
Dan





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