Patch "can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery" has been added to the 5.9-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery

to the 5.9-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     can-flexcan-flexcan_chip_start-fix-erroneous-flexcan.patch
and it can be found in the queue-5.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit a96c73679da53d5207961e3020827d8903f96b64
Author: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>
Date:   Wed Nov 18 16:01:48 2020 +0100

    can: flexcan: flexcan_chip_start(): fix erroneous flexcan_transceiver_enable() during bus-off recovery
    
    [ Upstream commit cd9f13c59461351d7a5fd07924264fb49b287359 ]
    
    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")
    Link: https://lore.kernel.org/r/20201118150148.2664024-1-mkl@xxxxxxxxxxxxxx
    Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 20a56f389c20c..4cbe8889f546f 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1229,14 +1229,10 @@ static int flexcan_chip_start(struct net_device *dev)
 		priv->write(reg_mecr, &regs->mecr);
 	}
 
-	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;
 
@@ -1254,8 +1250,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;
@@ -1285,7 +1279,6 @@ static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
 	priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 		    &regs->ctrl);
 
-	flexcan_transceiver_disable(priv);
 	priv->can.state = CAN_STATE_STOPPED;
 
 	return 0;
@@ -1321,10 +1314,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;
+
 	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
 	priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
 			 (sizeof(priv->regs->mb[1]) / priv->mb_size);
@@ -1373,6 +1370,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:
@@ -1391,6 +1390,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);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux