Message ID | 20240511104341.151550-5-aleksandar.rikalo@syrmia.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | MIPS: Support I6500 multi-cluster configuration | expand |
On Sat, May 11 2024 at 12:43, Aleksandar Rikalo 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 > for_each_online_cpu_gic(). 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. Again: We do nothing. See docs. > @@ -70,6 +70,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(); Eew. static inline void gic_unlock_cluster(void) { if (mips_cps_multicluster_cpus()) mips_cm_unlock_other(); } #define for_each_online_cpu_gic(cpu, gic_lock) \ guard(raw_spinlock_irqsave)(gic_lock); \ for ((cpu) = __gic_with_next_online_cpu(-1); \ (cpu) < nr_cpu_ids; \ gic_unlock_cluster(), \ (cpu) = __gic_with_next_online_cpu(cpu);) No? Thanks, tglx
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 9e7182150b5c..317ccc2593d1 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -70,6 +70,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); @@ -80,10 +94,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; } @@ -105,6 +125,9 @@ static inline void __lockdep_assert_held(raw_spinlock_t *gic_lock) * * The caller must hold gic_lock throughout the loop, such that GIC_VL_OTHER * cannot be clobbered. + * + * Please note that if you start a loop this way, it must be completed to the + * end, otherwise, GIC local register block will remain locked. */ #define for_each_online_cpu_gic(cpu, gic_lock) \ for (__lockdep_assert_held(gic_lock), \