Commit b1c803d5 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Paolo Abeni
Browse files

net: airoha: Rework the code flow in airoha_remove() and in airoha_probe() error path

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: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260321-airoha-remove-rework-v2-1-16c7bade5fe5@kernel.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent a4b908c8
Loading
Loading
Loading
Loading
+44 −32
Original line number Diff line number Diff line
@@ -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 @@ static int airoha_probe(struct platform_device *pdev)
			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);
}