summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSanchayan Maity <maitysanchayan@gmail.com>2015-04-29 19:07:35 +0530
committerStefan Agner <stefan.agner@toradex.com>2015-05-04 16:11:51 +0200
commitfeb85c154f0a457e17c8b74e9eb2938207a76090 (patch)
treef48b86983e32f7e2ec2e2794188d8fb38b9d4a66 /drivers
parente3382455cf55e95f30585a141c3fc8ee5adb584b (diff)
drivers: w1: tegra_w1: Fix race condition on high CPU load
On Tegra3 at high CPU load, for example while running stress, reading data from one wire results in the following stack trace: [ 58.436052] [<c05e93d4>] (__raw_spin_lock_irqsave+0x3c/0xac) from [<c05e945c>] (_raw_spin_lock_irqsave+0x18/0x1c) [ 58.446322] [<c05e945c>] (_raw_spin_lock_irqsave+0x18/0x1c) from [<c0048eb4>] (complete+0x28/0x64) [ 58.455276] [<c0048eb4>] (complete+0x28/0x64) from [<c03e276c>] (tegra_w1_irq+0x74/0xb4) [ 58.463376] [<c03e276c>] (tegra_w1_irq+0x74/0xb4) from [<c009a1fc>] (handle_irq_event_percpu+0x9c/0x278) [ 58.472847] [<c009a1fc>] (handle_irq_event_percpu+0x9c/0x278) from [<c009a424>] (handle_irq_event+0x4c/0x6c) [ 58.482666] [<c009a424>] (handle_irq_event+0x4c/0x6c) from [<c009cc40>] (handle_fasteoi_irq+0xe0/0x118) [ 58.492048] [<c009cc40>] (handle_fasteoi_irq+0xe0/0x118) from [<c0099bd8>] (generic_handle_irq+0x30/0x40) [ 58.501616] [<c0099bd8>] (generic_handle_irq+0x30/0x40) from [<c000ecfc>] (handle_IRQ+0x88/0xc8) [ 58.510393] [<c000ecfc>] (handle_IRQ+0x88/0xc8) from [<c0008430>] (asm_do_IRQ+0x18/0x1c) [ 58.518475] [<c0008430>] (asm_do_IRQ+0x18/0x1c) from [<c000e098>] (__irq_usr+0x38/0xc0) [ 58.526464] Exception stack(0xe51a3fb0 to 0xe51a3ff8) [ 58.531506] 3fa0: 00000000 bea29b04 4030b1b0 4030b4c8 [ 58.539673] 3fc0: 4030b22c 4fd2f305 0000d770 0000d6b0 00000000 00000001 0000000d 00000145 [ 58.547839] 3fe0: 193c62ce bea29af4 4030b22c 4020beb4 600b0010 ffffffff [ 58.554445] Code: e5843004 e10f0000 f10c0080 e3a02001 (e1953f9f) [ 58.560539] ---[ end trace fb2fc83ceb8e95c1 ]--- [ 58.565154] Kernel panic - not syncing: Fatal exception in interrupt [ 58.571520] [<c0014ef4>] (unwind_backtrace+0x0/0xec) from [<c05e10c8>] (dump_stack+0x20/0x24) [ 58.580039] [<c05e10c8>] (dump_stack+0x20/0x24) from [<c05e16a0>] (panic+0x7c/0x1ac) [ 58.587783] [<c05e16a0>] (panic+0x7c/0x1ac) from [<c0012038>] (die+0x280/0x2e8) [ 58.595087] [<c0012038>] (die+0x280/0x2e8) from [<c05e1130>] (__do_kernel_fault.part.3+0x64/0x84) [ 58.603952] [<c05e1130>] (__do_kernel_fault.part.3+0x64/0x84) from [<c0015c84>] (do_page_fault+0x204/0x21c) [ 58.613681] [<c0015c84>] (do_page_fault+0x204/0x21c) from [<c000830c>] (do_DataAbort+0x44/0xa8) [ 58.622369] [<c000830c>] (do_DataAbort+0x44/0xa8) from [<c000de18>] (__dabt_svc+0x38/0x60) This seems to be generated due a possible race condition between the on stack kernel completion being set to NULL in tegra_w1_touch_bit, while a possible spurious IRQ calling this completion in the IRQ handler. This is a temporary bandaid and the ideal solution would be to find why this affects the Tegra3 and not Tegra2. Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/w1/masters/tegra_w1.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/w1/masters/tegra_w1.c b/drivers/w1/masters/tegra_w1.c
index 9443c4b1dbc6..85eefd4d7eb5 100644
--- a/drivers/w1/masters/tegra_w1.c
+++ b/drivers/w1/masters/tegra_w1.c
@@ -290,7 +290,9 @@ static u8 tegra_w1_touch_bit(void *data, u8 bit)
done:
w1_imask(dev, 0);
+ spin_lock(&dev->spinlock);
dev->transfer_completion = NULL;
+ spin_unlock(&dev->spinlock);
clk_disable(dev->clk);
mutex_unlock(&dev->mutex);
return return_bit;
@@ -334,7 +336,9 @@ done:
}
w1_imask(dev, 0);
+ spin_lock(&dev->spinlock);
dev->transfer_completion = NULL;
+ spin_unlock(&dev->spinlock);
clk_disable(dev->clk);
mutex_unlock(&dev->mutex);
return presence;