[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20241114084816.1128647-4-zhenglifeng1@huawei.com>
Date: Thu, 14 Nov 2024 16:48:16 +0800
From: Lifeng Zheng <zhenglifeng1@...wei.com>
To: <rafael@...nel.org>, <lenb@...nel.org>, <robert.moore@...el.com>,
<viresh.kumar@...aro.org>
CC: <acpica-devel@...ts.linux.dev>, <linux-acpi@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <linux-pm@...r.kernel.org>,
<zhanjie9@...ilicon.com>, <lihuisong@...wei.com>, <fanghao11@...wei.com>,
<zhenglifeng1@...wei.com>
Subject: [PATCH 3/3] cpufreq: CPPC: Support for autonomous selection in cppc_cpufreq
Add sysfs interfaces for CPPC autonomous selection in the cppc_cpufreq
driver.
Signed-off-by: Lifeng Zheng <zhenglifeng1@...wei.com>
---
.../ABI/testing/sysfs-devices-system-cpu | 54 +++++++
drivers/cpufreq/cppc_cpufreq.c | 141 ++++++++++++++++++
2 files changed, 195 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 206079d3bd5b..ba7b8ea613e5 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -268,6 +268,60 @@ Description: Discover CPUs in the same CPU frequency coordination domain
This file is only present if the acpi-cpufreq or the cppc-cpufreq
drivers are in use.
+What: /sys/devices/system/cpu/cpuX/cpufreq/auto_select
+Date: October 2024
+Contact: linux-pm@...r.kernel.org
+Description: Autonomous selection enable
+
+ Read/write interface to control autonomous selection enable
+ Read returns autonomous selection status:
+ 0: autonomous selection is disabled
+ 1: autonomous selection is enabled
+
+ Write '1' to enable autonomous selection.
+ Write '0' to disable autonomous selection.
+
+ This file only presents if the cppc-cpufreq driver is in use.
+
+What: /sys/devices/system/cpu/cpuX/cpufreq/auto_act_window
+Date: October 2024
+Contact: linux-pm@...r.kernel.org
+Description: Autonomous activity window
+
+ This file indicates a moving utilization sensitivity window to
+ the platform's autonomous selection policy.
+
+ Read/write an integer represents autonomous activity window (in
+ microseconds) from/to this file. The max value to write is
+ 1270000000 but the max significand is 127. This means that if 128
+ is written to this file, 127 will be stored. If the value is
+ greater than 130, only the first two digits will be saved as
+ significand.
+
+ Writing a zero value to this file enable the platform to
+ determine an appropriate Activity Window depending on the workload.
+
+ Writing to this file only has meaning when Autonomous Selection is
+ enabled.
+
+ This file only presents if the cppc-cpufreq driver is in use.
+
+What: /sys/devices/system/cpu/cpuX/cpufreq/energy_perf
+Date: October 2024
+Contact: linux-pm@...r.kernel.org
+Description: Energy performance preference
+
+ Read/write an 8-bit integer from/to this file. This file
+ represents a range of values from 0 (performance preference) to
+ 0xFF (energy efficiency preference) that influences the rate of
+ performance increase/decrease and the result of the hardware's
+ energy efficiency and performance optimization policies.
+
+ Writing to this file only has meaning when Autonomous Selection is
+ enabled.
+
+ This file only presents if the cppc-cpufreq driver is in use.
+
What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
Date: August 2008
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 2b8708475ac7..b435e1751d0d 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -792,10 +792,151 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
return cpufreq_show_cpus(cpu_data->shared_cpu_map, buf);
}
+
+static ssize_t show_auto_select(struct cpufreq_policy *policy, char *buf)
+{
+ u64 val;
+ int ret;
+
+ ret = cppc_get_auto_sel(policy->cpu, &val);
+
+ /* show "<unsupported>" when this register is not supported by cpc */
+ if (ret == -EOPNOTSUPP)
+ return sysfs_emit(buf, "%s\n", "<unsupported>");
+
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lld\n", val);
+}
+
+static ssize_t store_auto_select(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val > 1)
+ return -EINVAL;
+
+ ret = cppc_set_auto_sel(policy->cpu, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+#define AUTO_ACT_WINDOW_SIG_BIT_SIZE (7)
+#define AUTO_ACT_WINDOW_EXP_BIT_SIZE (3)
+#define AUTO_ACT_WINDOW_MAX_SIG ((1 << AUTO_ACT_WINDOW_SIG_BIT_SIZE) - 1)
+#define AUTO_ACT_WINDOW_MAX_EXP ((1 << AUTO_ACT_WINDOW_EXP_BIT_SIZE) - 1)
+/* AUTO_ACT_WINDOW_MAX_SIG is 127, so 128 and 129 will decay to 127 when writing */
+#define AUTO_ACT_WINDOW_SIG_CARRY_THRESH 129
+
+static ssize_t show_auto_act_window(struct cpufreq_policy *policy, char *buf)
+{
+ int sig, exp;
+ u64 val;
+ int ret;
+
+ ret = cppc_get_auto_act_window(policy->cpu, &val);
+
+ /* show "<unsupported>" when this register is not supported by cpc */
+ if (ret == -EOPNOTSUPP)
+ return sysfs_emit(buf, "%s\n", "<unsupported>");
+
+ if (ret)
+ return ret;
+
+ sig = val & AUTO_ACT_WINDOW_MAX_SIG;
+ exp = (val >> AUTO_ACT_WINDOW_SIG_BIT_SIZE) & AUTO_ACT_WINDOW_MAX_EXP;
+
+ return sysfs_emit(buf, "%lld\n", sig * int_pow(10, exp));
+}
+
+static ssize_t store_auto_act_window(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ unsigned long usec;
+ int digits = 0;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &usec);
+ if (ret)
+ return ret;
+
+ if (usec > AUTO_ACT_WINDOW_MAX_SIG * int_pow(10, AUTO_ACT_WINDOW_MAX_EXP))
+ return -EINVAL;
+
+ while (usec > AUTO_ACT_WINDOW_SIG_CARRY_THRESH) {
+ usec /= 10;
+ digits += 1;
+ }
+
+ if (usec > AUTO_ACT_WINDOW_MAX_SIG)
+ usec = AUTO_ACT_WINDOW_MAX_SIG;
+
+ ret = cppc_set_auto_act_window(policy->cpu,
+ (digits << AUTO_ACT_WINDOW_SIG_BIT_SIZE) + usec);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static ssize_t show_energy_perf(struct cpufreq_policy *policy, char *buf)
+{
+ u64 val;
+ int ret;
+
+ ret = cppc_get_epp_perf(policy->cpu, &val);
+
+ /* show "<unsupported>" when this register is not supported by cpc */
+ if (ret == -EOPNOTSUPP)
+ return sysfs_emit(buf, "%s\n", "<unsupported>");
+
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lld\n", val);
+}
+
+#define ENERGY_PERF_MAX (0xFF)
+
+static ssize_t store_energy_perf(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val > ENERGY_PERF_MAX)
+ return -EINVAL;
+
+ ret = cppc_set_epp(policy->cpu, val);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
cpufreq_freq_attr_ro(freqdomain_cpus);
+cpufreq_freq_attr_rw(auto_select);
+cpufreq_freq_attr_rw(auto_act_window);
+cpufreq_freq_attr_rw(energy_perf);
static struct freq_attr *cppc_cpufreq_attr[] = {
&freqdomain_cpus,
+ &auto_select,
+ &auto_act_window,
+ &energy_perf,
NULL,
};
--
2.33.0
Powered by blists - more mailing lists