summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kernel/smp.c24
-rw-r--r--arch/sparc/kernel/time_64.c28
-rw-r--r--arch/x86/kernel/tsc.c2
-rw-r--r--arch/x86/kvm/x86.c31
-rw-r--r--drivers/cpufreq/cpufreq.c19
-rw-r--r--include/linux/cpufreq.h14
6 files changed, 69 insertions, 49 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index facd4240ca02..c6d37563610a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -754,15 +754,20 @@ static int cpufreq_callback(struct notifier_block *nb,
754 unsigned long val, void *data) 754 unsigned long val, void *data)
755{ 755{
756 struct cpufreq_freqs *freq = data; 756 struct cpufreq_freqs *freq = data;
757 int cpu = freq->cpu; 757 struct cpumask *cpus = freq->policy->cpus;
758 int cpu, first = cpumask_first(cpus);
759 unsigned int lpj;
758 760
759 if (freq->flags & CPUFREQ_CONST_LOOPS) 761 if (freq->flags & CPUFREQ_CONST_LOOPS)
760 return NOTIFY_OK; 762 return NOTIFY_OK;
761 763
762 if (!per_cpu(l_p_j_ref, cpu)) { 764 if (!per_cpu(l_p_j_ref, first)) {
763 per_cpu(l_p_j_ref, cpu) = 765 for_each_cpu(cpu, cpus) {
764 per_cpu(cpu_data, cpu).loops_per_jiffy; 766 per_cpu(l_p_j_ref, cpu) =
765 per_cpu(l_p_j_ref_freq, cpu) = freq->old; 767 per_cpu(cpu_data, cpu).loops_per_jiffy;
768 per_cpu(l_p_j_ref_freq, cpu) = freq->old;
769 }
770
766 if (!global_l_p_j_ref) { 771 if (!global_l_p_j_ref) {
767 global_l_p_j_ref = loops_per_jiffy; 772 global_l_p_j_ref = loops_per_jiffy;
768 global_l_p_j_ref_freq = freq->old; 773 global_l_p_j_ref_freq = freq->old;
@@ -774,10 +779,11 @@ static int cpufreq_callback(struct notifier_block *nb,
774 loops_per_jiffy = cpufreq_scale(global_l_p_j_ref, 779 loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
775 global_l_p_j_ref_freq, 780 global_l_p_j_ref_freq,
776 freq->new); 781 freq->new);
777 per_cpu(cpu_data, cpu).loops_per_jiffy = 782
778 cpufreq_scale(per_cpu(l_p_j_ref, cpu), 783 lpj = cpufreq_scale(per_cpu(l_p_j_ref, first),
779 per_cpu(l_p_j_ref_freq, cpu), 784 per_cpu(l_p_j_ref_freq, first), freq->new);
780 freq->new); 785 for_each_cpu(cpu, cpus)
786 per_cpu(cpu_data, cpu).loops_per_jiffy = lpj;
781 } 787 }
782 return NOTIFY_OK; 788 return NOTIFY_OK;
783} 789}
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index 3eb77943ce12..89fb05f90609 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -653,19 +653,23 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
653 void *data) 653 void *data)
654{ 654{
655 struct cpufreq_freqs *freq = data; 655 struct cpufreq_freqs *freq = data;
656 unsigned int cpu = freq->cpu; 656 unsigned int cpu;
657 struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu); 657 struct freq_table *ft;
658 658
659 if (!ft->ref_freq) { 659 for_each_cpu(cpu, freq->policy->cpus) {
660 ft->ref_freq = freq->old; 660 ft = &per_cpu(sparc64_freq_table, cpu);
661 ft->clock_tick_ref = cpu_data(cpu).clock_tick; 661
662 } 662 if (!ft->ref_freq) {
663 if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || 663 ft->ref_freq = freq->old;
664 (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) { 664 ft->clock_tick_ref = cpu_data(cpu).clock_tick;
665 cpu_data(cpu).clock_tick = 665 }
666 cpufreq_scale(ft->clock_tick_ref, 666
667 ft->ref_freq, 667 if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
668 freq->new); 668 (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
669 cpu_data(cpu).clock_tick =
670 cpufreq_scale(ft->clock_tick_ref, ft->ref_freq,
671 freq->new);
672 }
669 } 673 }
670 674
671 return 0; 675 return 0;
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 15b5e98a86f9..356dfc555a27 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -979,7 +979,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
979 if (!(freq->flags & CPUFREQ_CONST_LOOPS)) 979 if (!(freq->flags & CPUFREQ_CONST_LOOPS))
980 mark_tsc_unstable("cpufreq changes"); 980 mark_tsc_unstable("cpufreq changes");
981 981
982 set_cyc2ns_scale(tsc_khz, freq->cpu, rdtsc()); 982 set_cyc2ns_scale(tsc_khz, freq->policy->cpu, rdtsc());
983 } 983 }
984 984
985 return 0; 985 return 0;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b5edc8e3ce1d..22cc90baa67f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6698,10 +6698,8 @@ static void kvm_hyperv_tsc_notifier(void)
6698} 6698}
6699#endif 6699#endif
6700 6700
6701static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 6701static void __kvmclock_cpufreq_notifier(struct cpufreq_freqs *freq, int cpu)
6702 void *data)
6703{ 6702{
6704 struct cpufreq_freqs *freq = data;
6705 struct kvm *kvm; 6703 struct kvm *kvm;
6706 struct kvm_vcpu *vcpu; 6704 struct kvm_vcpu *vcpu;
6707 int i, send_ipi = 0; 6705 int i, send_ipi = 0;
@@ -6745,17 +6743,12 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
6745 * 6743 *
6746 */ 6744 */
6747 6745
6748 if (val == CPUFREQ_PRECHANGE && freq->old > freq->new) 6746 smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
6749 return 0;
6750 if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
6751 return 0;
6752
6753 smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
6754 6747
6755 spin_lock(&kvm_lock); 6748 spin_lock(&kvm_lock);
6756 list_for_each_entry(kvm, &vm_list, vm_list) { 6749 list_for_each_entry(kvm, &vm_list, vm_list) {
6757 kvm_for_each_vcpu(i, vcpu, kvm) { 6750 kvm_for_each_vcpu(i, vcpu, kvm) {
6758 if (vcpu->cpu != freq->cpu) 6751 if (vcpu->cpu != cpu)
6759 continue; 6752 continue;
6760 kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); 6753 kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
6761 if (vcpu->cpu != smp_processor_id()) 6754 if (vcpu->cpu != smp_processor_id())
@@ -6777,8 +6770,24 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
6777 * guest context is entered kvmclock will be updated, 6770 * guest context is entered kvmclock will be updated,
6778 * so the guest will not see stale values. 6771 * so the guest will not see stale values.
6779 */ 6772 */
6780 smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1); 6773 smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
6781 } 6774 }
6775}
6776
6777static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
6778 void *data)
6779{
6780 struct cpufreq_freqs *freq = data;
6781 int cpu;
6782
6783 if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
6784 return 0;
6785 if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
6786 return 0;
6787
6788 for_each_cpu(cpu, freq->policy->cpus)
6789 __kvmclock_cpufreq_notifier(freq, cpu);
6790
6782 return 0; 6791 return 0;
6783} 6792}
6784 6793
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7ea217c88c2e..c66eefe928c5 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -340,11 +340,14 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
340 struct cpufreq_freqs *freqs, 340 struct cpufreq_freqs *freqs,
341 unsigned int state) 341 unsigned int state)
342{ 342{
343 int cpu;
344
343 BUG_ON(irqs_disabled()); 345 BUG_ON(irqs_disabled());
344 346
345 if (cpufreq_disabled()) 347 if (cpufreq_disabled())
346 return; 348 return;
347 349
350 freqs->policy = policy;
348 freqs->flags = cpufreq_driver->flags; 351 freqs->flags = cpufreq_driver->flags;
349 pr_debug("notification %u of frequency transition to %u kHz\n", 352 pr_debug("notification %u of frequency transition to %u kHz\n",
350 state, freqs->new); 353 state, freqs->new);
@@ -364,10 +367,8 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
364 } 367 }
365 } 368 }
366 369
367 for_each_cpu(freqs->cpu, policy->cpus) { 370 srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
368 srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 371 CPUFREQ_PRECHANGE, freqs);
369 CPUFREQ_PRECHANGE, freqs);
370 }
371 372
372 adjust_jiffies(CPUFREQ_PRECHANGE, freqs); 373 adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
373 break; 374 break;
@@ -377,11 +378,11 @@ static void cpufreq_notify_transition(struct cpufreq_policy *policy,
377 pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new, 378 pr_debug("FREQ: %u - CPUs: %*pbl\n", freqs->new,
378 cpumask_pr_args(policy->cpus)); 379 cpumask_pr_args(policy->cpus));
379 380
380 for_each_cpu(freqs->cpu, policy->cpus) { 381 for_each_cpu(cpu, policy->cpus)
381 trace_cpu_frequency(freqs->new, freqs->cpu); 382 trace_cpu_frequency(freqs->new, cpu);
382 srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 383
383 CPUFREQ_POSTCHANGE, freqs); 384 srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
384 } 385 CPUFREQ_POSTCHANGE, freqs);
385 386
386 cpufreq_stats_record_transition(policy, freqs->new); 387 cpufreq_stats_record_transition(policy, freqs->new);
387 policy->cur = freqs->new; 388 policy->cur = freqs->new;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 684caf067003..d01a74fbc4db 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -42,13 +42,6 @@ enum cpufreq_table_sorting {
42 CPUFREQ_TABLE_SORTED_DESCENDING 42 CPUFREQ_TABLE_SORTED_DESCENDING
43}; 43};
44 44
45struct cpufreq_freqs {
46 unsigned int cpu; /* cpu nr */
47 unsigned int old;
48 unsigned int new;
49 u8 flags; /* flags of cpufreq_driver, see below. */
50};
51
52struct cpufreq_cpuinfo { 45struct cpufreq_cpuinfo {
53 unsigned int max_freq; 46 unsigned int max_freq;
54 unsigned int min_freq; 47 unsigned int min_freq;
@@ -156,6 +149,13 @@ struct cpufreq_policy {
156 struct thermal_cooling_device *cdev; 149 struct thermal_cooling_device *cdev;
157}; 150};
158 151
152struct cpufreq_freqs {
153 struct cpufreq_policy *policy;
154 unsigned int old;
155 unsigned int new;
156 u8 flags; /* flags of cpufreq_driver, see below. */
157};
158
159/* Only for ACPI */ 159/* Only for ACPI */
160#define CPUFREQ_SHARED_TYPE_NONE (0) /* None */ 160#define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
161#define CPUFREQ_SHARED_TYPE_HW (1) /* HW does needed coordination */ 161#define CPUFREQ_SHARED_TYPE_HW (1) /* HW does needed coordination */