aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-04-11 04:13:11 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-04-24 16:08:55 -0400
commitef1d2e286a2d8876e03a3f58ea1a1f549727e518 (patch)
tree7c85a445c90d79bd972fc10dc644cccc1b363b16
parentbed11db3d4095e5f818f5e8bf7f43ef2beb36d4e (diff)
can: c_can: Make bus off interrupt disable logic work
The state change handler is called with device interrupts disabled already. So no point in disabling them again when we enter bus off state. But what's worse is that we reenable the interrupts at the end of NAPI poll unconditionally. So c_can_start() which is called from the restart timer can trigger interrupts which confuse the hell out of the half reinitialized driver/hw. Remove the pointless device interrupt disable in the BUS_OFF handler and prevent reenabling the device interrupts at the end of the poll routine when the current state is BUS_OFF. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Alexander Stein <alexander.stein@systec-electronic.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/c_can/c_can.c11
1 files changed, 4 insertions, 7 deletions
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index b1629a47c03b..8c725f40bc1d 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -954,11 +954,6 @@ static int c_can_handle_state_change(struct net_device *dev,
954 /* bus-off state */ 954 /* bus-off state */
955 priv->can.state = CAN_STATE_BUS_OFF; 955 priv->can.state = CAN_STATE_BUS_OFF;
956 cf->can_id |= CAN_ERR_BUSOFF; 956 cf->can_id |= CAN_ERR_BUSOFF;
957 /*
958 * disable all interrupts in bus-off mode to ensure that
959 * the CPU is not hogged down
960 */
961 c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
962 can_bus_off(dev); 957 can_bus_off(dev);
963 break; 958 break;
964 default: 959 default:
@@ -1089,6 +1084,7 @@ static int c_can_poll(struct napi_struct *napi, int quota)
1089 netdev_dbg(dev, "entered bus off state\n"); 1084 netdev_dbg(dev, "entered bus off state\n");
1090 work_done += c_can_handle_state_change(dev, 1085 work_done += c_can_handle_state_change(dev,
1091 C_CAN_BUS_OFF); 1086 C_CAN_BUS_OFF);
1087 goto end;
1092 } 1088 }
1093 1089
1094 /* handle bus recovery events */ 1090 /* handle bus recovery events */
@@ -1122,8 +1118,9 @@ static int c_can_poll(struct napi_struct *napi, int quota)
1122end: 1118end:
1123 if (work_done < quota) { 1119 if (work_done < quota) {
1124 napi_complete(napi); 1120 napi_complete(napi);
1125 /* enable all IRQs */ 1121 /* enable all IRQs if we are not in bus off state */
1126 c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); 1122 if (priv->can.state != CAN_STATE_BUS_OFF)
1123 c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
1127 } 1124 }
1128 1125
1129 return work_done; 1126 return work_done;