]> www.infradead.org Git - users/hch/misc.git/commitdiff
net: dlink: handle dma_map_single() failure properly
authorYeounsu Moon <yyyynoom@gmail.com>
Thu, 9 Oct 2025 15:57:16 +0000 (00:57 +0900)
committerDavid S. Miller <davem@davemloft.net>
Sun, 12 Oct 2025 18:02:16 +0000 (19:02 +0100)
There is no error handling for `dma_map_single()` failures.

Add error handling by checking `dma_mapping_error()` and freeing
the `skb` using `dev_kfree_skb()` (process context) when it fails.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Yeounsu Moon <yyyynoom@gmail.com>
Tested-on: D-Link DGE-550T Rev-A3
Suggested-by: Simon Horman <horms@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/dlink/dl2k.c

index 1996d2e4e3e2c97eccbfa9c217a70123883c6248..7077d705e471fb327921f9b7f42471fdc8bfc7f5 100644 (file)
@@ -508,25 +508,34 @@ static int alloc_list(struct net_device *dev)
        for (i = 0; i < RX_RING_SIZE; i++) {
                /* Allocated fixed size of skbuff */
                struct sk_buff *skb;
+               dma_addr_t addr;
 
                skb = netdev_alloc_skb_ip_align(dev, np->rx_buf_sz);
                np->rx_skbuff[i] = skb;
-               if (!skb) {
-                       free_list(dev);
-                       return -ENOMEM;
-               }
+               if (!skb)
+                       goto err_free_list;
+
+               addr = dma_map_single(&np->pdev->dev, skb->data,
+                                     np->rx_buf_sz, DMA_FROM_DEVICE);
+               if (dma_mapping_error(&np->pdev->dev, addr))
+                       goto err_kfree_skb;
 
                np->rx_ring[i].next_desc = cpu_to_le64(np->rx_ring_dma +
                                                ((i + 1) % RX_RING_SIZE) *
                                                sizeof(struct netdev_desc));
                /* Rubicon now supports 40 bits of addressing space. */
-               np->rx_ring[i].fraginfo =
-                   cpu_to_le64(dma_map_single(&np->pdev->dev, skb->data,
-                                              np->rx_buf_sz, DMA_FROM_DEVICE));
+               np->rx_ring[i].fraginfo = cpu_to_le64(addr);
                np->rx_ring[i].fraginfo |= cpu_to_le64((u64)np->rx_buf_sz << 48);
        }
 
        return 0;
+
+err_kfree_skb:
+       dev_kfree_skb(np->rx_skbuff[i]);
+       np->rx_skbuff[i] = NULL;
+err_free_list:
+       free_list(dev);
+       return -ENOMEM;
 }
 
 static void rio_hw_init(struct net_device *dev)