From: Yoshihiro Shimoda <yoshihiro.shimoda...@renesas.com>

[ Upstream commit 015c5d5e6aa3523c758a70eb87b291cece2dbbb4 ]

According to the report of [1], this driver is possible to cause
the following error in ravb_tx_timeout_work().

ravb e6800000.ethernet ethernet: failed to switch device to config mode

This error means that the hardware could not change the state
from "Operation" to "Configuration" while some tx and/or rx queue
are operating. After that, ravb_config() in ravb_dmac_init() will fail,
and then any descriptors will be not allocaled anymore so that NULL
pointer dereference happens after that on ravb_start_xmit().

To fix the issue, the ravb_tx_timeout_work() should check
the return values of ravb_stop_dma() and ravb_dmac_init().
If ravb_stop_dma() fails, ravb_tx_timeout_work() re-enables TX and RX
and just exits. If ravb_dmac_init() fails, just exits.

[1]
https://lore.kernel.org/linux-renesas-soc/20200518045452.2390-1-dirk.be...@de.bosch.com/

Reported-by: Dirk Behme <dirk.be...@de.bosch.com>
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda...@renesas.com>
Reviewed-by: Sergei Shtylyov <sergei.shtyl...@gmail.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/net/ethernet/renesas/ravb_main.c | 26 ++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/renesas/ravb_main.c 
b/drivers/net/ethernet/renesas/ravb_main.c
index 3f165c137236d..30cdabf64ccc1 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -1444,6 +1444,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
        struct ravb_private *priv = container_of(work, struct ravb_private,
                                                 work);
        struct net_device *ndev = priv->ndev;
+       int error;
 
        netif_tx_stop_all_queues(ndev);
 
@@ -1452,15 +1453,36 @@ static void ravb_tx_timeout_work(struct work_struct 
*work)
                ravb_ptp_stop(ndev);
 
        /* Wait for DMA stopping */
-       ravb_stop_dma(ndev);
+       if (ravb_stop_dma(ndev)) {
+               /* If ravb_stop_dma() fails, the hardware is still operating
+                * for TX and/or RX. So, this should not call the following
+                * functions because ravb_dmac_init() is possible to fail too.
+                * Also, this should not retry ravb_stop_dma() again and again
+                * here because it's possible to wait forever. So, this just
+                * re-enables the TX and RX and skip the following
+                * re-initialization procedure.
+                */
+               ravb_rcv_snd_enable(ndev);
+               goto out;
+       }
 
        ravb_ring_free(ndev, RAVB_BE);
        ravb_ring_free(ndev, RAVB_NC);
 
        /* Device init */
-       ravb_dmac_init(ndev);
+       error = ravb_dmac_init(ndev);
+       if (error) {
+               /* If ravb_dmac_init() fails, descriptors are freed. So, this
+                * should return here to avoid re-enabling the TX and RX in
+                * ravb_emac_init().
+                */
+               netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
+                          __func__, error);
+               return;
+       }
        ravb_emac_init(ndev);
 
+out:
        /* Initialise PTP Clock driver */
        if (priv->chip_id == RCAR_GEN2)
                ravb_ptp_init(ndev, priv->pdev);
-- 
2.25.1



Reply via email to