[PATCH 2/3] arch_topology: Export CPPC-based asympacking prios

Christian Loehle posted 3 patches 1 week, 1 day ago
[PATCH 2/3] arch_topology: Export CPPC-based asympacking prios
Posted by Christian Loehle 1 week, 1 day ago
Determine asymmetric packing priorities by reading CPPC's
highest_perf so it can be read by arch code later to enable
asympacking if the difference between the minimum and
maximum highest_perf is small (<5%).

Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
 drivers/base/arch_topology.c | 40 ++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index 8c5e47c28d9a..c80c782e5eb2 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -321,8 +321,47 @@ void __weak freq_inv_set_max_ratio(int cpu, u64 max_rate)
 {
 }
 
+void __weak arch_topology_init_cppc_asym(void)
+{
+}
+
 #ifdef CONFIG_ACPI_CPPC_LIB
 #include <acpi/cppc_acpi.h>
+#include <linux/limits.h>
+
+/**
+ * topology_init_cppc_asym_packing() - Detect CPPC-based asymmetric packing
+ * @priority_var: Per-CPU variable to store CPU priorities
+ *
+ * Query CPPC highest_perf for all CPUs and determine if asymmetric packing
+ * should be enabled based on minor performance differences (~5% threshold).
+ *
+ * Return: true if asympacking should be enabled, false otherwise
+ */
+bool topology_init_cppc_asym_packing(int __percpu *priority_var)
+{
+	struct cppc_perf_caps perf_caps;
+	u32 max_perf = 0, min_perf = U32_MAX;
+	int cpu;
+
+	if (!acpi_cpc_valid())
+		return false;
+
+	for_each_possible_cpu(cpu) {
+		if (cppc_get_perf_caps(cpu, &perf_caps))
+			return false;
+		if (perf_caps.highest_perf < perf_caps.nominal_perf ||
+		    perf_caps.highest_perf < perf_caps.lowest_perf)
+			return false;
+
+		*per_cpu_ptr(priority_var, cpu) = perf_caps.highest_perf;
+		max_perf = max(max_perf, perf_caps.highest_perf);
+		min_perf = min(min_perf, perf_caps.highest_perf);
+	}
+
+	return (max_perf != min_perf) && !capacity_greater(max_perf, min_perf);
+}
+EXPORT_SYMBOL_GPL(topology_init_cppc_asym_packing);
 
 static inline void topology_init_cpu_capacity_cppc(void)
 {
@@ -369,6 +408,7 @@ static inline void topology_init_cpu_capacity_cppc(void)
 			cpu, topology_get_cpu_scale(cpu));
 	}
 
+	arch_topology_init_cppc_asym();
 	schedule_work(&update_topology_flags_work);
 	pr_debug("cpu_capacity: cpu_capacity initialization done\n");
 
-- 
2.34.1