Message ID | 20220525121030.16054-5-Dragan.Mladjenovic@syrmia.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | MIPS: Support I6500 multi-cluster configuration | expand |
On Wed, 25 May 2022 13:10:22 +0100, Dragan Mladjenovic <Dragan.Mladjenovic@syrmia.com> wrote: > > From: Paul Burton <paulburton@kernel.org> > > Introduce support for multi-cluster GIC register access in > __gic_with_next_online_cpu(), and therefore in its user > gic_with_each_online_cpu(). We access registers in remote clusters using > the CM's GCR_CL_REDIRECT register, and so here we delegate to > mips_cm_lock_other() in order to configure this access. > > With this done, users of gic_with_each_online_cpu() gain support for > multi-cluster with no further changes. > > Signed-off-by: Paul Burton <paulburton@kernel.org> > Signed-off-by: Chao-ying Fu <cfu@wavecomp.com> > Signed-off-by: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com> > > diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c > index 4872bebe24cf..89a3c6d04e09 100644 > --- a/drivers/irqchip/irq-mips-gic.c > +++ b/drivers/irqchip/irq-mips-gic.c > @@ -69,6 +69,20 @@ static int __gic_with_next_online_cpu(int prev) > { > unsigned int cpu; > > + /* > + * Unlock access to the previous CPU's GIC local register block. > + * > + * Delegate to the CM locking code in the multi-cluster case, since > + * other clusters can only be accessed using GCR_CL_REDIRECT. > + * > + * In the single cluster case we don't need to do anything; the caller > + * is responsible for maintaining gic_lock & nothing should be > + * expecting any particular value of GIC_VL_OTHER so we can leave it > + * as-is. > + */ > + if ((prev != -1) && mips_cps_multicluster_cpus()) > + mips_cm_unlock_other(); Huh. It now strikes me that if you exit the gic_with_next_online_cpu() early (with a 'break;', for example), the state machine breaks as you won't have performed the unlock... This definitely needs some documenting, at the very least. M.
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 4872bebe24cf..89a3c6d04e09 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -69,6 +69,20 @@ static int __gic_with_next_online_cpu(int prev) { unsigned int cpu; + /* + * Unlock access to the previous CPU's GIC local register block. + * + * Delegate to the CM locking code in the multi-cluster case, since + * other clusters can only be accessed using GCR_CL_REDIRECT. + * + * In the single cluster case we don't need to do anything; the caller + * is responsible for maintaining gic_lock & nothing should be + * expecting any particular value of GIC_VL_OTHER so we can leave it + * as-is. + */ + if ((prev != -1) && mips_cps_multicluster_cpus()) + mips_cm_unlock_other(); + /* Discover the next online CPU */ cpu = cpumask_next(prev, cpu_online_mask); @@ -79,10 +93,16 @@ static int __gic_with_next_online_cpu(int prev) /* * Lock access to the next CPU's GIC local register block. * + * Delegate to the CM locking code in the multi-cluster case, since + * other clusters can only be accessed using GCR_CL_REDIRECT. + * * In the single cluster case we simply set GIC_VL_OTHER. The caller * holds gic_lock so nothing can clobber the value we write. */ - write_gic_vl_other(mips_cm_vp_id(cpu)); + if (mips_cps_multicluster_cpus()) + mips_cm_lock_other_cpu(cpu, CM_GCR_Cx_OTHER_BLOCK_LOCAL); + else + write_gic_vl_other(mips_cm_vp_id(cpu)); return cpu; }