ACPI and power management fixes for 3.9-rc6

- Revert of a recent cpuidle change that caused Nehalem machines
   to hang on boot from Alex Shi.
 
 - USB power management fix addressing a crash in the port device
   object's release routine from Rafael J. Wysocki.
 
 - Device PM QoS fix for a potential deadlock related to sysfs
   interface from Rafael J. Wysocki.
 
 - Fix for a cpufreq crash when the /cpus Device Tree node is missing
   from Paolo Pisati.
 
 - Fix for a build issue on ia64 related to the Boot Graphics Resource
   Table (BGRT) from Tony Luck.
 
 - Two fixes for ACPI handles being set incorrectly for device
   objects that don't correspond to any ACPI namespace nodes in
   the I2C and SPI subsystems from Rafael J. Wysocki.
 
 - Fix for compiler warnings related to CONFIG_PM_DEVFREQ being
   unset from Rajagopal Venkat.
 
 - Fix for a symbol definition typo in cpufreq_governor.h from
   Borislav Petkov.
 
 /
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iQIcBAABAgAGBQJRXeiaAAoJEKhOf7ml8uNsZwUP/RmKD3wQEqHFPWk94wb0JhiI
 J5nOfmmSjriLxV2XA2ajK48Zh8WDdvpVX0JHEBqPUYeVK09NVaN4L4Jr2ELAbeit
 i2NKeWPtudTFEzJqZfK6d7s4TirbvD1+6TUCckI5N0Ku9Exf9R0jCGrEx4TCunOJ
 UHluCxGKL9/GWc8Jc0HXto0w8cMAKgNN41quWD77u6qXOTujPafQ69DR6EFuLta6
 pRz8tJ2g1oG43K0m5bZwPtIa6k+/6yP2e5zRaOQQM8ca0fxVJVuo2/kc9Warnx1m
 Njayp3q9xmqfC5lt4F386BohnwFDBtqKoIbiNt1bJeiqDAnFCRpFAyFhx+sPNg3O
 +D77BUdAB3fpxC8My9YgDG/YEK72HI/OVSceQ2txMssZyU5d24aH5P1ZAMwiGaJf
 tAVQU/exCYMeJbD7xgjjK5Ny2yUpeUze2BYhRUCB2cseyJqdGc9j5hD/YGdnk9rC
 YAxJq94HQUlcsOcFko//z/22ANda5OeLc1xtcX87sBAjsYXFNEyPirrR0b6YqqPr
 gshfyE6HXNTzwbbH2uPRRuXGYVn7pGjcPxulPeP/i8pklhInj0rtWnCIq8f/bik1
 uudEp/z2Zl9eNKkezAp32Eczn13ivEkz8By+SHrjluqCCpNzZVRNeGBg6uFOMTkL
 Gz8dAAvK/Hb05OfgQWad
 =s/w4
 -----END PGP SIGNATURE-----

Merge tag 'pm+acpi-3.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI and power management fixes from Rafael Wysocki:

 - Revert of a recent cpuidle change that caused Nehalem machines to
   hang on boot from Alex Shi.

 - USB power management fix addressing a crash in the port device
   object's release routine from Rafael J Wysocki.

 - Device PM QoS fix for a potential deadlock related to sysfs interface
   from Rafael J Wysocki.

 - Fix for a cpufreq crash when the /cpus Device Tree node is missing
   from Paolo Pisati.

 - Fix for a build issue on ia64 related to the Boot Graphics Resource
   Table (BGRT) from Tony Luck.

 - Two fixes for ACPI handles being set incorrectly for device objects
   that don't correspond to any ACPI namespace nodes in the I2C and SPI
   subsystems from Rafael J Wysocki.

 - Fix for compiler warnings related to CONFIG_PM_DEVFREQ being unset
   from Rajagopal Venkat.

 - Fix for a symbol definition typo in cpufreq_governor.h from Borislav
   Petkov.

* tag 'pm+acpi-3.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / BGRT: Don't let users configure BGRT on non X86 systems
  cpuidle / ACPI: recover percpu ACPI processor cstate
  ACPI / I2C: Use parent's ACPI_HANDLE() in acpi_i2c_register_devices()
  cpufreq: Correct header guards typo
  ACPI / SPI: Use parent's ACPI_HANDLE() in acpi_register_spi_devices()
  cpufreq: check OF node /cpus presence before dereferencing it
  PM / devfreq: Fix compiler warnings for CONFIG_PM_DEVFREQ unset
  PM / QoS: Avoid possible deadlock related to sysfs access
  USB / PM: Don't try to hide PM QoS flags from usb_port_device_release()
This commit is contained in:
Linus Torvalds 2013-04-04 15:56:28 -07:00
commit d08d528dc1
11 changed files with 76 additions and 38 deletions

View file

@ -396,7 +396,7 @@ config ACPI_CUSTOM_METHOD
config ACPI_BGRT
bool "Boottime Graphics Resource Table support"
depends on EFI
depends on EFI && X86
help
This driver adds support for exposing the ACPI Boottime Graphics
Resource Table, which allows the operating system to obtain

View file

@ -90,7 +90,7 @@ void acpi_i2c_register_devices(struct i2c_adapter *adapter)
acpi_handle handle;
acpi_status status;
handle = ACPI_HANDLE(&adapter->dev);
handle = ACPI_HANDLE(adapter->dev.parent);
if (!handle)
return;

View file

@ -66,7 +66,8 @@ module_param(latency_factor, uint, 0644);
static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
static struct acpi_processor_cx *acpi_cstate[CPUIDLE_STATE_MAX];
static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX],
acpi_cstate);
static int disabled_by_idle_boot_param(void)
{
@ -722,7 +723,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor *pr;
struct acpi_processor_cx *cx = acpi_cstate[index];
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
pr = __this_cpu_read(processors);
@ -745,7 +746,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
*/
static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
{
struct acpi_processor_cx *cx = acpi_cstate[index];
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
ACPI_FLUSH_CPU_CACHE();
@ -775,7 +776,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor *pr;
struct acpi_processor_cx *cx = acpi_cstate[index];
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
pr = __this_cpu_read(processors);
@ -833,7 +834,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
struct acpi_processor *pr;
struct acpi_processor_cx *cx = acpi_cstate[index];
struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
pr = __this_cpu_read(processors);
@ -960,7 +961,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
!(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
continue;
#endif
acpi_cstate[count] = cx;
per_cpu(acpi_cstate[count], dev->cpu) = cx;
count++;
if (count == CPUIDLE_STATE_MAX)

View file

@ -46,6 +46,7 @@
#include "power.h"
static DEFINE_MUTEX(dev_pm_qos_mtx);
static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx);
static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
struct pm_qos_constraints *c;
struct pm_qos_flags *f;
mutex_lock(&dev_pm_qos_mtx);
mutex_lock(&dev_pm_qos_sysfs_mtx);
/*
* If the device's PM QoS resume latency limit or PM QoS flags have been
* exposed to user space, they have to be hidden at this point.
*/
pm_qos_sysfs_remove_latency(dev);
pm_qos_sysfs_remove_flags(dev);
mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_hide_latency_limit(dev);
__dev_pm_qos_hide_flags(dev);
@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
out:
mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
}
/**
@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
kfree(req);
}
static void dev_pm_qos_drop_user_request(struct device *dev,
enum dev_pm_qos_req_type type)
{
mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_drop_user_request(dev, type);
mutex_unlock(&dev_pm_qos_mtx);
}
/**
* dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
* @dev: Device whose PM QoS latency limit is to be exposed to user space.
@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
return ret;
}
mutex_lock(&dev_pm_qos_sysfs_mtx);
mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos))
@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
if (ret < 0) {
__dev_pm_qos_remove_request(req);
kfree(req);
mutex_unlock(&dev_pm_qos_mtx);
goto out;
}
dev->power.qos->latency_req = req;
mutex_unlock(&dev_pm_qos_mtx);
ret = pm_qos_sysfs_add_latency(dev);
if (ret)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
out:
mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
static void __dev_pm_qos_hide_latency_limit(struct device *dev)
{
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
pm_qos_sysfs_remove_latency(dev);
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
}
}
/**
@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev)
*/
void dev_pm_qos_hide_latency_limit(struct device *dev)
{
mutex_lock(&dev_pm_qos_sysfs_mtx);
pm_qos_sysfs_remove_latency(dev);
mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_hide_latency_limit(dev);
mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
}
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
}
pm_runtime_get_sync(dev);
mutex_lock(&dev_pm_qos_sysfs_mtx);
mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos))
@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
if (ret < 0) {
__dev_pm_qos_remove_request(req);
kfree(req);
mutex_unlock(&dev_pm_qos_mtx);
goto out;
}
dev->power.qos->flags_req = req;
mutex_unlock(&dev_pm_qos_mtx);
ret = pm_qos_sysfs_add_flags(dev);
if (ret)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
out:
mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
pm_runtime_put(dev);
return ret;
}
@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
static void __dev_pm_qos_hide_flags(struct device *dev)
{
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
pm_qos_sysfs_remove_flags(dev);
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
}
}
/**
@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev)
void dev_pm_qos_hide_flags(struct device *dev)
{
pm_runtime_get_sync(dev);
mutex_lock(&dev_pm_qos_sysfs_mtx);
pm_qos_sysfs_remove_flags(dev);
mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_hide_flags(dev);
mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
pm_runtime_put(dev);
}
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);

View file

@ -178,10 +178,16 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
static int cpu0_cpufreq_probe(struct platform_device *pdev)
{
struct device_node *np;
struct device_node *np, *parent;
int ret;
for_each_child_of_node(of_find_node_by_path("/cpus"), np) {
parent = of_find_node_by_path("/cpus");
if (!parent) {
pr_err("failed to find OF /cpus\n");
return -ENOENT;
}
for_each_child_of_node(parent, np) {
if (of_get_property(np, "operating-points", NULL))
break;
}

View file

@ -14,8 +14,8 @@
* published by the Free Software Foundation.
*/
#ifndef _CPUFREQ_GOVERNER_H
#define _CPUFREQ_GOVERNER_H
#ifndef _CPUFREQ_GOVERNOR_H
#define _CPUFREQ_GOVERNOR_H
#include <linux/cpufreq.h>
#include <linux/kobject.h>
@ -175,4 +175,4 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
unsigned int sampling_rate);
int cpufreq_governor_dbs(struct dbs_data *dbs_data,
struct cpufreq_policy *policy, unsigned int event);
#endif /* _CPUFREQ_GOVERNER_H */
#endif /* _CPUFREQ_GOVERNOR_H */

View file

@ -182,7 +182,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
adap->algo = &i2c_dw_algo;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
ACPI_HANDLE_SET(&adap->dev, ACPI_HANDLE(&pdev->dev));
r = i2c_add_numbered_adapter(adap);
if (r) {

View file

@ -1168,7 +1168,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
master->dev.parent = &pdev->dev;
master->dev.of_node = pdev->dev.of_node;
ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;

View file

@ -984,7 +984,7 @@ static void acpi_register_spi_devices(struct spi_master *master)
acpi_status status;
acpi_handle handle;
handle = ACPI_HANDLE(&master->dev);
handle = ACPI_HANDLE(master->dev.parent);
if (!handle)
return;

View file

@ -67,7 +67,6 @@ static void usb_port_device_release(struct device *dev)
{
struct usb_port *port_dev = to_usb_port(dev);
dev_pm_qos_hide_flags(dev);
kfree(port_dev);
}

View file

@ -213,7 +213,7 @@ struct devfreq_simple_ondemand_data {
#endif
#else /* !CONFIG_PM_DEVFREQ */
static struct devfreq *devfreq_add_device(struct device *dev,
static inline struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
const char *governor_name,
void *data)
@ -221,34 +221,34 @@ static struct devfreq *devfreq_add_device(struct device *dev,
return NULL;
}
static int devfreq_remove_device(struct devfreq *devfreq)
static inline int devfreq_remove_device(struct devfreq *devfreq)
{
return 0;
}
static int devfreq_suspend_device(struct devfreq *devfreq)
static inline int devfreq_suspend_device(struct devfreq *devfreq)
{
return 0;
}
static int devfreq_resume_device(struct devfreq *devfreq)
static inline int devfreq_resume_device(struct devfreq *devfreq)
{
return 0;
}
static struct opp *devfreq_recommended_opp(struct device *dev,
static inline struct opp *devfreq_recommended_opp(struct device *dev,
unsigned long *freq, u32 flags)
{
return -EINVAL;
return ERR_PTR(-EINVAL);
}
static int devfreq_register_opp_notifier(struct device *dev,
static inline int devfreq_register_opp_notifier(struct device *dev,
struct devfreq *devfreq)
{
return -EINVAL;
}
static int devfreq_unregister_opp_notifier(struct device *dev,
static inline int devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq)
{
return -EINVAL;