diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-02 21:32:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-02 21:32:35 -0400 |
commit | 16642a2e7be23bbda013fc32d8f6c68982eab603 (patch) | |
tree | 346ae485f485f6901e5d8150f0d34d178a7dd448 /drivers/acpi | |
parent | 51562cba98939da0a1d10fe7c25359b77a069033 (diff) | |
parent | b9142167a2bb979b58b98ffcd928a311b55cbd9f (diff) |
Merge tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael J Wysocki:
- Improved system suspend/resume and runtime PM handling for the SH
TMU, CMT and MTU2 clock event devices (also used by ARM/shmobile).
- Generic PM domains framework extensions related to cpuidle support
and domain objects lookup using names.
- ARM/shmobile power management updates including improved support for
the SH7372's A4S power domain containing the CPU core.
- cpufreq changes related to AMD CPUs support from Matthew Garrett,
Andre Przywara and Borislav Petkov.
- cpu0 cpufreq driver from Shawn Guo.
- cpufreq governor fixes related to the relaxing of limit from Michal
Pecio.
- OMAP cpufreq updates from Axel Lin and Richard Zhao.
- cpuidle ladder governor fixes related to the disabling of states from
Carsten Emde and me.
- Runtime PM core updates related to the interactions with the system
suspend core from Alan Stern and Kevin Hilman.
- Wakeup sources modification allowing more helper functions to be
called from interrupt context from John Stultz and additional
diagnostic code from Todd Poynor.
- System suspend error code path fix from Feng Hong.
Fixed up conflicts in cpufreq/powernow-k8 that stemmed from the
workqueue fixes conflicting fairly badly with the removal of support for
hardware P-state chips. The changes were independent but somewhat
intertwined.
* tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (76 commits)
Revert "PM QoS: Use spinlock in the per-device PM QoS constraints code"
PM / Runtime: let rpm_resume() succeed if RPM_ACTIVE, even when disabled, v2
cpuidle: rename function name "__cpuidle_register_driver", v2
cpufreq: OMAP: Check IS_ERR() instead of NULL for omap_device_get_by_hwmod_name
cpuidle: remove some empty lines
PM: Prevent runtime suspend during system resume
PM QoS: Use spinlock in the per-device PM QoS constraints code
PM / Sleep: use resume event when call dpm_resume_early
cpuidle / ACPI : move cpuidle_device field out of the acpi_processor_power structure
ACPI / processor: remove pointless variable initialization
ACPI / processor: remove unused function parameter
cpufreq: OMAP: remove loops_per_jiffy recalculate for smp
sections: fix section conflicts in drivers/cpufreq
cpufreq: conservative: update frequency when limits are relaxed
cpufreq / ondemand: update frequency when limits are relaxed
properly __init-annotate pm_sysrq_init()
cpufreq: Add a generic cpufreq-cpu0 driver
PM / OPP: Initialize OPP table from device tree
ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp
cpufreq: Remove support for hardware P-state chips from powernow-k8
...
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_driver.c | 8 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 40 | ||||
-rw-r--r-- | drivers/acpi/processor_perflib.c | 30 |
3 files changed, 59 insertions, 19 deletions
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index bfc31cb0dd3e..e78c2a52ea46 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -475,7 +475,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) | |||
475 | acpi_processor_get_limit_info(pr); | 475 | acpi_processor_get_limit_info(pr); |
476 | 476 | ||
477 | if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) | 477 | if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) |
478 | acpi_processor_power_init(pr, device); | 478 | acpi_processor_power_init(pr); |
479 | 479 | ||
480 | pr->cdev = thermal_cooling_device_register("Processor", device, | 480 | pr->cdev = thermal_cooling_device_register("Processor", device, |
481 | &processor_cooling_ops); | 481 | &processor_cooling_ops); |
@@ -509,7 +509,7 @@ err_remove_sysfs_thermal: | |||
509 | err_thermal_unregister: | 509 | err_thermal_unregister: |
510 | thermal_cooling_device_unregister(pr->cdev); | 510 | thermal_cooling_device_unregister(pr->cdev); |
511 | err_power_exit: | 511 | err_power_exit: |
512 | acpi_processor_power_exit(pr, device); | 512 | acpi_processor_power_exit(pr); |
513 | 513 | ||
514 | return result; | 514 | return result; |
515 | } | 515 | } |
@@ -620,7 +620,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type) | |||
620 | return -EINVAL; | 620 | return -EINVAL; |
621 | } | 621 | } |
622 | 622 | ||
623 | acpi_processor_power_exit(pr, device); | 623 | acpi_processor_power_exit(pr); |
624 | 624 | ||
625 | sysfs_remove_link(&device->dev.kobj, "sysdev"); | 625 | sysfs_remove_link(&device->dev.kobj, "sysdev"); |
626 | 626 | ||
@@ -905,8 +905,6 @@ static int __init acpi_processor_init(void) | |||
905 | if (acpi_disabled) | 905 | if (acpi_disabled) |
906 | return 0; | 906 | return 0; |
907 | 907 | ||
908 | memset(&errata, 0, sizeof(errata)); | ||
909 | |||
910 | result = acpi_bus_register_driver(&acpi_processor_driver); | 908 | result = acpi_bus_register_driver(&acpi_processor_driver); |
911 | if (result < 0) | 909 | if (result < 0) |
912 | return result; | 910 | return result; |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index ad3730b4038b..3655ab923812 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -79,6 +79,8 @@ module_param(bm_check_disable, uint, 0000); | |||
79 | static unsigned int latency_factor __read_mostly = 2; | 79 | static unsigned int latency_factor __read_mostly = 2; |
80 | module_param(latency_factor, uint, 0644); | 80 | module_param(latency_factor, uint, 0644); |
81 | 81 | ||
82 | static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); | ||
83 | |||
82 | static int disabled_by_idle_boot_param(void) | 84 | static int disabled_by_idle_boot_param(void) |
83 | { | 85 | { |
84 | return boot_option_idle_override == IDLE_POLL || | 86 | return boot_option_idle_override == IDLE_POLL || |
@@ -483,8 +485,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
483 | if (obj->type != ACPI_TYPE_INTEGER) | 485 | if (obj->type != ACPI_TYPE_INTEGER) |
484 | continue; | 486 | continue; |
485 | 487 | ||
486 | cx.power = obj->integer.value; | ||
487 | |||
488 | current_count++; | 488 | current_count++; |
489 | memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx)); | 489 | memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx)); |
490 | 490 | ||
@@ -1000,7 +1000,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) | |||
1000 | int i, count = CPUIDLE_DRIVER_STATE_START; | 1000 | int i, count = CPUIDLE_DRIVER_STATE_START; |
1001 | struct acpi_processor_cx *cx; | 1001 | struct acpi_processor_cx *cx; |
1002 | struct cpuidle_state_usage *state_usage; | 1002 | struct cpuidle_state_usage *state_usage; |
1003 | struct cpuidle_device *dev = &pr->power.dev; | 1003 | struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); |
1004 | 1004 | ||
1005 | if (!pr->flags.power_setup_done) | 1005 | if (!pr->flags.power_setup_done) |
1006 | return -EINVAL; | 1006 | return -EINVAL; |
@@ -1132,6 +1132,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
1132 | int acpi_processor_hotplug(struct acpi_processor *pr) | 1132 | int acpi_processor_hotplug(struct acpi_processor *pr) |
1133 | { | 1133 | { |
1134 | int ret = 0; | 1134 | int ret = 0; |
1135 | struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); | ||
1135 | 1136 | ||
1136 | if (disabled_by_idle_boot_param()) | 1137 | if (disabled_by_idle_boot_param()) |
1137 | return 0; | 1138 | return 0; |
@@ -1147,11 +1148,11 @@ int acpi_processor_hotplug(struct acpi_processor *pr) | |||
1147 | return -ENODEV; | 1148 | return -ENODEV; |
1148 | 1149 | ||
1149 | cpuidle_pause_and_lock(); | 1150 | cpuidle_pause_and_lock(); |
1150 | cpuidle_disable_device(&pr->power.dev); | 1151 | cpuidle_disable_device(dev); |
1151 | acpi_processor_get_power_info(pr); | 1152 | acpi_processor_get_power_info(pr); |
1152 | if (pr->flags.power) { | 1153 | if (pr->flags.power) { |
1153 | acpi_processor_setup_cpuidle_cx(pr); | 1154 | acpi_processor_setup_cpuidle_cx(pr); |
1154 | ret = cpuidle_enable_device(&pr->power.dev); | 1155 | ret = cpuidle_enable_device(dev); |
1155 | } | 1156 | } |
1156 | cpuidle_resume_and_unlock(); | 1157 | cpuidle_resume_and_unlock(); |
1157 | 1158 | ||
@@ -1162,6 +1163,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1162 | { | 1163 | { |
1163 | int cpu; | 1164 | int cpu; |
1164 | struct acpi_processor *_pr; | 1165 | struct acpi_processor *_pr; |
1166 | struct cpuidle_device *dev; | ||
1165 | 1167 | ||
1166 | if (disabled_by_idle_boot_param()) | 1168 | if (disabled_by_idle_boot_param()) |
1167 | return 0; | 1169 | return 0; |
@@ -1192,7 +1194,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1192 | _pr = per_cpu(processors, cpu); | 1194 | _pr = per_cpu(processors, cpu); |
1193 | if (!_pr || !_pr->flags.power_setup_done) | 1195 | if (!_pr || !_pr->flags.power_setup_done) |
1194 | continue; | 1196 | continue; |
1195 | cpuidle_disable_device(&_pr->power.dev); | 1197 | dev = per_cpu(acpi_cpuidle_device, cpu); |
1198 | cpuidle_disable_device(dev); | ||
1196 | } | 1199 | } |
1197 | 1200 | ||
1198 | /* Populate Updated C-state information */ | 1201 | /* Populate Updated C-state information */ |
@@ -1206,7 +1209,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1206 | acpi_processor_get_power_info(_pr); | 1209 | acpi_processor_get_power_info(_pr); |
1207 | if (_pr->flags.power) { | 1210 | if (_pr->flags.power) { |
1208 | acpi_processor_setup_cpuidle_cx(_pr); | 1211 | acpi_processor_setup_cpuidle_cx(_pr); |
1209 | cpuidle_enable_device(&_pr->power.dev); | 1212 | dev = per_cpu(acpi_cpuidle_device, cpu); |
1213 | cpuidle_enable_device(dev); | ||
1210 | } | 1214 | } |
1211 | } | 1215 | } |
1212 | put_online_cpus(); | 1216 | put_online_cpus(); |
@@ -1218,11 +1222,11 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1218 | 1222 | ||
1219 | static int acpi_processor_registered; | 1223 | static int acpi_processor_registered; |
1220 | 1224 | ||
1221 | int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | 1225 | int __cpuinit acpi_processor_power_init(struct acpi_processor *pr) |
1222 | struct acpi_device *device) | ||
1223 | { | 1226 | { |
1224 | acpi_status status = 0; | 1227 | acpi_status status = 0; |
1225 | int retval; | 1228 | int retval; |
1229 | struct cpuidle_device *dev; | ||
1226 | static int first_run; | 1230 | static int first_run; |
1227 | 1231 | ||
1228 | if (disabled_by_idle_boot_param()) | 1232 | if (disabled_by_idle_boot_param()) |
@@ -1268,11 +1272,18 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1268 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", | 1272 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", |
1269 | acpi_idle_driver.name); | 1273 | acpi_idle_driver.name); |
1270 | } | 1274 | } |
1275 | |||
1276 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
1277 | if (!dev) | ||
1278 | return -ENOMEM; | ||
1279 | per_cpu(acpi_cpuidle_device, pr->id) = dev; | ||
1280 | |||
1281 | acpi_processor_setup_cpuidle_cx(pr); | ||
1282 | |||
1271 | /* Register per-cpu cpuidle_device. Cpuidle driver | 1283 | /* Register per-cpu cpuidle_device. Cpuidle driver |
1272 | * must already be registered before registering device | 1284 | * must already be registered before registering device |
1273 | */ | 1285 | */ |
1274 | acpi_processor_setup_cpuidle_cx(pr); | 1286 | retval = cpuidle_register_device(dev); |
1275 | retval = cpuidle_register_device(&pr->power.dev); | ||
1276 | if (retval) { | 1287 | if (retval) { |
1277 | if (acpi_processor_registered == 0) | 1288 | if (acpi_processor_registered == 0) |
1278 | cpuidle_unregister_driver(&acpi_idle_driver); | 1289 | cpuidle_unregister_driver(&acpi_idle_driver); |
@@ -1283,14 +1294,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1283 | return 0; | 1294 | return 0; |
1284 | } | 1295 | } |
1285 | 1296 | ||
1286 | int acpi_processor_power_exit(struct acpi_processor *pr, | 1297 | int acpi_processor_power_exit(struct acpi_processor *pr) |
1287 | struct acpi_device *device) | ||
1288 | { | 1298 | { |
1299 | struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); | ||
1300 | |||
1289 | if (disabled_by_idle_boot_param()) | 1301 | if (disabled_by_idle_boot_param()) |
1290 | return 0; | 1302 | return 0; |
1291 | 1303 | ||
1292 | if (pr->flags.power) { | 1304 | if (pr->flags.power) { |
1293 | cpuidle_unregister_device(&pr->power.dev); | 1305 | cpuidle_unregister_device(dev); |
1294 | acpi_processor_registered--; | 1306 | acpi_processor_registered--; |
1295 | if (acpi_processor_registered == 0) | 1307 | if (acpi_processor_registered == 0) |
1296 | cpuidle_unregister_driver(&acpi_idle_driver); | 1308 | cpuidle_unregister_driver(&acpi_idle_driver); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index a093dc163a42..836bfe069042 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -324,6 +324,34 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr) | |||
324 | return result; | 324 | return result; |
325 | } | 325 | } |
326 | 326 | ||
327 | #ifdef CONFIG_X86 | ||
328 | /* | ||
329 | * Some AMDs have 50MHz frequency multiples, but only provide 100MHz rounding | ||
330 | * in their ACPI data. Calculate the real values and fix up the _PSS data. | ||
331 | */ | ||
332 | static void amd_fixup_frequency(struct acpi_processor_px *px, int i) | ||
333 | { | ||
334 | u32 hi, lo, fid, did; | ||
335 | int index = px->control & 0x00000007; | ||
336 | |||
337 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | ||
338 | return; | ||
339 | |||
340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) | ||
341 | || boot_cpu_data.x86 == 0x11) { | ||
342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); | ||
343 | fid = lo & 0x3f; | ||
344 | did = (lo >> 6) & 7; | ||
345 | if (boot_cpu_data.x86 == 0x10) | ||
346 | px->core_frequency = (100 * (fid + 0x10)) >> did; | ||
347 | else | ||
348 | px->core_frequency = (100 * (fid + 8)) >> did; | ||
349 | } | ||
350 | } | ||
351 | #else | ||
352 | static void amd_fixup_frequency(struct acpi_processor_px *px, int i) {}; | ||
353 | #endif | ||
354 | |||
327 | static int acpi_processor_get_performance_states(struct acpi_processor *pr) | 355 | static int acpi_processor_get_performance_states(struct acpi_processor *pr) |
328 | { | 356 | { |
329 | int result = 0; | 357 | int result = 0; |
@@ -379,6 +407,8 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) | |||
379 | goto end; | 407 | goto end; |
380 | } | 408 | } |
381 | 409 | ||
410 | amd_fixup_frequency(px, i); | ||
411 | |||
382 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 412 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
383 | "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", | 413 | "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", |
384 | i, | 414 | i, |