MIPS: CPS: Introduce struct cluster_boot_config

In preparation for supporting multi-cluster systems, introduce a struct
cluster_boot_config as an extra layer in the boot configuration
maintained by the MIPS Coherent Processing System (CPS) SMP
implementation. For now only one struct cluster_boot_config will be
allocated & we'll simply defererence its core_config field to find the
struct core_boot_config array which can be used to boot as usual.

Signed-off-by: Paul Burton <paulburton@kernel.org>
Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com>
Tested-by: Serge Semin <fancer.lancer@gmail.com>
Tested-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
This commit is contained in:
Paul Burton
2025-01-29 13:32:49 +01:00
committed by Thomas Bogendoerfer
parent 00a134fc2b
commit 75fa6a5838
5 changed files with 81 additions and 34 deletions

View File

@@ -40,7 +40,7 @@ static DECLARE_BITMAP(core_power, NR_CPUS);
static u64 core_entry_reg;
static phys_addr_t cps_vec_pa;
struct core_boot_config *mips_cps_core_bootcfg;
struct cluster_boot_config *mips_cps_cluster_bootcfg;
static unsigned __init core_vpe_count(unsigned int cluster, unsigned core)
{
@@ -238,8 +238,10 @@ static void __init cps_smp_setup(void)
static void __init cps_prepare_cpus(unsigned int max_cpus)
{
unsigned ncores, core_vpes, c, cca;
unsigned int nclusters, ncores, core_vpes, c, cl, cca;
bool cca_unsuitable, cores_limited;
struct cluster_boot_config *cluster_bootcfg;
struct core_boot_config *core_bootcfg;
mips_mt_set_cpuoptions();
@@ -281,40 +283,54 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
setup_cps_vecs();
/* Allocate core boot configuration structs */
ncores = mips_cps_numcores(0);
mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
GFP_KERNEL);
if (!mips_cps_core_bootcfg) {
pr_err("Failed to allocate boot config for %u cores\n", ncores);
goto err_out;
}
/* Allocate cluster boot configuration structs */
nclusters = mips_cps_numclusters();
mips_cps_cluster_bootcfg = kcalloc(nclusters,
sizeof(*mips_cps_cluster_bootcfg),
GFP_KERNEL);
/* Allocate VPE boot configuration structs */
for (c = 0; c < ncores; c++) {
core_vpes = core_vpe_count(0, c);
mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes,
sizeof(*mips_cps_core_bootcfg[c].vpe_config),
GFP_KERNEL);
if (!mips_cps_core_bootcfg[c].vpe_config) {
pr_err("Failed to allocate %u VPE boot configs\n",
core_vpes);
for (cl = 0; cl < nclusters; cl++) {
/* Allocate core boot configuration structs */
ncores = mips_cps_numcores(cl);
core_bootcfg = kcalloc(ncores, sizeof(*core_bootcfg),
GFP_KERNEL);
if (!core_bootcfg)
goto err_out;
mips_cps_cluster_bootcfg[cl].core_config = core_bootcfg;
/* Allocate VPE boot configuration structs */
for (c = 0; c < ncores; c++) {
core_vpes = core_vpe_count(cl, c);
core_bootcfg[c].vpe_config = kcalloc(core_vpes,
sizeof(*core_bootcfg[c].vpe_config),
GFP_KERNEL);
if (!core_bootcfg[c].vpe_config)
goto err_out;
}
}
/* Mark this CPU as booted */
atomic_set(&mips_cps_core_bootcfg[cpu_core(&current_cpu_data)].vpe_mask,
1 << cpu_vpe_id(&current_cpu_data));
cl = cpu_cluster(&current_cpu_data);
c = cpu_core(&current_cpu_data);
cluster_bootcfg = &mips_cps_cluster_bootcfg[cl];
core_bootcfg = &cluster_bootcfg->core_config[c];
atomic_set(&core_bootcfg->vpe_mask, 1 << cpu_vpe_id(&current_cpu_data));
return;
err_out:
/* Clean up allocations */
if (mips_cps_core_bootcfg) {
for (c = 0; c < ncores; c++)
kfree(mips_cps_core_bootcfg[c].vpe_config);
kfree(mips_cps_core_bootcfg);
mips_cps_core_bootcfg = NULL;
if (mips_cps_cluster_bootcfg) {
for (cl = 0; cl < nclusters; cl++) {
cluster_bootcfg = &mips_cps_cluster_bootcfg[cl];
ncores = mips_cps_numcores(cl);
for (c = 0; c < ncores; c++) {
core_bootcfg = &cluster_bootcfg->core_config[c];
kfree(core_bootcfg->vpe_config);
}
kfree(mips_cps_cluster_bootcfg[c].core_config);
}
kfree(mips_cps_cluster_bootcfg);
mips_cps_cluster_bootcfg = NULL;
}
/* Effectively disable SMP by declaring CPUs not present */
@@ -405,17 +421,23 @@ static void boot_core(unsigned int core, unsigned int vpe_id)
static void remote_vpe_boot(void *dummy)
{
unsigned int cluster = cpu_cluster(&current_cpu_data);
unsigned core = cpu_core(&current_cpu_data);
struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
struct cluster_boot_config *cluster_cfg =
&mips_cps_cluster_bootcfg[cluster];
struct core_boot_config *core_cfg = &cluster_cfg->core_config[core];
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data));
}
static int cps_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned int cluster = cpu_cluster(&cpu_data[cpu]);
unsigned core = cpu_core(&cpu_data[cpu]);
unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
struct cluster_boot_config *cluster_cfg =
&mips_cps_cluster_bootcfg[cluster];
struct core_boot_config *core_cfg = &cluster_cfg->core_config[core];
struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
unsigned int remote;
int err;
@@ -576,12 +598,14 @@ static void cps_kexec_nonboot_cpu(void)
static int cps_cpu_disable(void)
{
unsigned cpu = smp_processor_id();
struct cluster_boot_config *cluster_cfg;
struct core_boot_config *core_cfg;
if (!cps_pm_support_state(CPS_PM_POWER_GATED))
return -EINVAL;
core_cfg = &mips_cps_core_bootcfg[cpu_core(&current_cpu_data)];
cluster_cfg = &mips_cps_cluster_bootcfg[cpu_cluster(&current_cpu_data)];
core_cfg = &cluster_cfg->core_config[cpu_core(&current_cpu_data)];
atomic_sub(1 << cpu_vpe_id(&current_cpu_data), &core_cfg->vpe_mask);
smp_mb__after_atomic();
set_cpu_online(cpu, false);