net: ethernet: ti: am65-cpsw: Fix error handling in am65_cpsw_nuss_common_open()
authorRoger Quadros <rogerq@kernel.org>
Fri, 17 Nov 2023 12:17:55 +0000 (14:17 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 19 Nov 2023 19:46:40 +0000 (19:46 +0000)
k3_udma_glue_enable_rx/tx_chn returns error code on failure.
Bail out on error while enabling TX/RX channel.

In the error path, clean up the RX descriptors and SKBs.
Get rid of kmemleak_not_leak() as it seems unnecessary now.

Fixes: 93a76530316a ("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver")
Signed-off-by: Roger Quadros <rogerq@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/am65-cpsw-nuss.c

index 78b3e69fbccb1c8f6ca766a7aea686e9b07eeb84..7992a76ed4d8166928a0b0360babea296a6b18eb 100644 (file)
@@ -443,7 +443,7 @@ static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma)
 static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
 {
        struct am65_cpsw_host *host_p = am65_common_get_host(common);
-       int port_idx, i, ret;
+       int port_idx, i, ret, tx;
        struct sk_buff *skb;
        u32 val, port_mask;
 
@@ -510,8 +510,12 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
                                                  AM65_CPSW_MAX_PACKET_SIZE,
                                                  GFP_KERNEL);
                if (!skb) {
+                       ret = -ENOMEM;
                        dev_err(common->dev, "cannot allocate skb\n");
-                       return -ENOMEM;
+                       if (i)
+                               goto fail_rx;
+
+                       return ret;
                }
 
                ret = am65_cpsw_nuss_rx_push(common, skb);
@@ -520,17 +524,28 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
                                "cannot submit skb to channel rx, error %d\n",
                                ret);
                        kfree_skb(skb);
+                       if (i)
+                               goto fail_rx;
+
                        return ret;
                }
-               kmemleak_not_leak(skb);
        }
-       k3_udma_glue_enable_rx_chn(common->rx_chns.rx_chn);
 
-       for (i = 0; i < common->tx_ch_num; i++) {
-               ret = k3_udma_glue_enable_tx_chn(common->tx_chns[i].tx_chn);
-               if (ret)
-                       return ret;
-               napi_enable(&common->tx_chns[i].napi_tx);
+       ret = k3_udma_glue_enable_rx_chn(common->rx_chns.rx_chn);
+       if (ret) {
+               dev_err(common->dev, "couldn't enable rx chn: %d\n", ret);
+               goto fail_rx;
+       }
+
+       for (tx = 0; tx < common->tx_ch_num; tx++) {
+               ret = k3_udma_glue_enable_tx_chn(common->tx_chns[tx].tx_chn);
+               if (ret) {
+                       dev_err(common->dev, "couldn't enable tx chn %d: %d\n",
+                               tx, ret);
+                       tx--;
+                       goto fail_tx;
+               }
+               napi_enable(&common->tx_chns[tx].napi_tx);
        }
 
        napi_enable(&common->napi_rx);
@@ -541,6 +556,21 @@ static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common)
 
        dev_dbg(common->dev, "cpsw_nuss started\n");
        return 0;
+
+fail_tx:
+       while (tx >= 0) {
+               napi_disable(&common->tx_chns[tx].napi_tx);
+               k3_udma_glue_disable_tx_chn(common->tx_chns[tx].tx_chn);
+               tx--;
+       }
+
+       k3_udma_glue_disable_rx_chn(common->rx_chns.rx_chn);
+
+fail_rx:
+       k3_udma_glue_reset_rx_chn(common->rx_chns.rx_chn, 0,
+                                 &common->rx_chns,
+                                 am65_cpsw_nuss_rx_cleanup, 0);
+       return ret;
 }
 
 static int am65_cpsw_nuss_common_stop(struct am65_cpsw_common *common)