Skip to content

Commit 36675ac

Browse files
paulburtontsbogend
authored andcommitted
MIPS: CPS: Add a couple of multi-cluster utility functions
This patch introduces a couple of utility functions which help later patches with introducing support for multi-cluster systems. - mips_cps_multicluster_cpus() allows its caller to determine whether the system includes CPUs spread across multiple clusters. This is useful because in some cases behaviour can be more optimal taking this knowledge into account. The means by which we check this is dependent upon the way we probe CPUs & assign their numbers, so keeping this knowledge confined here in arch/mips/ seems appropriate. - mips_cps_first_online_in_cluster() allows its caller to determine whether it is running upon the first CPU online within its cluster. This information is useful in cases where some cluster-wide configuration may need to occur, but should not be repeated if another CPU in the cluster is already online. Similarly to the above this is determined based upon knowledge of CPU numbering so it makes sense to keep that knowledge in arch/mips/. The function is defined in mips-cm.c rather than in asm/mips-cps.h in order to allow us to use asm/cpu-info.h & linux/smp.h without encountering an include nightmare. Signed-off-by: Paul Burton <[email protected]> Signed-off-by: Chao-ying Fu <[email protected]> Signed-off-by: Dragan Mladjenovic <[email protected]> Signed-off-by: Aleksandar Rikalo <[email protected]> Signed-off-by: Thomas Bogendoerfer <[email protected]>
1 parent 89c7f50 commit 36675ac

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

arch/mips/include/asm/mips-cps.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define __MIPS_ASM_MIPS_CPS_H__
99

1010
#include <linux/bitfield.h>
11+
#include <linux/cpumask.h>
1112
#include <linux/io.h>
1213
#include <linux/types.h>
1314

@@ -228,4 +229,42 @@ static inline unsigned int mips_cps_numvps(unsigned int cluster, unsigned int co
228229
return FIELD_GET(CM_GCR_Cx_CONFIG_PVPE, cfg + 1);
229230
}
230231

232+
/**
233+
* mips_cps_multicluster_cpus() - Detect whether CPUs are in multiple clusters
234+
*
235+
* Determine whether the system includes CPUs in multiple clusters - ie.
236+
* whether we can treat the system as single or multi-cluster as far as CPUs
237+
* are concerned. Note that this is slightly different to simply checking
238+
* whether multiple clusters are present - it is possible for there to be
239+
* clusters which contain no CPUs, which this function will effectively ignore.
240+
*
241+
* Returns true if CPUs are spread across multiple clusters, else false.
242+
*/
243+
static inline bool mips_cps_multicluster_cpus(void)
244+
{
245+
unsigned int first_cl, last_cl;
246+
247+
/*
248+
* CPUs are numbered sequentially by cluster - ie. CPUs 0..X will be in
249+
* cluster 0, CPUs X+1..Y in cluster 1, CPUs Y+1..Z in cluster 2 etc.
250+
*
251+
* Thus we can detect multiple clusters trivially by checking whether
252+
* the first & last CPUs belong to the same cluster.
253+
*/
254+
first_cl = cpu_cluster(&boot_cpu_data);
255+
last_cl = cpu_cluster(&cpu_data[nr_cpu_ids - 1]);
256+
return first_cl != last_cl;
257+
}
258+
259+
/**
260+
* mips_cps_first_online_in_cluster() - Detect if CPU is first online in cluster
261+
*
262+
* Determine whether the local CPU is the first to be brought online in its
263+
* cluster - that is, whether there are any other online CPUs in the local
264+
* cluster.
265+
*
266+
* Returns true if this CPU is first online, else false.
267+
*/
268+
extern unsigned int mips_cps_first_online_in_cluster(void);
269+
231270
#endif /* __MIPS_ASM_MIPS_CPS_H__ */

arch/mips/kernel/mips-cm.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,3 +512,40 @@ void mips_cm_error_report(void)
512512
/* reprime cause register */
513513
write_gcr_error_cause(cm_error);
514514
}
515+
516+
unsigned int mips_cps_first_online_in_cluster(void)
517+
{
518+
unsigned int local_cl;
519+
int i;
520+
521+
local_cl = cpu_cluster(&current_cpu_data);
522+
523+
/*
524+
* We rely upon knowledge that CPUs are numbered sequentially by
525+
* cluster - ie. CPUs 0..X will be in cluster 0, CPUs X+1..Y in cluster
526+
* 1, CPUs Y+1..Z in cluster 2 etc. This means that CPUs in the same
527+
* cluster will immediately precede or follow one another.
528+
*
529+
* First we scan backwards, until we find an online CPU in the cluster
530+
* or we move on to another cluster.
531+
*/
532+
for (i = smp_processor_id() - 1; i >= 0; i--) {
533+
if (cpu_cluster(&cpu_data[i]) != local_cl)
534+
break;
535+
if (!cpu_online(i))
536+
continue;
537+
return false;
538+
}
539+
540+
/* Then do the same for higher numbered CPUs */
541+
for (i = smp_processor_id() + 1; i < nr_cpu_ids; i++) {
542+
if (cpu_cluster(&cpu_data[i]) != local_cl)
543+
break;
544+
if (!cpu_online(i))
545+
continue;
546+
return false;
547+
}
548+
549+
/* We found no online CPUs in the local cluster */
550+
return true;
551+
}

0 commit comments

Comments
 (0)