|  | #include <linux/sched.h> | 
|  | #include <linux/math64.h> | 
|  | #include <linux/percpu.h> | 
|  | #include <linux/irqflags.h> | 
|  |  | 
|  | #include <asm/cpufeature.h> | 
|  | #include <asm/processor.h> | 
|  |  | 
|  | #ifdef CONFIG_SMP | 
|  |  | 
|  | static DEFINE_PER_CPU(struct aperfmperf, old_perf_sched); | 
|  |  | 
|  | static unsigned long scale_aperfmperf(void) | 
|  | { | 
|  | struct aperfmperf val, *old = &__get_cpu_var(old_perf_sched); | 
|  | unsigned long ratio, flags; | 
|  |  | 
|  | local_irq_save(flags); | 
|  | get_aperfmperf(&val); | 
|  | local_irq_restore(flags); | 
|  |  | 
|  | ratio = calc_aperfmperf_ratio(old, &val); | 
|  | *old = val; | 
|  |  | 
|  | return ratio; | 
|  | } | 
|  |  | 
|  | unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu) | 
|  | { | 
|  | /* | 
|  | * do aperf/mperf on the cpu level because it includes things | 
|  | * like turbo mode, which are relevant to full cores. | 
|  | */ | 
|  | if (boot_cpu_has(X86_FEATURE_APERFMPERF)) | 
|  | return scale_aperfmperf(); | 
|  |  | 
|  | /* | 
|  | * maybe have something cpufreq here | 
|  | */ | 
|  |  | 
|  | return default_scale_freq_power(sd, cpu); | 
|  | } | 
|  |  | 
|  | unsigned long arch_scale_smt_power(struct sched_domain *sd, int cpu) | 
|  | { | 
|  | /* | 
|  | * aperf/mperf already includes the smt gain | 
|  | */ | 
|  | if (boot_cpu_has(X86_FEATURE_APERFMPERF)) | 
|  | return SCHED_LOAD_SCALE; | 
|  |  | 
|  | return default_scale_smt_power(sd, cpu); | 
|  | } | 
|  |  | 
|  | #endif |