mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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:
parent
00a134fc2b
commit
75fa6a5838
5 changed files with 81 additions and 34 deletions
|
@ -22,7 +22,11 @@ struct core_boot_config {
|
||||||
struct vpe_boot_config *vpe_config;
|
struct vpe_boot_config *vpe_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct core_boot_config *mips_cps_core_bootcfg;
|
struct cluster_boot_config {
|
||||||
|
struct core_boot_config *core_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct cluster_boot_config *mips_cps_cluster_bootcfg;
|
||||||
|
|
||||||
extern void mips_cps_core_boot(int cca, void __iomem *gcr_base);
|
extern void mips_cps_core_boot(int cca, void __iomem *gcr_base);
|
||||||
extern void mips_cps_core_init(void);
|
extern void mips_cps_core_init(void);
|
||||||
|
|
|
@ -410,6 +410,9 @@ void output_cps_defines(void)
|
||||||
{
|
{
|
||||||
COMMENT(" MIPS CPS offsets. ");
|
COMMENT(" MIPS CPS offsets. ");
|
||||||
|
|
||||||
|
OFFSET(CLUSTERBOOTCFG_CORECONFIG, cluster_boot_config, core_config);
|
||||||
|
DEFINE(CLUSTERBOOTCFG_SIZE, sizeof(struct cluster_boot_config));
|
||||||
|
|
||||||
OFFSET(COREBOOTCFG_VPEMASK, core_boot_config, vpe_mask);
|
OFFSET(COREBOOTCFG_VPEMASK, core_boot_config, vpe_mask);
|
||||||
OFFSET(COREBOOTCFG_VPECONFIG, core_boot_config, vpe_config);
|
OFFSET(COREBOOTCFG_VPECONFIG, core_boot_config, vpe_config);
|
||||||
DEFINE(COREBOOTCFG_SIZE, sizeof(struct core_boot_config));
|
DEFINE(COREBOOTCFG_SIZE, sizeof(struct core_boot_config));
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
#define GCR_CPC_BASE_OFS 0x0088
|
#define GCR_CPC_BASE_OFS 0x0088
|
||||||
#define GCR_CL_COHERENCE_OFS 0x2008
|
#define GCR_CL_COHERENCE_OFS 0x2008
|
||||||
#define GCR_CL_ID_OFS 0x2028
|
#define GCR_CL_ID_OFS 0x2028
|
||||||
|
#define CM3_GCR_Cx_ID_CLUSTER_SHF 8
|
||||||
|
#define CM3_GCR_Cx_ID_CLUSTER_MSK (0xff << 8)
|
||||||
|
#define CM3_GCR_Cx_ID_CORENUM_SHF 0
|
||||||
|
#define CM3_GCR_Cx_ID_CORENUM_MSK (0xff << 0)
|
||||||
|
|
||||||
#define CPC_CL_VC_STOP_OFS 0x2020
|
#define CPC_CL_VC_STOP_OFS 0x2020
|
||||||
#define CPC_CL_VC_RUN_OFS 0x2028
|
#define CPC_CL_VC_RUN_OFS 0x2028
|
||||||
|
@ -271,12 +275,21 @@ LEAF(mips_cps_core_init)
|
||||||
*/
|
*/
|
||||||
LEAF(mips_cps_get_bootcfg)
|
LEAF(mips_cps_get_bootcfg)
|
||||||
/* Calculate a pointer to this cores struct core_boot_config */
|
/* Calculate a pointer to this cores struct core_boot_config */
|
||||||
|
PTR_LA v0, mips_cps_cluster_bootcfg
|
||||||
|
PTR_L v0, 0(v0)
|
||||||
lw t0, GCR_CL_ID_OFS(s1)
|
lw t0, GCR_CL_ID_OFS(s1)
|
||||||
|
#ifdef CONFIG_CPU_MIPSR6
|
||||||
|
ext t1, t0, CM3_GCR_Cx_ID_CLUSTER_SHF, 8
|
||||||
|
li t2, CLUSTERBOOTCFG_SIZE
|
||||||
|
mul t1, t1, t2
|
||||||
|
PTR_ADDU \
|
||||||
|
v0, v0, t1
|
||||||
|
#endif
|
||||||
|
PTR_L v0, CLUSTERBOOTCFG_CORECONFIG(v0)
|
||||||
|
andi t0, t0, CM3_GCR_Cx_ID_CORENUM_MSK
|
||||||
li t1, COREBOOTCFG_SIZE
|
li t1, COREBOOTCFG_SIZE
|
||||||
mul t0, t0, t1
|
mul t0, t0, t1
|
||||||
PTR_LA t1, mips_cps_core_bootcfg
|
PTR_ADDU v0, v0, t0
|
||||||
PTR_L t1, 0(t1)
|
|
||||||
PTR_ADDU v0, t0, t1
|
|
||||||
|
|
||||||
/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
|
/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
|
||||||
li t9, 0
|
li t9, 0
|
||||||
|
|
|
@ -101,12 +101,14 @@ static void coupled_barrier(atomic_t *a, unsigned online)
|
||||||
int cps_pm_enter_state(enum cps_pm_state state)
|
int cps_pm_enter_state(enum cps_pm_state state)
|
||||||
{
|
{
|
||||||
unsigned cpu = smp_processor_id();
|
unsigned cpu = smp_processor_id();
|
||||||
|
unsigned int cluster = cpu_cluster(¤t_cpu_data);
|
||||||
unsigned core = cpu_core(¤t_cpu_data);
|
unsigned core = cpu_core(¤t_cpu_data);
|
||||||
unsigned online, left;
|
unsigned online, left;
|
||||||
cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled);
|
cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled);
|
||||||
u32 *core_ready_count, *nc_core_ready_count;
|
u32 *core_ready_count, *nc_core_ready_count;
|
||||||
void *nc_addr;
|
void *nc_addr;
|
||||||
cps_nc_entry_fn entry;
|
cps_nc_entry_fn entry;
|
||||||
|
struct cluster_boot_config *cluster_cfg;
|
||||||
struct core_boot_config *core_cfg;
|
struct core_boot_config *core_cfg;
|
||||||
struct vpe_boot_config *vpe_cfg;
|
struct vpe_boot_config *vpe_cfg;
|
||||||
atomic_t *barrier;
|
atomic_t *barrier;
|
||||||
|
@ -136,7 +138,8 @@ int cps_pm_enter_state(enum cps_pm_state state)
|
||||||
if (!mips_cps_smp_in_use())
|
if (!mips_cps_smp_in_use())
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
core_cfg = &mips_cps_core_bootcfg[core];
|
cluster_cfg = &mips_cps_cluster_bootcfg[cluster];
|
||||||
|
core_cfg = &cluster_cfg->core_config[core];
|
||||||
vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(¤t_cpu_data)];
|
vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(¤t_cpu_data)];
|
||||||
vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
|
vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
|
||||||
vpe_cfg->gp = (unsigned long)current_thread_info();
|
vpe_cfg->gp = (unsigned long)current_thread_info();
|
||||||
|
|
|
@ -40,7 +40,7 @@ static DECLARE_BITMAP(core_power, NR_CPUS);
|
||||||
static u64 core_entry_reg;
|
static u64 core_entry_reg;
|
||||||
static phys_addr_t cps_vec_pa;
|
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)
|
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)
|
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;
|
bool cca_unsuitable, cores_limited;
|
||||||
|
struct cluster_boot_config *cluster_bootcfg;
|
||||||
|
struct core_boot_config *core_bootcfg;
|
||||||
|
|
||||||
mips_mt_set_cpuoptions();
|
mips_mt_set_cpuoptions();
|
||||||
|
|
||||||
|
@ -281,40 +283,54 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
|
||||||
|
|
||||||
setup_cps_vecs();
|
setup_cps_vecs();
|
||||||
|
|
||||||
/* Allocate core boot configuration structs */
|
/* Allocate cluster boot configuration structs */
|
||||||
ncores = mips_cps_numcores(0);
|
nclusters = mips_cps_numclusters();
|
||||||
mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
|
mips_cps_cluster_bootcfg = kcalloc(nclusters,
|
||||||
|
sizeof(*mips_cps_cluster_bootcfg),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!mips_cps_core_bootcfg) {
|
|
||||||
pr_err("Failed to allocate boot config for %u cores\n", ncores);
|
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;
|
goto err_out;
|
||||||
}
|
mips_cps_cluster_bootcfg[cl].core_config = core_bootcfg;
|
||||||
|
|
||||||
/* Allocate VPE boot configuration structs */
|
/* Allocate VPE boot configuration structs */
|
||||||
for (c = 0; c < ncores; c++) {
|
for (c = 0; c < ncores; c++) {
|
||||||
core_vpes = core_vpe_count(0, c);
|
core_vpes = core_vpe_count(cl, c);
|
||||||
mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes,
|
core_bootcfg[c].vpe_config = kcalloc(core_vpes,
|
||||||
sizeof(*mips_cps_core_bootcfg[c].vpe_config),
|
sizeof(*core_bootcfg[c].vpe_config),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!mips_cps_core_bootcfg[c].vpe_config) {
|
if (!core_bootcfg[c].vpe_config)
|
||||||
pr_err("Failed to allocate %u VPE boot configs\n",
|
|
||||||
core_vpes);
|
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark this CPU as booted */
|
/* Mark this CPU as booted */
|
||||||
atomic_set(&mips_cps_core_bootcfg[cpu_core(¤t_cpu_data)].vpe_mask,
|
cl = cpu_cluster(¤t_cpu_data);
|
||||||
1 << cpu_vpe_id(¤t_cpu_data));
|
c = cpu_core(¤t_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(¤t_cpu_data));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
err_out:
|
err_out:
|
||||||
/* Clean up allocations */
|
/* Clean up allocations */
|
||||||
if (mips_cps_core_bootcfg) {
|
if (mips_cps_cluster_bootcfg) {
|
||||||
for (c = 0; c < ncores; c++)
|
for (cl = 0; cl < nclusters; cl++) {
|
||||||
kfree(mips_cps_core_bootcfg[c].vpe_config);
|
cluster_bootcfg = &mips_cps_cluster_bootcfg[cl];
|
||||||
kfree(mips_cps_core_bootcfg);
|
ncores = mips_cps_numcores(cl);
|
||||||
mips_cps_core_bootcfg = NULL;
|
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 */
|
/* 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)
|
static void remote_vpe_boot(void *dummy)
|
||||||
{
|
{
|
||||||
|
unsigned int cluster = cpu_cluster(¤t_cpu_data);
|
||||||
unsigned core = cpu_core(¤t_cpu_data);
|
unsigned core = cpu_core(¤t_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(¤t_cpu_data));
|
mips_cps_boot_vpes(core_cfg, cpu_vpe_id(¤t_cpu_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cps_boot_secondary(int cpu, struct task_struct *idle)
|
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 core = cpu_core(&cpu_data[cpu]);
|
||||||
unsigned vpe_id = cpu_vpe_id(&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];
|
struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
|
||||||
unsigned int remote;
|
unsigned int remote;
|
||||||
int err;
|
int err;
|
||||||
|
@ -576,12 +598,14 @@ static void cps_kexec_nonboot_cpu(void)
|
||||||
static int cps_cpu_disable(void)
|
static int cps_cpu_disable(void)
|
||||||
{
|
{
|
||||||
unsigned cpu = smp_processor_id();
|
unsigned cpu = smp_processor_id();
|
||||||
|
struct cluster_boot_config *cluster_cfg;
|
||||||
struct core_boot_config *core_cfg;
|
struct core_boot_config *core_cfg;
|
||||||
|
|
||||||
if (!cps_pm_support_state(CPS_PM_POWER_GATED))
|
if (!cps_pm_support_state(CPS_PM_POWER_GATED))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
core_cfg = &mips_cps_core_bootcfg[cpu_core(¤t_cpu_data)];
|
cluster_cfg = &mips_cps_cluster_bootcfg[cpu_cluster(¤t_cpu_data)];
|
||||||
|
core_cfg = &cluster_cfg->core_config[cpu_core(¤t_cpu_data)];
|
||||||
atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask);
|
atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask);
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
set_cpu_online(cpu, false);
|
set_cpu_online(cpu, false);
|
||||||
|
|
Loading…
Add table
Reference in a new issue