mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
ACPI and power management fixes for 3.9-rc1
- Fixes for blackfin and microblaze build problems introduced by the removal of global pm_idle. From Lars-Peter Clausen. - OPP core build fix from Shawn Guo. - Error condition check fix for the new imx6q-cpufreq driver from Wei Yongjun. - Fix for an AER driver crash related to the lack of APEI initialization for acpi=off. From Rafael J. Wysocki. - Fix for a USB breakage on Thinkpad T430 related to ACPI power resources and PCI wakeup from Rafael J. Wysocki. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJRKUy/AAoJEKhOf7ml8uNsKskQAIj8rzVUsQcyk77U2NmACLhE EGdcxiwLrOc5bR2NEwyF66VN398pYrC2BqtCsj7vE070YEdt8VOcfOQ7FNtp3Z8R hgGkpALL6QusV3V+f9rOxberqbU+Ei7XzeZs/74gilTF5+xFDt8Vd+PkJSMzpOug BX06ZP5NWALL2qUKbJsz6TTLY1IjkxNrcn4iWMNcCZfCFS4r9KFd9SJhiD9lDY66 FdE2H69IDWrIEoPuEQHVk79YZu9CKUldMdBAIYfyWGSpxZ5IU/fmvIKlamFgTT7I Voz0l69TTSlQYp+6WG7HCla6B371BwYEvZOgjgXNzW+gVPaqj9+wTpOln1GX4oZc qBukY59b1NgaJahwX/lHaJZckoF0gcBoqCp3eW3LMPe6tkVk/Kd4cRrTCUXgUMtX IHMZc/jkqMQmvEspXqzc+/mZAf9RBzUMG7mgDG4yrxPoSLBUZM1DOWG93lqc6T9u nPhvb444GaDRilAc8vW/Bnc5hzaMYGlpoX2MCi0aisevcvD6c5aW4HZ80UirZMPA OiOvQJ4vbtdFTrlupv0kBE+fKFXyb+qYtVkrAemcAyvo4KmEbS5n1p79NnI8S4Sp DNk/Fh+nUG0t9EKS0bnH/MZYVWqPaTPIq7StUf/iicngLfSIGj4zPflL0GjjC6Wf gWqNH0wjit/64gUQsQAN =FCbx -----END PGP SIGNATURE----- Merge tag 'pm+acpi-fixes-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull ACPI and power management fixes from Rafael Wysocki: - Fixes for blackfin and microblaze build problems introduced by the removal of global pm_idle. From Lars-Peter Clausen. - OPP core build fix from Shawn Guo. - Error condition check fix for the new imx6q-cpufreq driver from Wei Yongjun. - Fix for an AER driver crash related to the lack of APEI initialization for acpi=off. From Rafael J Wysocki. - Fix for a USB breakage on Thinkpad T430 related to ACPI power resources and PCI wakeup from Rafael J. Wysocki. * tag 'pm+acpi-fixes-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / PM: Take unusual configurations of power resources into account imx6q-cpufreq: fix return value check in imx6q_cpufreq_probe() PM / OPP: fix condition for empty of_init_opp_table() ACPI / APEI: Fix crash in apei_hest_parse() for acpi=off microblaze idle: Fix compile error blackfin idle: Fix compile error
This commit is contained in:
commit
c41b3810c0
@ -80,12 +80,10 @@ void cpu_idle(void)
|
||||
if (cpu_is_offline(smp_processor_id()))
|
||||
cpu_die();
|
||||
#endif
|
||||
if (!idle)
|
||||
idle = default_idle;
|
||||
tick_nohz_idle_enter();
|
||||
rcu_idle_enter();
|
||||
while (!need_resched())
|
||||
idle();
|
||||
default_idle();
|
||||
rcu_idle_exit();
|
||||
tick_nohz_idle_exit();
|
||||
preempt_enable_no_resched();
|
||||
|
@ -97,13 +97,10 @@ void cpu_idle(void)
|
||||
|
||||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
if (!idle)
|
||||
idle = default_idle;
|
||||
|
||||
tick_nohz_idle_enter();
|
||||
rcu_idle_enter();
|
||||
while (!need_resched())
|
||||
idle();
|
||||
default_idle();
|
||||
rcu_idle_exit();
|
||||
tick_nohz_idle_exit();
|
||||
|
||||
|
@ -89,7 +89,7 @@ int apei_hest_parse(apei_hest_func_t func, void *data)
|
||||
struct acpi_hest_header *hest_hdr;
|
||||
int i, rc, len;
|
||||
|
||||
if (hest_disable)
|
||||
if (hest_disable || !hest_tab)
|
||||
return -EINVAL;
|
||||
|
||||
hest_hdr = (struct acpi_hest_header *)(hest_tab + 1);
|
||||
@ -216,9 +216,6 @@ void __init acpi_hest_init(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (acpi_disabled)
|
||||
goto err;
|
||||
|
||||
status = acpi_get_table(ACPI_SIG_HEST, 0,
|
||||
(struct acpi_table_header **)&hest_tab);
|
||||
if (status == AE_NOT_FOUND)
|
||||
|
@ -71,7 +71,7 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
|
||||
struct list_head *list);
|
||||
int acpi_add_power_resource(acpi_handle handle);
|
||||
void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
|
||||
int acpi_power_min_system_level(struct list_head *list);
|
||||
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level);
|
||||
int acpi_device_sleep_wake(struct acpi_device *dev,
|
||||
int enable, int sleep_state, int dev_state);
|
||||
int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
|
||||
|
@ -73,6 +73,7 @@ struct acpi_power_resource {
|
||||
u32 system_level;
|
||||
u32 order;
|
||||
unsigned int ref_count;
|
||||
bool wakeup_enabled;
|
||||
struct mutex resource_lock;
|
||||
};
|
||||
|
||||
@ -272,11 +273,9 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_power_on(struct acpi_power_resource *resource)
|
||||
static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
|
||||
{
|
||||
int result = 0;;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
int result = 0;
|
||||
|
||||
if (resource->ref_count++) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
@ -293,9 +292,16 @@ static int acpi_power_on(struct acpi_power_resource *resource)
|
||||
schedule_work(&dep->work);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int acpi_power_on(struct acpi_power_resource *resource)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
result = acpi_power_on_unlocked(resource);
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -313,17 +319,15 @@ static int __acpi_power_off(struct acpi_power_resource *resource)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_power_off(struct acpi_power_resource *resource)
|
||||
static int acpi_power_off_unlocked(struct acpi_power_resource *resource)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
|
||||
if (!resource->ref_count) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Power resource [%s] already off",
|
||||
resource->name));
|
||||
goto unlock;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (--resource->ref_count) {
|
||||
@ -335,10 +339,16 @@ static int acpi_power_off(struct acpi_power_resource *resource)
|
||||
if (result)
|
||||
resource->ref_count++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unlock:
|
||||
static int acpi_power_off(struct acpi_power_resource *resource)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
result = acpi_power_off_unlocked(resource);
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -521,18 +531,35 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
|
||||
}
|
||||
}
|
||||
|
||||
int acpi_power_min_system_level(struct list_head *list)
|
||||
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
|
||||
{
|
||||
struct acpi_power_resource_entry *entry;
|
||||
int system_level = 5;
|
||||
|
||||
list_for_each_entry(entry, list, node) {
|
||||
struct acpi_power_resource *resource = entry->resource;
|
||||
acpi_handle handle = resource->device.handle;
|
||||
int result;
|
||||
int state;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
|
||||
result = acpi_power_get_state(handle, &state);
|
||||
if (result) {
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
return result;
|
||||
}
|
||||
if (state == ACPI_POWER_RESOURCE_STATE_ON) {
|
||||
resource->ref_count++;
|
||||
resource->wakeup_enabled = true;
|
||||
}
|
||||
if (system_level > resource->system_level)
|
||||
system_level = resource->system_level;
|
||||
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
}
|
||||
return system_level;
|
||||
*system_level_p = system_level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
@ -610,6 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
|
||||
*/
|
||||
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
||||
{
|
||||
struct acpi_power_resource_entry *entry;
|
||||
int err = 0;
|
||||
|
||||
if (!dev || !dev->wakeup.flags.valid)
|
||||
@ -620,17 +648,31 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
||||
if (dev->wakeup.prepare_count++)
|
||||
goto out;
|
||||
|
||||
err = acpi_power_on_list(&dev->wakeup.resources);
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "Cannot turn wakeup power resources on\n");
|
||||
dev->wakeup.flags.valid = 0;
|
||||
} else {
|
||||
/*
|
||||
* Passing 3 as the third argument below means the device may be
|
||||
* put into arbitrary power state afterward.
|
||||
*/
|
||||
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
|
||||
list_for_each_entry(entry, &dev->wakeup.resources, node) {
|
||||
struct acpi_power_resource *resource = entry->resource;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
|
||||
if (!resource->wakeup_enabled) {
|
||||
err = acpi_power_on_unlocked(resource);
|
||||
if (!err)
|
||||
resource->wakeup_enabled = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
|
||||
if (err) {
|
||||
dev_err(&dev->dev,
|
||||
"Cannot turn wakeup power resources on\n");
|
||||
dev->wakeup.flags.valid = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Passing 3 as the third argument below means the device may be
|
||||
* put into arbitrary power state afterward.
|
||||
*/
|
||||
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
|
||||
if (err)
|
||||
dev->wakeup.prepare_count = 0;
|
||||
|
||||
@ -647,6 +689,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
||||
*/
|
||||
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
|
||||
{
|
||||
struct acpi_power_resource_entry *entry;
|
||||
int err = 0;
|
||||
|
||||
if (!dev || !dev->wakeup.flags.valid)
|
||||
@ -668,10 +711,25 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = acpi_power_off_list(&dev->wakeup.resources);
|
||||
if (err) {
|
||||
dev_err(&dev->dev, "Cannot turn wakeup power resources off\n");
|
||||
dev->wakeup.flags.valid = 0;
|
||||
list_for_each_entry(entry, &dev->wakeup.resources, node) {
|
||||
struct acpi_power_resource *resource = entry->resource;
|
||||
|
||||
mutex_lock(&resource->resource_lock);
|
||||
|
||||
if (resource->wakeup_enabled) {
|
||||
err = acpi_power_off_unlocked(resource);
|
||||
if (!err)
|
||||
resource->wakeup_enabled = false;
|
||||
}
|
||||
|
||||
mutex_unlock(&resource->resource_lock);
|
||||
|
||||
if (err) {
|
||||
dev_err(&dev->dev,
|
||||
"Cannot turn wakeup power resources off\n");
|
||||
dev->wakeup.flags.valid = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -1002,7 +1002,14 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
|
||||
if (!list_empty(&wakeup->resources)) {
|
||||
int sleep_state;
|
||||
|
||||
sleep_state = acpi_power_min_system_level(&wakeup->resources);
|
||||
err = acpi_power_wakeup_list_init(&wakeup->resources,
|
||||
&sleep_state);
|
||||
if (err) {
|
||||
acpi_handle_warn(handle, "Retrieving current states "
|
||||
"of wakeup power resources failed\n");
|
||||
acpi_power_resources_list_free(&wakeup->resources);
|
||||
goto out;
|
||||
}
|
||||
if (sleep_state < wakeup->sleep_state) {
|
||||
acpi_handle_warn(handle, "Overriding _PRW sleep state "
|
||||
"(S%d) by S%d from power resources\n",
|
||||
|
@ -245,7 +245,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
|
||||
arm_reg = devm_regulator_get(cpu_dev, "arm");
|
||||
pu_reg = devm_regulator_get(cpu_dev, "pu");
|
||||
soc_reg = devm_regulator_get(cpu_dev, "soc");
|
||||
if (!arm_reg || !pu_reg || !soc_reg) {
|
||||
if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
|
||||
dev_err(cpu_dev, "failed to get regulators\n");
|
||||
ret = -ENOENT;
|
||||
goto put_node;
|
||||
|
@ -47,15 +47,6 @@ int opp_enable(struct device *dev, unsigned long freq);
|
||||
int opp_disable(struct device *dev, unsigned long freq);
|
||||
|
||||
struct srcu_notifier_head *opp_get_notifier(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int of_init_opp_table(struct device *dev);
|
||||
#else
|
||||
static inline int of_init_opp_table(struct device *dev)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
#else
|
||||
static inline unsigned long opp_get_voltage(struct opp *opp)
|
||||
{
|
||||
@ -112,6 +103,15 @@ static inline struct srcu_notifier_head *opp_get_notifier(struct device *dev)
|
||||
}
|
||||
#endif /* CONFIG_PM_OPP */
|
||||
|
||||
#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
|
||||
int of_init_opp_table(struct device *dev);
|
||||
#else
|
||||
static inline int of_init_opp_table(struct device *dev)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
|
||||
int opp_init_cpufreq_table(struct device *dev,
|
||||
struct cpufreq_frequency_table **table);
|
||||
|
Loading…
Reference in New Issue
Block a user