Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c50b30f3 authored by Marc Zyngier's avatar Marc Zyngier Committed by Greg Kroah-Hartman
Browse files

irqchip/gic: Atomically update affinity



commit 005c34ae4b44f085120d7f371121ec7ded677761 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: 04c8b0f8 ("irqchip/gic: Make locking a BL_SWITCHER only feature")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8b72b56b
Loading
Loading
Loading
Loading
+3 −10
Original line number Diff line number Diff line
@@ -324,10 +324,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,
			    bool force)
{
	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
	unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
	u32 val, mask, bit;
	unsigned long flags;
	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
	unsigned int cpu;

	if (!force)
		cpu = cpumask_any_and(mask_val, cpu_online_mask);
@@ -337,12 +335,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)
		return -EINVAL;

	gic_lock_irqsave(flags);
	mask = 0xff << shift;
	bit = gic_cpu_map[cpu] << shift;
	val = readl_relaxed(reg) & ~mask;
	writel_relaxed(val | bit, reg);
	gic_unlock_irqrestore(flags);
	writeb_relaxed(gic_cpu_map[cpu], reg);

	return IRQ_SET_MASK_OK_DONE;
}