diff --git a/drivers/opp/core.c b/drivers/opp/core.c index d7f97167cac3..0420f7e8ad5b 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -760,7 +760,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) old_freq, freq); /* Scaling up? Configure required OPPs before frequency */ - if (freq > old_freq) { + if (freq >= old_freq) { ret = _set_required_opps(dev, opp_table, opp); if (ret) goto put_opp; diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 62504b18f198..c10c782d15aa 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -173,7 +173,7 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, struct opp_table **required_opp_tables; struct device **genpd_virt_devs = NULL; struct device_node *required_np, *np; - int count, i; + int count, count_pd, i; /* Traversing the first OPP node is all we need */ np = of_get_next_available_child(opp_np, NULL); @@ -186,7 +186,19 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table, if (!count) goto put_np; - if (count > 1) { + /* + * Check the number of power-domains to know if we need to deal + * with virtual devices. In some cases we have devices with multiple + * power domains but with only one of them being scalable, hence + * 'count' could be 1, but we still have to deal with multiple genpds + * and virtual devices. + */ + count_pd = of_count_phandle_with_args(dev->of_node, "power-domains", + "#power-domain-cells"); + if (!count_pd) + goto put_np; + + if (count_pd > 1) { genpd_virt_devs = kcalloc(count, sizeof(*genpd_virt_devs), GFP_KERNEL); if (!genpd_virt_devs) diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c index 0c0f3e3f0d80..80650497fb80 100644 --- a/tools/power/cpupower/lib/cpufreq.c +++ b/tools/power/cpupower/lib/cpufreq.c @@ -333,17 +333,20 @@ void cpufreq_put_available_governors(struct cpufreq_available_governors *any) } -struct cpufreq_available_frequencies -*cpufreq_get_available_frequencies(unsigned int cpu) +struct cpufreq_frequencies +*cpufreq_get_frequencies(const char *type, unsigned int cpu) { - struct cpufreq_available_frequencies *first = NULL; - struct cpufreq_available_frequencies *current = NULL; + struct cpufreq_frequencies *first = NULL; + struct cpufreq_frequencies *current = NULL; char one_value[SYSFS_PATH_MAX]; char linebuf[MAX_LINE_LEN]; + char fname[MAX_LINE_LEN]; unsigned int pos, i; unsigned int len; - len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies", + snprintf(fname, MAX_LINE_LEN, "scaling_%s_frequencies", type); + + len = sysfs_cpufreq_read_file(cpu, fname, linebuf, sizeof(linebuf)); if (len == 0) return NULL; @@ -389,9 +392,9 @@ struct cpufreq_available_frequencies return NULL; } -void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies - *any) { - struct cpufreq_available_frequencies *tmp, *next; +void cpufreq_put_frequencies(struct cpufreq_frequencies *any) +{ + struct cpufreq_frequencies *tmp, *next; if (!any) return; diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h index 60beaf5ed2ea..775738269cbf 100644 --- a/tools/power/cpupower/lib/cpufreq.h +++ b/tools/power/cpupower/lib/cpufreq.h @@ -28,10 +28,10 @@ struct cpufreq_available_governors { struct cpufreq_available_governors *first; }; -struct cpufreq_available_frequencies { +struct cpufreq_frequencies { unsigned long frequency; - struct cpufreq_available_frequencies *next; - struct cpufreq_available_frequencies *first; + struct cpufreq_frequencies *next; + struct cpufreq_frequencies *first; }; @@ -129,14 +129,14 @@ void cpufreq_put_available_governors( * * Only present on _some_ ->target() cpufreq drivers. For information purposes * only. Please free allocated memory by calling - * cpufreq_put_available_frequencies after use. + * cpufreq_put_frequencies after use. */ -struct cpufreq_available_frequencies -*cpufreq_get_available_frequencies(unsigned int cpu); +struct cpufreq_frequencies +*cpufreq_get_frequencies(const char *type, unsigned int cpu); -void cpufreq_put_available_frequencies( - struct cpufreq_available_frequencies *first); +void cpufreq_put_frequencies( + struct cpufreq_frequencies *first); /* determine affected CPUs diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c index c3f39d5128ee..10290b308797 100644 --- a/tools/power/cpupower/utils/cpufreq-info.c +++ b/tools/power/cpupower/utils/cpufreq-info.c @@ -161,19 +161,12 @@ static void print_duration(unsigned long duration) return; } -/* --boost / -b */ - -static int get_boost_mode(unsigned int cpu) +static int get_boost_mode_x86(unsigned int cpu) { int support, active, b_states = 0, ret, pstate_no, i; /* ToDo: Make this more global */ unsigned long pstates[MAX_HW_PSTATES] = {0,}; - if (cpupower_cpu_info.vendor != X86_VENDOR_AMD && - cpupower_cpu_info.vendor != X86_VENDOR_HYGON && - cpupower_cpu_info.vendor != X86_VENDOR_INTEL) - return 0; - ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states); if (ret) { printf(_("Error while evaluating Boost Capabilities" @@ -248,6 +241,33 @@ static int get_boost_mode(unsigned int cpu) return 0; } +/* --boost / -b */ + +static int get_boost_mode(unsigned int cpu) +{ + struct cpufreq_frequencies *freqs; + + if (cpupower_cpu_info.vendor == X86_VENDOR_AMD || + cpupower_cpu_info.vendor == X86_VENDOR_HYGON || + cpupower_cpu_info.vendor == X86_VENDOR_INTEL) + return get_boost_mode_x86(cpu); + + freqs = cpufreq_get_frequencies("boost", cpu); + if (freqs) { + printf(_(" boost frequency steps: ")); + while (freqs->next) { + print_speed(freqs->frequency); + printf(", "); + freqs = freqs->next; + } + print_speed(freqs->frequency); + printf("\n"); + cpufreq_put_frequencies(freqs); + } + + return 0; +} + /* --freq / -f */ static int get_freq_kernel(unsigned int cpu, unsigned int human) @@ -456,7 +476,7 @@ static int get_latency(unsigned int cpu, unsigned int human) static void debug_output_one(unsigned int cpu) { - struct cpufreq_available_frequencies *freqs; + struct cpufreq_frequencies *freqs; get_driver(cpu); get_related_cpus(cpu); @@ -464,7 +484,7 @@ static void debug_output_one(unsigned int cpu) get_latency(cpu, 1); get_hardware_limits(cpu, 1); - freqs = cpufreq_get_available_frequencies(cpu); + freqs = cpufreq_get_frequencies("available", cpu); if (freqs) { printf(_(" available frequency steps: ")); while (freqs->next) { @@ -474,7 +494,7 @@ static void debug_output_one(unsigned int cpu) } print_speed(freqs->frequency); printf("\n"); - cpufreq_put_available_frequencies(freqs); + cpufreq_put_frequencies(freqs); } get_available_governors(cpu);