From 703cbaa601ff3fb554d1246c336ba727cc083ea0 Mon Sep 17 00:00:00 2001 From: Bo Yan Date: Tue, 23 Jan 2018 13:57:55 -0800 Subject: cpufreq: Skip cpufreq resume if it's not suspended cpufreq_resume can be called even without preceding cpufreq_suspend. This can happen in following scenario: suspend_devices_and_enter --> dpm_suspend_start --> dpm_prepare --> device_prepare : this function errors out --> dpm_suspend: this is skipped due to dpm_prepare failure this means cpufreq_suspend is skipped over --> goto Recover_platform, due to previous error --> goto Resume_devices --> dpm_resume_end --> dpm_resume --> cpufreq_resume In case schedutil is used as frequency governor, cpufreq_resume will eventually call sugov_start, which does following: memset(sg_cpu, 0, sizeof(*sg_cpu)); .... This effectively erases function pointer for frequency update, causing crash later on. The function pointer would have been set correctly if subsequent cpufreq_add_update_util_hook runs successfully, but that function returns earlier because cpufreq_suspend was not called: if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu))) return; The fix is to check cpufreq_suspended first, if it's false, that means cpufreq_suspend was not called in the first place, so do not resume cpufreq. Signed-off-by: Bo Yan Acked-by: Viresh Kumar [ rjw: Dropped printing a message ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 421f318c0e66..de33ebf008ad 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1686,6 +1686,9 @@ void cpufreq_resume(void) if (!cpufreq_driver) return; + if (unlikely(!cpufreq_suspended)) + return; + cpufreq_suspended = false; if (!has_target() && !cpufreq_driver->resume) -- cgit v1.2.3-59-g8ed1b From 59a3b3a8db16621574cbac69f6f1eddb9c60e821 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Thu, 18 Jan 2018 15:51:30 +0530 Subject: cpufreq: AMD: Ignore the check for ProcFeedback in ST/CZ In ST/CZ CPUID 8000_0007_EDX[11, ProcFeedbackInterface] is 0, but the mechanism is still available and can be used. Signed-off-by: Akshu Agrawal Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/amd_freq_sensitivity.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c index 042023bbbf62..be926d9a66e5 100644 --- a/drivers/cpufreq/amd_freq_sensitivity.c +++ b/drivers/cpufreq/amd_freq_sensitivity.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -109,12 +110,18 @@ out: static int __init amd_freq_sensitivity_init(void) { u64 val; + struct pci_dev *pcidev; if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return -ENODEV; - if (!static_cpu_has(X86_FEATURE_PROC_FEEDBACK)) - return -ENODEV; + pcidev = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, NULL); + + if (!pcidev) { + if (!static_cpu_has(X86_FEATURE_PROC_FEEDBACK)) + return -ENODEV; + } if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val)) return -ENODEV; -- cgit v1.2.3-59-g8ed1b From 3d70671667f15f4bae260541cd91330ef20d2f2e Mon Sep 17 00:00:00 2001 From: Corentin LABBE Date: Thu, 18 Jan 2018 21:02:02 +0100 Subject: cpufreq: remove at32ap-cpufreq Since AVR32 arch was removed, at32ap-cpufreq is useless. Remove this driver. Signed-off-by: Corentin Labbe Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig | 10 --- drivers/cpufreq/Makefile | 1 - drivers/cpufreq/at32ap-cpufreq.c | 127 --------------------------------------- 3 files changed, 138 deletions(-) delete mode 100644 drivers/cpufreq/at32ap-cpufreq.c (limited to 'drivers') diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d8addbce40bc..608af20a3494 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -239,16 +239,6 @@ if PPC32 || PPC64 source "drivers/cpufreq/Kconfig.powerpc" endif -if AVR32 -config AVR32_AT32AP_CPUFREQ - bool "CPU frequency driver for AT32AP" - depends on PLATFORM_AT32AP - default n - help - This enables the CPU frequency driver for AT32AP processors. - If in doubt, say N. -endif - if IA64 config IA64_ACPI_CPUFREQ tristate "ACPI Processor P-States driver" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index e07715ce8844..c60c1e141d9d 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,6 @@ obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o ################################################################################## # Other platform drivers -obj-$(CONFIG_AVR32_AT32AP_CPUFREQ) += at32ap-cpufreq.o obj-$(CONFIG_BFIN_CPU_FREQ) += blackfin-cpufreq.o obj-$(CONFIG_BMIPS_CPUFREQ) += bmips-cpufreq.o obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c deleted file mode 100644 index 7b612c8bb09e..000000000000 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2004-2007 Atmel Corporation - * - * Based on MIPS implementation arch/mips/kernel/time.c - * Copyright 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/*#define DEBUG*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct cpufreq_frequency_table *freq_table; - -static unsigned int ref_freq; -static unsigned long loops_per_jiffy_ref; - -static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) -{ - unsigned int old_freq, new_freq; - - old_freq = policy->cur; - new_freq = freq_table[index].frequency; - - if (!ref_freq) { - ref_freq = old_freq; - loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy; - } - - if (old_freq < new_freq) - boot_cpu_data.loops_per_jiffy = cpufreq_scale( - loops_per_jiffy_ref, ref_freq, new_freq); - clk_set_rate(policy->clk, new_freq * 1000); - if (new_freq < old_freq) - boot_cpu_data.loops_per_jiffy = cpufreq_scale( - loops_per_jiffy_ref, ref_freq, new_freq); - - return 0; -} - -static int at32_cpufreq_driver_init(struct cpufreq_policy *policy) -{ - unsigned int frequency, rate, min_freq; - struct clk *cpuclk; - int retval, steps, i; - - if (policy->cpu != 0) - return -EINVAL; - - cpuclk = clk_get(NULL, "cpu"); - if (IS_ERR(cpuclk)) { - pr_debug("cpufreq: could not get CPU clk\n"); - retval = PTR_ERR(cpuclk); - goto out_err; - } - - min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; - frequency = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; - policy->cpuinfo.transition_latency = 0; - - /* - * AVR32 CPU frequency rate scales in power of two between maximum and - * minimum, also add space for the table end marker. - * - * Further validate that the frequency is usable, and append it to the - * frequency table. - */ - steps = fls(frequency / min_freq) + 1; - freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table), - GFP_KERNEL); - if (!freq_table) { - retval = -ENOMEM; - goto out_err_put_clk; - } - - for (i = 0; i < (steps - 1); i++) { - rate = clk_round_rate(cpuclk, frequency * 1000) / 1000; - - if (rate != frequency) - freq_table[i].frequency = CPUFREQ_ENTRY_INVALID; - else - freq_table[i].frequency = frequency; - - frequency /= 2; - } - - policy->clk = cpuclk; - freq_table[steps - 1].frequency = CPUFREQ_TABLE_END; - - retval = cpufreq_table_validate_and_show(policy, freq_table); - if (!retval) { - printk("cpufreq: AT32AP CPU frequency driver\n"); - return 0; - } - - kfree(freq_table); -out_err_put_clk: - clk_put(cpuclk); -out_err: - return retval; -} - -static struct cpufreq_driver at32_driver = { - .name = "at32ap", - .init = at32_cpufreq_driver_init, - .verify = cpufreq_generic_frequency_table_verify, - .target_index = at32_set_target, - .get = cpufreq_generic_get, - .flags = CPUFREQ_STICKY, -}; - -static int __init at32_cpufreq_init(void) -{ - return cpufreq_register_driver(&at32_driver); -} -late_initcall(at32_cpufreq_init); -- cgit v1.2.3-59-g8ed1b From eb85c50c24cf3e96f9aa01fd3e6219ad36845a96 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 22 Jan 2018 14:41:07 +0000 Subject: cpufreq: scpi: fix static checker warning cdev isn't an ERR_PTR Commit 343a8d17fa8d (cpufreq: scpi: remove arm_big_little dependency) leads to the following static checker warning: drivers/cpufreq/scpi-cpufreq.c:203 scpi_cpufreq_ready() warn: 'cdev' isn't an ERR_PTR of_cpufreq_cooling_register() returns NULL on error. This patch removes the incorrect IS_ERR check on the returned pointer. Fixes: 343a8d17fa8d (cpufreq: scpi: remove arm_big_little dependency) Reported-by: Dan Carpenter Signed-off-by: Sudeep Holla Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/scpi-cpufreq.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index 247fcbfa4cb5..efe32cbefa06 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -197,11 +197,8 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy) static void scpi_cpufreq_ready(struct cpufreq_policy *policy) { struct scpi_data *priv = policy->driver_data; - struct thermal_cooling_device *cdev; - cdev = of_cpufreq_cooling_register(policy); - if (!IS_ERR(cdev)) - priv->cdev = cdev; + priv->cdev = of_cpufreq_cooling_register(policy); } static struct cpufreq_driver scpi_cpufreq_driver = { -- cgit v1.2.3-59-g8ed1b From a3381e3a65cbaf612c8f584906c4dba27e84267c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 23 Jan 2018 21:43:08 +0100 Subject: PM / domains: Fix up domain-idle-states OF parsing Commit b539cc82d493 (PM / Domains: Ignore domain-idle-states that are not compatible), made it possible to ignore non-compatible domain-idle-states OF nodes. However, in case that happens while doing the OF parsing, the number of elements in the allocated array would exceed the numbers actually needed, thus wasting memory. Fix this by pre-iterating the genpd OF node and counting the number of compatible domain-idle-states nodes, before doing the allocation. While doing this, it makes sense to rework the code a bit to avoid open coding, of parts responsible for the OF node iteration. Let's also take the opportunity to clarify the function header for of_genpd_parse_idle_states(), about what is being returned in case of errors. Fixes: b539cc82d493 (PM / Domains: Ignore domain-idle-states that are not compatible) Signed-off-by: Ulf Hansson Reviewed-by: Lina Iyer Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 76 +++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 528b24149bc7..1ea0e2502e8e 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2290,6 +2290,38 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, return 0; } +static int genpd_iterate_idle_states(struct device_node *dn, + struct genpd_power_state *states) +{ + int ret; + struct of_phandle_iterator it; + struct device_node *np; + int i = 0; + + ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); + if (ret <= 0) + return ret; + + /* Loop over the phandles until all the requested entry is found */ + of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { + np = it.node; + if (!of_match_node(idle_state_match, np)) + continue; + if (states) { + ret = genpd_parse_state(&states[i], np); + if (ret) { + pr_err("Parsing idle state node %pOF failed with err %d\n", + np, ret); + of_node_put(np); + return ret; + } + } + i++; + } + + return i; +} + /** * of_genpd_parse_idle_states: Return array of idle states for the genpd. * @@ -2299,49 +2331,31 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, * * Returns the device states parsed from the OF node. The memory for the states * is allocated by this function and is the responsibility of the caller to - * free the memory after use. + * free the memory after use. If no domain idle states is found it returns + * -EINVAL and in case of errors, a negative error code. */ int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n) { struct genpd_power_state *st; - struct device_node *np; - int i = 0; - int err, ret; - int count; - struct of_phandle_iterator it; - const struct of_device_id *match_id; + int ret; - count = of_count_phandle_with_args(dn, "domain-idle-states", NULL); - if (count <= 0) - return -EINVAL; + ret = genpd_iterate_idle_states(dn, NULL); + if (ret <= 0) + return ret < 0 ? ret : -EINVAL; - st = kcalloc(count, sizeof(*st), GFP_KERNEL); + st = kcalloc(ret, sizeof(*st), GFP_KERNEL); if (!st) return -ENOMEM; - /* Loop over the phandles until all the requested entry is found */ - of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) { - np = it.node; - match_id = of_match_node(idle_state_match, np); - if (!match_id) - continue; - ret = genpd_parse_state(&st[i++], np); - if (ret) { - pr_err - ("Parsing idle state node %pOF failed with err %d\n", - np, ret); - of_node_put(np); - kfree(st); - return ret; - } + ret = genpd_iterate_idle_states(dn, st); + if (ret <= 0) { + kfree(st); + return ret < 0 ? ret : -EINVAL; } - *n = i; - if (!i) - kfree(st); - else - *states = st; + *states = st; + *n = ret; return 0; } -- cgit v1.2.3-59-g8ed1b From 0725390da9fb5add90a6ee5d5bbe58b5f47b25ac Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 23 Jan 2018 02:09:02 +0000 Subject: cpufreq: scpi: fix error return code in scpi_cpufreq_init() Fix to return a negative error code from the clk_get() error handling case instead of 0, as done elsewhere in this function. Fixes: 343a8d17fa8d (cpufreq: scpi: remove arm_big_little dependency) Signed-off-by: Wei Yongjun Acked-by: Viresh Kumar Acked-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/scpi-cpufreq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index efe32cbefa06..c32a833e1b00 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -145,6 +145,7 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy) if (IS_ERR(priv->clk)) { dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d\n", __func__, cpu_dev->id); + ret = PTR_ERR(priv->clk); goto out_free_cpufreq_table; } -- cgit v1.2.3-59-g8ed1b From 70f6bf2a3b7e40c3f802b0ea837762a8bc6c1430 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 29 Jan 2018 10:27:57 +0800 Subject: cpufreq: intel_pstate: Enable HWP during system resume on CPU0 When maxcpus=1 is in the kernel command line, the BP is responsible for re-enabling the HWP - because currently only the APs invoke intel_pstate_hwp_enable() during their online process - which might put the system into unstable state after resume. Fix this by enabling the HWP explicitly on BP during resume. Reported-by: Doug Smythies Suggested-by: Srinivas Pandruvada Signed-off-by: Yu Chen [ rjw: Subject/changelog, minor modifications ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7edf7a0e5a96..6d084c61ee25 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -779,6 +779,8 @@ static int intel_pstate_hwp_save_state(struct cpufreq_policy *policy) return 0; } +static void intel_pstate_hwp_enable(struct cpudata *cpudata); + static int intel_pstate_resume(struct cpufreq_policy *policy) { if (!hwp_active) @@ -786,6 +788,9 @@ static int intel_pstate_resume(struct cpufreq_policy *policy) mutex_lock(&intel_pstate_limits_lock); + if (policy->cpu == 0) + intel_pstate_hwp_enable(all_cpu_data[policy->cpu]); + all_cpu_data[policy->cpu]->epp_policy = 0; intel_pstate_hwp_set(policy->cpu); -- cgit v1.2.3-59-g8ed1b From ffd81dcfef85a33729f90e4acd2f61a68e56b993 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 30 Jan 2018 06:42:37 +0100 Subject: cpufreq: Add and use cpufreq_for_each_{valid_,}entry_idx() Pointer subtraction is slow and tedious. Therefore, replace all instances where cpufreq_for_each_{valid_,}entry loops contained such substractions with an iteration macro providing an index to the frequency_table entry. Suggested-by: Al Viro Link: http://lkml.kernel.org/r/20180120020237.GM13338@ZenIV.linux.org.uk Acked-by: Viresh Kumar Signed-off-by: Dominik Brodowski Signed-off-by: Rafael J. Wysocki --- Documentation/cpu-freq/cpu-drivers.txt | 4 ++ drivers/cpufreq/exynos5440-cpufreq.c | 7 +- drivers/cpufreq/freq_table.c | 8 +-- drivers/cpufreq/longhaul.c | 4 +- drivers/cpufreq/pasemi-cpufreq.c | 6 +- drivers/sh/clk/core.c | 5 +- drivers/staging/irda/drivers/sh_sir.c | 4 +- include/linux/cpufreq.h | 125 +++++++++++++++++++++------------ 8 files changed, 100 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 434c49cc7330..61546ac578d6 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -291,3 +291,7 @@ For example: /* Do something with pos */ pos->frequency = ... } + +If you need to work with the position of pos within driver_freq_table, +do not subtract the pointers, as it is quite costly. Instead, use the +macros cpufreq_for_each_entry_idx() and cpufreq_for_each_valid_entry_idx(). diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index b6b369c22272..932caa386ece 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -115,10 +115,10 @@ static struct cpufreq_freqs freqs; static int init_div_table(void) { struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table; - unsigned int tmp, clk_div, ema_div, freq, volt_id; + unsigned int tmp, clk_div, ema_div, freq, volt_id, idx; struct dev_pm_opp *opp; - cpufreq_for_each_entry(pos, freq_tbl) { + cpufreq_for_each_entry_idx(pos, freq_tbl, idx) { opp = dev_pm_opp_find_freq_exact(dvfs_info->dev, pos->frequency * 1000, true); if (IS_ERR(opp)) { @@ -154,8 +154,7 @@ static int init_div_table(void) tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT) | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT)); - __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * - (pos - freq_tbl)); + __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * idx); dev_pm_opp_put(opp); } diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 3bbbf9e6960c..6d007f824ca7 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -143,10 +143,9 @@ int cpufreq_table_index_unsorted(struct cpufreq_policy *policy, break; } - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, i) { freq = pos->frequency; - i = pos - table; if ((freq < policy->min) || (freq > policy->max)) continue; if (freq == target_freq) { @@ -211,15 +210,16 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, unsigned int freq) { struct cpufreq_frequency_table *pos, *table = policy->freq_table; + int idx; if (unlikely(!table)) { pr_debug("%s: Unable to find frequency table\n", __func__); return -ENOENT; } - cpufreq_for_each_valid_entry(pos, table) + cpufreq_for_each_valid_entry_idx(pos, table, idx) if (pos->frequency == freq) - return pos - table; + return idx; return -EINVAL; } diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 5faa37c5b091..942632a27b50 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -600,7 +600,7 @@ static void longhaul_setup_voltagescaling(void) /* Calculate kHz for one voltage step */ kHz_step = (highest_speed - min_vid_speed) / numvscales; - cpufreq_for_each_entry(freq_pos, longhaul_table) { + cpufreq_for_each_entry_idx(freq_pos, longhaul_table, j) { speed = freq_pos->frequency; if (speed > min_vid_speed) pos = (speed - min_vid_speed) / kHz_step + minvid.pos; @@ -609,7 +609,7 @@ static void longhaul_setup_voltagescaling(void) freq_pos->driver_data |= mV_vrm_table[pos] << 8; vid = vrm_mV_table[mV_vrm_table[pos]]; pr_info("f: %d kHz, index: %d, vid: %d mV\n", - speed, (int)(freq_pos - longhaul_table), vid.mV); + speed, j, vid.mV); } can_scale_voltage = 1; diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index b257fc7d5204..75dfbd2a58ea 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -139,7 +139,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) struct cpufreq_frequency_table *pos; const u32 *max_freqp; u32 max_freq; - int cur_astate; + int cur_astate, idx; struct resource res; struct device_node *cpu, *dn; int err = -ENODEV; @@ -198,9 +198,9 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) pr_debug("initializing frequency table\n"); /* initialize frequency table */ - cpufreq_for_each_entry(pos, pas_freqs) { + cpufreq_for_each_entry_idx(pos, pas_freqs, idx) { pos->frequency = get_astate_freq(pos->driver_data) * 100000; - pr_debug("%d: %d\n", (int)(pos - pas_freqs), pos->frequency); + pr_debug("%d: %d\n", idx, pos->frequency); } cur_astate = get_cur_astate(policy->cpu); diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 92863e3818e5..9475353f49d6 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -197,10 +197,11 @@ int clk_rate_table_find(struct clk *clk, unsigned long rate) { struct cpufreq_frequency_table *pos; + int idx; - cpufreq_for_each_valid_entry(pos, freq_table) + cpufreq_for_each_valid_entry_idx(pos, freq_table, idx) if (pos->frequency == rate) - return pos - freq_table; + return idx; return -ENOENT; } diff --git a/drivers/staging/irda/drivers/sh_sir.c b/drivers/staging/irda/drivers/sh_sir.c index fede6864c737..0d0687cc454a 100644 --- a/drivers/staging/irda/drivers/sh_sir.c +++ b/drivers/staging/irda/drivers/sh_sir.c @@ -226,7 +226,7 @@ static u32 sh_sir_find_sclk(struct clk *irda_clk) clk_put(pclk); /* IrDA can not set over peripheral_clk */ - cpufreq_for_each_valid_entry(pos, freq_table) { + cpufreq_for_each_valid_entry_idx(pos, freq_table, index) { u32 freq = pos->frequency; /* IrDA should not over peripheral_clk */ @@ -236,7 +236,7 @@ static u32 sh_sir_find_sclk(struct clk *irda_clk) tmp = freq % SCLK_BASE; if (tmp < min) { min = tmp; - index = pos - freq_table; + break; } } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 065f3a8eb486..21e8d248d956 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -628,6 +628,18 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev, #define cpufreq_for_each_entry(pos, table) \ for (pos = table; pos->frequency != CPUFREQ_TABLE_END; pos++) +/* + * cpufreq_for_each_entry_idx - iterate over a cpufreq_frequency_table + * with index + * @pos: the cpufreq_frequency_table * to use as a loop cursor. + * @table: the cpufreq_frequency_table * to iterate over. + * @idx: the table entry currently being processed + */ + +#define cpufreq_for_each_entry_idx(pos, table, idx) \ + for (pos = table, idx = 0; pos->frequency != CPUFREQ_TABLE_END; \ + pos++, idx++) + /* * cpufreq_for_each_valid_entry - iterate over a cpufreq_frequency_table * excluding CPUFREQ_ENTRY_INVALID frequencies. @@ -641,6 +653,21 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev, continue; \ else +/* + * cpufreq_for_each_valid_entry_idx - iterate with index over a cpufreq + * frequency_table excluding CPUFREQ_ENTRY_INVALID frequencies. + * @pos: the cpufreq_frequency_table * to use as a loop cursor. + * @table: the cpufreq_frequency_table * to iterate over. + * @idx: the table entry currently being processed + */ + +#define cpufreq_for_each_valid_entry_idx(pos, table, idx) \ + cpufreq_for_each_entry_idx(pos, table, idx) \ + if (pos->frequency == CPUFREQ_ENTRY_INVALID) \ + continue; \ + else + + int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); @@ -667,19 +694,20 @@ static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq >= target_freq) - return pos - table; + return idx; - best = pos; + best = idx; } - return best - table; + return best; } /* Find lowest freq at or above target in a table in descending order */ @@ -687,28 +715,29 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq > target_freq) { - best = pos; + best = idx; continue; } /* No freq found above target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Works only on sorted freq-tables */ @@ -728,28 +757,29 @@ static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq < target_freq) { - best = pos; + best = idx; continue; } /* No freq found below target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Find highest freq at or below target in a table in descending order */ @@ -757,19 +787,20 @@ static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq <= target_freq) - return pos - table; + return idx; - best = pos; + best = idx; } - return best - table; + return best; } /* Works only on sorted freq-tables */ @@ -789,32 +820,33 @@ static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq < target_freq) { - best = pos; + best = idx; continue; } /* No freq found below target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; /* Choose the closest freq */ - if (target_freq - best->frequency > freq - target_freq) - return pos - table; + if (target_freq - table[best].frequency > freq - target_freq) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Find closest freq to target in a table in descending order */ @@ -822,32 +854,33 @@ static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq > target_freq) { - best = pos; + best = idx; continue; } /* No freq found above target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; /* Choose the closest freq */ - if (best->frequency - target_freq > target_freq - freq) - return pos - table; + if (table[best].frequency - target_freq > target_freq - freq) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Works only on sorted freq-tables */ -- cgit v1.2.3-59-g8ed1b From d0404738c687c0ecaa7d6b7c5c39e4c0dac791e6 Mon Sep 17 00:00:00 2001 From: Nicolas Chauvet Date: Tue, 30 Jan 2018 10:55:26 +0100 Subject: arm: imx: Add MODULE_ALIAS for cpufreq Without this, the imx6q-cpufreq driver isn't loaded automatically when built as a module Tested on wandboard quad with a fedora 27 kernel rpm Signed-off-by: Nicolas Chauvet Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/imx6q-cpufreq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 741f22e5cee3..ff67859948b3 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -504,6 +504,7 @@ static struct platform_driver imx6q_cpufreq_platdrv = { }; module_platform_driver(imx6q_cpufreq_platdrv); +MODULE_ALIAS("platform:imx6q-cpufreq"); MODULE_AUTHOR("Shawn Guo "); MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b