Toggling port power currently leads to three unintended disconnect
scenarios that are addressed by this rework of port power recovery and
usb device resume:
1/ Superspeed devices downgrade to their hispeed connection when rx-detection
fails on the superspeed pins. Address this by preventing superspeed port
poweroff/suspension until the peer port is suspended. This depends on the
ability to identify peer ports (patches 2-5), and then patch 6 implements the
policy.
2/ khubd prematurely disconnects ports that are in the process of being
resumed or reset. After this series khubd will ignore ports in the
pm-runtime-suspended state (patch 10) and holds a new port status lock
to synchronize the port status changes of usb_port_{suspend|resume}
(patch 11).
3/ Superspeed devices fail to reconnect after a 2 second timeout This
event has two causes:
3.1/ Repeated {Set|Clear}PortFeature(PORT_POWER) toggles caused the
device to switch to its hispeed connection (perceived
instability of the superspeed connection). Address this by
arranging for the child device to be woken up when the parent
port resumes. (patch 12)
3.2/ Devices may require a warm reset when recovering the power
session. When the child device is woken up per above and the
port timed out on reconnect, force a warm-reset during the
child's reset-resume (patch 13).
Changes since v4 [1]:
Lots of updates thanks to Alan's thorough review, much appreciated Alan!
Relative diffstat:
7 files changed, 452 insertions(+), 347 deletions(-)
* Deleted "xhci: cancel in-flight resume requests when the port is
powered off" (patch 10 in v4). The new usb_wakeup_notification()
closes the failure window my tests were hitting.
* Patch 1: "usb: disable port power control if not supported in
wHubCharacteristics"
* Added to prevent port runtime power management from being
enabled if not supported by the hub.
* Patch 2: "usb: assign default peer ports for root hubs"
* peer_lock now covers both finding and linking peers
* Made find_default_peer() independent of the order shared_hcd is
registered
* Undid the device_initialize/device_register split
* Patch 4: "usb: find internal hub tier mismatch via acpi"
* Rewrote the recursive walk through the USB topology to be more
readable and safer with a recursion limit
* Added detail to the changelog
* Patch 5: "usb: sysfs link peer ports"
* Clarified the changelog
* Killed "do if" usage
* Patch 6: "usb: defer suspension of superspeed port while peer is powered"
* Cleaned up how the USB2 port holds a pm runtime reference on behalf
of the USB3 port
* Patch 8: "usb: usb3 ports do not support FEAT_C_ENABLE"
* Clarified the changelog
* Patch 9: "usb: refactor port handling in hub_events()"
* Refactored hub_port_connect_change() to split off the bottom portion
into a new hub_port_reconnect() routine that can be called without
the port status lock held at entry.
* Patch 10: "usb: synchronize port poweroff and khubd"
* Moved pm runtime synchronization outside of port_event() to prevent
needing to re-read portstatus
* Patch 11: "usb: introduce port status lock"
* Clarified the changelog
* Pushed usb_lock_device() into usb_remote_wakeup()
* Sparse annotations
* Take usb_lock_port() around usb_reset_and_verify_device()
* Killed hub->busy_bits
* Killed hub_port_connect_change_unlock() in favor of introducing
hub_port_reconnect() called without the port lock held.
* Patch 12: "usb: resume (wakeup) child device when port is powered on"
* Clarified the changelog
* Repurposed usb_wakeup_notification() and wakeup_change for handling
these child device resume requests.
* Patch 13: "usb: force warm reset to break link re-connect livelock"
* Clarified the changelog
* Made the warm-reset request unconditional. If re-connect times out a
warm-reset is the last stop before force disconnecting the device.
* Patch 14: "usb: documentation for usb port power off mechanisms"
* Clarified that port power control will be disabled when the hub does
not advertise port power control capabilities.
* Patch 15 / 16 (New and optional)
* This is a RFC implementation of the mechanism Alan and I discussed to
close the window of rpm_suspend() event occurring while we are still
resolving tier mismatch [2]. RFC-only due to the locking horror in
hub_quiesce() this causes.
[1]: v4: http://marc.info/?l=linux-usb&m=139121878519367&w=2
[2]: http://marc.info/?l=linux-usb&m=139180783415065&w=2
---
[PATCH v5 01/16] usb: disable port power control if not supported in
wHubCharacteristics
[PATCH v5 02/16] usb: assign default peer ports for root hubs
[PATCH v5 03/16] usb: assign usb3 external hub port peers
[PATCH v5 04/16] usb: find internal hub tier mismatch via acpi
[PATCH v5 05/16] usb: sysfs link peer ports
[PATCH v5 06/16] usb: defer suspension of superspeed port while peer is powered
[PATCH v5 07/16] usb: don't clear FEAT_C_ENABLE on usb_port_runtime_resume
failure
[PATCH v5 08/16] usb: usb3 ports do not support FEAT_C_ENABLE
[PATCH v5 09/16] usb: refactor port handling in hub_events()
[PATCH v5 10/16] usb: synchronize port poweroff and khubd
[PATCH v5 11/16] usb: introduce port status lock
[PATCH v5 12/16] usb: resume (wakeup) child device when port is powered on
[PATCH v5 13/16] usb: force warm reset to break link re-connect livelock
[PATCH v5 14/16] usb: documentation for usb port power off mechanisms
[PATCH v5 15/16] usb: convert khubd to a workqueue
[RFC PATCH v5 16/16] usb, xhci: flush initial hub discovery to gate port power
control
Documentation/usb/power-management.txt | 237 ++++++++++
drivers/usb/core/hcd.c | 3
drivers/usb/core/hub.c | 743 ++++++++++++++++++--------------
drivers/usb/core/hub.h | 35 +-
drivers/usb/core/port.c | 391 ++++++++++++++++-
drivers/usb/core/usb-acpi.c | 35 +-
drivers/usb/core/usb.h | 8
drivers/usb/host/xhci-pci.c | 5
drivers/usb/host/xhci-plat.c | 4
drivers/usb/host/xhci.c | 10
drivers/usb/host/xhci.h | 5
include/linux/device.h | 5
include/linux/usb.h | 1
include/linux/usb/hcd.h | 3
14 files changed, 1113 insertions(+), 372 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html