* [PATCH] can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery
@ 2020-11-18 15:01 Marc Kleine-Budde
2020-11-19 0:59 ` Joakim Zhang
0 siblings, 1 reply; 2+ messages in thread
From: Marc Kleine-Budde @ 2020-11-18 15:01 UTC (permalink / raw)
To: linux-can; +Cc: Joakim Zhang, kernel, Marc Kleine-Budde
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: e955cead0311 ("CAN: Add Flexcan CAN controller driver")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
drivers/net/can/flexcan.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index d6a9cf0e9b60..99e5f272205d 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1567,14 +1567,10 @@ static int flexcan_chip_start(struct net_device *dev)
priv->write(reg_ctrl2, ®s->ctrl2);
}
- err = flexcan_transceiver_enable(priv);
- if (err)
- goto out_chip_disable;
-
/* synchronize with the can bus */
err = flexcan_chip_unfreeze(priv);
if (err)
- goto out_transceiver_disable;
+ goto out_chip_disable;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
@@ -1592,8 +1588,6 @@ static int flexcan_chip_start(struct net_device *dev)
return 0;
- out_transceiver_disable:
- flexcan_transceiver_disable(priv);
out_chip_disable:
flexcan_chip_disable(priv);
return err;
@@ -1623,7 +1617,6 @@ static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
®s->ctrl);
- flexcan_transceiver_disable(priv);
priv->can.state = CAN_STATE_STOPPED;
return 0;
@@ -1665,10 +1658,14 @@ static int flexcan_open(struct net_device *dev)
if (err)
goto out_runtime_put;
- err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+ err = flexcan_transceiver_enable(priv);
if (err)
goto out_close;
+ err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+ if (err)
+ goto out_transceiver_disable;
+
if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
else
@@ -1720,6 +1717,8 @@ static int flexcan_open(struct net_device *dev)
can_rx_offload_del(&priv->offload);
out_free_irq:
free_irq(dev->irq, dev);
+ out_transceiver_disable:
+ flexcan_transceiver_disable(priv);
out_close:
close_candev(dev);
out_runtime_put:
@@ -1738,6 +1737,7 @@ static int flexcan_close(struct net_device *dev)
can_rx_offload_del(&priv->offload);
free_irq(dev->irq, dev);
+ flexcan_transceiver_disable(priv);
close_candev(dev);
pm_runtime_put(priv->dev);
--
2.29.2
^ permalink raw reply related [flat|nested] 2+ messages in thread
* RE: [PATCH] can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery
2020-11-18 15:01 [PATCH] can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery Marc Kleine-Budde
@ 2020-11-19 0:59 ` Joakim Zhang
0 siblings, 0 replies; 2+ messages in thread
From: Joakim Zhang @ 2020-11-19 0:59 UTC (permalink / raw)
To: Marc Kleine-Budde, linux-can; +Cc: kernel
> -----Original Message-----
> From: Marc Kleine-Budde <mkl@pengutronix.de>
> Sent: 2020年11月18日 23:02
> To: linux-can@vger.kernel.org
> Cc: Joakim Zhang <qiangqing.zhang@nxp.com>; kernel@pengutronix.de; Marc
> Kleine-Budde <mkl@pengutronix.de>
> Subject: [PATCH] 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: e955cead0311 ("CAN: Add Flexcan CAN controller driver")
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Reviewed-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Best Regards,
Joakim Zhang
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-11-19 0:59 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-18 15:01 [PATCH] can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery Marc Kleine-Budde
2020-11-19 0:59 ` Joakim Zhang
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.