aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-25 23:32:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-25 23:32:00 -0400
commit1aad08dc571604ebe473e2a187f0f7b211ae6c3f (patch)
tree6d95d35c187a4d1ccf07d620d6c84df567cd4df0
parent27a24cfa04c6f041c0191847d047f25e5627cd63 (diff)
parent5a2bff8d7c7f63e2e8d467f66f6492fbb4d9509c (diff)
Merge tag 'pm+acpi-3.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management and ACPI fixes from Rafael Wysocki: - Additional CPU ID for the intel_pstate driver from Dirk Brandewie. - More cpufreq fixes related to ARM big.LITTLE support and locking from Viresh Kumar. - VIA C7 cpufreq build fix from RafaƂ Bilski. - ACPI power management fix making it possible to use device power states regardless of the CONFIG_PM setting from Rafael J Wysocki. - New ACPI video blacklist item from Bastian Triller. * tag 'pm+acpi-3.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / video: Add "Asus UL30A" to ACPI video detect blacklist cpufreq: arm_big_little_dt: Instantiate as platform_driver cpufreq: arm_big_little_dt: Register driver only if DT has valid data cpufreq / e_powersaver: Fix linker error when ACPI processor is a module cpufreq / intel_pstate: Add additional supported CPU ID cpufreq: Drop rwsem lock around CPUFREQ_GOV_POLICY_EXIT ACPI / PM: Allow device power states to be used for CONFIG_PM unset
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/device_pm.c126
-rw-r--r--drivers/acpi/video_detect.c8
-rw-r--r--drivers/cpufreq/Kconfig.x862
-rw-r--r--drivers/cpufreq/arm_big_little_dt.c93
-rw-r--r--drivers/cpufreq/cpufreq.c9
-rw-r--r--drivers/cpufreq/intel_pstate.c1
-rw-r--r--include/acpi/acpi_bus.h40
8 files changed, 144 insertions, 137 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 6050c8028dce..536562c626a2 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -24,7 +24,7 @@ acpi-y += nvs.o
24# Power management related files 24# Power management related files
25acpi-y += wakeup.o 25acpi-y += wakeup.o
26acpi-y += sleep.o 26acpi-y += sleep.o
27acpi-$(CONFIG_PM) += device_pm.o 27acpi-y += device_pm.o
28acpi-$(CONFIG_ACPI_SLEEP) += proc.o 28acpi-$(CONFIG_ACPI_SLEEP) += proc.o
29 29
30 30
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 96de787e6104..bc493aa3af19 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -37,68 +37,6 @@
37#define _COMPONENT ACPI_POWER_COMPONENT 37#define _COMPONENT ACPI_POWER_COMPONENT
38ACPI_MODULE_NAME("device_pm"); 38ACPI_MODULE_NAME("device_pm");
39 39
40static DEFINE_MUTEX(acpi_pm_notifier_lock);
41
42/**
43 * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
44 * @adev: ACPI device to add the notifier for.
45 * @context: Context information to pass to the notifier routine.
46 *
47 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
48 * PM wakeup events. For example, wakeup events may be generated for bridges
49 * if one of the devices below the bridge is signaling wakeup, even if the
50 * bridge itself doesn't have a wakeup GPE associated with it.
51 */
52acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
53 acpi_notify_handler handler, void *context)
54{
55 acpi_status status = AE_ALREADY_EXISTS;
56
57 mutex_lock(&acpi_pm_notifier_lock);
58
59 if (adev->wakeup.flags.notifier_present)
60 goto out;
61
62 status = acpi_install_notify_handler(adev->handle,
63 ACPI_SYSTEM_NOTIFY,
64 handler, context);
65 if (ACPI_FAILURE(status))
66 goto out;
67
68 adev->wakeup.flags.notifier_present = true;
69
70 out:
71 mutex_unlock(&acpi_pm_notifier_lock);
72 return status;
73}
74
75/**
76 * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
77 * @adev: ACPI device to remove the notifier from.
78 */
79acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
80 acpi_notify_handler handler)
81{
82 acpi_status status = AE_BAD_PARAMETER;
83
84 mutex_lock(&acpi_pm_notifier_lock);
85
86 if (!adev->wakeup.flags.notifier_present)
87 goto out;
88
89 status = acpi_remove_notify_handler(adev->handle,
90 ACPI_SYSTEM_NOTIFY,
91 handler);
92 if (ACPI_FAILURE(status))
93 goto out;
94
95 adev->wakeup.flags.notifier_present = false;
96
97 out:
98 mutex_unlock(&acpi_pm_notifier_lock);
99 return status;
100}
101
102/** 40/**
103 * acpi_power_state_string - String representation of ACPI device power state. 41 * acpi_power_state_string - String representation of ACPI device power state.
104 * @state: ACPI device power state to return the string representation of. 42 * @state: ACPI device power state to return the string representation of.
@@ -385,6 +323,69 @@ bool acpi_bus_power_manageable(acpi_handle handle)
385} 323}
386EXPORT_SYMBOL(acpi_bus_power_manageable); 324EXPORT_SYMBOL(acpi_bus_power_manageable);
387 325
326#ifdef CONFIG_PM
327static DEFINE_MUTEX(acpi_pm_notifier_lock);
328
329/**
330 * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
331 * @adev: ACPI device to add the notifier for.
332 * @context: Context information to pass to the notifier routine.
333 *
334 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
335 * PM wakeup events. For example, wakeup events may be generated for bridges
336 * if one of the devices below the bridge is signaling wakeup, even if the
337 * bridge itself doesn't have a wakeup GPE associated with it.
338 */
339acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
340 acpi_notify_handler handler, void *context)
341{
342 acpi_status status = AE_ALREADY_EXISTS;
343
344 mutex_lock(&acpi_pm_notifier_lock);
345
346 if (adev->wakeup.flags.notifier_present)
347 goto out;
348
349 status = acpi_install_notify_handler(adev->handle,
350 ACPI_SYSTEM_NOTIFY,
351 handler, context);
352 if (ACPI_FAILURE(status))
353 goto out;
354
355 adev->wakeup.flags.notifier_present = true;
356
357 out:
358 mutex_unlock(&acpi_pm_notifier_lock);
359 return status;
360}
361
362/**
363 * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
364 * @adev: ACPI device to remove the notifier from.
365 */
366acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
367 acpi_notify_handler handler)
368{
369 acpi_status status = AE_BAD_PARAMETER;
370
371 mutex_lock(&acpi_pm_notifier_lock);
372
373 if (!adev->wakeup.flags.notifier_present)
374 goto out;
375
376 status = acpi_remove_notify_handler(adev->handle,
377 ACPI_SYSTEM_NOTIFY,
378 handler);
379 if (ACPI_FAILURE(status))
380 goto out;
381
382 adev->wakeup.flags.notifier_present = false;
383
384 out:
385 mutex_unlock(&acpi_pm_notifier_lock);
386 return status;
387}
388
388bool acpi_bus_can_wakeup(acpi_handle handle) 389bool acpi_bus_can_wakeup(acpi_handle handle)
389{ 390{
390 struct acpi_device *device; 391 struct acpi_device *device;
@@ -1023,3 +1024,4 @@ void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
1023 mutex_unlock(&adev->physical_node_lock); 1024 mutex_unlock(&adev->physical_node_lock);
1024} 1025}
1025EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent); 1026EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
1027#endif /* CONFIG_PM */
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 66f67626f02e..e6bd910bc6ed 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -161,6 +161,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
161 DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"), 161 DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
162 }, 162 },
163 }, 163 },
164 {
165 .callback = video_detect_force_vendor,
166 .ident = "Asus UL30A",
167 .matches = {
168 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
169 DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
170 },
171 },
164 { }, 172 { },
165}; 173};
166 174
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 2b8a8c374548..6bd63d63d356 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -272,7 +272,7 @@ config X86_LONGHAUL
272config X86_E_POWERSAVER 272config X86_E_POWERSAVER
273 tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)" 273 tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
274 select CPU_FREQ_TABLE 274 select CPU_FREQ_TABLE
275 depends on X86_32 275 depends on X86_32 && ACPI_PROCESSOR
276 help 276 help
277 This adds the CPUFreq driver for VIA C7 processors. However, this driver 277 This adds the CPUFreq driver for VIA C7 processors. However, this driver
278 does not have any safeguards to prevent operating the CPU out of spec 278 does not have any safeguards to prevent operating the CPU out of spec
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index 173ed059d95f..fd9e3ea6a480 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -19,70 +19,75 @@
19 19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 21
22#include <linux/cpu.h>
22#include <linux/cpufreq.h> 23#include <linux/cpufreq.h>
23#include <linux/device.h> 24#include <linux/device.h>
24#include <linux/export.h> 25#include <linux/export.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <linux/of.h> 27#include <linux/of.h>
27#include <linux/opp.h> 28#include <linux/opp.h>
29#include <linux/platform_device.h>
28#include <linux/slab.h> 30#include <linux/slab.h>
29#include <linux/types.h> 31#include <linux/types.h>
30#include "arm_big_little.h" 32#include "arm_big_little.h"
31 33
32static int dt_init_opp_table(struct device *cpu_dev) 34/* get cpu node with valid operating-points */
35static struct device_node *get_cpu_node_with_valid_op(int cpu)
33{ 36{
34 struct device_node *np, *parent; 37 struct device_node *np = NULL, *parent;
35 int count = 0, ret; 38 int count = 0;
36 39
37 parent = of_find_node_by_path("/cpus"); 40 parent = of_find_node_by_path("/cpus");
38 if (!parent) { 41 if (!parent) {
39 pr_err("failed to find OF /cpus\n"); 42 pr_err("failed to find OF /cpus\n");
40 return -ENOENT; 43 return NULL;
41 } 44 }
42 45
43 for_each_child_of_node(parent, np) { 46 for_each_child_of_node(parent, np) {
44 if (count++ != cpu_dev->id) 47 if (count++ != cpu)
45 continue; 48 continue;
46 if (!of_get_property(np, "operating-points", NULL)) { 49 if (!of_get_property(np, "operating-points", NULL)) {
47 ret = -ENODATA; 50 of_node_put(np);
48 } else { 51 np = NULL;
49 cpu_dev->of_node = np;
50 ret = of_init_opp_table(cpu_dev);
51 } 52 }
52 of_node_put(np);
53 of_node_put(parent);
54 53
55 return ret; 54 break;
56 } 55 }
57 56
58 return -ENODEV; 57 of_node_put(parent);
58 return np;
59}
60
61static int dt_init_opp_table(struct device *cpu_dev)
62{
63 struct device_node *np;
64 int ret;
65
66 np = get_cpu_node_with_valid_op(cpu_dev->id);
67 if (!np)
68 return -ENODATA;
69
70 cpu_dev->of_node = np;
71 ret = of_init_opp_table(cpu_dev);
72 of_node_put(np);
73
74 return ret;
59} 75}
60 76
61static int dt_get_transition_latency(struct device *cpu_dev) 77static int dt_get_transition_latency(struct device *cpu_dev)
62{ 78{
63 struct device_node *np, *parent; 79 struct device_node *np;
64 u32 transition_latency = CPUFREQ_ETERNAL; 80 u32 transition_latency = CPUFREQ_ETERNAL;
65 int count = 0;
66 81
67 parent = of_find_node_by_path("/cpus"); 82 np = get_cpu_node_with_valid_op(cpu_dev->id);
68 if (!parent) { 83 if (!np)
69 pr_info("Failed to find OF /cpus. Use CPUFREQ_ETERNAL transition latency\n");
70 return CPUFREQ_ETERNAL; 84 return CPUFREQ_ETERNAL;
71 }
72
73 for_each_child_of_node(parent, np) {
74 if (count++ != cpu_dev->id)
75 continue;
76 85
77 of_property_read_u32(np, "clock-latency", &transition_latency); 86 of_property_read_u32(np, "clock-latency", &transition_latency);
78 of_node_put(np); 87 of_node_put(np);
79 of_node_put(parent);
80 88
81 return transition_latency; 89 pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
82 } 90 return transition_latency;
83
84 pr_info("clock-latency isn't found, use CPUFREQ_ETERNAL transition latency\n");
85 return CPUFREQ_ETERNAL;
86} 91}
87 92
88static struct cpufreq_arm_bL_ops dt_bL_ops = { 93static struct cpufreq_arm_bL_ops dt_bL_ops = {
@@ -91,17 +96,33 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = {
91 .init_opp_table = dt_init_opp_table, 96 .init_opp_table = dt_init_opp_table,
92}; 97};
93 98
94static int generic_bL_init(void) 99static int generic_bL_probe(struct platform_device *pdev)
95{ 100{
101 struct device_node *np;
102
103 np = get_cpu_node_with_valid_op(0);
104 if (!np)
105 return -ENODEV;
106
107 of_node_put(np);
96 return bL_cpufreq_register(&dt_bL_ops); 108 return bL_cpufreq_register(&dt_bL_ops);
97} 109}
98module_init(generic_bL_init);
99 110
100static void generic_bL_exit(void) 111static int generic_bL_remove(struct platform_device *pdev)
101{ 112{
102 return bL_cpufreq_unregister(&dt_bL_ops); 113 bL_cpufreq_unregister(&dt_bL_ops);
114 return 0;
103} 115}
104module_exit(generic_bL_exit); 116
117static struct platform_driver generic_bL_platdrv = {
118 .driver = {
119 .name = "arm-bL-cpufreq-dt",
120 .owner = THIS_MODULE,
121 },
122 .probe = generic_bL_probe,
123 .remove = generic_bL_remove,
124};
125module_platform_driver(generic_bL_platdrv);
105 126
106MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); 127MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
107MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT"); 128MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 4b8c7f297d74..2d53f47d1747 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1729,18 +1729,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
1729 /* end old governor */ 1729 /* end old governor */
1730 if (data->governor) { 1730 if (data->governor) {
1731 __cpufreq_governor(data, CPUFREQ_GOV_STOP); 1731 __cpufreq_governor(data, CPUFREQ_GOV_STOP);
1732 unlock_policy_rwsem_write(policy->cpu);
1732 __cpufreq_governor(data, 1733 __cpufreq_governor(data,
1733 CPUFREQ_GOV_POLICY_EXIT); 1734 CPUFREQ_GOV_POLICY_EXIT);
1735 lock_policy_rwsem_write(policy->cpu);
1734 } 1736 }
1735 1737
1736 /* start new governor */ 1738 /* start new governor */
1737 data->governor = policy->governor; 1739 data->governor = policy->governor;
1738 if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) { 1740 if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
1739 if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) 1741 if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) {
1740 failed = 0; 1742 failed = 0;
1741 else 1743 } else {
1744 unlock_policy_rwsem_write(policy->cpu);
1742 __cpufreq_governor(data, 1745 __cpufreq_governor(data,
1743 CPUFREQ_GOV_POLICY_EXIT); 1746 CPUFREQ_GOV_POLICY_EXIT);
1747 lock_policy_rwsem_write(policy->cpu);
1748 }
1744 } 1749 }
1745 1750
1746 if (failed) { 1751 if (failed) {
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 9c36ace92a39..07f2840ad805 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -521,6 +521,7 @@ static void intel_pstate_timer_func(unsigned long __data)
521static const struct x86_cpu_id intel_pstate_cpu_ids[] = { 521static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
522 ICPU(0x2a, default_policy), 522 ICPU(0x2a, default_policy),
523 ICPU(0x2d, default_policy), 523 ICPU(0x2d, default_policy),
524 ICPU(0x3a, default_policy),
524 {} 525 {}
525}; 526};
526MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); 527MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 98db31d9f9b4..636c59f2003a 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -377,7 +377,6 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
377 unsigned long long *sta); 377 unsigned long long *sta);
378int acpi_bus_get_status(struct acpi_device *device); 378int acpi_bus_get_status(struct acpi_device *device);
379 379
380#ifdef CONFIG_PM
381int acpi_bus_set_power(acpi_handle handle, int state); 380int acpi_bus_set_power(acpi_handle handle, int state);
382const char *acpi_power_state_string(int state); 381const char *acpi_power_state_string(int state);
383int acpi_device_get_power(struct acpi_device *device, int *state); 382int acpi_device_get_power(struct acpi_device *device, int *state);
@@ -385,41 +384,12 @@ int acpi_device_set_power(struct acpi_device *device, int state);
385int acpi_bus_init_power(struct acpi_device *device); 384int acpi_bus_init_power(struct acpi_device *device);
386int acpi_bus_update_power(acpi_handle handle, int *state_p); 385int acpi_bus_update_power(acpi_handle handle, int *state_p);
387bool acpi_bus_power_manageable(acpi_handle handle); 386bool acpi_bus_power_manageable(acpi_handle handle);
387
388#ifdef CONFIG_PM
388bool acpi_bus_can_wakeup(acpi_handle handle); 389bool acpi_bus_can_wakeup(acpi_handle handle);
389#else /* !CONFIG_PM */ 390#else
390static inline int acpi_bus_set_power(acpi_handle handle, int state) 391static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; }
391{ 392#endif
392 return 0;
393}
394static inline const char *acpi_power_state_string(int state)
395{
396 return "D0";
397}
398static inline int acpi_device_get_power(struct acpi_device *device, int *state)
399{
400 return 0;
401}
402static inline int acpi_device_set_power(struct acpi_device *device, int state)
403{
404 return 0;
405}
406static inline int acpi_bus_init_power(struct acpi_device *device)
407{
408 return 0;
409}
410static inline int acpi_bus_update_power(acpi_handle handle, int *state_p)
411{
412 return 0;
413}
414static inline bool acpi_bus_power_manageable(acpi_handle handle)
415{
416 return false;
417}
418static inline bool acpi_bus_can_wakeup(acpi_handle handle)
419{
420 return false;
421}
422#endif /* !CONFIG_PM */
423 393
424#ifdef CONFIG_ACPI_PROC_EVENT 394#ifdef CONFIG_ACPI_PROC_EVENT
425int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); 395int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data);