Skip to content

Commit

Permalink
Merge tag 'pm+acpi-4.1-rc1' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/rafael/linux-pm

Pull power management and ACPI updates from Rafael Wysocki:
 "These are mostly fixes and cleanups all over, although there are a few
  items that sort of fall into the new feature category.

  First off, we have new callbacks for PM domains that should help us to
  handle some issues related to device initialization in a better way.

  There also is some consolidation in the unified device properties API
  area allowing us to use that inferface for accessing data coming from
  platform initialization code in addition to firmware-provided data.

  We have some new device/CPU IDs in a few drivers, support for new
  chips and a new cpufreq driver too.

  Specifics:

   - Generic PM domains support update including new PM domain callbacks
     to handle device initialization better (Russell King, Rafael J
     Wysocki, Kevin Hilman)

   - Unified device properties API update including a new mechanism for
     accessing data provided by platform initialization code (Rafael J
     Wysocki, Adrian Hunter)

   - ARM cpuidle update including ARM32/ARM64 handling consolidation
     (Daniel Lezcano)

   - intel_idle update including support for the Silvermont Core in the
     Baytrail SOC and for the Airmont Core in the Cherrytrail and
     Braswell SOCs (Len Brown, Mathias Krause)

   - New cpufreq driver for Hisilicon ACPU (Leo Yan)

   - intel_pstate update including support for the Knights Landing chip
     (Dasaratharaman Chandramouli, Kristen Carlson Accardi)

   - QorIQ cpufreq driver update (Tang Yuantian, Arnd Bergmann)

   - powernv cpufreq driver update (Shilpasri G Bhat)

   - devfreq update including Tegra support changes (Tomeu Vizoso,
     MyungJoo Ham, Chanwoo Choi)

   - powercap RAPL (Running-Average Power Limit) driver update including
     support for Intel Broadwell server chips (Jacob Pan, Mathias Krause)

   - ACPI device enumeration update related to the handling of the
     special PRP0001 device ID allowing DT-style 'compatible' property
     to be used for ACPI device identification (Rafael J Wysocki)

   - ACPI EC driver update including limited _DEP support (Lan Tianyu,
     Lv Zheng)

   - ACPI backlight driver update including a new mechanism to allow
     native backlight handling to be forced on non-Windows 8 systems and
     a new quirk for Lenovo Ideapad Z570 (Aaron Lu, Hans de Goede)

   - New Windows Vista compatibility quirk for Sony VGN-SR19XN (Chen Yu)

   - Assorted ACPI fixes and cleanups (Aaron Lu, Martin Kepplinger,
     Masanari Iida, Mika Westerberg, Nan Li, Rafael J Wysocki)

   - Fixes related to suspend-to-idle for the iTCO watchdog driver and
     the ACPI core system suspend/resume code (Rafael J Wysocki, Chen Yu)

   - PM tracing support for the suspend phase of system suspend/resume
     transitions (Zhonghui Fu)

   - Configurable delay for the system suspend/resume testing facility
     (Brian Norris)

   - PNP subsystem cleanups (Peter Huewe, Rafael J Wysocki)"

* tag 'pm+acpi-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (74 commits)
  ACPI / scan: Fix NULL pointer dereference in acpi_companion_match()
  ACPI / scan: Rework modalias creation when "compatible" is present
  intel_idle: mark cpu id array as __initconst
  powercap / RAPL: mark rapl_ids array as __initconst
  powercap / RAPL: add ID for Broadwell server
  intel_pstate: Knights Landing support
  intel_pstate: remove MSR test
  cpufreq: fix qoriq uniprocessor build
  ACPI / scan: Take the PRP0001 position in the list of IDs into account
  ACPI / scan: Simplify acpi_match_device()
  ACPI / scan: Generalize of_compatible matching
  device property: Introduce firmware node type for platform data
  device property: Make it possible to use secondary firmware nodes
  PM / watchdog: iTCO: stop watchdog during system suspend
  cpufreq: hisilicon: add acpu driver
  ACPI / EC: Call acpi_walk_dep_device_list() after installing EC opregion handler
  cpufreq: powernv: Report cpu frequency throttling
  intel_idle: Add support for the Airmont Core in the Cherrytrail and Braswell SOCs
  intel_idle: Update support for Silvermont Core in Baytrail SOC
  PM / devfreq: tegra: Register governor on module init
  ...
  • Loading branch information
torvalds committed Apr 15, 2015
2 parents 8691c13 + 518b4e2 commit 2481bc7
Show file tree
Hide file tree
Showing 96 changed files with 1,797 additions and 928 deletions.
26 changes: 23 additions & 3 deletions Documentation/acpi/enumeration.txt
Expand Up @@ -254,8 +254,13 @@ GPIO support
~~~~~~~~~~~~
ACPI 5 introduced two new resources to describe GPIO connections: GpioIo
and GpioInt. These resources are used be used to pass GPIO numbers used by
the device to the driver. For example:
the device to the driver. ACPI 5.1 extended this with _DSD (Device
Specific Data) which made it possible to name the GPIOs among other things.

For example:

Device (DEV)
{
Method (_CRS, 0, NotSerialized)
{
Name (SBUF, ResourceTemplate()
Expand Down Expand Up @@ -285,6 +290,18 @@ the device to the driver. For example:
Return (SBUF)
}

// ACPI 5.1 _DSD used for naming the GPIOs
Name (_DSD, Package ()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"power-gpios", Package() {^DEV, 0, 0, 0 }},
Package () {"irq-gpios", Package() {^DEV, 1, 0, 0 }},
}
})
...

These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
specifies the path to the controller. In order to use these GPIOs in Linux
we need to translate them to the corresponding Linux GPIO descriptors.
Expand All @@ -300,11 +317,11 @@ a code like this:

struct gpio_desc *irq_desc, *power_desc;

irq_desc = gpiod_get_index(dev, NULL, 1);
irq_desc = gpiod_get(dev, "irq");
if (IS_ERR(irq_desc))
/* handle error */

power_desc = gpiod_get_index(dev, NULL, 0);
power_desc = gpiod_get(dev, "power");
if (IS_ERR(power_desc))
/* handle error */

Expand All @@ -313,6 +330,9 @@ a code like this:
There are also devm_* versions of these functions which release the
descriptors once the device is released.

See Documentation/acpi/gpio-properties.txt for more information about the
_DSD binding related to GPIOs.

MFD devices
~~~~~~~~~~~
The MFD devices register their children as platform devices. For the child
Expand Down
7 changes: 7 additions & 0 deletions Documentation/kernel-parameters.txt
Expand Up @@ -3477,6 +3477,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
improve throughput, but will also increase the
amount of memory reserved for use by the client.

suspend.pm_test_delay=
[SUSPEND]
Sets the number of seconds to remain in a suspend test
mode before resuming the system (see
/sys/power/pm_test). Only available when CONFIG_PM_DEBUG
is set. Default value is 5.

swapaccount=[0|1]
[KNL] Enable accounting of swap in memory resource
controller if no parameter or 1 is given or disable
Expand Down
10 changes: 6 additions & 4 deletions Documentation/power/basic-pm-debugging.txt
Expand Up @@ -75,12 +75,14 @@ you should do the following:
# echo platform > /sys/power/disk
# echo disk > /sys/power/state

Then, the kernel will try to freeze processes, suspend devices, wait 5 seconds,
resume devices and thaw processes. If "platform" is written to
Then, the kernel will try to freeze processes, suspend devices, wait a few
seconds (5 by default, but configurable by the suspend.pm_test_delay module
parameter), resume devices and thaw processes. If "platform" is written to
/sys/power/pm_test , then after suspending devices the kernel will additionally
invoke the global control methods (eg. ACPI global control methods) used to
prepare the platform firmware for hibernation. Next, it will wait 5 seconds and
invoke the platform (eg. ACPI) global methods used to cancel hibernation etc.
prepare the platform firmware for hibernation. Next, it will wait a
configurable number of seconds and invoke the platform (eg. ACPI) global
methods used to cancel hibernation etc.

Writing "none" to /sys/power/pm_test causes the kernel to switch to the normal
hibernation/suspend operations. Also, when open for reading, /sys/power/pm_test
Expand Down
9 changes: 9 additions & 0 deletions MAINTAINERS
Expand Up @@ -4331,6 +4331,15 @@ S: Supported
F: drivers/phy/
F: include/linux/phy/

GENERIC PM DOMAINS
M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
M: Kevin Hilman <khilman@kernel.org>
M: Ulf Hansson <ulf.hansson@linaro.org>
L: linux-pm@vger.kernel.org
S: Supported
F: drivers/base/power/domain*.c
F: include/linux/pm_domain.h

GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org
Expand Down
23 changes: 23 additions & 0 deletions arch/arm/include/asm/cpuidle.h
@@ -1,6 +1,8 @@
#ifndef __ASM_ARM_CPUIDLE_H
#define __ASM_ARM_CPUIDLE_H

#include <asm/proc-fns.h>

#ifdef CONFIG_CPU_IDLE
extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
Expand All @@ -25,4 +27,25 @@ static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
*/
#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX)

struct device_node;

struct cpuidle_ops {
int (*suspend)(int cpu, unsigned long arg);
int (*init)(struct device_node *, int cpu);
};

struct of_cpuidle_method {
const char *method;
struct cpuidle_ops *ops;
};

#define CPUIDLE_METHOD_OF_DECLARE(name, _method, _ops) \
static const struct of_cpuidle_method __cpuidle_method_of_table_##name \
__used __section(__cpuidle_method_of_table) \
= { .method = _method, .ops = _ops }

extern int arm_cpuidle_suspend(int index);

extern int arm_cpuidle_init(int cpu);

#endif
133 changes: 132 additions & 1 deletion arch/arm/kernel/cpuidle.c
Expand Up @@ -10,12 +10,143 @@
*/

#include <linux/cpuidle.h>
#include <asm/proc-fns.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <asm/cpuidle.h>

extern struct of_cpuidle_method __cpuidle_method_of_table[];

static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel
__used __section(__cpuidle_method_of_table_end);

static struct cpuidle_ops cpuidle_ops[NR_CPUS];

/**
* arm_cpuidle_simple_enter() - a wrapper to cpu_do_idle()
* @dev: not used
* @drv: not used
* @index: not used
*
* A trivial wrapper to allow the cpu_do_idle function to be assigned as a
* cpuidle callback by matching the function signature.
*
* Returns the index passed as parameter
*/
int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
cpu_do_idle();

return index;
}

/**
* arm_cpuidle_suspend() - function to enter low power idle states
* @index: an integer used as an identifier for the low level PM callbacks
*
* This function calls the underlying arch specific low level PM code as
* registered at the init time.
*
* Returns -EOPNOTSUPP if no suspend callback is defined, the result of the
* callback otherwise.
*/
int arm_cpuidle_suspend(int index)
{
int ret = -EOPNOTSUPP;
int cpu = smp_processor_id();

if (cpuidle_ops[cpu].suspend)
ret = cpuidle_ops[cpu].suspend(cpu, index);

return ret;
}

/**
* arm_cpuidle_get_ops() - find a registered cpuidle_ops by name
* @method: the method name
*
* Search in the __cpuidle_method_of_table array the cpuidle ops matching the
* method name.
*
* Returns a struct cpuidle_ops pointer, NULL if not found.
*/
static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
{
struct of_cpuidle_method *m = __cpuidle_method_of_table;

for (; m->method; m++)
if (!strcmp(m->method, method))
return m->ops;

return NULL;
}

/**
* arm_cpuidle_read_ops() - Initialize the cpuidle ops with the device tree
* @dn: a pointer to a struct device node corresponding to a cpu node
* @cpu: the cpu identifier
*
* Get the method name defined in the 'enable-method' property, retrieve the
* associated cpuidle_ops and do a struct copy. This copy is needed because all
* cpuidle_ops are tagged __initdata and will be unloaded after the init
* process.
*
* Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if
* no cpuidle_ops is registered for the 'enable-method'.
*/
static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
{
const char *enable_method;
struct cpuidle_ops *ops;

enable_method = of_get_property(dn, "enable-method", NULL);
if (!enable_method)
return -ENOENT;

ops = arm_cpuidle_get_ops(enable_method);
if (!ops) {
pr_warn("%s: unsupported enable-method property: %s\n",
dn->full_name, enable_method);
return -EOPNOTSUPP;
}

cpuidle_ops[cpu] = *ops; /* structure copy */

pr_notice("cpuidle: enable-method property '%s'"
" found operations\n", enable_method);

return 0;
}

/**
* arm_cpuidle_init() - Initialize cpuidle_ops for a specific cpu
* @cpu: the cpu to be initialized
*
* Initialize the cpuidle ops with the device for the cpu and then call
* the cpu's idle initialization callback. This may fail if the underlying HW
* is not operational.
*
* Returns:
* 0 on success,
* -ENODEV if it fails to find the cpu node in the device tree,
* -EOPNOTSUPP if it does not find a registered cpuidle_ops for this cpu,
* -ENOENT if it fails to find an 'enable-method' property,
* -ENXIO if the HW reports a failure or a misconfiguration,
* -ENOMEM if the HW report an memory allocation failure
*/
int __init arm_cpuidle_init(int cpu)
{
struct device_node *cpu_node = of_cpu_device_node_get(cpu);
int ret;

if (!cpu_node)
return -ENODEV;

ret = arm_cpuidle_read_ops(cpu_node, cpu);
if (!ret && cpuidle_ops[cpu].init)
ret = cpuidle_ops[cpu].init(cpu_node, cpu);

of_node_put(cpu_node);

return ret;
}
1 change: 0 additions & 1 deletion arch/arm/mach-davinci/cpuidle.c
Expand Up @@ -17,7 +17,6 @@
#include <linux/cpuidle.h>
#include <linux/io.h>
#include <linux/export.h>
#include <asm/proc-fns.h>
#include <asm/cpuidle.h>

#include <mach/cpuidle.h>
Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-imx/cpuidle-imx6q.c
Expand Up @@ -9,7 +9,6 @@
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/cpuidle.h>
#include <asm/proc-fns.h>

#include "common.h"
#include "cpuidle.h"
Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-imx/cpuidle-imx6sl.c
Expand Up @@ -9,7 +9,6 @@
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <asm/cpuidle.h>
#include <asm/proc-fns.h>

#include "common.h"
#include "cpuidle.h"
Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-imx/cpuidle-imx6sx.c
Expand Up @@ -10,7 +10,6 @@
#include <linux/cpu_pm.h>
#include <linux/module.h>
#include <asm/cpuidle.h>
#include <asm/proc-fns.h>
#include <asm/suspend.h>

#include "common.h"
Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-omap2/cpuidle44xx.c
Expand Up @@ -17,7 +17,6 @@
#include <linux/tick.h>

#include <asm/cpuidle.h>
#include <asm/proc-fns.h>

#include "common.h"
#include "pm.h"
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-s3c64xx/cpuidle.c
Expand Up @@ -16,7 +16,7 @@
#include <linux/export.h>
#include <linux/time.h>

#include <asm/proc-fns.h>
#include <asm/cpuidle.h>

#include <mach/map.h>

Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-tegra/cpuidle-tegra20.c
Expand Up @@ -27,7 +27,6 @@
#include <linux/module.h>

#include <asm/cpuidle.h>
#include <asm/proc-fns.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>

Expand Down
1 change: 0 additions & 1 deletion arch/arm/mach-tegra/cpuidle-tegra30.c
Expand Up @@ -27,7 +27,6 @@
#include <linux/module.h>

#include <asm/cpuidle.h>
#include <asm/proc-fns.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>

Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/configs/defconfig
Expand Up @@ -48,7 +48,7 @@ CONFIG_CMDLINE="console=ttyAMA0"
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
CONFIG_CPU_IDLE=y
CONFIG_ARM64_CPUIDLE=y
CONFIG_ARM_CPUIDLE=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
Expand Down
9 changes: 6 additions & 3 deletions arch/arm64/include/asm/cpuidle.h
Expand Up @@ -4,10 +4,10 @@
#include <asm/proc-fns.h>

#ifdef CONFIG_CPU_IDLE
extern int cpu_init_idle(unsigned int cpu);
extern int arm_cpuidle_init(unsigned int cpu);
extern int cpu_suspend(unsigned long arg);
#else
static inline int cpu_init_idle(unsigned int cpu)
static inline int arm_cpuidle_init(unsigned int cpu)
{
return -EOPNOTSUPP;
}
Expand All @@ -17,5 +17,8 @@ static inline int cpu_suspend(unsigned long arg)
return -EOPNOTSUPP;
}
#endif

static inline int arm_cpuidle_suspend(int index)
{
return cpu_suspend(index);
}
#endif
2 changes: 1 addition & 1 deletion arch/arm64/kernel/cpuidle.c
Expand Up @@ -15,7 +15,7 @@
#include <asm/cpuidle.h>
#include <asm/cpu_ops.h>

int cpu_init_idle(unsigned int cpu)
int arm_cpuidle_init(unsigned int cpu)
{
int ret = -EOPNOTSUPP;
struct device_node *cpu_node = of_cpu_device_node_get(cpu);
Expand Down

0 comments on commit 2481bc7

Please sign in to comment.