Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1737208

[PATCH 2/2] irqchip: mips-gic: Use effective affinity to unmask

From Paul Burton <paul.burton@imgtec.com>
Newsgroups linux.kernel
Subject [PATCH 2/2] irqchip: mips-gic: Use effective affinity to unmask
Date 2017-09-22 08:30 +0200
Message-ID <uspDk-2JB-7@gated-at.bofh.it> (permalink)
References <uspDj-2JB-1@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


Commit 7778c4b27cbe ("irqchip: mips-gic: Use pcpu_masks to avoid reading
GIC_SH_MASK*") adjusted the way we handle masking interrupts to set &
clear the interrupt's bit in each pcpu_mask. This allows us to avoid
needing to read the GIC mask registers and perform a bitwise and of
their values with the pending & pcpu_masks.

Unfortunately this didn't quite work for IPIs, which were mapped to a
particular CPU/VP during initialisation but never set the affinity or
effective_affinity fields of their struct irq_desc. This led to them
losing their affinity when gic_unmask_irq() was called for them, and
they'd all become affine to cpu0.

Fix this by:

 1) Setting the effective affinity of interrupts in
    gic_shared_irq_domain_map(), which is where we actually map an
    interrupt to a CPU/VP. This ensures that the effective affinity mask
    is always valid, not just after explicitly setting affinity.

 2) Using an interrupt's effective affinity when unmasking it, which
    prevents gic_unmask_irq() from unintentionally changing which
    pcpu_mask includes an interrupt.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Fixes: 7778c4b27cbe ("irqchip: mips-gic: Use pcpu_masks to avoid reading GIC_SH_MASK*")
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org

---

 drivers/irqchip/irq-mips-gic.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 0022b31ad2c5..c90976d7e53c 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -175,14 +175,13 @@ static void gic_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	struct cpumask *affinity = irq_data_get_affinity_mask(d);
 	unsigned int intr = GIC_HWIRQ_TO_SHARED(d->hwirq);
 	unsigned int cpu;
 
 	write_gic_smask(intr);
 
 	gic_clear_pcpu_masks(intr);
-	cpu = cpumask_first_and(affinity, cpu_online_mask);
+	cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
 	set_bit(intr, per_cpu_ptr(pcpu_masks, cpu));
 }
 
@@ -420,13 +419,17 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
 				     irq_hw_number_t hw, unsigned int cpu)
 {
 	int intr = GIC_HWIRQ_TO_SHARED(hw);
+	struct irq_data *data;
 	unsigned long flags;
 
+	data = irq_get_irq_data(virq);
+
 	spin_lock_irqsave(&gic_lock, flags);
 	write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
 	write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
 	gic_clear_pcpu_masks(intr);
 	set_bit(intr, per_cpu_ptr(pcpu_masks, cpu));
+	irq_data_update_effective_affinity(data, cpumask_of(cpu));
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
-- 
2.14.1

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 0/2] irqchip: mips-gic: Couple of fixes for v4.14-rc1 breakage Paul Burton <paul.burton@imgtec.com> - 2017-09-22 08:30 +0200
  [PATCH 2/2] irqchip: mips-gic: Use effective affinity to unmask Paul Burton <paul.burton@imgtec.com> - 2017-09-22 08:30 +0200
  [PATCH 1/2] irqchip: mips-gic: Fix shifts to extract register fields Paul Burton <paul.burton@imgtec.com> - 2017-09-22 08:30 +0200

csiph-web