irqchip/gic: Atomically update affinity
commit5.4-rM2-2.2.x-imx-squashed005c34ae4b
upstream. The GIC driver uses a RMW sequence to update the affinity, and relies on the gic_lock_irqsave/gic_unlock_irqrestore sequences to update it atomically. But these sequences only expand into anything meaningful if the BL_SWITCHER option is selected, which almost never happens. It also turns out that using a RMW and locks is just as silly, as the GIC distributor supports byte accesses for the GICD_TARGETRn registers, which when used make the update atomic by definition. Drop the terminally broken code and replace it by a byte write. Fixes:04c8b0f82c
("irqchip/gic: Make locking a BL_SWITCHER only feature") Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
parent
7ba23593cb
commit
2a9278ac9c
|
@ -329,10 +329,8 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
|
||||||
static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
||||||
bool force)
|
bool force)
|
||||||
{
|
{
|
||||||
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
|
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
|
||||||
unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
|
unsigned int cpu;
|
||||||
u32 val, mask, bit;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!force)
|
if (!force)
|
||||||
cpu = cpumask_any_and(mask_val, cpu_online_mask);
|
cpu = cpumask_any_and(mask_val, cpu_online_mask);
|
||||||
|
@ -342,13 +340,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
||||||
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
|
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
gic_lock_irqsave(flags);
|
writeb_relaxed(gic_cpu_map[cpu], reg);
|
||||||
mask = 0xff << shift;
|
|
||||||
bit = gic_cpu_map[cpu] << shift;
|
|
||||||
val = readl_relaxed(reg) & ~mask;
|
|
||||||
writel_relaxed(val | bit, reg);
|
|
||||||
gic_unlock_irqrestore(flags);
|
|
||||||
|
|
||||||
irq_data_update_effective_affinity(d, cpumask_of(cpu));
|
irq_data_update_effective_affinity(d, cpumask_of(cpu));
|
||||||
|
|
||||||
return IRQ_SET_MASK_OK_DONE;
|
return IRQ_SET_MASK_OK_DONE;
|
||||||
|
|
Loading…
Reference in New Issue