Skip to content

Commit cd9f13c

Browse files
can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery
If the CAN controller goes into bus off, the do_set_mode() callback with CAN_MODE_START can be used to recover the controller, which then calls flexcan_chip_start(). If configured, this is done automatically by the framework or manually by the user. In flexcan_chip_start() there is an explicit call to flexcan_transceiver_enable(), which does a regulator_enable() on the transceiver regulator. This results in a net usage counter increase, as there is no corresponding flexcan_transceiver_disable() in the bus off code path. This further leads to the transceiver stuck enabled, even if the CAN interface is shut down. To fix this problem the flexcan_transceiver_enable()/flexcan_transceiver_disable() are moved out of flexcan_chip_start()/flexcan_chip_stop() into flexcan_open()/flexcan_close(). Fixes: e955cea ("CAN: Add Flexcan CAN controller driver") Link: https://lore.kernel.org/r/20201118150148.2664024-1-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
1 parent d003868 commit cd9f13c

1 file changed

Lines changed: 9 additions & 9 deletions

File tree

drivers/net/can/flexcan.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,14 +1567,10 @@ static int flexcan_chip_start(struct net_device *dev)
15671567
priv->write(reg_ctrl2, &regs->ctrl2);
15681568
}
15691569

1570-
err = flexcan_transceiver_enable(priv);
1571-
if (err)
1572-
goto out_chip_disable;
1573-
15741570
/* synchronize with the can bus */
15751571
err = flexcan_chip_unfreeze(priv);
15761572
if (err)
1577-
goto out_transceiver_disable;
1573+
goto out_chip_disable;
15781574

15791575
priv->can.state = CAN_STATE_ERROR_ACTIVE;
15801576

@@ -1592,8 +1588,6 @@ static int flexcan_chip_start(struct net_device *dev)
15921588

15931589
return 0;
15941590

1595-
out_transceiver_disable:
1596-
flexcan_transceiver_disable(priv);
15971591
out_chip_disable:
15981592
flexcan_chip_disable(priv);
15991593
return err;
@@ -1623,7 +1617,6 @@ static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
16231617
priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
16241618
&regs->ctrl);
16251619

1626-
flexcan_transceiver_disable(priv);
16271620
priv->can.state = CAN_STATE_STOPPED;
16281621

16291622
return 0;
@@ -1665,10 +1658,14 @@ static int flexcan_open(struct net_device *dev)
16651658
if (err)
16661659
goto out_runtime_put;
16671660

1668-
err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
1661+
err = flexcan_transceiver_enable(priv);
16691662
if (err)
16701663
goto out_close;
16711664

1665+
err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
1666+
if (err)
1667+
goto out_transceiver_disable;
1668+
16721669
if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
16731670
priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
16741671
else
@@ -1720,6 +1717,8 @@ static int flexcan_open(struct net_device *dev)
17201717
can_rx_offload_del(&priv->offload);
17211718
out_free_irq:
17221719
free_irq(dev->irq, dev);
1720+
out_transceiver_disable:
1721+
flexcan_transceiver_disable(priv);
17231722
out_close:
17241723
close_candev(dev);
17251724
out_runtime_put:
@@ -1738,6 +1737,7 @@ static int flexcan_close(struct net_device *dev)
17381737

17391738
can_rx_offload_del(&priv->offload);
17401739
free_irq(dev->irq, dev);
1740+
flexcan_transceiver_disable(priv);
17411741

17421742
close_candev(dev);
17431743
pm_runtime_put(priv->dev);

0 commit comments

Comments
 (0)