Commit 373a3499 authored by Catalin Marinas's avatar Catalin Marinas

DSB needed after disabling masking the IRQ

Starting with ARMv6, accesses to strongly ordered memory are not
guaranteed to complete before a subsequent instruction modifying the
interrupt mask in CPSR. This can cause potential problems with masking
or acknowledging an IRQ at the device or interrupt controller level
followed by a local_irq_enable or local_irq_restore (see B2.4.3 in ARM
ARM revI). This patch adds a DSB after masking the interrupts at the
interrupt controller level to ensure that the strongly ordered memory
access was completed.
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent fc65a471
......@@ -30,6 +30,7 @@
#include <linux/threads.h>
#include <linux/irq.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
......@@ -89,6 +90,7 @@ static void gic_ack_irq(unsigned int irq)
spin_lock(&irq_controller_lock);
writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
dsb();
spin_unlock(&irq_controller_lock);
}
......@@ -98,6 +100,7 @@ static void gic_mask_irq(unsigned int irq)
spin_lock(&irq_controller_lock);
writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
dsb();
spin_unlock(&irq_controller_lock);
}
......@@ -231,6 +234,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
*/
for (i = 0; i < max_irq; i += 32)
writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
dsb();
/*
* Setup the Linux IRQ subsystem.
......
......@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/hardware/vic.h>
......@@ -30,6 +31,7 @@ static void vic_mask_irq(unsigned int irq)
void __iomem *base = get_irq_chipdata(irq);
irq &= 31;
writel(1 << irq, base + VIC_INT_ENABLE_CLEAR);
dsb();
}
static void vic_unmask_irq(unsigned int irq)
......
......@@ -154,6 +154,7 @@ static void __init ap_map_io(void)
static void sc_mask_irq(unsigned int irq)
{
writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
dsb();
}
static void sc_unmask_irq(unsigned int irq)
......
......@@ -148,6 +148,7 @@ static void cic_mask_irq(unsigned int irq)
{
irq -= IRQ_CIC_START;
cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
dsb();
}
static void cic_unmask_irq(unsigned int irq)
......
......@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>
......@@ -61,6 +62,7 @@ static void omap_mask_irq(unsigned int irq)
}
omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset);
dsb();
}
static void omap_unmask_irq(unsigned int irq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment