Re: [PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-02-13 Thread Bjorn Helgaas
On Sun, Feb 12, 2017 at 05:31:30PM +0100, Lukas Wunner wrote:
> On Sat, Jan 28, 2017 at 05:32:37PM -0600, Bjorn Helgaas wrote:
> > On Sun, Jan 15, 2017 at 09:03:45PM +0100, Lukas Wunner wrote:

> > > +#define pr_fmt(fmt) KBUILD_MODNAME " %s: " fmt, dev_name(dev)
> [...]
> > > + /* prevent interrupts during system sleep transition */
> > > + if (ACPI_FAILURE(acpi_disable_gpe(NULL, power->wake_gpe))) {
> > > + pr_err("cannot disable wake GPE, resuming\n");
> > 
> > Can you use dev_err() here and below?  This is related to a specific
> > device, and it'd be nice to know which one.
> 
> See above, the device name is included in pr_fmt.  The reason to use
> pr_err() instead of dev_err() is to get the error message prefixed
> with "thunderbolt" instead of "pcieport".  Recall that this function
> is executed in the context of the upstream bridge, whose driver name
> is pcieport.  I would like to prevent people from grepping the portdrv
> code for the error message.  You're the second person to raise this
> question (Andy Shevchenko made the same comment on an earlier version
> of this patch), so I've now added a comment to explain it.

Oh, right, I missed the sneaky dev_name(dev) in pr_fmt().  I guess we
may have a mix of "pcieport" and "thunderbolt" messages related to
the same device, which is sort of sub-optimal, but maybe the best we
can do for now.

Bjorn


Re: [PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-02-13 Thread Bjorn Helgaas
On Sun, Feb 12, 2017 at 05:31:30PM +0100, Lukas Wunner wrote:
> On Sat, Jan 28, 2017 at 05:32:37PM -0600, Bjorn Helgaas wrote:
> > On Sun, Jan 15, 2017 at 09:03:45PM +0100, Lukas Wunner wrote:

> > > +#define pr_fmt(fmt) KBUILD_MODNAME " %s: " fmt, dev_name(dev)
> [...]
> > > + /* prevent interrupts during system sleep transition */
> > > + if (ACPI_FAILURE(acpi_disable_gpe(NULL, power->wake_gpe))) {
> > > + pr_err("cannot disable wake GPE, resuming\n");
> > 
> > Can you use dev_err() here and below?  This is related to a specific
> > device, and it'd be nice to know which one.
> 
> See above, the device name is included in pr_fmt.  The reason to use
> pr_err() instead of dev_err() is to get the error message prefixed
> with "thunderbolt" instead of "pcieport".  Recall that this function
> is executed in the context of the upstream bridge, whose driver name
> is pcieport.  I would like to prevent people from grepping the portdrv
> code for the error message.  You're the second person to raise this
> question (Andy Shevchenko made the same comment on an earlier version
> of this patch), so I've now added a comment to explain it.

Oh, right, I missed the sneaky dev_name(dev) in pr_fmt().  I guess we
may have a mix of "pcieport" and "thunderbolt" messages related to
the same device, which is sort of sub-optimal, but maybe the best we
can do for now.

Bjorn


Re: [PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-02-12 Thread Lukas Wunner
On Sat, Jan 28, 2017 at 05:32:37PM -0600, Bjorn Helgaas wrote:
> On Sun, Jan 15, 2017 at 09:03:45PM +0100, Lukas Wunner wrote:
> > A Thunderbolt controller appears to the OS as a set of virtual devices:
> > One upstream bridge, multiple downstream bridges and one NHI (Native
> > Host Interface).  The upstream and downstream bridges represent a PCIe
> > switch (see definition of a switch in the PCIe spec).  The NHI device is
> > used to manage the switch fabric.  Hotplugged devices appear behind the
> > downstream bridges:
> > 
> >   (Root Port)  Upstream Bridge --+-- Downstream Bridge 0  NHI
> >  +-- Downstream Bridge 1 --
> >  +-- Downstream Bridge 2 --
> >  ...
> > 
> > Power is cut to the entire set of devices.  The Linux pm model is
> > hierarchical and assumes that a child cannot resume before its parent.
> > To conform to this model, power control must be governed by the
> > Thunderbolt controller's topmost device, which is the upstream bridge.
> > The NHI and downstream bridges go to D3hot independently and the
> > upstream bridge goes to D3cold once all its children have suspended.
> > This commit only adds runtime pm for the upstream bridge.  Runtime pm
> > for the NHI is added in a separate commit to signify its independence.
> > Runtime pm for the downstream bridges is handled by the pcieport driver.
> > 
> > Because Apple's ACPI methods are nonstandard, a struct dev_pm_domain is
> > used to override the PCI bus pm_ops.  The thunderbolt driver binds to
> 
> What are the default PCI bus pm_ops?  I looked briefly for it to see
> if there was some way to use hooks there instead of using
> dev_pm_domain_set() with its weird out-of-orderness.

The default PCI bus pm_ops are defined in drivers/pci/pci-driver.c as
struct dev_pm_ops pci_dev_pm_ops.

I did hook into those callbacks in an earlier version of this series
but it required more patches and more modifications to the PCI core
and PCIe port services driver to get Thunderbolt runpm to work:
https://www.spinics.net/lists/linux-pci/msg51158.html

Using dev_pm_domain_set() is the de facto standard to solve this,
vga_switcheroo does the same, that's why I settled on this approach.
(see drivers/gpu/vga/vga_switcheroo.c:vga_switcheroo_init_domain_pm_ops())


> I guess what you do in thunderbolt_power_init() is copy the upstream
> device's bus's ops, then override a few of them?  Seems like we then
> have the problem of keeping the Thunderbolt ones in sync with the
> generic ones, e.g., if something got added to the generic one,
> somebody should look at the Thunderbolt one to see if it's also need
> there?

Not a problem.  upstream_runtime_suspend() essentially does this:

// call pci_dev_pm_ops ->runtime_suspend hook:
ret = dev->bus->pm->runtime_suspend(dev);
// power down:
acpi_execute_simple_method(power->set, NULL, 0)
// enable wake interrupt:
acpi_enable_gpe(NULL, power->wake_gpe)

So any changes to the pci_dev_pm_ops are inherited.  Again,
vga_switcheroo does the same (see vga_switcheroo_runtime_suspend()).


> > +#define pr_fmt(fmt) KBUILD_MODNAME " %s: " fmt, dev_name(dev)
[...]
> > +   /* prevent interrupts during system sleep transition */
> > +   if (ACPI_FAILURE(acpi_disable_gpe(NULL, power->wake_gpe))) {
> > +   pr_err("cannot disable wake GPE, resuming\n");
> 
> Can you use dev_err() here and below?  This is related to a specific
> device, and it'd be nice to know which one.

See above, the device name is included in pr_fmt.  The reason to use
pr_err() instead of dev_err() is to get the error message prefixed
with "thunderbolt" instead of "pcieport".  Recall that this function
is executed in the context of the upstream bridge, whose driver name
is pcieport.  I would like to prevent people from grepping the portdrv
code for the error message.  You're the second person to raise this
question (Andy Shevchenko made the same comment on an earlier version
of this patch), so I've now added a comment to explain it.


> > +void thunderbolt_power_init(struct tb *tb)
> > +{
> > +   struct device *upstream_dev, *nhi_dev = >nhi->pdev->dev;
> > +   struct tb_power *power = NULL;
> 
> Unnecessary initialization.

Good point.

Thanks,

Lukas


Re: [PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-02-12 Thread Lukas Wunner
On Sat, Jan 28, 2017 at 05:32:37PM -0600, Bjorn Helgaas wrote:
> On Sun, Jan 15, 2017 at 09:03:45PM +0100, Lukas Wunner wrote:
> > A Thunderbolt controller appears to the OS as a set of virtual devices:
> > One upstream bridge, multiple downstream bridges and one NHI (Native
> > Host Interface).  The upstream and downstream bridges represent a PCIe
> > switch (see definition of a switch in the PCIe spec).  The NHI device is
> > used to manage the switch fabric.  Hotplugged devices appear behind the
> > downstream bridges:
> > 
> >   (Root Port)  Upstream Bridge --+-- Downstream Bridge 0  NHI
> >  +-- Downstream Bridge 1 --
> >  +-- Downstream Bridge 2 --
> >  ...
> > 
> > Power is cut to the entire set of devices.  The Linux pm model is
> > hierarchical and assumes that a child cannot resume before its parent.
> > To conform to this model, power control must be governed by the
> > Thunderbolt controller's topmost device, which is the upstream bridge.
> > The NHI and downstream bridges go to D3hot independently and the
> > upstream bridge goes to D3cold once all its children have suspended.
> > This commit only adds runtime pm for the upstream bridge.  Runtime pm
> > for the NHI is added in a separate commit to signify its independence.
> > Runtime pm for the downstream bridges is handled by the pcieport driver.
> > 
> > Because Apple's ACPI methods are nonstandard, a struct dev_pm_domain is
> > used to override the PCI bus pm_ops.  The thunderbolt driver binds to
> 
> What are the default PCI bus pm_ops?  I looked briefly for it to see
> if there was some way to use hooks there instead of using
> dev_pm_domain_set() with its weird out-of-orderness.

The default PCI bus pm_ops are defined in drivers/pci/pci-driver.c as
struct dev_pm_ops pci_dev_pm_ops.

I did hook into those callbacks in an earlier version of this series
but it required more patches and more modifications to the PCI core
and PCIe port services driver to get Thunderbolt runpm to work:
https://www.spinics.net/lists/linux-pci/msg51158.html

Using dev_pm_domain_set() is the de facto standard to solve this,
vga_switcheroo does the same, that's why I settled on this approach.
(see drivers/gpu/vga/vga_switcheroo.c:vga_switcheroo_init_domain_pm_ops())


> I guess what you do in thunderbolt_power_init() is copy the upstream
> device's bus's ops, then override a few of them?  Seems like we then
> have the problem of keeping the Thunderbolt ones in sync with the
> generic ones, e.g., if something got added to the generic one,
> somebody should look at the Thunderbolt one to see if it's also need
> there?

Not a problem.  upstream_runtime_suspend() essentially does this:

// call pci_dev_pm_ops ->runtime_suspend hook:
ret = dev->bus->pm->runtime_suspend(dev);
// power down:
acpi_execute_simple_method(power->set, NULL, 0)
// enable wake interrupt:
acpi_enable_gpe(NULL, power->wake_gpe)

So any changes to the pci_dev_pm_ops are inherited.  Again,
vga_switcheroo does the same (see vga_switcheroo_runtime_suspend()).


> > +#define pr_fmt(fmt) KBUILD_MODNAME " %s: " fmt, dev_name(dev)
[...]
> > +   /* prevent interrupts during system sleep transition */
> > +   if (ACPI_FAILURE(acpi_disable_gpe(NULL, power->wake_gpe))) {
> > +   pr_err("cannot disable wake GPE, resuming\n");
> 
> Can you use dev_err() here and below?  This is related to a specific
> device, and it'd be nice to know which one.

See above, the device name is included in pr_fmt.  The reason to use
pr_err() instead of dev_err() is to get the error message prefixed
with "thunderbolt" instead of "pcieport".  Recall that this function
is executed in the context of the upstream bridge, whose driver name
is pcieport.  I would like to prevent people from grepping the portdrv
code for the error message.  You're the second person to raise this
question (Andy Shevchenko made the same comment on an earlier version
of this patch), so I've now added a comment to explain it.


> > +void thunderbolt_power_init(struct tb *tb)
> > +{
> > +   struct device *upstream_dev, *nhi_dev = >nhi->pdev->dev;
> > +   struct tb_power *power = NULL;
> 
> Unnecessary initialization.

Good point.

Thanks,

Lukas


Re: [PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-01-28 Thread Bjorn Helgaas
On Sun, Jan 15, 2017 at 09:03:45PM +0100, Lukas Wunner wrote:
> Document and implement Apple's ACPI-based (but nonstandard) pm mechanism
> for Thunderbolt.  Briefly, an ACPI method provided by Apple is used to
> cut power to the controller.  A GPE is enabled while the controller is
> powered down which sideband-signals a plug event, whereupon we reinstate
> power using the ACPI method.
> 
> This saves 1.7 W on machines with a Light Ridge controller and is
> reported to save 4 W on Cactus Ridge 4C and Falcon Ridge 4C.  (I believe
> 4 W includes the bus power drawn by Apple's Gigabit Ethernet adapter.)
> It fixes (at least partially) a power regression introduced in 3.17 by
> commit 7bc5a2bad0b8 ("ACPI: Support _OSI("Darwin") correctly").
> 
> A Thunderbolt controller appears to the OS as a set of virtual devices:
> One upstream bridge, multiple downstream bridges and one NHI (Native
> Host Interface).  The upstream and downstream bridges represent a PCIe
> switch (see definition of a switch in the PCIe spec).  The NHI device is
> used to manage the switch fabric.  Hotplugged devices appear behind the
> downstream bridges:
> 
>   (Root Port)  Upstream Bridge --+-- Downstream Bridge 0  NHI
>  +-- Downstream Bridge 1 --
>  +-- Downstream Bridge 2 --
>  ...
> 
> Power is cut to the entire set of devices.  The Linux pm model is
> hierarchical and assumes that a child cannot resume before its parent.
> To conform to this model, power control must be governed by the
> Thunderbolt controller's topmost device, which is the upstream bridge.
> The NHI and downstream bridges go to D3hot independently and the
> upstream bridge goes to D3cold once all its children have suspended.
> This commit only adds runtime pm for the upstream bridge.  Runtime pm
> for the NHI is added in a separate commit to signify its independence.
> Runtime pm for the downstream bridges is handled by the pcieport driver.
> 
> Because Apple's ACPI methods are nonstandard, a struct dev_pm_domain is
> used to override the PCI bus pm_ops.  The thunderbolt driver binds to

What are the default PCI bus pm_ops?  I looked briefly for it to see
if there was some way to use hooks there instead of using
dev_pm_domain_set() with its weird out-of-orderness.

I guess what you do in thunderbolt_power_init() is copy the upstream
device's bus's ops, then override a few of them?  Seems like we then
have the problem of keeping the Thunderbolt ones in sync with the
generic ones, e.g., if something got added to the generic one,
somebody should look at the Thunderbolt one to see if it's also need
there?

A couple minor code comments below.

> the NHI, thus the dev_pm_domain is assigned to the upstream bridge when
> its grandchild ->probes and evicted when it ->removes.
> 
> There are no Thunderbolt specs publicly available from Intel or Apple,
> so I've included documentation to the extent that I was able to reverse-
> engineer things.  Documentation on the Go2Sx and Ok2Go2Sx pins is
> tentative as those are missing on my Light Ridge.  Apple only uses them
> on Cactus Ridge 4C.  Someone with such a controller needs to find out
> through experimentation if the documentation is accurate and amend it if
> necessary.
> 
> To maximize power saving, the controller utilizes the PM core's direct-
> complete procedure, i.e. it stays suspended during the system sleep
> process.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=92111
> Cc: Andreas Noever 
> Signed-off-by: Lukas Wunner 
> ---
>  drivers/thunderbolt/Kconfig  |   3 +-
>  drivers/thunderbolt/Makefile |   4 +-
>  drivers/thunderbolt/nhi.c|   3 +
>  drivers/thunderbolt/power.c  | 346 
> +++
>  drivers/thunderbolt/power.h  |  37 +
>  drivers/thunderbolt/tb.h |   2 +
>  6 files changed, 392 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/thunderbolt/power.c
>  create mode 100644 drivers/thunderbolt/power.h
> 
> diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig
> index d35db16aa43f..41625cf3f461 100644
> --- a/drivers/thunderbolt/Kconfig
> +++ b/drivers/thunderbolt/Kconfig
> @@ -1,9 +1,10 @@
>  menuconfig THUNDERBOLT
>   tristate "Thunderbolt support for Apple devices"
> - depends on PCI
> + depends on PCI && ACPI
>   depends on X86 || COMPILE_TEST
>   select APPLE_PROPERTIES if EFI_STUB && X86
>   select CRC32
> + select PM
>   help
> Cactus Ridge Thunderbolt Controller driver
> This driver is required if you want to hotplug Thunderbolt devices on
> diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
> index 5d1053cdfa54..b22082596c42 100644
> --- a/drivers/thunderbolt/Makefile
> +++ b/drivers/thunderbolt/Makefile
> @@ -1,3 +1,3 @@
>  obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
> -thunderbolt-objs := 

Re: [PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-01-28 Thread Bjorn Helgaas
On Sun, Jan 15, 2017 at 09:03:45PM +0100, Lukas Wunner wrote:
> Document and implement Apple's ACPI-based (but nonstandard) pm mechanism
> for Thunderbolt.  Briefly, an ACPI method provided by Apple is used to
> cut power to the controller.  A GPE is enabled while the controller is
> powered down which sideband-signals a plug event, whereupon we reinstate
> power using the ACPI method.
> 
> This saves 1.7 W on machines with a Light Ridge controller and is
> reported to save 4 W on Cactus Ridge 4C and Falcon Ridge 4C.  (I believe
> 4 W includes the bus power drawn by Apple's Gigabit Ethernet adapter.)
> It fixes (at least partially) a power regression introduced in 3.17 by
> commit 7bc5a2bad0b8 ("ACPI: Support _OSI("Darwin") correctly").
> 
> A Thunderbolt controller appears to the OS as a set of virtual devices:
> One upstream bridge, multiple downstream bridges and one NHI (Native
> Host Interface).  The upstream and downstream bridges represent a PCIe
> switch (see definition of a switch in the PCIe spec).  The NHI device is
> used to manage the switch fabric.  Hotplugged devices appear behind the
> downstream bridges:
> 
>   (Root Port)  Upstream Bridge --+-- Downstream Bridge 0  NHI
>  +-- Downstream Bridge 1 --
>  +-- Downstream Bridge 2 --
>  ...
> 
> Power is cut to the entire set of devices.  The Linux pm model is
> hierarchical and assumes that a child cannot resume before its parent.
> To conform to this model, power control must be governed by the
> Thunderbolt controller's topmost device, which is the upstream bridge.
> The NHI and downstream bridges go to D3hot independently and the
> upstream bridge goes to D3cold once all its children have suspended.
> This commit only adds runtime pm for the upstream bridge.  Runtime pm
> for the NHI is added in a separate commit to signify its independence.
> Runtime pm for the downstream bridges is handled by the pcieport driver.
> 
> Because Apple's ACPI methods are nonstandard, a struct dev_pm_domain is
> used to override the PCI bus pm_ops.  The thunderbolt driver binds to

What are the default PCI bus pm_ops?  I looked briefly for it to see
if there was some way to use hooks there instead of using
dev_pm_domain_set() with its weird out-of-orderness.

I guess what you do in thunderbolt_power_init() is copy the upstream
device's bus's ops, then override a few of them?  Seems like we then
have the problem of keeping the Thunderbolt ones in sync with the
generic ones, e.g., if something got added to the generic one,
somebody should look at the Thunderbolt one to see if it's also need
there?

A couple minor code comments below.

> the NHI, thus the dev_pm_domain is assigned to the upstream bridge when
> its grandchild ->probes and evicted when it ->removes.
> 
> There are no Thunderbolt specs publicly available from Intel or Apple,
> so I've included documentation to the extent that I was able to reverse-
> engineer things.  Documentation on the Go2Sx and Ok2Go2Sx pins is
> tentative as those are missing on my Light Ridge.  Apple only uses them
> on Cactus Ridge 4C.  Someone with such a controller needs to find out
> through experimentation if the documentation is accurate and amend it if
> necessary.
> 
> To maximize power saving, the controller utilizes the PM core's direct-
> complete procedure, i.e. it stays suspended during the system sleep
> process.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=92111
> Cc: Andreas Noever 
> Signed-off-by: Lukas Wunner 
> ---
>  drivers/thunderbolt/Kconfig  |   3 +-
>  drivers/thunderbolt/Makefile |   4 +-
>  drivers/thunderbolt/nhi.c|   3 +
>  drivers/thunderbolt/power.c  | 346 
> +++
>  drivers/thunderbolt/power.h  |  37 +
>  drivers/thunderbolt/tb.h |   2 +
>  6 files changed, 392 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/thunderbolt/power.c
>  create mode 100644 drivers/thunderbolt/power.h
> 
> diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig
> index d35db16aa43f..41625cf3f461 100644
> --- a/drivers/thunderbolt/Kconfig
> +++ b/drivers/thunderbolt/Kconfig
> @@ -1,9 +1,10 @@
>  menuconfig THUNDERBOLT
>   tristate "Thunderbolt support for Apple devices"
> - depends on PCI
> + depends on PCI && ACPI
>   depends on X86 || COMPILE_TEST
>   select APPLE_PROPERTIES if EFI_STUB && X86
>   select CRC32
> + select PM
>   help
> Cactus Ridge Thunderbolt Controller driver
> This driver is required if you want to hotplug Thunderbolt devices on
> diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
> index 5d1053cdfa54..b22082596c42 100644
> --- a/drivers/thunderbolt/Makefile
> +++ b/drivers/thunderbolt/Makefile
> @@ -1,3 +1,3 @@
>  obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
> -thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o 

[PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-01-15 Thread Lukas Wunner
Document and implement Apple's ACPI-based (but nonstandard) pm mechanism
for Thunderbolt.  Briefly, an ACPI method provided by Apple is used to
cut power to the controller.  A GPE is enabled while the controller is
powered down which sideband-signals a plug event, whereupon we reinstate
power using the ACPI method.

This saves 1.7 W on machines with a Light Ridge controller and is
reported to save 4 W on Cactus Ridge 4C and Falcon Ridge 4C.  (I believe
4 W includes the bus power drawn by Apple's Gigabit Ethernet adapter.)
It fixes (at least partially) a power regression introduced in 3.17 by
commit 7bc5a2bad0b8 ("ACPI: Support _OSI("Darwin") correctly").

A Thunderbolt controller appears to the OS as a set of virtual devices:
One upstream bridge, multiple downstream bridges and one NHI (Native
Host Interface).  The upstream and downstream bridges represent a PCIe
switch (see definition of a switch in the PCIe spec).  The NHI device is
used to manage the switch fabric.  Hotplugged devices appear behind the
downstream bridges:

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

Power is cut to the entire set of devices.  The Linux pm model is
hierarchical and assumes that a child cannot resume before its parent.
To conform to this model, power control must be governed by the
Thunderbolt controller's topmost device, which is the upstream bridge.
The NHI and downstream bridges go to D3hot independently and the
upstream bridge goes to D3cold once all its children have suspended.
This commit only adds runtime pm for the upstream bridge.  Runtime pm
for the NHI is added in a separate commit to signify its independence.
Runtime pm for the downstream bridges is handled by the pcieport driver.

Because Apple's ACPI methods are nonstandard, a struct dev_pm_domain is
used to override the PCI bus pm_ops.  The thunderbolt driver binds to
the NHI, thus the dev_pm_domain is assigned to the upstream bridge when
its grandchild ->probes and evicted when it ->removes.

There are no Thunderbolt specs publicly available from Intel or Apple,
so I've included documentation to the extent that I was able to reverse-
engineer things.  Documentation on the Go2Sx and Ok2Go2Sx pins is
tentative as those are missing on my Light Ridge.  Apple only uses them
on Cactus Ridge 4C.  Someone with such a controller needs to find out
through experimentation if the documentation is accurate and amend it if
necessary.

To maximize power saving, the controller utilizes the PM core's direct-
complete procedure, i.e. it stays suspended during the system sleep
process.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=92111
Cc: Andreas Noever 
Signed-off-by: Lukas Wunner 
---
 drivers/thunderbolt/Kconfig  |   3 +-
 drivers/thunderbolt/Makefile |   4 +-
 drivers/thunderbolt/nhi.c|   3 +
 drivers/thunderbolt/power.c  | 346 +++
 drivers/thunderbolt/power.h  |  37 +
 drivers/thunderbolt/tb.h |   2 +
 6 files changed, 392 insertions(+), 3 deletions(-)
 create mode 100644 drivers/thunderbolt/power.c
 create mode 100644 drivers/thunderbolt/power.h

diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig
index d35db16aa43f..41625cf3f461 100644
--- a/drivers/thunderbolt/Kconfig
+++ b/drivers/thunderbolt/Kconfig
@@ -1,9 +1,10 @@
 menuconfig THUNDERBOLT
tristate "Thunderbolt support for Apple devices"
-   depends on PCI
+   depends on PCI && ACPI
depends on X86 || COMPILE_TEST
select APPLE_PROPERTIES if EFI_STUB && X86
select CRC32
+   select PM
help
  Cactus Ridge Thunderbolt Controller driver
  This driver is required if you want to hotplug Thunderbolt devices on
diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
index 5d1053cdfa54..b22082596c42 100644
--- a/drivers/thunderbolt/Makefile
+++ b/drivers/thunderbolt/Makefile
@@ -1,3 +1,3 @@
 obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
-thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o 
eeprom.o
-
+thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o \
+   eeprom.o power.o
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index a8c20413dbda..88fb2fb8cf4e 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -605,6 +605,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
}
pci_set_drvdata(pdev, tb);
 
+   thunderbolt_power_init(tb);
+
return 0;
 }
 
@@ -612,6 +614,7 @@ static void nhi_remove(struct pci_dev *pdev)
 {
struct tb *tb = pci_get_drvdata(pdev);
struct tb_nhi *nhi = tb->nhi;
+   thunderbolt_power_fini(tb);
thunderbolt_shutdown_and_free(tb);
 

[PATCH v5 7/8] thunderbolt: Power down controller when idle

2017-01-15 Thread Lukas Wunner
Document and implement Apple's ACPI-based (but nonstandard) pm mechanism
for Thunderbolt.  Briefly, an ACPI method provided by Apple is used to
cut power to the controller.  A GPE is enabled while the controller is
powered down which sideband-signals a plug event, whereupon we reinstate
power using the ACPI method.

This saves 1.7 W on machines with a Light Ridge controller and is
reported to save 4 W on Cactus Ridge 4C and Falcon Ridge 4C.  (I believe
4 W includes the bus power drawn by Apple's Gigabit Ethernet adapter.)
It fixes (at least partially) a power regression introduced in 3.17 by
commit 7bc5a2bad0b8 ("ACPI: Support _OSI("Darwin") correctly").

A Thunderbolt controller appears to the OS as a set of virtual devices:
One upstream bridge, multiple downstream bridges and one NHI (Native
Host Interface).  The upstream and downstream bridges represent a PCIe
switch (see definition of a switch in the PCIe spec).  The NHI device is
used to manage the switch fabric.  Hotplugged devices appear behind the
downstream bridges:

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

Power is cut to the entire set of devices.  The Linux pm model is
hierarchical and assumes that a child cannot resume before its parent.
To conform to this model, power control must be governed by the
Thunderbolt controller's topmost device, which is the upstream bridge.
The NHI and downstream bridges go to D3hot independently and the
upstream bridge goes to D3cold once all its children have suspended.
This commit only adds runtime pm for the upstream bridge.  Runtime pm
for the NHI is added in a separate commit to signify its independence.
Runtime pm for the downstream bridges is handled by the pcieport driver.

Because Apple's ACPI methods are nonstandard, a struct dev_pm_domain is
used to override the PCI bus pm_ops.  The thunderbolt driver binds to
the NHI, thus the dev_pm_domain is assigned to the upstream bridge when
its grandchild ->probes and evicted when it ->removes.

There are no Thunderbolt specs publicly available from Intel or Apple,
so I've included documentation to the extent that I was able to reverse-
engineer things.  Documentation on the Go2Sx and Ok2Go2Sx pins is
tentative as those are missing on my Light Ridge.  Apple only uses them
on Cactus Ridge 4C.  Someone with such a controller needs to find out
through experimentation if the documentation is accurate and amend it if
necessary.

To maximize power saving, the controller utilizes the PM core's direct-
complete procedure, i.e. it stays suspended during the system sleep
process.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=92111
Cc: Andreas Noever 
Signed-off-by: Lukas Wunner 
---
 drivers/thunderbolt/Kconfig  |   3 +-
 drivers/thunderbolt/Makefile |   4 +-
 drivers/thunderbolt/nhi.c|   3 +
 drivers/thunderbolt/power.c  | 346 +++
 drivers/thunderbolt/power.h  |  37 +
 drivers/thunderbolt/tb.h |   2 +
 6 files changed, 392 insertions(+), 3 deletions(-)
 create mode 100644 drivers/thunderbolt/power.c
 create mode 100644 drivers/thunderbolt/power.h

diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig
index d35db16aa43f..41625cf3f461 100644
--- a/drivers/thunderbolt/Kconfig
+++ b/drivers/thunderbolt/Kconfig
@@ -1,9 +1,10 @@
 menuconfig THUNDERBOLT
tristate "Thunderbolt support for Apple devices"
-   depends on PCI
+   depends on PCI && ACPI
depends on X86 || COMPILE_TEST
select APPLE_PROPERTIES if EFI_STUB && X86
select CRC32
+   select PM
help
  Cactus Ridge Thunderbolt Controller driver
  This driver is required if you want to hotplug Thunderbolt devices on
diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile
index 5d1053cdfa54..b22082596c42 100644
--- a/drivers/thunderbolt/Makefile
+++ b/drivers/thunderbolt/Makefile
@@ -1,3 +1,3 @@
 obj-${CONFIG_THUNDERBOLT} := thunderbolt.o
-thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o 
eeprom.o
-
+thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o \
+   eeprom.o power.o
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index a8c20413dbda..88fb2fb8cf4e 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -605,6 +605,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
}
pci_set_drvdata(pdev, tb);
 
+   thunderbolt_power_init(tb);
+
return 0;
 }
 
@@ -612,6 +614,7 @@ static void nhi_remove(struct pci_dev *pdev)
 {
struct tb *tb = pci_get_drvdata(pdev);
struct tb_nhi *nhi = tb->nhi;
+   thunderbolt_power_fini(tb);
thunderbolt_shutdown_and_free(tb);
nhi_shutdown(nhi);
 }
diff --git