diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-24 13:19:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-24 13:19:13 -0500 |
commit | ba2ab41f3d68f277860768b2c5b197768b196332 (patch) | |
tree | 807605fea8dcd16b89a8c4c95838e57e200019b5 | |
parent | bff92411eb93b2b2a06c4de76e6811486771a76f (diff) | |
parent | efa17194581bdfca0986dabc178908bd7c21ba00 (diff) |
Merge tag 'pm+acpi-for-3.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
- Two cpuidle initialization fixes from Konrad Rzeszutek Wilk.
- cpufreq regression fixes for AMD processors from Borislav Petkov,
Stefan Bader, and Matthew Garrett.
- ACPI cpufreq fix from Thomas Schlichter.
- cpufreq and devfreq fixes related to incorrect usage of operating
performance points (OPP) framework and RCU from Nishanth Menon.
- APEI workaround for incorrect BIOS information from Lans Zhang.
* tag 'pm+acpi-for-3.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
cpufreq: Add module aliases for acpi-cpufreq
ACPI: Check MSR valid bit before using P-state frequencies
PM / devfreq: exynos4_bus: honor RCU lock usage
PM / devfreq: add locking documentation for recommended_opp
cpufreq: cpufreq-cpu0: use RCU locks around usage of OPP
cpufreq: OMAP: use RCU locks around usage of OPP
ACPI, APEI: Fixup incorrect 64-bit access width firmware bug
ACPI / processor: Get power info before updating the C-states
powernow-k8: Add a kconfig dependency on acpi-cpufreq
ACPI / cpuidle: Fix NULL pointer issues when cpuidle is disabled
intel_idle: Don't register CPU notifier if we are not running.
-rw-r--r-- | drivers/acpi/apei/apei-base.c | 3 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 4 | ||||
-rw-r--r-- | drivers/acpi/processor_perflib.c | 7 | ||||
-rw-r--r-- | drivers/cpufreq/Kconfig.x86 | 2 | ||||
-rw-r--r-- | drivers/cpufreq/acpi-cpufreq.c | 7 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq-cpu0.c | 5 | ||||
-rw-r--r-- | drivers/cpufreq/omap-cpufreq.c | 3 | ||||
-rw-r--r-- | drivers/devfreq/devfreq.c | 5 | ||||
-rw-r--r-- | drivers/devfreq/exynos4_bus.c | 94 | ||||
-rw-r--r-- | drivers/idle/intel_idle.c | 3 |
10 files changed, 103 insertions, 30 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 00a783661d0b..46f80e2c92f7 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, | |||
590 | if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && | 590 | if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && |
591 | *access_bit_width < 32) | 591 | *access_bit_width < 32) |
592 | *access_bit_width = 32; | 592 | *access_bit_width = 32; |
593 | else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 && | ||
594 | *access_bit_width < 64) | ||
595 | *access_bit_width = 64; | ||
593 | 596 | ||
594 | if ((bit_width + bit_offset) > *access_bit_width) { | 597 | if ((bit_width + bit_offset) > *access_bit_width) { |
595 | pr_warning(FW_BUG APEI_PFX | 598 | pr_warning(FW_BUG APEI_PFX |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f1a5da44591d..ed9a1cc690be 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) | |||
958 | return -EINVAL; | 958 | return -EINVAL; |
959 | } | 959 | } |
960 | 960 | ||
961 | if (!dev) | ||
962 | return -EINVAL; | ||
963 | |||
961 | dev->cpu = pr->id; | 964 | dev->cpu = pr->id; |
962 | 965 | ||
963 | if (max_cstate == 0) | 966 | if (max_cstate == 0) |
@@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1149 | } | 1152 | } |
1150 | 1153 | ||
1151 | /* Populate Updated C-state information */ | 1154 | /* Populate Updated C-state information */ |
1155 | acpi_processor_get_power_info(pr); | ||
1152 | acpi_processor_setup_cpuidle_states(pr); | 1156 | acpi_processor_setup_cpuidle_states(pr); |
1153 | 1157 | ||
1154 | /* Enable all cpuidle devices */ | 1158 | /* Enable all cpuidle devices */ |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 836bfe069042..53e7ac9403a7 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) | |||
340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) | 340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) |
341 | || boot_cpu_data.x86 == 0x11) { | 341 | || boot_cpu_data.x86 == 0x11) { |
342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); | 342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); |
343 | /* | ||
344 | * MSR C001_0064+: | ||
345 | * Bit 63: PstateEn. Read-write. If set, the P-state is valid. | ||
346 | */ | ||
347 | if (!(hi & BIT(31))) | ||
348 | return; | ||
349 | |||
343 | fid = lo & 0x3f; | 350 | fid = lo & 0x3f; |
344 | did = (lo >> 6) & 7; | 351 | did = (lo >> 6) & 7; |
345 | if (boot_cpu_data.x86 == 0x10) | 352 | if (boot_cpu_data.x86 == 0x10) |
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 934854ae5eb4..7227cd734042 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 | |||
@@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI | |||
106 | config X86_POWERNOW_K8 | 106 | config X86_POWERNOW_K8 |
107 | tristate "AMD Opteron/Athlon64 PowerNow!" | 107 | tristate "AMD Opteron/Athlon64 PowerNow!" |
108 | select CPU_FREQ_TABLE | 108 | select CPU_FREQ_TABLE |
109 | depends on ACPI && ACPI_PROCESSOR | 109 | depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ |
110 | help | 110 | help |
111 | This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. | 111 | This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. |
112 | Support for K10 and newer processors is now in acpi-cpufreq. | 112 | Support for K10 and newer processors is now in acpi-cpufreq. |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 0d048f6a2b23..7b0d49d78c61 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict, | |||
1030 | late_initcall(acpi_cpufreq_init); | 1030 | late_initcall(acpi_cpufreq_init); |
1031 | module_exit(acpi_cpufreq_exit); | 1031 | module_exit(acpi_cpufreq_exit); |
1032 | 1032 | ||
1033 | static const struct x86_cpu_id acpi_cpufreq_ids[] = { | ||
1034 | X86_FEATURE_MATCH(X86_FEATURE_ACPI), | ||
1035 | X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), | ||
1036 | {} | ||
1037 | }; | ||
1038 | MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids); | ||
1039 | |||
1033 | MODULE_ALIAS("acpi"); | 1040 | MODULE_ALIAS("acpi"); |
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 52bf36d599f5..debc5a7c8db6 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c | |||
@@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, | |||
71 | } | 71 | } |
72 | 72 | ||
73 | if (cpu_reg) { | 73 | if (cpu_reg) { |
74 | rcu_read_lock(); | ||
74 | opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); | 75 | opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); |
75 | if (IS_ERR(opp)) { | 76 | if (IS_ERR(opp)) { |
77 | rcu_read_unlock(); | ||
76 | pr_err("failed to find OPP for %ld\n", freq_Hz); | 78 | pr_err("failed to find OPP for %ld\n", freq_Hz); |
77 | return PTR_ERR(opp); | 79 | return PTR_ERR(opp); |
78 | } | 80 | } |
79 | volt = opp_get_voltage(opp); | 81 | volt = opp_get_voltage(opp); |
82 | rcu_read_unlock(); | ||
80 | tol = volt * voltage_tolerance / 100; | 83 | tol = volt * voltage_tolerance / 100; |
81 | volt_old = regulator_get_voltage(cpu_reg); | 84 | volt_old = regulator_get_voltage(cpu_reg); |
82 | } | 85 | } |
@@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void) | |||
236 | */ | 239 | */ |
237 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 240 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) |
238 | ; | 241 | ; |
242 | rcu_read_lock(); | ||
239 | opp = opp_find_freq_exact(cpu_dev, | 243 | opp = opp_find_freq_exact(cpu_dev, |
240 | freq_table[0].frequency * 1000, true); | 244 | freq_table[0].frequency * 1000, true); |
241 | min_uV = opp_get_voltage(opp); | 245 | min_uV = opp_get_voltage(opp); |
242 | opp = opp_find_freq_exact(cpu_dev, | 246 | opp = opp_find_freq_exact(cpu_dev, |
243 | freq_table[i-1].frequency * 1000, true); | 247 | freq_table[i-1].frequency * 1000, true); |
244 | max_uV = opp_get_voltage(opp); | 248 | max_uV = opp_get_voltage(opp); |
249 | rcu_read_unlock(); | ||
245 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); | 250 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); |
246 | if (ret > 0) | 251 | if (ret > 0) |
247 | transition_latency += ret * 1000; | 252 | transition_latency += ret * 1000; |
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 1f3417a8322d..97102b05843f 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c | |||
@@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy, | |||
110 | freq = ret; | 110 | freq = ret; |
111 | 111 | ||
112 | if (mpu_reg) { | 112 | if (mpu_reg) { |
113 | rcu_read_lock(); | ||
113 | opp = opp_find_freq_ceil(mpu_dev, &freq); | 114 | opp = opp_find_freq_ceil(mpu_dev, &freq); |
114 | if (IS_ERR(opp)) { | 115 | if (IS_ERR(opp)) { |
116 | rcu_read_unlock(); | ||
115 | dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", | 117 | dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", |
116 | __func__, freqs.new); | 118 | __func__, freqs.new); |
117 | return -EINVAL; | 119 | return -EINVAL; |
118 | } | 120 | } |
119 | volt = opp_get_voltage(opp); | 121 | volt = opp_get_voltage(opp); |
122 | rcu_read_unlock(); | ||
120 | tol = volt * OPP_TOLERANCE / 100; | 123 | tol = volt * OPP_TOLERANCE / 100; |
121 | volt_old = regulator_get_voltage(mpu_reg); | 124 | volt_old = regulator_get_voltage(mpu_reg); |
122 | } | 125 | } |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 53766f39aadd..3b367973a802 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -994,6 +994,11 @@ module_exit(devfreq_exit); | |||
994 | * @freq: The frequency given to target function | 994 | * @freq: The frequency given to target function |
995 | * @flags: Flags handed from devfreq framework. | 995 | * @flags: Flags handed from devfreq framework. |
996 | * | 996 | * |
997 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
998 | * protected pointer. The reason for the same is that the opp pointer which is | ||
999 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
1000 | * under the locked area. The pointer returned must be used prior to unlocking | ||
1001 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
997 | */ | 1002 | */ |
998 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, | 1003 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, |
999 | u32 flags) | 1004 | u32 flags) |
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 80c745e83082..46d94e9e95b5 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c | |||
@@ -73,6 +73,16 @@ enum busclk_level_idx { | |||
73 | #define EX4210_LV_NUM (LV_2 + 1) | 73 | #define EX4210_LV_NUM (LV_2 + 1) |
74 | #define EX4x12_LV_NUM (LV_4 + 1) | 74 | #define EX4x12_LV_NUM (LV_4 + 1) |
75 | 75 | ||
76 | /** | ||
77 | * struct busfreq_opp_info - opp information for bus | ||
78 | * @rate: Frequency in hertz | ||
79 | * @volt: Voltage in microvolts corresponding to this OPP | ||
80 | */ | ||
81 | struct busfreq_opp_info { | ||
82 | unsigned long rate; | ||
83 | unsigned long volt; | ||
84 | }; | ||
85 | |||
76 | struct busfreq_data { | 86 | struct busfreq_data { |
77 | enum exynos4_busf_type type; | 87 | enum exynos4_busf_type type; |
78 | struct device *dev; | 88 | struct device *dev; |
@@ -80,7 +90,7 @@ struct busfreq_data { | |||
80 | bool disabled; | 90 | bool disabled; |
81 | struct regulator *vdd_int; | 91 | struct regulator *vdd_int; |
82 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ | 92 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ |
83 | struct opp *curr_opp; | 93 | struct busfreq_opp_info curr_oppinfo; |
84 | struct exynos4_ppmu dmc[2]; | 94 | struct exynos4_ppmu dmc[2]; |
85 | 95 | ||
86 | struct notifier_block pm_notifier; | 96 | struct notifier_block pm_notifier; |
@@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = { | |||
296 | }; | 306 | }; |
297 | 307 | ||
298 | 308 | ||
299 | static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | 309 | static int exynos4210_set_busclk(struct busfreq_data *data, |
310 | struct busfreq_opp_info *oppi) | ||
300 | { | 311 | { |
301 | unsigned int index; | 312 | unsigned int index; |
302 | unsigned int tmp; | 313 | unsigned int tmp; |
303 | 314 | ||
304 | for (index = LV_0; index < EX4210_LV_NUM; index++) | 315 | for (index = LV_0; index < EX4210_LV_NUM; index++) |
305 | if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk) | 316 | if (oppi->rate == exynos4210_busclk_table[index].clk) |
306 | break; | 317 | break; |
307 | 318 | ||
308 | if (index == EX4210_LV_NUM) | 319 | if (index == EX4210_LV_NUM) |
@@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | |||
361 | return 0; | 372 | return 0; |
362 | } | 373 | } |
363 | 374 | ||
364 | static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp) | 375 | static int exynos4x12_set_busclk(struct busfreq_data *data, |
376 | struct busfreq_opp_info *oppi) | ||
365 | { | 377 | { |
366 | unsigned int index; | 378 | unsigned int index; |
367 | unsigned int tmp; | 379 | unsigned int tmp; |
368 | 380 | ||
369 | for (index = LV_0; index < EX4x12_LV_NUM; index++) | 381 | for (index = LV_0; index < EX4x12_LV_NUM; index++) |
370 | if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk) | 382 | if (oppi->rate == exynos4x12_mifclk_table[index].clk) |
371 | break; | 383 | break; |
372 | 384 | ||
373 | if (index == EX4x12_LV_NUM) | 385 | if (index == EX4x12_LV_NUM) |
@@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk) | |||
576 | return -EINVAL; | 588 | return -EINVAL; |
577 | } | 589 | } |
578 | 590 | ||
579 | static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | 591 | static int exynos4_bus_setvolt(struct busfreq_data *data, |
580 | struct opp *oldopp) | 592 | struct busfreq_opp_info *oppi, |
593 | struct busfreq_opp_info *oldoppi) | ||
581 | { | 594 | { |
582 | int err = 0, tmp; | 595 | int err = 0, tmp; |
583 | unsigned long volt = opp_get_voltage(opp); | 596 | unsigned long volt = oppi->volt; |
584 | 597 | ||
585 | switch (data->type) { | 598 | switch (data->type) { |
586 | case TYPE_BUSF_EXYNOS4210: | 599 | case TYPE_BUSF_EXYNOS4210: |
@@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
595 | if (err) | 608 | if (err) |
596 | break; | 609 | break; |
597 | 610 | ||
598 | tmp = exynos4x12_get_intspec(opp_get_freq(opp)); | 611 | tmp = exynos4x12_get_intspec(oppi->rate); |
599 | if (tmp < 0) { | 612 | if (tmp < 0) { |
600 | err = tmp; | 613 | err = tmp; |
601 | regulator_set_voltage(data->vdd_mif, | 614 | regulator_set_voltage(data->vdd_mif, |
602 | opp_get_voltage(oldopp), | 615 | oldoppi->volt, |
603 | MAX_SAFEVOLT); | 616 | MAX_SAFEVOLT); |
604 | break; | 617 | break; |
605 | } | 618 | } |
@@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
609 | /* Try to recover */ | 622 | /* Try to recover */ |
610 | if (err) | 623 | if (err) |
611 | regulator_set_voltage(data->vdd_mif, | 624 | regulator_set_voltage(data->vdd_mif, |
612 | opp_get_voltage(oldopp), | 625 | oldoppi->volt, |
613 | MAX_SAFEVOLT); | 626 | MAX_SAFEVOLT); |
614 | break; | 627 | break; |
615 | default: | 628 | default: |
@@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
626 | struct platform_device *pdev = container_of(dev, struct platform_device, | 639 | struct platform_device *pdev = container_of(dev, struct platform_device, |
627 | dev); | 640 | dev); |
628 | struct busfreq_data *data = platform_get_drvdata(pdev); | 641 | struct busfreq_data *data = platform_get_drvdata(pdev); |
629 | struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); | 642 | struct opp *opp; |
630 | unsigned long freq = opp_get_freq(opp); | 643 | unsigned long freq; |
631 | unsigned long old_freq = opp_get_freq(data->curr_opp); | 644 | unsigned long old_freq = data->curr_oppinfo.rate; |
645 | struct busfreq_opp_info new_oppinfo; | ||
632 | 646 | ||
633 | if (IS_ERR(opp)) | 647 | rcu_read_lock(); |
648 | opp = devfreq_recommended_opp(dev, _freq, flags); | ||
649 | if (IS_ERR(opp)) { | ||
650 | rcu_read_unlock(); | ||
634 | return PTR_ERR(opp); | 651 | return PTR_ERR(opp); |
652 | } | ||
653 | new_oppinfo.rate = opp_get_freq(opp); | ||
654 | new_oppinfo.volt = opp_get_voltage(opp); | ||
655 | rcu_read_unlock(); | ||
656 | freq = new_oppinfo.rate; | ||
635 | 657 | ||
636 | if (old_freq == freq) | 658 | if (old_freq == freq) |
637 | return 0; | 659 | return 0; |
638 | 660 | ||
639 | dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp)); | 661 | dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt); |
640 | 662 | ||
641 | mutex_lock(&data->lock); | 663 | mutex_lock(&data->lock); |
642 | 664 | ||
@@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
644 | goto out; | 666 | goto out; |
645 | 667 | ||
646 | if (old_freq < freq) | 668 | if (old_freq < freq) |
647 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 669 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
670 | &data->curr_oppinfo); | ||
648 | if (err) | 671 | if (err) |
649 | goto out; | 672 | goto out; |
650 | 673 | ||
651 | if (old_freq != freq) { | 674 | if (old_freq != freq) { |
652 | switch (data->type) { | 675 | switch (data->type) { |
653 | case TYPE_BUSF_EXYNOS4210: | 676 | case TYPE_BUSF_EXYNOS4210: |
654 | err = exynos4210_set_busclk(data, opp); | 677 | err = exynos4210_set_busclk(data, &new_oppinfo); |
655 | break; | 678 | break; |
656 | case TYPE_BUSF_EXYNOS4x12: | 679 | case TYPE_BUSF_EXYNOS4x12: |
657 | err = exynos4x12_set_busclk(data, opp); | 680 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
658 | break; | 681 | break; |
659 | default: | 682 | default: |
660 | err = -EINVAL; | 683 | err = -EINVAL; |
@@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
664 | goto out; | 687 | goto out; |
665 | 688 | ||
666 | if (old_freq > freq) | 689 | if (old_freq > freq) |
667 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 690 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
691 | &data->curr_oppinfo); | ||
668 | if (err) | 692 | if (err) |
669 | goto out; | 693 | goto out; |
670 | 694 | ||
671 | data->curr_opp = opp; | 695 | data->curr_oppinfo = new_oppinfo; |
672 | out: | 696 | out: |
673 | mutex_unlock(&data->lock); | 697 | mutex_unlock(&data->lock); |
674 | return err; | 698 | return err; |
@@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, | |||
702 | 726 | ||
703 | exynos4_read_ppmu(data); | 727 | exynos4_read_ppmu(data); |
704 | busier_dmc = exynos4_get_busier_dmc(data); | 728 | busier_dmc = exynos4_get_busier_dmc(data); |
705 | stat->current_frequency = opp_get_freq(data->curr_opp); | 729 | stat->current_frequency = data->curr_oppinfo.rate; |
706 | 730 | ||
707 | if (busier_dmc) | 731 | if (busier_dmc) |
708 | addr = S5P_VA_DMC1; | 732 | addr = S5P_VA_DMC1; |
@@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
933 | struct busfreq_data *data = container_of(this, struct busfreq_data, | 957 | struct busfreq_data *data = container_of(this, struct busfreq_data, |
934 | pm_notifier); | 958 | pm_notifier); |
935 | struct opp *opp; | 959 | struct opp *opp; |
960 | struct busfreq_opp_info new_oppinfo; | ||
936 | unsigned long maxfreq = ULONG_MAX; | 961 | unsigned long maxfreq = ULONG_MAX; |
937 | int err = 0; | 962 | int err = 0; |
938 | 963 | ||
@@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
943 | 968 | ||
944 | data->disabled = true; | 969 | data->disabled = true; |
945 | 970 | ||
971 | rcu_read_lock(); | ||
946 | opp = opp_find_freq_floor(data->dev, &maxfreq); | 972 | opp = opp_find_freq_floor(data->dev, &maxfreq); |
973 | if (IS_ERR(opp)) { | ||
974 | rcu_read_unlock(); | ||
975 | dev_err(data->dev, "%s: unable to find a min freq\n", | ||
976 | __func__); | ||
977 | return PTR_ERR(opp); | ||
978 | } | ||
979 | new_oppinfo.rate = opp_get_freq(opp); | ||
980 | new_oppinfo.volt = opp_get_voltage(opp); | ||
981 | rcu_read_unlock(); | ||
947 | 982 | ||
948 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 983 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
984 | &data->curr_oppinfo); | ||
949 | if (err) | 985 | if (err) |
950 | goto unlock; | 986 | goto unlock; |
951 | 987 | ||
952 | switch (data->type) { | 988 | switch (data->type) { |
953 | case TYPE_BUSF_EXYNOS4210: | 989 | case TYPE_BUSF_EXYNOS4210: |
954 | err = exynos4210_set_busclk(data, opp); | 990 | err = exynos4210_set_busclk(data, &new_oppinfo); |
955 | break; | 991 | break; |
956 | case TYPE_BUSF_EXYNOS4x12: | 992 | case TYPE_BUSF_EXYNOS4x12: |
957 | err = exynos4x12_set_busclk(data, opp); | 993 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
958 | break; | 994 | break; |
959 | default: | 995 | default: |
960 | err = -EINVAL; | 996 | err = -EINVAL; |
@@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
962 | if (err) | 998 | if (err) |
963 | goto unlock; | 999 | goto unlock; |
964 | 1000 | ||
965 | data->curr_opp = opp; | 1001 | data->curr_oppinfo = new_oppinfo; |
966 | unlock: | 1002 | unlock: |
967 | mutex_unlock(&data->lock); | 1003 | mutex_unlock(&data->lock); |
968 | if (err) | 1004 | if (err) |
@@ -1027,13 +1063,17 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) | |||
1027 | } | 1063 | } |
1028 | } | 1064 | } |
1029 | 1065 | ||
1066 | rcu_read_lock(); | ||
1030 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); | 1067 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); |
1031 | if (IS_ERR(opp)) { | 1068 | if (IS_ERR(opp)) { |
1069 | rcu_read_unlock(); | ||
1032 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", | 1070 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", |
1033 | exynos4_devfreq_profile.initial_freq); | 1071 | exynos4_devfreq_profile.initial_freq); |
1034 | return PTR_ERR(opp); | 1072 | return PTR_ERR(opp); |
1035 | } | 1073 | } |
1036 | data->curr_opp = opp; | 1074 | data->curr_oppinfo.rate = opp_get_freq(opp); |
1075 | data->curr_oppinfo.volt = opp_get_voltage(opp); | ||
1076 | rcu_read_unlock(); | ||
1037 | 1077 | ||
1038 | platform_set_drvdata(pdev, data); | 1078 | platform_set_drvdata(pdev, data); |
1039 | 1079 | ||
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4ba384f1ab54..2df9414a72f7 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -448,8 +448,6 @@ static int intel_idle_probe(void) | |||
448 | else | 448 | else |
449 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); | 449 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); |
450 | 450 | ||
451 | register_cpu_notifier(&cpu_hotplug_notifier); | ||
452 | |||
453 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION | 451 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION |
454 | " model 0x%X\n", boot_cpu_data.x86_model); | 452 | " model 0x%X\n", boot_cpu_data.x86_model); |
455 | 453 | ||
@@ -612,6 +610,7 @@ static int __init intel_idle_init(void) | |||
612 | return retval; | 610 | return retval; |
613 | } | 611 | } |
614 | } | 612 | } |
613 | register_cpu_notifier(&cpu_hotplug_notifier); | ||
615 | 614 | ||
616 | return 0; | 615 | return 0; |
617 | } | 616 | } |