aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnilKumar Ch <anilkumar@ti.com>2012-05-23 17:45:11 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-17 11:23:11 -0700
commit4286e566ff410a64f5a329fb42f2d44193c52945 (patch)
treea9b9c4d093ed44459db901efc8464c0afd992df5
parente3c8262d150883d1dbd9b5cbb03d6cca7cf68cad (diff)
downloadkernel_samsung_smdk4412-4286e566ff410a64f5a329fb42f2d44193c52945.zip
kernel_samsung_smdk4412-4286e566ff410a64f5a329fb42f2d44193c52945.tar.gz
kernel_samsung_smdk4412-4286e566ff410a64f5a329fb42f2d44193c52945.tar.bz2
can: c_can: fix race condition in c_can_open()
commit f461f27a4436dbe691908fe08b867ef888848cc3 upstream. Fix the issue of C_CAN interrupts getting disabled forever when canconfig utility is used multiple times. According to NAPI usage we disable all the hardware interrupts in ISR and re-enable them in poll(). Current implementation calls napi_enable() after hardware interrupts are enabled. If we get any interrupts between these two steps then we do not process those interrupts because napi is not enabled. Mostly these interrupts come because of STATUS is not 0x7 or ERROR interrupts. If napi_enable() happens before HW interrupts enabled then c_can_poll() function will be called eventual re-enabling. This patch moves the napi_enable() call before interrupts enabled. Signed-off-by: AnilKumar Ch <anilkumar@ti.com> Acked-by: Wolfgang Grandegger <wg@grandegger.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/can/c_can/c_can.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 227dfd8..1f8a824 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -1066,10 +1066,11 @@ static int c_can_open(struct net_device *dev)
goto exit_irq_fail;
}
+ napi_enable(&priv->napi);
+
/* start the c_can controller */
c_can_start(dev);
- napi_enable(&priv->napi);
netif_start_queue(dev);
return 0;