[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250704-smp_calib-v2-1-bade7e9c0463@bootlin.com>
Date: Fri, 04 Jul 2025 17:13:10 +0200
From: Gregory CLEMENT <gregory.clement@...tlin.com>
To: Thomas Bogendoerfer <tsbogend@...ha.franken.de>
Cc: Jiaxun Yang <jiaxun.yang@...goat.com>,
Vladimir Kondratiev <vladimir.kondratiev@...ileye.com>,
Théo Lebrun <theo.lebrun@...tlin.com>,
Tawfik Bayouk <tawfik.bayouk@...ileye.com>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>, linux-mips@...r.kernel.org,
linux-kernel@...r.kernel.org, Gregory CLEMENT <gregory.clement@...tlin.com>
Subject: [PATCH v2 1/3] MIPS: CPS: Improve
mips_cps_first_online_in_cluster()
The initial implementation of this function goes through all the CPUs
in a cluster to determine if the current CPU is the only one
running. This process occurs every time the function is called.
However, during boot, we already perform this task, so let's take
advantage of this opportunity to create and fill a CPU bitmask that
can be easily and efficiently used later.
This requires creating a single CPU bitmask per cluster, which is why
it's essential to know how many clusters can be utilized. The default
setting is 4 clusters, but this value can be changed when configuring
the kernel or even customized for a given SoC family.
This patch modifies the function to allow providing the first
available online CPU when one already exists, which is necessary for
delay CPU calibration optimization.
Signed-off-by: Gregory CLEMENT <gregory.clement@...tlin.com>
---
arch/mips/Kconfig | 6 ++++++
arch/mips/include/asm/mips-cps.h | 18 ++++++++++++++++--
arch/mips/kernel/mips-cm.c | 40 +++++++---------------------------------
arch/mips/kernel/smp-cps.c | 2 ++
4 files changed, 31 insertions(+), 35 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1e48184ecf1ec8e29c0a25de6452ece5da835e30..47aa3f8849f05632773c9064282147608483c715 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2329,6 +2329,12 @@ config MIPS_CPS
no external assistance. It is safe to enable this when hardware
support is unavailable.
+config MIPS_CPS_CLUSTER_MAX
+ int "Maximum cluster supported"
+ default 4
+ help
+ Maximum number of cluster available on the SoC.
+
config MIPS_CPS_PM
depends on MIPS_CPS
bool
diff --git a/arch/mips/include/asm/mips-cps.h b/arch/mips/include/asm/mips-cps.h
index 917009b80e6951dc7e2b308ad7fb42cd9fbbf7d7..674f0628a2ded42f4f42c7362a667a457944caa0 100644
--- a/arch/mips/include/asm/mips-cps.h
+++ b/arch/mips/include/asm/mips-cps.h
@@ -12,6 +12,8 @@
#include <linux/io.h>
#include <linux/types.h>
+extern struct cpumask __cpu_cluster_mask[CONFIG_MIPS_CPS_CLUSTER_MAX] __read_mostly;
+
extern unsigned long __cps_access_bad_size(void)
__compiletime_error("Bad size for CPS accessor");
@@ -114,10 +116,20 @@ static inline void clear_##unit##_##name(uint##sz##_t val) \
*/
static inline unsigned int mips_cps_numclusters(void)
{
+ unsigned int nclusters;
+
if (mips_cm_revision() < CM_REV_CM3_5)
return 1;
- return FIELD_GET(CM_GCR_CONFIG_NUM_CLUSTERS, read_gcr_config());
+ nclusters = FIELD_GET(CM_GCR_CONFIG_NUM_CLUSTERS, read_gcr_config());
+ if (nclusters > CONFIG_MIPS_CPS_CLUSTER_MAX) {
+ pr_warn("%d clusters detected but limited to %d because of CONFIG_MIPS_CPU_CLUSTER_MAX value\n"
+ "consider modifying it to match the hardware capability.\n",
+ nclusters, CONFIG_MIPS_CPS_CLUSTER_MAX);
+ nclusters = CONFIG_MIPS_CPS_CLUSTER_MAX;
+ }
+
+ return nclusters;
}
/**
@@ -258,6 +270,8 @@ static inline bool mips_cps_multicluster_cpus(void)
/**
* mips_cps_first_online_in_cluster() - Detect if CPU is first online in cluster
+ * @first_cpu: The first other online CPU in cluster, or nr_cpu_ids if
+ * the function returns true.
*
* Determine whether the local CPU is the first to be brought online in its
* cluster - that is, whether there are any other online CPUs in the local
@@ -265,6 +279,6 @@ static inline bool mips_cps_multicluster_cpus(void)
*
* Returns true if this CPU is first online, else false.
*/
-extern unsigned int mips_cps_first_online_in_cluster(void);
+extern unsigned int mips_cps_first_online_in_cluster(int *first_cpu);
#endif /* __MIPS_ASM_MIPS_CPS_H__ */
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 43cb1e20baed3648ff83bb5d3bbe6a726072e063..d1d98e03559df5f891c3afce0955d63db7eb1c45 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -529,39 +529,13 @@ void mips_cm_error_report(void)
write_gcr_error_cause(cm_error);
}
-unsigned int mips_cps_first_online_in_cluster(void)
+unsigned int mips_cps_first_online_in_cluster(int *first_cpu)
{
- unsigned int local_cl;
- int i;
+ unsigned int local_cl = cpu_cluster(¤t_cpu_data);
+ struct cpumask *local_cluster_mask = &__cpu_cluster_mask[local_cl];
- local_cl = cpu_cluster(¤t_cpu_data);
-
- /*
- * We rely upon knowledge that CPUs are numbered sequentially by
- * cluster - ie. CPUs 0..X will be in cluster 0, CPUs X+1..Y in cluster
- * 1, CPUs Y+1..Z in cluster 2 etc. This means that CPUs in the same
- * cluster will immediately precede or follow one another.
- *
- * First we scan backwards, until we find an online CPU in the cluster
- * or we move on to another cluster.
- */
- for (i = smp_processor_id() - 1; i >= 0; i--) {
- if (cpu_cluster(&cpu_data[i]) != local_cl)
- break;
- if (!cpu_online(i))
- continue;
- return false;
- }
-
- /* Then do the same for higher numbered CPUs */
- for (i = smp_processor_id() + 1; i < nr_cpu_ids; i++) {
- if (cpu_cluster(&cpu_data[i]) != local_cl)
- break;
- if (!cpu_online(i))
- continue;
- return false;
- }
-
- /* We found no online CPUs in the local cluster */
- return true;
+ *first_cpu = cpumask_any_and_but(local_cluster_mask,
+ cpu_online_mask,
+ smp_processor_id());
+ return (*first_cpu >= nr_cpu_ids);
}
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 7b0e69af4097025196b93115139a5e89c1d71fcc..a5c538742769dcbf22e27d2d4485c071e2e64ec2 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -40,6 +40,7 @@ static u64 core_entry_reg;
static phys_addr_t cps_vec_pa;
struct cluster_boot_config *mips_cps_cluster_bootcfg;
+struct cpumask __cpu_cluster_mask[CONFIG_MIPS_CPS_CLUSTER_MAX] __read_mostly;
static void power_up_other_cluster(unsigned int cluster)
{
@@ -242,6 +243,7 @@ static void __init cps_smp_setup(void)
cpu_set_cluster(&cpu_data[nvpes + v], cl);
cpu_set_core(&cpu_data[nvpes + v], c);
cpu_set_vpe_id(&cpu_data[nvpes + v], v);
+ cpumask_set_cpu(nvpes + v, &__cpu_cluster_mask[cl]);
}
nvpes += core_vpes;
--
2.47.2
Powered by blists - more mailing lists