[PATCH v3 1/3] can: mcp251x: Correctly handle restart-ms

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Always stop device when CAN_STATE_BUS_OFF is entered because the restart is
issued automatically through can.do_set_mode depending on restart-ms. Otherwise
the device re-enters CAN_STATE_ERROR_ACTIVE automatically after "128 occurences
of 11 consecutive recessive bits". Also fixes potential race condition by
resetting force_quit before enabling interrupts.

Signed-off-by: Timo Schlüßler <schluessler@xxxxxxxxx>
---
 drivers/net/can/spi/mcp251x.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index f569fd4..6f359df 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -485,10 +485,10 @@ static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode)
 	case CAN_MODE_START:
 		mcp251x_clean(net);
 		/* We have to delay work since SPI I/O may sleep */
+		if (priv->can.state == CAN_STATE_BUS_OFF)
+			priv->after_suspend = AFTER_SUSPEND_RESTART;
 		priv->can.state = CAN_STATE_ERROR_ACTIVE;
 		priv->restart_tx = 1;
-		if (priv->can.restart_ms == 0)
-			priv->after_suspend = AFTER_SUSPEND_RESTART;
 		queue_work(priv->wq, &priv->restart_work);
 		break;
 	default:
@@ -716,6 +716,7 @@ static void mcp251x_restart_work_handler(struct work_struct *ws)
 	if (priv->after_suspend) {
 		mcp251x_hw_reset(spi);
 		mcp251x_setup(net, spi);
+		priv->force_quit = 0;
 		if (priv->after_suspend & AFTER_SUSPEND_RESTART) {
 			mcp251x_set_normal_mode(spi);
 		} else if (priv->after_suspend & AFTER_SUSPEND_UP) {
@@ -727,7 +728,6 @@ static void mcp251x_restart_work_handler(struct work_struct *ws)
 			mcp251x_hw_sleep(spi);
 		}
 		priv->after_suspend = 0;
-		priv->force_quit = 0;
 	}
 
 	if (priv->restart_tx) {
@@ -845,13 +845,11 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
 		}
 
 		if (priv->can.state == CAN_STATE_BUS_OFF) {
-			if (priv->can.restart_ms == 0) {
-				priv->force_quit = 1;
-				priv->can.can_stats.bus_off++;
-				can_bus_off(net);
-				mcp251x_hw_sleep(spi);
-				break;
-			}
+			priv->force_quit = 1;
+			priv->can.can_stats.bus_off++;
+			can_bus_off(net);
+			mcp251x_hw_sleep(spi);
+			break;
 		}
 
 		if (intf == 0)
-- 
2.7.2




[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux