From eba87ef89f7e669062a14d6008e40a8b8f777e74 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 21 Feb 2013 09:56:43 +0000 Subject: blackfin idle: Fix compile error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 26bab0c ("blackfin idle: delete pm_idle") introduced the following compile error: arch/blackfin/kernel/process.c: In function ‘cpu_idle’: arch/blackfin/kernel/process.c:83: error: ‘idle’ undeclared (first use in this function) arch/blackfin/kernel/process.c:83: error: (Each undeclared identifier is reported only once arch/blackfin/kernel/process.c:83: error: for each function it appears in.) arch/blackfin/kernel/process.c:88: error: implicit declaration of function ‘idle’ This patch fixes it. Signed-off-by: Lars-Peter Clausen Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 8061426..9782c03 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -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(); -- cgit v0.10.2 From c192b196d0f3a239f9f056d02a983c48cdf128d9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 21 Feb 2013 10:15:31 +0000 Subject: microblaze idle: Fix compile error Commit def8203 ("microblaze idle: delete pm_idle") introduced the following compile error: arch/microblaze/kernel/process.c: In function 'cpu_idle': arch/microblaze/kernel/process.c:100: error: 'idle' undeclared (first use in this function) arch/microblaze/kernel/process.c:100: error: (Each undeclared identifier is reported only once arch/microblaze/kernel/process.c:100: error: for each function it appears in.) arch/microblaze/kernel/process.c:106: error: implicit declaration of function 'idle' This patch fixes it. Signed-off-by: Lars-Peter Clausen Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 6ff2dcf..08f8734 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -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(); -- cgit v0.10.2 From a84363d6fdba14663b6b155eec604b6c0f6f8866 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 23 Feb 2013 00:14:57 +0100 Subject: ACPI / APEI: Fix crash in apei_hest_parse() for acpi=off After commit 92ef2a2 (ACPI: Change the ordering of PCI root bridge driver registrarion), acpi_hest_init() is never called for acpi=off (acpi_disabled), so hest_disable is not set, but hest_tab is NULL, which causes apei_hest_parse() to crash when it is called from aer_acpi_firmware_first(). Fix that by making apei_hest_parse() check if hest_tab is not NULL in addition to checking hest_disable. Also remove the now useless acpi_disabled check from apei_hest_parse(). Reported-by: Thomas Gleixner Tested-by: Thomas Gleixner Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 7f00cf3..f5ef5d5 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -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) -- cgit v0.10.2 From d6561bb206aae9de8eee4516549339ee96386b87 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 21 Feb 2013 11:04:45 +0000 Subject: PM / OPP: fix condition for empty of_init_opp_table() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit randconfig build reports the following error which is caused by CONFIG_PM_OPP being unset. CC arch/arm/mach-imx/mach-imx6q.o arch/arm/mach-imx/mach-imx6q.c: In function ‘imx6q_opp_init’: arch/arm/mach-imx/mach-imx6q.c:248:2: error: implicit declaration of function ‘of_init_opp_table’ [-Werror=implicit-function-declaration] Fix the error by giving a more correct condition for empty of_init_opp_table() implementation. Reported-by: Rob Herring Signed-off-by: Shawn Guo Acked-by: Nishanth Menon Signed-off-by: Rafael J. Wysocki diff --git a/include/linux/opp.h b/include/linux/opp.h index 214e0ebc..3aca2b8 100644 --- a/include/linux/opp.h +++ b/include/linux/opp.h @@ -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); -- cgit v0.10.2 From 3a3656d4011625cf98f8cc351968fe30af3cc9ac Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 22 Feb 2013 04:39:30 +0000 Subject: imx6q-cpufreq: fix return value check in imx6q_cpufreq_probe() In case of error, the function devm_regulator_get() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Acked-by: Viresh Kumar Acked-by: Shawn Guo Signed-off-by: Rafael J. Wysocki diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index d6b6ef3..54e336d 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -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; -- cgit v0.10.2 From b5d667eb392ed901fc7ae76869c7a130559e193c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 23 Feb 2013 23:15:21 +0100 Subject: ACPI / PM: Take unusual configurations of power resources into account Commit d2e5f0c (ACPI / PCI: Rework the setup and cleanup of device wakeup) moved the initial disabling of system wakeup for PCI devices into a place where it can actually work and that exposed a hidden old issue with crap^Wunusual system designs where the same power resources are used for both wakeup power and device power control at run time. Namely, say there is one power resource such that the ACPI power state D0 of a PCI device depends on that power resource (i.e. the device is in D0 when that power resource is "on") and it is used as a wakeup power resource for the same device. Then, calling acpi_pci_sleep_wake(pci_dev, false) for the device in question will cause the reference counter of that power resource to drop to 0, which in turn will cause it to be turned off. As a result, the device will go into D3cold at that point, although it should have stayed in D0. As it turns out, that happens to USB controllers on some laptops and USB becomes unusable on those machines as a result, which is a major regression from v3.8. To fix this problem, (1) increment the reference counters of wakup power resources during their initialization if they are "on" initially, (2) prevent acpi_disable_wakeup_device_power() from decrementing the reference counters of wakeup power resources that were not enabled for wakeup power previously, and (3) prevent acpi_enable_wakeup_device_power() from incrementing the reference counters of wakeup power resources that already are enabled for wakeup power. In addition to that, if it is impossible to determine the initial states of wakeup power resources, avoid enabling wakeup for devices whose wakeup power depends on those power resources. Reported-by: Dave Jones Reported-by: Fabio Baltieri Tested-by: Fabio Baltieri Signed-off-by: Rafael J. Wysocki diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index c5a61cd..6306d2e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -56,7 +56,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); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index b820528..34f5ef1 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -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; +} - mutex_unlock(&resource->resource_lock); +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: - mutex_unlock(&resource->resource_lock); +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: diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f75f25c..560b055 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1004,7 +1004,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", -- cgit v0.10.2