Commit 75fa6a58 authored by Paul Burton's avatar Paul Burton Committed by Thomas Bogendoerfer
Browse files

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: default avatarPaul Burton <paulburton@kernel.org>
Signed-off-by: default avatarDragan Mladjenovic <dragan.mladjenovic@syrmia.com>
Signed-off-by: default avatarAleksandar Rikalo <arikalo@gmail.com>
Tested-by: default avatarSerge Semin <fancer.lancer@gmail.com>
Tested-by: default avatarGregory CLEMENT <gregory.clement@bootlin.com>
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
parent 00a134fc
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -22,7 +22,11 @@ struct core_boot_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_init(void);
+3 −0
Original line number Diff line number Diff line
@@ -410,6 +410,9 @@ void output_cps_defines(void)
{
	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_VPECONFIG, core_boot_config, vpe_config);
	DEFINE(COREBOOTCFG_SIZE, sizeof(struct core_boot_config));
+16 −3
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@
#define GCR_CPC_BASE_OFS	0x0088
#define GCR_CL_COHERENCE_OFS	0x2008
#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_RUN_OFS	0x2028
@@ -271,12 +275,21 @@ LEAF(mips_cps_core_init)
 */
LEAF(mips_cps_get_bootcfg)
	/* 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)
#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
	mul	t0, t0, t1
	PTR_LA	t1, mips_cps_core_bootcfg
	PTR_L	t1, 0(t1)
	PTR_ADDU v0, t0, t1
	PTR_ADDU v0, v0, t0

	/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
	li	t9, 0
+4 −1
Original line number Diff line number Diff line
@@ -101,12 +101,14 @@ static void coupled_barrier(atomic_t *a, unsigned online)
int cps_pm_enter_state(enum cps_pm_state state)
{
	unsigned cpu = smp_processor_id();
	unsigned int cluster = cpu_cluster(&current_cpu_data);
	unsigned core = cpu_core(&current_cpu_data);
	unsigned online, left;
	cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled);
	u32 *core_ready_count, *nc_core_ready_count;
	void *nc_addr;
	cps_nc_entry_fn entry;
	struct cluster_boot_config *cluster_cfg;
	struct core_boot_config *core_cfg;
	struct vpe_boot_config *vpe_cfg;
	atomic_t *barrier;
@@ -136,7 +138,8 @@ int cps_pm_enter_state(enum cps_pm_state state)
		if (!mips_cps_smp_in_use())
			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(&current_cpu_data)];
		vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
		vpe_cfg->gp = (unsigned long)current_thread_info();
+53 −29
Original line number Diff line number Diff line
@@ -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 cluster boot configuration structs */
	nclusters = mips_cps_numclusters();
	mips_cps_cluster_bootcfg = kcalloc(nclusters,
					   sizeof(*mips_cps_cluster_bootcfg),
					   GFP_KERNEL);

	for (cl = 0; cl < nclusters; cl++) {
		/* Allocate core boot configuration structs */
	ncores = mips_cps_numcores(0);
	mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
		ncores = mips_cps_numcores(cl);
		core_bootcfg = kcalloc(ncores, sizeof(*core_bootcfg),
					GFP_KERNEL);
	if (!mips_cps_core_bootcfg) {
		pr_err("Failed to allocate boot config for %u cores\n", ncores);
		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(0, c);
		mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes,
				sizeof(*mips_cps_core_bootcfg[c].vpe_config),
			core_vpes = core_vpe_count(cl, c);
			core_bootcfg[c].vpe_config = kcalloc(core_vpes,
					sizeof(*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);
			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);