[PATCH v2 00/13] Runtime PM for Thunderbolt on Macs

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

 



This series powers Thunderbolt controllers on Macs down when nothing is
plugged in, saving 1.7 W on machines with a Light Ridge controller and
reportedly 4 W on Cactus Ridge 4C and Falcon Ridge 4C.

Briefly, a custom ACPI method provided by Apple is used to cut power to
the controller.  A GPE is enabled while the controller is powered down
which side-band signals a plug event, whereupon power is reinstated using
the ACPI method.  Note that even though this mechanism is ACPI-based,
it does not use _PSx methods and is thus entirely nonstandard.


A Thunderbolt controller appears to the OS as a set of PCI devices:  One
NHI (Native Host Interface) and multiple bridges.  Power is cut to the
entire set of devices:

  (Root Port) ---- Upstream Bridge --+-- Downstream Bridge 0 ---- NHI
                                     +-- Downstream Bridge 1 --
                                     +-- Downstream Bridge 2 --
                                     ...

v1 of this series shoehorned power control into the NHI driver.  This
violated the Linux pm model which assumes that a child cannot resume
before its parent. As seen above, the NHI is a child, so the child cut
power to the bridges above it.

v2 resolves this by positioning power control on the controller's
topmost device, which is the upstream bridge.  That is achieved by
binding to it as a Thunderbolt port service driver.  portdrv already
calls down to each service driver on ->suspend and ->resume and I
extended that scheme to further PM callbacks.  E.g. when the upstream
bridge is runtime suspended, portdrv invokes the ->runtime_suspend
callback of each attached service driver, and the Thunderbolt service
driver's callback in turn invokes the ACPI method to cut power to the
controller.


For such a nonstandard ACPI-based PM mechanism one would normally assign
a dev_pm_domain to the upstream bridge which overrides the PCI subsystem
PM callbacks.  But that's not an option here because dev_pm_domain_set()
can only be called during driver probe.  The driver is portdrv and
obviously loads earlier than the thunderbolt port service driver.
So one has to make do with the PCI subsystem PM callbacks.

The PCI core currently assumes that devices can only be put into D3cold
by the platform, i.e. using the standard ACPI _PSx methods.  I extended
the PCI core so that it can deal with devices which are put into D3cold
by the driver callbacks.  It turns out only two changes are needed to
make this work, and they are in patches [09/13] and [10/13].  Runtime
suspend works out of the box, but runtime resume tries to set the device
power state *before* invoking the driver callback, and this goes awry
since the device is still in D3cold.  I solved this by returning an error
in pci_raw_set_power_state() if the device's current_state is D3cold
(patch [09/13]).

Theoretically it would also be possible to patch the missing _PSx methods
into the ACPI namespace at runtime but I suspect it wouldn't be pretty:
I think I'd have to include pre-compiled AML methods in the kernel and
modify those blobs at runtime (adjust GPE number etc) before patching
them into the namespace.


To make direct-complete work for such non-platform-power-managed devices,
I also had to modify pci_target_state() (patch [10/13]).

Finally, I wanted to avoid the mandatory runtime resume after direct-
complete which was introduced by Rafael with 58a1fbbb2ee8 ("PM / PCI /
ACPI: Kick devices that might have been reset by firmware"), so I added
the possibility to opt out of it (patch [11/13]).


I've pushed these patches to GitHub where they can be reviewed more
comfortably with green/red highlighting:
https://github.com/l1k/linux/commits/thunderbolt_runpm_v2

For reference, here's a link to v1:
http://thread.gmane.org/gmane.linux.power-management.general/73197

Thanks in advance for your comments.

Lukas


Lukas Wunner (13):
  PCI: Recognize Thunderbolt devices
  PCI: Allow D3 for Thunderbolt ports
  PCI: Add Thunderbolt portdrv service type
  PCI: Generalize portdrv pm iterator
  PCI: Use portdrv pm iterator on further callbacks
  PCI: pciehp: Support runtime pm
  PCI: pciehp: Ignore interrupts during D3cold
  PCI: Allow runtime PM for Thunderbolt hotplug ports on Macs
  PCI: Do not write to PM control register while in D3cold
  PCI: Avoid going from D3cold to D3hot for system sleep
  PM / sleep: Allow opt-out from runtime resume after direct-complete
  thunderbolt: Support runtime pm on upstream bridge
  thunderbolt: Support runtime pm on NHI

 drivers/base/power/generic_ops.c  |   3 +-
 drivers/pci/hotplug/pciehp_ctrl.c |   9 +-
 drivers/pci/hotplug/pciehp_hpc.c  |   4 +
 drivers/pci/pci.c                 |  50 ++----
 drivers/pci/pci.h                 |   2 +
 drivers/pci/pcie/portdrv.h        |   6 +-
 drivers/pci/pcie/portdrv_core.c   |  47 +-----
 drivers/pci/pcie/portdrv_pci.c    |  88 ++++++++--
 drivers/pci/probe.c               |  17 ++
 drivers/thunderbolt/Kconfig       |   4 +-
 drivers/thunderbolt/Makefile      |   4 +-
 drivers/thunderbolt/nhi.c         |  32 +++-
 drivers/thunderbolt/switch.c      |   9 +
 drivers/thunderbolt/tb.c          |  13 ++
 drivers/thunderbolt/upstream.c    | 345 ++++++++++++++++++++++++++++++++++++++
 include/linux/pci.h               |   1 +
 include/linux/pcieport_if.h       |   7 +
 include/linux/pm.h                |   1 +
 18 files changed, 539 insertions(+), 103 deletions(-)
 create mode 100644 drivers/thunderbolt/upstream.c

-- 
2.8.1

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux