aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2021-06-21 12:45:35 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2021-07-12 09:48:08 +0530
commit807c1ef194f17bd410b01566f9eab1686304acbb (patch)
tree81306969beebe36f6fd623f864f283d52ab1f0b2
parente73f0f0ee7541171d89f2e2491130c7771ba58d3 (diff)
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c417
-rw-r--r--drivers/cpufreq/cpufreq.c2
2 files changed, 20 insertions, 399 deletions
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index d4c27022b9c9..c639fa054e0d 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -41,26 +41,6 @@
*/
static LIST_HEAD(cpu_data_list);
-static bool boost_supported;
-
-struct cppc_workaround_oem_info {
- char oem_id[ACPI_OEM_ID_SIZE + 1];
- char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
- u32 oem_revision;
-};
-
-static struct cppc_workaround_oem_info wa_info[] = {
- {
- .oem_id = "HISI ",
- .oem_table_id = "HIP07 ",
- .oem_revision = 0,
- }, {
- .oem_id = "HISI ",
- .oem_table_id = "HIP08 ",
- .oem_revision = 0,
- }
-};
-
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
/* Frequency invariance support */
@@ -109,23 +89,19 @@ static void cppc_scale_freq_workfn(struct kthread_work *work)
cppc_fi = container_of(work, struct cppc_freq_invariance, work);
cpu_data = cppc_fi->cpu_data;
- if (cppc_get_perf_ctrs(cppc_fi->cpu, &fb_ctrs)) {
- pr_warn("%s: failed to read perf counters\n", __func__);
- return;
- }
-
perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs,
&fb_ctrs);
cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
perf <<= SCHED_CAPACITY_SHIFT;
- local_freq_scale = div64_u64(perf, cpu_data->perf_caps.highest_perf);
+ local_freq_scale = div64_u64(perf, 1024);
/* This can happen due to counter's overflow */
if (unlikely(local_freq_scale > 1024))
local_freq_scale = 1024;
per_cpu(arch_freq_scale, cppc_fi->cpu) = local_freq_scale;
+ pr_info("%s: %d\n", __func__, __LINE__);
}
static void cppc_irq_work(struct irq_work *irq_work)
@@ -155,7 +131,7 @@ static struct scale_freq_data cppc_sftd = {
static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
{
struct cppc_freq_invariance *cppc_fi;
- int cpu, ret;
+ int cpu, ret = 0;
if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
return;
@@ -167,7 +143,6 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn);
init_irq_work(&cppc_fi->irq_work, cppc_irq_work);
- ret = cppc_get_perf_ctrs(cpu, &cppc_fi->prev_perf_fb_ctrs);
if (ret) {
pr_warn("%s: failed to read perf counters for cpu:%d: %d\n",
__func__, cpu, ret);
@@ -211,6 +186,11 @@ static void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy)
}
}
+static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
+{
+ return 0;
+}
+
static void __init cppc_freq_invariance_init(void)
{
struct sched_attr attr = {
@@ -271,123 +251,12 @@ static inline void cppc_freq_invariance_exit(void)
}
#endif /* CONFIG_ACPI_CPPC_CPUFREQ_FIE */
-/* Callback function used to retrieve the max frequency from DMI */
-static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
-{
- const u8 *dmi_data = (const u8 *)dm;
- u16 *mhz = (u16 *)private;
-
- if (dm->type == DMI_ENTRY_PROCESSOR &&
- dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) {
- u16 val = (u16)get_unaligned((const u16 *)
- (dmi_data + DMI_PROCESSOR_MAX_SPEED));
- *mhz = val > *mhz ? val : *mhz;
- }
-}
-
-/* Look up the max frequency in DMI */
-static u64 cppc_get_dmi_max_khz(void)
-{
- u16 mhz = 0;
-
- dmi_walk(cppc_find_dmi_mhz, &mhz);
-
- /*
- * Real stupid fallback value, just in case there is no
- * actual value set.
- */
- mhz = mhz ? mhz : 1;
-
- return (1000 * mhz);
-}
-
-/*
- * If CPPC lowest_freq and nominal_freq registers are exposed then we can
- * use them to convert perf to freq and vice versa
- *
- * If the perf/freq point lies between Nominal and Lowest, we can treat
- * (Low perf, Low freq) and (Nom Perf, Nom freq) as 2D co-ordinates of a line
- * and extrapolate the rest
- * For perf/freq > Nominal, we use the ratio perf:freq at Nominal for conversion
- */
-static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu_data,
- unsigned int perf)
-{
- struct cppc_perf_caps *caps = &cpu_data->perf_caps;
- static u64 max_khz;
- u64 mul, div;
-
- if (caps->lowest_freq && caps->nominal_freq) {
- if (perf >= caps->nominal_perf) {
- mul = caps->nominal_freq;
- div = caps->nominal_perf;
- } else {
- mul = caps->nominal_freq - caps->lowest_freq;
- div = caps->nominal_perf - caps->lowest_perf;
- }
- } else {
- if (!max_khz)
- max_khz = cppc_get_dmi_max_khz();
- mul = max_khz;
- div = caps->highest_perf;
- }
- return (u64)perf * mul / div;
-}
-
-static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data,
- unsigned int freq)
-{
- struct cppc_perf_caps *caps = &cpu_data->perf_caps;
- static u64 max_khz;
- u64 mul, div;
-
- if (caps->lowest_freq && caps->nominal_freq) {
- if (freq >= caps->nominal_freq) {
- mul = caps->nominal_perf;
- div = caps->nominal_freq;
- } else {
- mul = caps->lowest_perf;
- div = caps->lowest_freq;
- }
- } else {
- if (!max_khz)
- max_khz = cppc_get_dmi_max_khz();
- mul = caps->highest_perf;
- div = max_khz;
- }
-
- return (u64)freq * mul / div;
-}
-
static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- struct cppc_cpudata *cpu_data = policy->driver_data;
- unsigned int cpu = policy->cpu;
- struct cpufreq_freqs freqs;
- u32 desired_perf;
- int ret = 0;
-
- desired_perf = cppc_cpufreq_khz_to_perf(cpu_data, target_freq);
- /* Return if it is exactly the same perf */
- if (desired_perf == cpu_data->perf_ctrls.desired_perf)
- return ret;
-
- cpu_data->perf_ctrls.desired_perf = desired_perf;
- freqs.old = policy->cur;
- freqs.new = target_freq;
-
- cpufreq_freq_transition_begin(policy, &freqs);
- ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
- cpufreq_freq_transition_end(policy, &freqs, ret != 0);
-
- if (ret)
- pr_debug("Failed to set target on CPU:%d. ret:%d\n",
- cpu, ret);
-
- return ret;
+ return 0;
}
static int cppc_verify_policy(struct cpufreq_policy_data *policy)
@@ -396,44 +265,9 @@ static int cppc_verify_policy(struct cpufreq_policy_data *policy)
return 0;
}
-/*
- * The PCC subspace describes the rate at which platform can accept commands
- * on the shared PCC channel (including READs which do not count towards freq
- * transition requests), so ideally we need to use the PCC values as a fallback
- * if we don't have a platform specific transition_delay_us
- */
-#ifdef CONFIG_ARM64
-#include <asm/cputype.h>
-
-static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu)
-{
- unsigned long implementor = read_cpuid_implementor();
- unsigned long part_num = read_cpuid_part_number();
-
- switch (implementor) {
- case ARM_CPU_IMP_QCOM:
- switch (part_num) {
- case QCOM_CPU_PART_FALKOR_V1:
- case QCOM_CPU_PART_FALKOR:
- return 10000;
- }
- }
- return cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
-}
-
-#else
-
-static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu)
-{
- return cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
-}
-#endif
-
-
static struct cppc_cpudata *cppc_cpufreq_get_cpu_data(unsigned int cpu)
{
struct cppc_cpudata *cpu_data;
- int ret;
cpu_data = kzalloc(sizeof(struct cppc_cpudata), GFP_KERNEL);
if (!cpu_data)
@@ -442,18 +276,6 @@ static struct cppc_cpudata *cppc_cpufreq_get_cpu_data(unsigned int cpu)
if (!zalloc_cpumask_var(&cpu_data->shared_cpu_map, GFP_KERNEL))
goto free_cpu;
- ret = acpi_get_psd_map(cpu, cpu_data);
- if (ret) {
- pr_debug("Err parsing CPU%d PSD data: ret:%d\n", cpu, ret);
- goto free_mask;
- }
-
- ret = cppc_get_perf_caps(cpu, &cpu_data->perf_caps);
- if (ret) {
- pr_debug("Err reading CPU%d perf caps: ret:%d\n", cpu, ret);
- goto free_mask;
- }
-
/* Convert the lowest and nominal freq from MHz to KHz */
cpu_data->perf_caps.lowest_freq *= 1000;
cpu_data->perf_caps.nominal_freq *= 1000;
@@ -462,14 +284,18 @@ static struct cppc_cpudata *cppc_cpufreq_get_cpu_data(unsigned int cpu)
return cpu_data;
-free_mask:
- free_cpumask_var(cpu_data->shared_cpu_map);
free_cpu:
kfree(cpu_data);
out:
return NULL;
}
+static struct cpufreq_frequency_table freq_table[] = {
+ {0, 0, 800000},
+ {0, 0, 1000000},
+ {0, 0, CPUFREQ_TABLE_END},
+};
+
static void cppc_cpufreq_put_cpu_data(struct cpufreq_policy *policy)
{
struct cppc_cpudata *cpu_data = policy->driver_data;
@@ -485,7 +311,6 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
unsigned int cpu = policy->cpu;
struct cppc_cpudata *cpu_data;
struct cppc_perf_caps *caps;
- int ret;
cpu_data = cppc_cpufreq_get_cpu_data(cpu);
if (!cpu_data) {
@@ -495,90 +320,14 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
caps = &cpu_data->perf_caps;
policy->driver_data = cpu_data;
- /*
- * Set min to lowest nonlinear perf to avoid any efficiency penalty (see
- * Section 8.4.7.1.1.5 of ACPI 6.1 spec)
- */
- policy->min = cppc_cpufreq_perf_to_khz(cpu_data,
- caps->lowest_nonlinear_perf);
- policy->max = cppc_cpufreq_perf_to_khz(cpu_data,
- caps->nominal_perf);
-
- /*
- * Set cpuinfo.min_freq to Lowest to make the full range of performance
- * available if userspace wants to use any perf between lowest & lowest
- * nonlinear perf
- */
- policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu_data,
- caps->lowest_perf);
- policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu_data,
- caps->nominal_perf);
-
- policy->transition_delay_us = cppc_cpufreq_get_transition_delay_us(cpu);
- policy->shared_type = cpu_data->shared_type;
-
- switch (policy->shared_type) {
- case CPUFREQ_SHARED_TYPE_HW:
- case CPUFREQ_SHARED_TYPE_NONE:
- /* Nothing to be done - we'll have a policy for each CPU */
- break;
- case CPUFREQ_SHARED_TYPE_ANY:
- /*
- * All CPUs in the domain will share a policy and all cpufreq
- * operations will use a single cppc_cpudata structure stored
- * in policy->driver_data.
- */
- cpumask_copy(policy->cpus, cpu_data->shared_cpu_map);
- break;
- default:
- pr_debug("Unsupported CPU co-ord type: %d\n",
- policy->shared_type);
- ret = -EFAULT;
- goto out;
- }
-
- /*
- * If 'highest_perf' is greater than 'nominal_perf', we assume CPU Boost
- * is supported.
- */
- if (caps->highest_perf > caps->nominal_perf)
- boost_supported = true;
-
- /* Set policy->cur to max now. The governors will adjust later. */
- policy->cur = cppc_cpufreq_perf_to_khz(cpu_data, caps->highest_perf);
- cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
-
- ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
- if (ret) {
- pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
- caps->highest_perf, cpu, ret);
- goto out;
- }
-
+ cpufreq_generic_init(policy, freq_table, 10000);
cppc_cpufreq_cpu_fie_init(policy);
return 0;
-
-out:
- cppc_cpufreq_put_cpu_data(policy);
- return ret;
}
static int cppc_cpufreq_cpu_exit(struct cpufreq_policy *policy)
{
- struct cppc_cpudata *cpu_data = policy->driver_data;
- struct cppc_perf_caps *caps = &cpu_data->perf_caps;
- unsigned int cpu = policy->cpu;
- int ret;
-
cppc_cpufreq_cpu_fie_exit(policy);
-
- cpu_data->perf_ctrls.desired_perf = caps->lowest_perf;
-
- ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
- if (ret)
- pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
- caps->lowest_perf, cpu, ret);
-
cppc_cpufreq_put_cpu_data(policy);
return 0;
}
@@ -605,77 +354,13 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
delta_delivered = get_delta(fb_ctrs_t1->delivered,
fb_ctrs_t0->delivered);
- /* Check to avoid divide-by zero and invalid delivered_perf */
- if (!delta_reference || !delta_delivered)
- return cpu_data->perf_ctrls.desired_perf;
-
- return (reference_perf * delta_delivered) / delta_reference;
+ return 1000;
}
static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
{
- struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- struct cppc_cpudata *cpu_data = policy->driver_data;
- u64 delivered_perf;
- int ret;
-
- cpufreq_cpu_put(policy);
-
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
- if (ret)
- return ret;
-
- udelay(2); /* 2usec delay between sampling */
-
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1);
- if (ret)
- return ret;
-
- delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
- &fb_ctrs_t1);
-
- return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);
-}
-
-static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)
-{
- struct cppc_cpudata *cpu_data = policy->driver_data;
- struct cppc_perf_caps *caps = &cpu_data->perf_caps;
- int ret;
-
- if (!boost_supported) {
- pr_err("BOOST not supported by CPU or firmware\n");
- return -EINVAL;
- }
-
- if (state)
- policy->max = cppc_cpufreq_perf_to_khz(cpu_data,
- caps->highest_perf);
- else
- policy->max = cppc_cpufreq_perf_to_khz(cpu_data,
- caps->nominal_perf);
- policy->cpuinfo.max_freq = policy->max;
-
- ret = freq_qos_update_request(policy->max_freq_req, policy->max);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
-{
- struct cppc_cpudata *cpu_data = policy->driver_data;
-
- return cpufreq_show_cpus(cpu_data->shared_cpu_map, buf);
+ return 1000000;
}
-cpufreq_freq_attr_ro(freqdomain_cpus);
-
-static struct freq_attr *cppc_cpufreq_attr[] = {
- &freqdomain_cpus,
- NULL,
-};
static struct cpufreq_driver cppc_cpufreq_driver = {
.flags = CPUFREQ_CONST_LOOPS,
@@ -684,66 +369,15 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
.get = cppc_cpufreq_get_rate,
.init = cppc_cpufreq_cpu_init,
.exit = cppc_cpufreq_cpu_exit,
- .set_boost = cppc_cpufreq_set_boost,
- .attr = cppc_cpufreq_attr,
.name = "cppc_cpufreq",
};
-/*
- * HISI platform does not support delivered performance counter and
- * reference performance counter. It can calculate the performance using the
- * platform specific mechanism. We reuse the desired performance register to
- * store the real performance calculated by the platform.
- */
-static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
-{
- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
- struct cppc_cpudata *cpu_data = policy->driver_data;
- u64 desired_perf;
- int ret;
-
- cpufreq_cpu_put(policy);
-
- ret = cppc_get_desired_perf(cpu, &desired_perf);
- if (ret < 0)
- return -EIO;
-
- return cppc_cpufreq_perf_to_khz(cpu_data, desired_perf);
-}
-
-static void cppc_check_hisi_workaround(void)
-{
- struct acpi_table_header *tbl;
- acpi_status status = AE_OK;
- int i;
-
- status = acpi_get_table(ACPI_SIG_PCCT, 0, &tbl);
- if (ACPI_FAILURE(status) || !tbl)
- return;
-
- for (i = 0; i < ARRAY_SIZE(wa_info); i++) {
- if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) &&
- !memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
- wa_info[i].oem_revision == tbl->oem_revision) {
- /* Overwrite the get() callback */
- cppc_cpufreq_driver.get = hisi_cppc_cpufreq_get_rate;
- break;
- }
- }
-
- acpi_put_table(tbl);
-}
-
static int __init cppc_cpufreq_init(void)
{
int ret;
- if ((acpi_disabled) || !acpi_cpc_valid())
- return -ENODEV;
-
INIT_LIST_HEAD(&cpu_data_list);
- cppc_check_hisi_workaround();
cppc_freq_invariance_init();
ret = cpufreq_register_driver(&cppc_cpufreq_driver);
@@ -753,27 +387,14 @@ static int __init cppc_cpufreq_init(void)
return ret;
}
-static inline void free_cpu_data(void)
-{
- struct cppc_cpudata *iter, *tmp;
-
- list_for_each_entry_safe(iter, tmp, &cpu_data_list, node) {
- free_cpumask_var(iter->shared_cpu_map);
- list_del(&iter->node);
- kfree(iter);
- }
-
-}
-
static void __exit cppc_cpufreq_exit(void)
{
cpufreq_unregister_driver(&cppc_cpufreq_driver);
cppc_freq_invariance_exit();
-
- free_cpu_data();
}
module_exit(cppc_cpufreq_exit);
+
MODULE_AUTHOR("Ashwin Chaugule");
MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec");
MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 45f3416988f1..c82f8b163396 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -175,7 +175,7 @@ void cpufreq_generic_init(struct cpufreq_policy *policy,
* The driver only supports the SMP configuration where all processors
* share the clock and voltage and clock.
*/
- cpumask_setall(policy->cpus);
+// cpumask_setall(policy->cpus);
}
EXPORT_SYMBOL_GPL(cpufreq_generic_init);