diff options
| -rw-r--r-- | arch/arm/kernel/smp.c | 24 | ||||
| -rw-r--r-- | arch/sparc/kernel/time_64.c | 28 | ||||
| -rw-r--r-- | arch/x86/kernel/tsc.c | 2 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 31 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 19 | ||||
| -rw-r--r-- | include/linux/cpufreq.h | 14 |
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 | ||
| 6701 | static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | 6701 | static 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 | |||
| 6777 | static 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 | ||
| 45 | struct 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 | |||
| 52 | struct cpufreq_cpuinfo { | 45 | struct 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 | ||
| 152 | struct 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 */ |
