]> www.infradead.org Git - users/hch/misc.git/commitdiff
net: ethernet: ti: am65-cpsw: Fix NAPI registration sequence
authorVignesh Raghavendra <vigneshr@ti.com>
Tue, 11 Mar 2025 15:42:59 +0000 (21:12 +0530)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 18 Mar 2025 10:14:35 +0000 (11:14 +0100)
Registering the interrupts for TX or RX DMA Channels prior to registering
their respective NAPI callbacks can result in a NULL pointer dereference.
This is seen in practice as a random occurrence since it depends on the
randomness associated with the generation of traffic by Linux and the
reception of traffic from the wire.

Fixes: 681eb2beb3ef ("net: ethernet: ti: am65-cpsw: ensure proper channel cleanup in error path")
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Co-developed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Reviewed-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
Reviewed-by: Roger Quadros <rogerq@kernel.org>
Link: https://patch.msgid.link/20250311154259.102865-1-s-vadapalli@ti.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/ti/am65-cpsw-nuss.c

index 2806238629f823ca4f708fa0c1ba9e86fef4d441..bef734c6e5c2b36751a8178161d158ab893df4de 100644 (file)
@@ -2306,14 +2306,18 @@ static void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common)
 static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
 {
        struct device *dev = common->dev;
+       struct am65_cpsw_tx_chn *tx_chn;
        int i, ret = 0;
 
        for (i = 0; i < common->tx_ch_num; i++) {
-               struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
+               tx_chn = &common->tx_chns[i];
 
                hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
                tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
 
+               netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
+                                 am65_cpsw_nuss_tx_poll);
+
                ret = devm_request_irq(dev, tx_chn->irq,
                                       am65_cpsw_nuss_tx_irq,
                                       IRQF_TRIGGER_HIGH,
@@ -2323,19 +2327,16 @@ static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
                                tx_chn->id, tx_chn->irq, ret);
                        goto err;
                }
-
-               netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
-                                 am65_cpsw_nuss_tx_poll);
        }
 
        return 0;
 
 err:
-       for (--i ; i >= 0 ; i--) {
-               struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
-
-               netif_napi_del(&tx_chn->napi_tx);
+       netif_napi_del(&tx_chn->napi_tx);
+       for (--i; i >= 0; i--) {
+               tx_chn = &common->tx_chns[i];
                devm_free_irq(dev, tx_chn->irq, tx_chn);
+               netif_napi_del(&tx_chn->napi_tx);
        }
 
        return ret;
@@ -2569,6 +2570,9 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
                             HRTIMER_MODE_REL_PINNED);
                flow->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
 
+               netif_napi_add(common->dma_ndev, &flow->napi_rx,
+                              am65_cpsw_nuss_rx_poll);
+
                ret = devm_request_irq(dev, flow->irq,
                                       am65_cpsw_nuss_rx_irq,
                                       IRQF_TRIGGER_HIGH,
@@ -2577,11 +2581,8 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
                        dev_err(dev, "failure requesting rx %d irq %u, %d\n",
                                i, flow->irq, ret);
                        flow->irq = -EINVAL;
-                       goto err_flow;
+                       goto err_request_irq;
                }
-
-               netif_napi_add(common->dma_ndev, &flow->napi_rx,
-                              am65_cpsw_nuss_rx_poll);
        }
 
        /* setup classifier to route priorities to flows */
@@ -2589,11 +2590,14 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 
        return 0;
 
+err_request_irq:
+       netif_napi_del(&flow->napi_rx);
+
 err_flow:
-       for (--i; i >= 0 ; i--) {
+       for (--i; i >= 0; i--) {
                flow = &rx_chn->flows[i];
-               netif_napi_del(&flow->napi_rx);
                devm_free_irq(dev, flow->irq, flow);
+               netif_napi_del(&flow->napi_rx);
        }
 
 err: