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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user