@@ -11,6 +11,7 @@
#include <linux/cleanup.h>
#include <linux/cpu.h>
#include <linux/cpufreq.h>
+#include <linux/cpu_smt.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/slab.h>
@@ -28,6 +29,7 @@
static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data);
static struct cpumask scale_freq_counters_mask;
static bool scale_freq_invariant;
+static unsigned int max_smt_thread_num;
DEFINE_PER_CPU(unsigned long, capacity_freq_ref) = 1;
EXPORT_PER_CPU_SYMBOL_GPL(capacity_freq_ref);
@@ -561,6 +563,17 @@ static int __init parse_core(struct device_node *core, int package_id,
i++;
} while (1);
+ if (max_smt_thread_num < i)
+ max_smt_thread_num = i;
+
+ /*
+ * If max_smt_thread_num has been initialized and doesn't match
+ * the thread number of this entry, then the system has
+ * heterogeneous SMT topology.
+ */
+ if (max_smt_thread_num && max_smt_thread_num != i)
+ pr_warn_once("Heterogeneous SMT topology is partly supported by SMT control\n");
+
cpu = get_cpu_for_node(core);
if (cpu >= 0) {
if (!leaf) {
@@ -673,6 +686,14 @@ static int __init parse_socket(struct device_node *socket)
if (!has_socket)
ret = parse_cluster(socket, 0, -1, 0);
+ /*
+ * Notify the CPU framework of the SMT support. A thread number of 1
+ * can be handled by the framework so we don't need to check
+ * max_smt_thread_num to see we support SMT or not.
+ */
+ if (max_smt_thread_num)
+ cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
+
return ret;
}