336ad8d75810b13db503ced2ead3013f0cf965f0
[openwrt/svn-archive/archive.git] / target / linux / mvebu / patches-3.10 / 0085-irqchip-armada-370-xp-fix-IPI-race-condition.patch
1 From 60b78d28057f9f1ecce39955755d26e4cd3130de Mon Sep 17 00:00:00 2001
2 From: Lior Amsalem <alior@marvell.com>
3 Date: Mon, 25 Nov 2013 17:26:44 +0100
4 Subject: [PATCH 085/203] irqchip: armada-370-xp: fix IPI race condition
5
6 In the Armada 370/XP driver, when we receive an IRQ 0, we read the
7 list of doorbells that caused the interrupt from register
8 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS. This gives the list of IPIs that
9 were generated. However, instead of acknowledging only the IPIs that
10 were generated, we acknowledge *all* the IPIs, by writing
11 ~IPI_DOORBELL_MASK in the ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS register.
12
13 This creates a race condition: if a new IPI that isn't part of the
14 ones read into the temporary "ipimask" variable is fired before we
15 acknowledge all IPIs, then we will simply loose it. This is causing
16 scheduling hangs on SMP intensive workloads.
17
18 It is important to mention that this ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS
19 register has the following behavior: "A CPU write of 0 clears the bits
20 in this field. A CPU write of 1 has no effect". This is what allows us
21 to simply write ~ipimask to acknoledge the handled IPIs.
22
23 Notice that the same problem is present in the MSI implementation, but
24 it will be fixed as a separate patch, so that this IPI fix can be
25 pushed to older stable versions as appropriate (all the way to 3.8),
26 while the MSI code only appeared in 3.13.
27
28 Signed-off-by: Lior Amsalem <alior@marvell.com>
29 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
30 Cc: stable@vger.kernel.org
31 Cc: Thomas Gleixner <tglx@linutronix.de>
32 ---
33 drivers/irqchip/irq-armada-370-xp.c | 2 +-
34 1 file changed, 1 insertion(+), 1 deletion(-)
35
36 --- a/drivers/irqchip/irq-armada-370-xp.c
37 +++ b/drivers/irqchip/irq-armada-370-xp.c
38 @@ -407,7 +407,7 @@ armada_370_xp_handle_irq(struct pt_regs
39 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
40 & IPI_DOORBELL_MASK;
41
42 - writel(~IPI_DOORBELL_MASK, per_cpu_int_base +
43 + writel(~ipimask, per_cpu_int_base +
44 ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
45
46 /* Handle all pending doorbells */