Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: ftgmac100: fix ring allocation unwind on open failure

ftgmac100_alloc_rings() allocates rx_skbs, tx_skbs, rxdes, txdes, and
rx_scratch in stages. On intermediate failures it returned -ENOMEM
directly, leaking resources allocated earlier in the function.

Rework the failure path to use staged local unwind labels and free
allocated resources in reverse order before returning -ENOMEM. This
matches common netdev allocation cleanup style.

Fixes: d72e01a0430f ("ftgmac100: Use a scratch buffer for failed RX allocations")
Cc: stable@vger.kernel.org
Signed-off-by: Yufan Chen <yufan.chen@linux.dev>
Link: https://patch.msgid.link/20260328163257.60836-1-yufan.chen@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Yufan Chen and committed by
Jakub Kicinski
c0fd0fe7 5dd8025a

+24 -4
+24 -4
drivers/net/ethernet/faraday/ftgmac100.c
··· 977 977 priv->tx_skbs = kcalloc(MAX_TX_QUEUE_ENTRIES, sizeof(void *), 978 978 GFP_KERNEL); 979 979 if (!priv->tx_skbs) 980 - return -ENOMEM; 980 + goto err_free_rx_skbs; 981 981 982 982 /* Allocate descriptors */ 983 983 priv->rxdes = dma_alloc_coherent(priv->dev, 984 984 MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes), 985 985 &priv->rxdes_dma, GFP_KERNEL); 986 986 if (!priv->rxdes) 987 - return -ENOMEM; 987 + goto err_free_tx_skbs; 988 988 priv->txdes = dma_alloc_coherent(priv->dev, 989 989 MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes), 990 990 &priv->txdes_dma, GFP_KERNEL); 991 991 if (!priv->txdes) 992 - return -ENOMEM; 992 + goto err_free_rxdes; 993 993 994 994 /* Allocate scratch packet buffer */ 995 995 priv->rx_scratch = dma_alloc_coherent(priv->dev, ··· 997 997 &priv->rx_scratch_dma, 998 998 GFP_KERNEL); 999 999 if (!priv->rx_scratch) 1000 - return -ENOMEM; 1000 + goto err_free_txdes; 1001 1001 1002 1002 return 0; 1003 + 1004 + err_free_txdes: 1005 + dma_free_coherent(priv->dev, 1006 + MAX_TX_QUEUE_ENTRIES * 1007 + sizeof(struct ftgmac100_txdes), 1008 + priv->txdes, priv->txdes_dma); 1009 + priv->txdes = NULL; 1010 + err_free_rxdes: 1011 + dma_free_coherent(priv->dev, 1012 + MAX_RX_QUEUE_ENTRIES * 1013 + sizeof(struct ftgmac100_rxdes), 1014 + priv->rxdes, priv->rxdes_dma); 1015 + priv->rxdes = NULL; 1016 + err_free_tx_skbs: 1017 + kfree(priv->tx_skbs); 1018 + priv->tx_skbs = NULL; 1019 + err_free_rx_skbs: 1020 + kfree(priv->rx_skbs); 1021 + priv->rx_skbs = NULL; 1022 + return -ENOMEM; 1003 1023 } 1004 1024 1005 1025 static void ftgmac100_init_rings(struct ftgmac100 *priv)