]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: airoha: Rework the code flow in airoha_remove() and in airoha_probe() error...
authorLorenzo Bianconi <lorenzo@kernel.org>
Sat, 21 Mar 2026 14:41:44 +0000 (15:41 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 24 Mar 2026 12:40:05 +0000 (13:40 +0100)
As suggested by Simon in [0], rework the code flow in airoha_remove()
and in the airoha_probe() error path in order to rely on a more common
approach un-registering configured net-devices first and destroying the
hw resources at the end of the code.
Introduce airoha_qdma_cleanup routine to release QDMA resources.

[0] https://lore.kernel.org/netdev/20251214-airoha-fix-dev-registration-v1-1-860e027ad4c6@kernel.org/

Suggested-by: Simon Horman <horms@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260321-airoha-remove-rework-v2-1-16c7bade5fe5@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/airoha/airoha_eth.c

index 961325da833b27eee31dfa03be26dfc82071097e..82e53c60f561f6314fbf201ba8bc8711e40edc68 100644 (file)
@@ -1368,6 +1368,33 @@ static int airoha_qdma_init(struct platform_device *pdev,
        return airoha_qdma_hw_init(qdma);
 }
 
+static void airoha_qdma_cleanup(struct airoha_qdma *qdma)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
+               if (!qdma->q_rx[i].ndesc)
+                       continue;
+
+               netif_napi_del(&qdma->q_rx[i].napi);
+               airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
+               if (qdma->q_rx[i].page_pool) {
+                       page_pool_destroy(qdma->q_rx[i].page_pool);
+                       qdma->q_rx[i].page_pool = NULL;
+               }
+       }
+
+       for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
+               netif_napi_del(&qdma->q_tx_irq[i].napi);
+
+       for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
+               if (!qdma->q_tx[i].ndesc)
+                       continue;
+
+               airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
+       }
+}
+
 static int airoha_hw_init(struct platform_device *pdev,
                          struct airoha_eth *eth)
 {
@@ -1395,41 +1422,30 @@ static int airoha_hw_init(struct platform_device *pdev,
        for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
                err = airoha_qdma_init(pdev, eth, &eth->qdma[i]);
                if (err)
-                       return err;
+                       goto error;
        }
 
        err = airoha_ppe_init(eth);
        if (err)
-               return err;
+               goto error;
 
        set_bit(DEV_STATE_INITIALIZED, &eth->state);
 
        return 0;
+error:
+       for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+               airoha_qdma_cleanup(&eth->qdma[i]);
+
+       return err;
 }
 
-static void airoha_hw_cleanup(struct airoha_qdma *qdma)
+static void airoha_hw_cleanup(struct airoha_eth *eth)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
-               if (!qdma->q_rx[i].ndesc)
-                       continue;
-
-               netif_napi_del(&qdma->q_rx[i].napi);
-               airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
-               if (qdma->q_rx[i].page_pool)
-                       page_pool_destroy(qdma->q_rx[i].page_pool);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
-               netif_napi_del(&qdma->q_tx_irq[i].napi);
-
-       for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
-               if (!qdma->q_tx[i].ndesc)
-                       continue;
-
-               airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
-       }
+       for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+               airoha_qdma_cleanup(&eth->qdma[i]);
+       airoha_ppe_deinit(eth);
 }
 
 static void airoha_qdma_start_napi(struct airoha_qdma *qdma)
@@ -3012,7 +3028,7 @@ static int airoha_probe(struct platform_device *pdev)
 
        err = airoha_hw_init(pdev, eth);
        if (err)
-               goto error_hw_cleanup;
+               goto error_netdev_free;
 
        for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
                airoha_qdma_start_napi(&eth->qdma[i]);
@@ -3040,10 +3056,6 @@ static int airoha_probe(struct platform_device *pdev)
 error_napi_stop:
        for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
                airoha_qdma_stop_napi(&eth->qdma[i]);
-       airoha_ppe_deinit(eth);
-error_hw_cleanup:
-       for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
-               airoha_hw_cleanup(&eth->qdma[i]);
 
        for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
                struct airoha_gdm_port *port = eth->ports[i];
@@ -3055,6 +3067,8 @@ error_hw_cleanup:
                        unregister_netdev(port->dev);
                airoha_metadata_dst_free(port);
        }
+       airoha_hw_cleanup(eth);
+error_netdev_free:
        free_netdev(eth->napi_dev);
        platform_set_drvdata(pdev, NULL);
 
@@ -3066,10 +3080,8 @@ static void airoha_remove(struct platform_device *pdev)
        struct airoha_eth *eth = platform_get_drvdata(pdev);
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
+       for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
                airoha_qdma_stop_napi(&eth->qdma[i]);
-               airoha_hw_cleanup(&eth->qdma[i]);
-       }
 
        for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
                struct airoha_gdm_port *port = eth->ports[i];
@@ -3080,9 +3092,9 @@ static void airoha_remove(struct platform_device *pdev)
                unregister_netdev(port->dev);
                airoha_metadata_dst_free(port);
        }
-       free_netdev(eth->napi_dev);
+       airoha_hw_cleanup(eth);
 
-       airoha_ppe_deinit(eth);
+       free_netdev(eth->napi_dev);
        platform_set_drvdata(pdev, NULL);
 }