Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 patch modifies the function to allow providing the first
available online CPU when one already exists, which is necessary for
delay CPU calibration optimization.

Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Gregory CLEMENT and committed by
Thomas Bogendoerfer
c71085f2 07f8888e

+23 -32
+3 -1
arch/mips/include/asm/mips-cps.h
··· 258 258 259 259 /** 260 260 * mips_cps_first_online_in_cluster() - Detect if CPU is first online in cluster 261 + * @first_cpu: The first other online CPU in cluster, or nr_cpu_ids if 262 + * the function returns true. 261 263 * 262 264 * Determine whether the local CPU is the first to be brought online in its 263 265 * cluster - that is, whether there are any other online CPUs in the local ··· 267 265 * 268 266 * Returns true if this CPU is first online, else false. 269 267 */ 270 - extern unsigned int mips_cps_first_online_in_cluster(void); 268 + extern unsigned int mips_cps_first_online_in_cluster(int *first_cpu); 271 269 272 270 #endif /* __MIPS_ASM_MIPS_CPS_H__ */
+1
arch/mips/include/asm/smp-cps.h
··· 24 24 25 25 struct cluster_boot_config { 26 26 unsigned long *core_power; 27 + struct cpumask cpumask; 27 28 struct core_boot_config *core_config; 28 29 }; 29 30
+15 -30
arch/mips/kernel/mips-cm.c
··· 10 10 #include <linux/spinlock.h> 11 11 12 12 #include <asm/mips-cps.h> 13 + #include <asm/smp-cps.h> 13 14 #include <asm/mipsregs.h> 14 15 15 16 void __iomem *mips_gcr_base; ··· 535 534 write_gcr_error_cause(cm_error); 536 535 } 537 536 538 - unsigned int mips_cps_first_online_in_cluster(void) 537 + unsigned int mips_cps_first_online_in_cluster(int *first_cpu) 539 538 { 540 - unsigned int local_cl; 541 - int i; 542 - 543 - local_cl = cpu_cluster(&current_cpu_data); 539 + unsigned int local_cl = cpu_cluster(&current_cpu_data); 540 + struct cpumask *local_cl_mask; 544 541 545 542 /* 546 - * We rely upon knowledge that CPUs are numbered sequentially by 547 - * cluster - ie. CPUs 0..X will be in cluster 0, CPUs X+1..Y in cluster 548 - * 1, CPUs Y+1..Z in cluster 2 etc. This means that CPUs in the same 549 - * cluster will immediately precede or follow one another. 550 - * 551 - * First we scan backwards, until we find an online CPU in the cluster 552 - * or we move on to another cluster. 543 + * mips_cps_cluster_bootcfg is allocated in cps_prepare_cpus. If it is 544 + * not yet done, then we are so early that only one CPU is running, so 545 + * it is the first online CPU in the cluster. 553 546 */ 554 - for (i = smp_processor_id() - 1; i >= 0; i--) { 555 - if (cpu_cluster(&cpu_data[i]) != local_cl) 556 - break; 557 - if (!cpu_online(i)) 558 - continue; 559 - return false; 560 - } 547 + if (IS_ENABLED(CONFIG_MIPS_CPS) && mips_cps_cluster_bootcfg) 548 + local_cl_mask = &mips_cps_cluster_bootcfg[local_cl].cpumask; 549 + else 550 + return true; 561 551 562 - /* Then do the same for higher numbered CPUs */ 563 - for (i = smp_processor_id() + 1; i < nr_cpu_ids; i++) { 564 - if (cpu_cluster(&cpu_data[i]) != local_cl) 565 - break; 566 - if (!cpu_online(i)) 567 - continue; 568 - return false; 569 - } 570 - 571 - /* We found no online CPUs in the local cluster */ 572 - return true; 552 + *first_cpu = cpumask_any_and_but(local_cl_mask, 553 + cpu_online_mask, 554 + smp_processor_id()); 555 + return (*first_cpu >= nr_cpu_ids); 573 556 }
+4 -1
arch/mips/kernel/smp-cps.c
··· 283 283 284 284 static void __init cps_prepare_cpus(unsigned int max_cpus) 285 285 { 286 - unsigned int nclusters, ncores, core_vpes, c, cl, cca; 286 + unsigned int nclusters, ncores, core_vpes, nvpe = 0, c, cl, cca; 287 287 bool cca_unsuitable, cores_limited; 288 288 struct cluster_boot_config *cluster_bootcfg; 289 289 struct core_boot_config *core_bootcfg; ··· 356 356 357 357 /* Allocate VPE boot configuration structs */ 358 358 for (c = 0; c < ncores; c++) { 359 + int v; 359 360 core_vpes = core_vpe_count(cl, c); 360 361 core_bootcfg[c].vpe_config = kcalloc(core_vpes, 361 362 sizeof(*core_bootcfg[c].vpe_config), 362 363 GFP_KERNEL); 364 + for (v = 0; v < core_vpes; v++) 365 + cpumask_set_cpu(nvpe++, &mips_cps_cluster_bootcfg[cl].cpumask); 363 366 if (!core_bootcfg[c].vpe_config) 364 367 goto err_out; 365 368 }