[PATCH] net: moxa: dispose IRQ mappings on probe failure and device removal

Diego Fernando Mancera Gomez <[email protected]>
Newsgroups org.kernel.vger.netdev
Message-ID <[email protected]>
moxart_mac_probe() maps the interrupt with irq_of_parse_and_map() but
never disposes of the mapping on the error paths that follow a
successful mapping, and neither does moxart_remove().  Every failed
probe (for example EPROBE_DEFER from platform_get_ethdev_address(),
DMA allocation failures or register_netdev() failure) and every device
removal therefore leaks the interrupt mapping.

Register the disposal as a devres action with devm_add_action_or_reset()
immediately after irq_of_parse_and_map() and before devm_request_irq(),
so on unwind devres disposes of the mapping only after the handler has
been released, and devm_add_action_or_reset() disposes of the mapping
itself if the action cannot be registered.  Since devres_release_all()
runs only after the probe error path frees the netdev, release the
handler with devm_free_irq() before free_netdev() on the error paths
that follow a successful devm_request_irq(), and likewise in
moxart_remove().

Fixes: 6c821bd9edc9 ("net: Add MOXA ART SoCs ethernet driver")
Signed-off-by: Diego Fernando Mancera Gomez <[email protected]>
---
 drivers/net/ethernet/moxa/moxart_ether.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 8bd60168624a..7b5720f993ae 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -451,6 +451,13 @@ static const struct net_device_ops moxart_netdev_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
+static void moxart_irq_dispose_mapping(void *data)
+{
+	unsigned int irq = (unsigned int)(uintptr_t)data;
+
+	irq_dispose_mapping(irq);
+}
+
 static int moxart_mac_probe(struct platform_device *pdev)
 {
 	struct device *p_dev = &pdev->dev;
@@ -459,6 +466,7 @@ static int moxart_mac_probe(struct platform_device *pdev)
 	struct moxart_mac_priv_t *priv;
 	struct resource *res;
 	unsigned int irq;
+	bool irq_requested = false;
 	int ret;
 
 	ndev = alloc_etherdev(sizeof(struct moxart_mac_priv_t));
@@ -472,6 +480,16 @@ static int moxart_mac_probe(struct platform_device *pdev)
 		goto irq_map_fail;
 	}
 
+	/* Dispose of the IRQ mapping after the devres-managed handler has
+	 * been released: devres runs actions in reverse registration order,
+	 * so registering this before devm_request_irq() guarantees the
+	 * correct order on probe unwind and device removal.
+	 */
+	ret = devm_add_action_or_reset(p_dev, moxart_irq_dispose_mapping,
+				       (void *)(uintptr_t)irq);
+	if (ret)
+		goto irq_map_fail;
+
 	priv = netdev_priv(ndev);
 	priv->ndev = ndev;
 	priv->pdev = pdev;
@@ -533,6 +551,7 @@ static int moxart_mac_probe(struct platform_device *pdev)
 		netdev_err(ndev, "devm_request_irq failed\n");
 		goto init_fail;
 	}
+	irq_requested = true;
 
 	ndev->netdev_ops = &moxart_netdev_ops;
 	netif_napi_add_weight(ndev, &priv->napi, moxart_rx_poll, RX_DESC_NUM);
@@ -552,6 +571,8 @@ static int moxart_mac_probe(struct platform_device *pdev)
 
 init_fail:
 	netdev_err(ndev, "init failed\n");
+	if (irq_requested)
+		devm_free_irq(p_dev, irq, ndev);
 	moxart_mac_free_memory(ndev);
 irq_map_fail:
 	free_netdev(ndev);
-- 
2.54.0.windows.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.