Skip to content

Commit

Permalink
Merge branch 'pm-cpufreq'
Browse files Browse the repository at this point in the history
* pm-cpufreq: (22 commits)
  cpufreq: stats: Handle the case when trans_table goes beyond PAGE_SIZE
  cpufreq: arm_big_little: make cpufreq_arm_bL_ops structures const
  cpufreq: arm_big_little: make function arguments and structure pointer const
  cpufreq: pxa: convert to clock API
  cpufreq: speedstep-lib: mark expected switch fall-through
  cpufreq: ti-cpufreq: add missing of_node_put()
  cpufreq: dt: Remove support for Exynos4212 SoCs
  cpufreq: imx6q: Move speed grading check to cpufreq driver
  cpufreq: ti-cpufreq: kfree opp_data when failure
  cpufreq: SPEAr: pr_err() strings should end with newlines
  cpufreq: powernow-k8: pr_err() strings should end with newlines
  cpufreq: dt-platdev: drop socionext,uniphier-ld6b from whitelist
  arm64: wire cpu-invariant accounting support up to the task scheduler
  arm64: wire frequency-invariant accounting support up to the task scheduler
  arm: wire cpu-invariant accounting support up to the task scheduler
  arm: wire frequency-invariant accounting support up to the task scheduler
  drivers base/arch_topology: allow inlining cpu-invariant accounting support
  drivers base/arch_topology: provide frequency-invariant accounting support
  cpufreq: dt: invoke frequency-invariance setter function
  cpufreq: arm_big_little: invoke frequency-invariance setter function
  ...
  • Loading branch information
rafaeljw committed Nov 13, 2017
2 parents 622ade3 + f7bc9b2 commit 60af981
Show file tree
Hide file tree
Showing 22 changed files with 214 additions and 286 deletions.
3 changes: 3 additions & 0 deletions Documentation/cpu-freq/cpufreq-stats.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ Freq_i to Freq_j. Freq_i is in descending order with increasing rows and
Freq_j is in descending order with increasing columns. The output here also
contains the actual freq values for each row and column for better readability.

If the transition table is bigger than PAGE_SIZE, reading this will
return an -EFBIG error.

--------------------------------------------------------------------------------
<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat trans_table
From : To
Expand Down
8 changes: 8 additions & 0 deletions arch/arm/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ void init_cpu_topology(void);
void store_cpu_topology(unsigned int cpuid);
const struct cpumask *cpu_coregroup_mask(int cpu);

#include <linux/arch_topology.h>

/* Replace task scheduler's default frequency-invariant accounting */
#define arch_scale_freq_capacity topology_get_freq_scale

/* Replace task scheduler's default cpu-invariant accounting */
#define arch_scale_cpu_capacity topology_get_cpu_scale

#else

static inline void init_cpu_topology(void) { }
Expand Down
88 changes: 2 additions & 86 deletions arch/arm/mach-imx/mach-imx6q.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,88 +286,6 @@ static void __init imx6q_init_machine(void)
imx6q_axi_init();
}

#define OCOTP_CFG3 0x440
#define OCOTP_CFG3_SPEED_SHIFT 16
#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
#define OCOTP_CFG3_SPEED_996MHZ 0x2
#define OCOTP_CFG3_SPEED_852MHZ 0x1

static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
{
struct device_node *np;
void __iomem *base;
u32 val;

np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
if (!np) {
pr_warn("failed to find ocotp node\n");
return;
}

base = of_iomap(np, 0);
if (!base) {
pr_warn("failed to map ocotp\n");
goto put_node;
}

/*
* SPEED_GRADING[1:0] defines the max speed of ARM:
* 2b'11: 1200000000Hz;
* 2b'10: 996000000Hz;
* 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
* 2b'00: 792000000Hz;
* We need to set the max speed of ARM according to fuse map.
*/
val = readl_relaxed(base + OCOTP_CFG3);
val >>= OCOTP_CFG3_SPEED_SHIFT;
val &= 0x3;

if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && cpu_is_imx6q())
if (dev_pm_opp_disable(cpu_dev, 1200000000))
pr_warn("failed to disable 1.2 GHz OPP\n");
if (val < OCOTP_CFG3_SPEED_996MHZ)
if (dev_pm_opp_disable(cpu_dev, 996000000))
pr_warn("failed to disable 996 MHz OPP\n");
if (cpu_is_imx6q()) {
if (val != OCOTP_CFG3_SPEED_852MHZ)
if (dev_pm_opp_disable(cpu_dev, 852000000))
pr_warn("failed to disable 852 MHz OPP\n");
}
iounmap(base);
put_node:
of_node_put(np);
}

static void __init imx6q_opp_init(void)
{
struct device_node *np;
struct device *cpu_dev = get_cpu_device(0);

if (!cpu_dev) {
pr_warn("failed to get cpu0 device\n");
return;
}
np = of_node_get(cpu_dev->of_node);
if (!np) {
pr_warn("failed to find cpu0 node\n");
return;
}

if (dev_pm_opp_of_add_table(cpu_dev)) {
pr_warn("failed to init OPP table\n");
goto put_node;
}

imx6q_opp_check_speed_grading(cpu_dev);

put_node:
of_node_put(np);
}

static struct platform_device imx6q_cpufreq_pdev = {
.name = "imx6q-cpufreq",
};

static void __init imx6q_init_late(void)
{
/*
Expand All @@ -377,10 +295,8 @@ static void __init imx6q_init_late(void)
if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
imx6q_cpuidle_init();

if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
imx6q_opp_init();
platform_device_register(&imx6q_cpufreq_pdev);
}
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
}

static void __init imx6q_map_io(void)
Expand Down
8 changes: 8 additions & 0 deletions arch/arm64/include/asm/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ int pcibus_to_node(struct pci_bus *bus);

#endif /* CONFIG_NUMA */

#include <linux/arch_topology.h>

/* Replace task scheduler's default frequency-invariant accounting */
#define arch_scale_freq_capacity topology_get_freq_scale

/* Replace task scheduler's default cpu-invariant accounting */
#define arch_scale_cpu_capacity topology_get_cpu_scale

#include <asm-generic/topology.h>

#endif /* _ASM_ARM_TOPOLOGY_H */
29 changes: 23 additions & 6 deletions drivers/base/arch_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,23 @@
#include <linux/string.h>
#include <linux/sched/topology.h>

static DEFINE_MUTEX(cpu_scale_mutex);
static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;

unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu)
void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,
unsigned long max_freq)
{
return per_cpu(cpu_scale, cpu);
unsigned long scale;
int i;

scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq;

for_each_cpu(i, cpus)
per_cpu(freq_scale, i) = scale;
}

static DEFINE_MUTEX(cpu_scale_mutex);
DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;

void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity)
{
per_cpu(cpu_scale, cpu) = capacity;
Expand Down Expand Up @@ -212,6 +221,8 @@ static struct notifier_block init_cpu_capacity_notifier __initdata = {

static int __init register_cpufreq_notifier(void)
{
int ret;

/*
* on ACPI-based systems we need to use the default cpu capacity
* until we have the necessary code to parse the cpu capacity, so
Expand All @@ -227,15 +238,21 @@ static int __init register_cpufreq_notifier(void)

cpumask_copy(cpus_to_visit, cpu_possible_mask);

return cpufreq_register_notifier(&init_cpu_capacity_notifier,
CPUFREQ_POLICY_NOTIFIER);
ret = cpufreq_register_notifier(&init_cpu_capacity_notifier,
CPUFREQ_POLICY_NOTIFIER);

if (ret)
free_cpumask_var(cpus_to_visit);

return ret;
}
core_initcall(register_cpufreq_notifier);

static void __init parsing_done_workfn(struct work_struct *work)
{
cpufreq_unregister_notifier(&init_cpu_capacity_notifier,
CPUFREQ_POLICY_NOTIFIER);
free_cpumask_var(cpus_to_visit);
}

#else
Expand Down
16 changes: 12 additions & 4 deletions drivers/cpufreq/arm_big_little.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static bool bL_switching_enabled;
#define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq)

static struct thermal_cooling_device *cdev[MAX_CLUSTERS];
static struct cpufreq_arm_bL_ops *arm_bL_ops;
static const struct cpufreq_arm_bL_ops *arm_bL_ops;
static struct clk *clk[MAX_CLUSTERS];
static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
static atomic_t cluster_usage[MAX_CLUSTERS + 1];
Expand Down Expand Up @@ -213,6 +213,7 @@ static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
{
u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster;
unsigned int freqs_new;
int ret;

cur_cluster = cpu_to_cluster(cpu);
new_cluster = actual_cluster = per_cpu(physical_cluster, cpu);
Expand All @@ -229,7 +230,14 @@ static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
}
}

return bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new);
ret = bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new);

if (!ret) {
arch_set_freq_scale(policy->related_cpus, freqs_new,
policy->cpuinfo.max_freq);
}

return ret;
}

static inline u32 get_table_count(struct cpufreq_frequency_table *table)
Expand Down Expand Up @@ -609,7 +617,7 @@ static int __bLs_register_notifier(void) { return 0; }
static int __bLs_unregister_notifier(void) { return 0; }
#endif

int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
int bL_cpufreq_register(const struct cpufreq_arm_bL_ops *ops)
{
int ret, i;

Expand Down Expand Up @@ -653,7 +661,7 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
}
EXPORT_SYMBOL_GPL(bL_cpufreq_register);

void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops)
void bL_cpufreq_unregister(const struct cpufreq_arm_bL_ops *ops)
{
if (arm_bL_ops != ops) {
pr_err("%s: Registered with: %s, can't unregister, exiting\n",
Expand Down
4 changes: 2 additions & 2 deletions drivers/cpufreq/arm_big_little.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct cpufreq_arm_bL_ops {
void (*free_opp_table)(const struct cpumask *cpumask);
};

int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops);
int bL_cpufreq_register(const struct cpufreq_arm_bL_ops *ops);
void bL_cpufreq_unregister(const struct cpufreq_arm_bL_ops *ops);

#endif /* CPUFREQ_ARM_BIG_LITTLE_H */
2 changes: 1 addition & 1 deletion drivers/cpufreq/arm_big_little_dt.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static int dt_get_transition_latency(struct device *cpu_dev)
return transition_latency;
}

static struct cpufreq_arm_bL_ops dt_bL_ops = {
static const struct cpufreq_arm_bL_ops dt_bL_ops = {
.name = "dt-bl",
.get_transition_latency = dt_get_transition_latency,
.init_opp_table = dev_pm_opp_of_cpumask_add_table,
Expand Down
3 changes: 0 additions & 3 deletions drivers/cpufreq/cpufreq-dt-platdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ static const struct of_device_id whitelist[] __initconst = {

{ .compatible = "samsung,exynos3250", },
{ .compatible = "samsung,exynos4210", },
{ .compatible = "samsung,exynos4212", },
{ .compatible = "samsung,exynos5250", },
#ifndef CONFIG_BL_SWITCHER
{ .compatible = "samsung,exynos5800", },
Expand Down Expand Up @@ -83,8 +82,6 @@ static const struct of_device_id whitelist[] __initconst = {
{ .compatible = "rockchip,rk3368", },
{ .compatible = "rockchip,rk3399", },

{ .compatible = "socionext,uniphier-ld6b", },

{ .compatible = "st-ericsson,u8500", },
{ .compatible = "st-ericsson,u8540", },
{ .compatible = "st-ericsson,u9500", },
Expand Down
12 changes: 10 additions & 2 deletions drivers/cpufreq/cpufreq-dt.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,17 @@ static struct freq_attr *cpufreq_dt_attr[] = {
static int set_target(struct cpufreq_policy *policy, unsigned int index)
{
struct private_data *priv = policy->driver_data;
unsigned long freq = policy->freq_table[index].frequency;
int ret;

ret = dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);

return dev_pm_opp_set_rate(priv->cpu_dev,
policy->freq_table[index].frequency * 1000);
if (!ret) {
arch_set_freq_scale(policy->related_cpus, freq,
policy->cpuinfo.max_freq);
}

return ret;
}

/*
Expand Down
6 changes: 6 additions & 0 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
}
EXPORT_SYMBOL_GPL(get_cpu_idle_time);

__weak void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,
unsigned long max_freq)
{
}
EXPORT_SYMBOL_GPL(arch_set_freq_scale);

/*
* This is a generic cpufreq init() routine which can be used by cpufreq
* drivers of SMP systems. It will do following:
Expand Down
7 changes: 5 additions & 2 deletions drivers/cpufreq/cpufreq_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
break;
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
}
if (len >= PAGE_SIZE)
return PAGE_SIZE;

if (len >= PAGE_SIZE) {
pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n");
return -EFBIG;
}
return len;
}
cpufreq_freq_attr_ro(trans_table);
Expand Down
Loading

0 comments on commit 60af981

Please sign in to comment.