mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
net: ftgmac100: fix ring allocation unwind on open failure
commitc0fd0fe745upstream. 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:d72e01a043("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
602596c69a
commit
8a71911fc7
@@ -934,19 +934,19 @@ static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
|
||||
priv->tx_skbs = kcalloc(MAX_TX_QUEUE_ENTRIES, sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!priv->tx_skbs)
|
||||
return -ENOMEM;
|
||||
goto err_free_rx_skbs;
|
||||
|
||||
/* Allocate descriptors */
|
||||
priv->rxdes = dma_alloc_coherent(priv->dev,
|
||||
MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes),
|
||||
&priv->rxdes_dma, GFP_KERNEL);
|
||||
if (!priv->rxdes)
|
||||
return -ENOMEM;
|
||||
goto err_free_tx_skbs;
|
||||
priv->txdes = dma_alloc_coherent(priv->dev,
|
||||
MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes),
|
||||
&priv->txdes_dma, GFP_KERNEL);
|
||||
if (!priv->txdes)
|
||||
return -ENOMEM;
|
||||
goto err_free_rxdes;
|
||||
|
||||
/* Allocate scratch packet buffer */
|
||||
priv->rx_scratch = dma_alloc_coherent(priv->dev,
|
||||
@@ -954,9 +954,29 @@ static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
|
||||
&priv->rx_scratch_dma,
|
||||
GFP_KERNEL);
|
||||
if (!priv->rx_scratch)
|
||||
return -ENOMEM;
|
||||
goto err_free_txdes;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_txdes:
|
||||
dma_free_coherent(priv->dev,
|
||||
MAX_TX_QUEUE_ENTRIES *
|
||||
sizeof(struct ftgmac100_txdes),
|
||||
priv->txdes, priv->txdes_dma);
|
||||
priv->txdes = NULL;
|
||||
err_free_rxdes:
|
||||
dma_free_coherent(priv->dev,
|
||||
MAX_RX_QUEUE_ENTRIES *
|
||||
sizeof(struct ftgmac100_rxdes),
|
||||
priv->rxdes, priv->rxdes_dma);
|
||||
priv->rxdes = NULL;
|
||||
err_free_tx_skbs:
|
||||
kfree(priv->tx_skbs);
|
||||
priv->tx_skbs = NULL;
|
||||
err_free_rx_skbs:
|
||||
kfree(priv->rx_skbs);
|
||||
priv->rx_skbs = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void ftgmac100_init_rings(struct ftgmac100 *priv)
|
||||
|
||||
Reference in New Issue
Block a user