History

cpufreq: CPPC: Enable fast_switch

The communication mean of the _CPC desired performance can be PCC, System Memory, System IO, or Functional Fixed Hardware. commit b7898fda5bc7 ("cpufreq: Support for fast frequency switching") fast_switching is 'for switching CPU frequencies from interrupt context'. Writes to SystemMemory and SystemIo are fast and suitable this. This is not the case for PCC and might not be the case for FFH. Enable fast_switching for the cppc_cpufreq driver in above cases. Add cppc_allow_fast_switch() to check the desired performance register address space and set fast_switching accordingly.

Pierre Gondois committed 4 years ago

Commit 3cc30dd1 parent 6380b7b3 files · +47 −0Browse files

Unified · Split

3 files
  1. drivers/acpi/cppc_acpi.c +18 −0
  2. drivers/cpufreq/cppc_cpufreq.c +24 −0
  3. include/acpi/cppc_acpi.h +5 −0
drivers/acpi/cppc_acpi.c+18−0
@@ -434,6 +434,24 @@ bool acpi_cpc_valid(void) · 433 unmodified lines
434434 }
435435 EXPORT_SYMBOL_GPL(acpi_cpc_valid);
436436
437+bool cppc_allow_fast_switch(void)
438+{
439+ struct cpc_register_resource *desired_reg;
440+ struct cpc_desc *cpc_ptr;
441+ int cpu;
442+
443+ for_each_possible_cpu(cpu) {
444+ cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
445+ desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF];
446+ if (!CPC_IN_SYSTEM_MEMORY(desired_reg) &&
447+ !CPC_IN_SYSTEM_IO(desired_reg))
448+ return false;
449+ }
450+
451+ return true;
452+}
453+EXPORT_SYMBOL_GPL(cppc_allow_fast_switch);
454+
437455 /**
438456 * acpi_get_psd_map - Map the CPUs in the freq domain of a given cpu
439457 * @cpu: Find all CPUs that share a domain with cpu.
drivers/cpufreq/cppc_cpufreq.c+24−0
@@ -389,6 +389,27 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy, · 388 unmodified lines
389389 return ret;
390390 }
391391
392+static unsigned int cppc_cpufreq_fast_switch(struct cpufreq_policy *policy,
393+ unsigned int target_freq)
394+{
395+ struct cppc_cpudata *cpu_data = policy->driver_data;
396+ unsigned int cpu = policy->cpu;
397+ u32 desired_perf;
398+ int ret;
399+
400+ desired_perf = cppc_cpufreq_khz_to_perf(cpu_data, target_freq);
401+ cpu_data->perf_ctrls.desired_perf = desired_perf;
402+ ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
403+
404+ if (ret) {
405+ pr_debug("Failed to set target on CPU:%d. ret:%d\n",
406+ cpu, ret);
407+ return 0;
408+ }
409+
410+ return target_freq;
411+}
412+
392413 static int cppc_verify_policy(struct cpufreq_policy_data *policy)
393414 {
394415 cpufreq_verify_within_cpu_limits(policy);
@@ -721,6 +742,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) · 326 unmodified lines
721742 goto out;
722743 }
723744
745+ policy->fast_switch_possible = cppc_allow_fast_switch();
746+
724747 /*
725748 * If 'highest_perf' is greater than 'nominal_perf', we assume CPU Boost
726749 * is supported.
@@ -866,6 +889,7 @@ static struct cpufreq_driver cppc_cpufreq_driver = { · 139 unmodified lines
866889 .verify = cppc_verify_policy,
867890 .target = cppc_cpufreq_set_target,
868891 .get = cppc_cpufreq_get_rate,
892+ .fast_switch = cppc_cpufreq_fast_switch,
869893 .init = cppc_cpufreq_cpu_init,
870894 .exit = cppc_cpufreq_cpu_exit,
871895 .set_boost = cppc_cpufreq_set_boost,
include/acpi/cppc_acpi.h+5−0
@@ -141,6 +141,7 @@ extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls); · 140 unmodified lines
141141 extern int cppc_set_enable(int cpu, bool enable);
142142 extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
143143 extern bool acpi_cpc_valid(void);
144+extern bool cppc_allow_fast_switch(void);
144145 extern int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data);
145146 extern unsigned int cppc_get_transition_latency(int cpu);
146147 extern bool cpc_ffh_supported(void);
@@ -175,6 +176,10 @@ static inline bool acpi_cpc_valid(void) · 28 unmodified lines
175176 {
176177 return false;
177178 }
179+static inline bool cppc_allow_fast_switch(void)
180+{
181+ return false;
182+}
178183 static inline unsigned int cppc_get_transition_latency(int cpu)
179184 {
180185 return CPUFREQ_ETERNAL;