summaryrefslogtreecommitdiff
path: root/tools/power/cpupower/utils
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 00:19:07 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 00:19:07 +0300
commit045e222d0a9dcec152abe0633f538cafd965b12b (patch)
tree09db255e1ef5ff3a3d17bb6744662650cfb99244 /tools/power/cpupower/utils
parent631aa744423173bf921191ba695bbc7c1aabd9e0 (diff)
parented6a00471dd444af085164f987e3d5e8145da35a (diff)
downloadlinux-045e222d0a9dcec152abe0633f538cafd965b12b.tar.xz
Merge tag 'pm-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "These include two new drivers (cpufreq driver for Apple SoC CPU P-states and the SCMI Powercap based power capping driver), other new hardware support and driver extensions (Qualcomm cpufreq driver and its DT bindings, TI cpufreq driver, intel_pstate, intel-uncore-freq), a bunch of fixes and cleanups all over and a cpupower utility update including new features related to RAPL support. Specifics: - Fix nasty and hard to debug race condition introduced by mistake in the runtime PM core code and clean up that code somewhat on top of the fix (Rafael Wysocki) - Generalize of_perf_domain_get_sharing_cpumask phandle format (Hector Martin) - Add new cpufreq driver for Apple SoC CPU P-states (Hector Martin) - Update Qualcomm cpufreq driver (Manivannan Sadhasivam, Chen Hui): - CPU clock provider support - Generic cleanups or reorganization - Potential memleak fix - Fix of the return value of cpufreq_driver->get() - Update Qualcomm cpufreq driver's DT bindings (Manivannan Sadhasivam, Rob Herring, Melody Olvera): - Support for CPU clock provider - Missing cache-related properties fixes - Support for QDU1000/QRU1000 - Add support for ti,am625 SoC and enable build of ti-cpufreq for ARCH_K3 (Dave Gerlach, and Vibhore Vardhan) - Use flexible array to simplify memory allocation in the tegra186 cpufreq driver (Christophe JAILLET) - Convert cpufreq statistics code to use sysfs_emit_at() (ye xingchen) - Allow intel_pstate to use no-HWP mode on Sapphire Rapids (Giovanni Gherdovich) - Add missing pci_dev_put() to the amd_freq_sensitivity cpufreq driver (Xiongfeng Wang) - Initialize the kobj_unregister completion before calling kobject_init_and_add() in the cpufreq core code (Yongqiang Liu) - Defer setting boost MSRs in the ACPI cpufreq driver (Stuart Hayes, Nathan Chancellor) - Make intel_pstate accept initial EPP value of 0x80 (Srinivas Pandruvada) - Make read-only array sys_clk_src in the SPEAr cpufreq driver static (Colin Ian King) - Make array speeds in the longhaul cpufreq driver static (Colin Ian King) - Use str_enabled_disabled() helper in the ACPI cpufreq driver (Andy Shevchenko) - Drop a reference to CVS from cpufreq documentation (Conghui Wang) - Improve kernel messages printed by the PSCI cpuidle driver (Ulf Hansson) - Make the DT cpuidle driver return the correct number of parsed idle states, clean it up and clarify a comment in it (Ulf Hansson) - Modify the tasks freezing code to avoid using pr_cont() and refine an error message printed by it (Rafael Wysocki) - Make the hibernation core code complain about memory map mismatches during resume to help diagnostics (Xueqin Luo) - Fix mistake in a kerneldoc comment in the hibernation code (xiongxin) - Reverse the order of performance and enabling operations in the generic power domains code (Abel Vesa) - Power off[on] domains in hibernate .freeze[thaw]_noirq hook of in the generic power domains code (Abel Vesa) - Consolidate genpd_restore_noirq() and genpd_resume_noirq() (Shawn Guo) - Pass generic PM noirq hooks to genpd_finish_suspend() (Shawn Guo) - Drop generic power domain status manipulation during hibernate restore (Shawn Guo) - Fix compiler warnings with make W=1 in the idle_inject power capping driver (Srinivas Pandruvada) - Use kstrtobool() instead of strtobool() in the power capping sysfs interface (Christophe JAILLET) - Add SCMI Powercap based power capping driver (Cristian Marussi) - Add Emerald Rapids support to the intel-uncore-freq driver (Artem Bityutskiy) - Repair slips in kernel-doc comments in the generic notifier code (Lukas Bulwahn) - Fix several DT issues in the OPP library reorganize code around opp-microvolt-<named> DT property (Viresh Kumar) - Allow any of opp-microvolt, opp-microamp, or opp-microwatt properties to be present without the others present (James Calligeros) - Fix clock-latency-ns property in DT example (Serge Semin) - Add a private governor_data for devfreq governors (Kant Fan) - Reorganize devfreq code to use device_match_of_node() and devm_platform_get_and_ioremap_resource() instead of open coding them (ye xingchen, Minghao Chi) - Make cpupower choose base_cpu to display default cpupower details instead of picking CPU 0 (Saket Kumar Bhaskar) - Add Georgian translation to cpupower documentation (Zurab Kargareteli) - Introduce powercap intel-rapl library, powercap-info command, and RAPL monitor into cpupower (Thomas Renninger)" * tag 'pm-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (64 commits) PM: runtime: Adjust white space in the core code cpufreq: Remove CVS version control contents from documentation cpufreq: stats: Convert to use sysfs_emit_at() API cpufreq: ACPI: Only set boost MSRs on supported CPUs PM: sleep: Refine error message in try_to_freeze_tasks() PM: sleep: Avoid using pr_cont() in the tasks freezing code PM: runtime: Relocate rpm_callback() right after __rpm_callback() PM: runtime: Do not call __rpm_callback() from rpm_idle() PM / devfreq: event: use devm_platform_get_and_ioremap_resource() PM / devfreq: event: Use device_match_of_node() PM / devfreq: Use device_match_of_node() powercap: idle_inject: Fix warnings with make W=1 PM: hibernate: Complain about memory map mismatches during resume dt-bindings: cpufreq: cpufreq-qcom-hw: Add QDU1000/QRU1000 cpufreq cpufreq: tegra186: Use flexible array to simplify memory allocation cpupower: rapl monitor - shows the used power consumption in uj for each rapl domain cpupower: Introduce powercap intel-rapl library and powercap-info command cpupower: Add Georgian translation cpufreq: intel_pstate: Add Sapphire Rapids support in no-HWP mode cpufreq: amd_freq_sensitivity: Add missing pci_dev_put() ...
Diffstat (limited to 'tools/power/cpupower/utils')
-rw-r--r--tools/power/cpupower/utils/builtin.h2
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c4
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c4
-rw-r--r--tools/power/cpupower/utils/cpupower-info.c4
-rw-r--r--tools/power/cpupower/utils/cpupower.c1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c7
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.def1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/rapl_monitor.c148
-rw-r--r--tools/power/cpupower/utils/powercap-info.c117
9 files changed, 279 insertions, 9 deletions
diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h
index f7065ae60a14..e1caefd467cd 100644
--- a/tools/power/cpupower/utils/builtin.h
+++ b/tools/power/cpupower/utils/builtin.h
@@ -8,6 +8,8 @@ extern int cmd_freq_set(int argc, const char **argv);
extern int cmd_freq_info(int argc, const char **argv);
extern int cmd_idle_set(int argc, const char **argv);
extern int cmd_idle_info(int argc, const char **argv);
+extern int cmd_cap_info(int argc, const char **argv);
+extern int cmd_cap_set(int argc, const char **argv);
extern int cmd_monitor(int argc, const char **argv);
#endif
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 0646f615fe2d..c96b77365c63 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -572,9 +572,9 @@ int cmd_freq_info(int argc, char **argv)
ret = 0;
- /* Default is: show output of CPU 0 only */
+ /* Default is: show output of base_cpu only */
if (bitmask_isallclear(cpus_chosen))
- bitmask_setbit(cpus_chosen, 0);
+ bitmask_setbit(cpus_chosen, base_cpu);
switch (output_param) {
case -1:
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index f2b202c5552a..44126a87fa7a 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -176,9 +176,9 @@ int cmd_idle_info(int argc, char **argv)
cpuidle_exit(EXIT_FAILURE);
}
- /* Default is: show output of CPU 0 only */
+ /* Default is: show output of base_cpu only */
if (bitmask_isallclear(cpus_chosen))
- bitmask_setbit(cpus_chosen, 0);
+ bitmask_setbit(cpus_chosen, base_cpu);
if (output_param == 0)
cpuidle_general_output();
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
index 06345b543786..18fd7751f509 100644
--- a/tools/power/cpupower/utils/cpupower-info.c
+++ b/tools/power/cpupower/utils/cpupower-info.c
@@ -67,9 +67,9 @@ int cmd_info(int argc, char **argv)
if (!params.params)
params.params = 0x7;
- /* Default is: show output of CPU 0 only */
+ /* Default is: show output of base_cpu only */
if (bitmask_isallclear(cpus_chosen))
- bitmask_setbit(cpus_chosen, 0);
+ bitmask_setbit(cpus_chosen, base_cpu);
/* Add more per cpu options here */
if (!params.perf_bias)
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 8ac3304a9957..9ec973165af1 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -54,6 +54,7 @@ static struct cmd_struct commands[] = {
{ "frequency-set", cmd_freq_set, 1 },
{ "idle-info", cmd_idle_info, 0 },
{ "idle-set", cmd_idle_set, 1 },
+ { "powercap-info", cmd_cap_info, 0 },
{ "set", cmd_set, 1 },
{ "info", cmd_info, 0 },
{ "monitor", cmd_monitor, 0 },
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
index 7c77045fef52..075e766ff1f3 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -459,9 +459,10 @@ int cmd_monitor(int argc, char **argv)
print_results(1, cpu);
}
- for (num = 0; num < avail_monitors; num++)
- monitors[num]->unregister();
-
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->unregister)
+ monitors[num]->unregister();
+ }
cpu_topology_release(cpu_top);
return 0;
}
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
index 0d6ba4dbb9c7..7c926e90c87e 100644
--- a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
@@ -4,5 +4,6 @@ DEF(intel_nhm)
DEF(intel_snb)
DEF(intel_hsw_ext)
DEF(mperf)
+DEF(rapl)
#endif
DEF(cpuidle_sysfs)
diff --git a/tools/power/cpupower/utils/idle_monitor/rapl_monitor.c b/tools/power/cpupower/utils/idle_monitor/rapl_monitor.c
new file mode 100644
index 000000000000..46153f1291c3
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/rapl_monitor.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * (C) 2016 SUSE Software Solutions GmbH
+ * Thomas Renninger <trenn@suse.de>
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <time.h>
+#include <string.h>
+
+#include <pci/pci.h>
+
+#include "idle_monitor/cpupower-monitor.h"
+#include "helpers/helpers.h"
+#include "powercap.h"
+
+#define MAX_RAPL_ZONES 10
+
+int rapl_zone_count;
+cstate_t rapl_zones[MAX_RAPL_ZONES];
+struct powercap_zone *rapl_zones_pt[MAX_RAPL_ZONES] = { 0 };
+
+unsigned long long rapl_zone_previous_count[MAX_RAPL_ZONES];
+unsigned long long rapl_zone_current_count[MAX_RAPL_ZONES];
+unsigned long long rapl_max_count;
+
+static int rapl_get_count_uj(unsigned int id, unsigned long long *count,
+ unsigned int cpu)
+{
+ if (rapl_zones_pt[id] == NULL)
+ /* error */
+ return -1;
+
+ *count = rapl_zone_current_count[id] - rapl_zone_previous_count[id];
+
+ return 0;
+}
+
+static int powercap_count_zones(struct powercap_zone *zone)
+{
+ uint64_t val;
+ int uj;
+
+ if (rapl_zone_count >= MAX_RAPL_ZONES)
+ return -1;
+
+ if (!zone->has_energy_uj)
+ return 0;
+
+ printf("%s\n", zone->sys_name);
+ uj = powercap_get_energy_uj(zone, &val);
+ printf("%d\n", uj);
+
+ strncpy(rapl_zones[rapl_zone_count].name, zone->name, CSTATE_NAME_LEN - 1);
+ strcpy(rapl_zones[rapl_zone_count].desc, "");
+ rapl_zones[rapl_zone_count].id = rapl_zone_count;
+ rapl_zones[rapl_zone_count].range = RANGE_MACHINE;
+ rapl_zones[rapl_zone_count].get_count = rapl_get_count_uj;
+ rapl_zones_pt[rapl_zone_count] = zone;
+ rapl_zone_count++;
+
+ return 0;
+}
+
+static int rapl_start(void)
+{
+ int i, ret;
+ uint64_t uj_val;
+
+ for (i = 0; i < rapl_zone_count; i++) {
+ ret = powercap_get_energy_uj(rapl_zones_pt[i], &uj_val);
+ if (ret)
+ return ret;
+ rapl_zone_previous_count[i] = uj_val;
+ }
+
+ return 0;
+}
+
+static int rapl_stop(void)
+{
+ int i;
+ uint64_t uj_val;
+
+ for (i = 0; i < rapl_zone_count; i++) {
+ int ret;
+
+ ret = powercap_get_energy_uj(rapl_zones_pt[i], &uj_val);
+ if (ret)
+ return ret;
+ rapl_zone_current_count[i] = uj_val;
+ if (rapl_max_count < uj_val)
+ rapl_max_count = uj_val - rapl_zone_previous_count[i];
+ }
+ return 0;
+}
+
+struct cpuidle_monitor *rapl_register(void)
+{
+ struct powercap_zone *root_zone;
+ char line[MAX_LINE_LEN] = "";
+ int ret, val;
+
+ ret = powercap_get_driver(line, MAX_LINE_LEN);
+ if (ret < 0) {
+ dprint("No powercapping driver loaded\n");
+ return NULL;
+ }
+
+ dprint("Driver: %s\n", line);
+ ret = powercap_get_enabled(&val);
+ if (ret < 0)
+ return NULL;
+ if (!val) {
+ dprint("Powercapping is disabled\n");
+ return NULL;
+ }
+
+ dprint("Powercap domain hierarchy:\n\n");
+ root_zone = powercap_init_zones();
+
+ if (root_zone == NULL) {
+ dprint("No powercap info found\n");
+ return NULL;
+ }
+
+ powercap_walk_zones(root_zone, powercap_count_zones);
+ rapl_monitor.hw_states_num = rapl_zone_count;
+
+ return &rapl_monitor;
+}
+
+struct cpuidle_monitor rapl_monitor = {
+ .name = "RAPL",
+ .hw_states = rapl_zones,
+ .hw_states_num = 0,
+ .start = rapl_start,
+ .stop = rapl_stop,
+ .do_register = rapl_register,
+ .flags.needs_root = 0,
+ .overflow_s = 60 * 60 * 24 * 100, /* To be implemented */
+};
+
+#endif
diff --git a/tools/power/cpupower/utils/powercap-info.c b/tools/power/cpupower/utils/powercap-info.c
new file mode 100644
index 000000000000..3ea4486f1a0e
--- /dev/null
+++ b/tools/power/cpupower/utils/powercap-info.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * (C) 2016 SUSE Software Solutions GmbH
+ * Thomas Renninger <trenn@suse.de>
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "powercap.h"
+#include "helpers/helpers.h"
+
+int powercap_show_all;
+
+static struct option info_opts[] = {
+ { "all", no_argument, NULL, 'a'},
+ { },
+};
+
+static int powercap_print_one_zone(struct powercap_zone *zone)
+{
+ int mode, i, ret = 0;
+ char pr_prefix[1024] = "";
+
+ for (i = 0; i < zone->tree_depth && i < POWERCAP_MAX_TREE_DEPTH; i++)
+ strcat(pr_prefix, "\t");
+
+ printf("%sZone: %s", pr_prefix, zone->name);
+ ret = powercap_zone_get_enabled(zone, &mode);
+ if (ret < 0)
+ return ret;
+ printf(" (%s)\n", mode ? "enabled" : "disabled");
+
+ if (zone->has_power_uw)
+ printf(_("%sPower can be monitored in micro Jules\n"),
+ pr_prefix);
+
+ if (zone->has_energy_uj)
+ printf(_("%sPower can be monitored in micro Watts\n"),
+ pr_prefix);
+
+ printf("\n");
+
+ if (ret != 0)
+ return ret;
+ return ret;
+}
+
+static int powercap_show(void)
+{
+ struct powercap_zone *root_zone;
+ char line[MAX_LINE_LEN] = "";
+ int ret, val;
+
+ ret = powercap_get_driver(line, MAX_LINE_LEN);
+ if (ret < 0) {
+ printf(_("No powercapping driver loaded\n"));
+ return ret;
+ }
+
+ printf("Driver: %s\n", line);
+ ret = powercap_get_enabled(&val);
+ if (ret < 0)
+ return ret;
+ if (!val) {
+ printf(_("Powercapping is disabled\n"));
+ return -1;
+ }
+
+ printf(_("Powercap domain hierarchy:\n\n"));
+ root_zone = powercap_init_zones();
+
+ if (root_zone == NULL) {
+ printf(_("No powercap info found\n"));
+ return 1;
+ }
+
+ powercap_walk_zones(root_zone, powercap_print_one_zone);
+
+ return 0;
+}
+
+int cmd_cap_set(int argc, char **argv)
+{
+ return 0;
+};
+int cmd_cap_info(int argc, char **argv)
+{
+ int ret = 0, cont = 1;
+
+ do {
+ ret = getopt_long(argc, argv, "a", info_opts, NULL);
+ switch (ret) {
+ case '?':
+ cont = 0;
+ break;
+ case -1:
+ cont = 0;
+ break;
+ case 'a':
+ powercap_show_all = 1;
+ break;
+ default:
+ fprintf(stderr, _("invalid or unknown argument\n"));
+ return EXIT_FAILURE;
+ }
+ } while (cont);
+
+ powercap_show();
+ return 0;
+}