diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2011-01-14 03:02:40 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-14 12:45:53 -0800 |
commit | b669e7f0580f3c0058f1b32c276ef6da8f05c138 (patch) | |
tree | 5bb14db09784d4cbc5a460a273980b3a470998a8 | |
parent | 2a2bc012b98729ce9a39386faed28d11ee021683 (diff) |
GRETH: fixed skb buffer memory leak on frame errors
A new SKB buffer should not be allocated when the old SKB is reused.
Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/greth.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 869e38d6f41..9386bce9dea 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -870,10 +870,9 @@ static int greth_rx_gbit(struct net_device *dev, int limit) } } - /* Allocate new skb to replace current */ - newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN); - - if (!bad && newskb) { + /* Allocate new skb to replace current, not needed if the + * current skb can be reused */ + if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) { skb_reserve(newskb, NET_IP_ALIGN); dma_addr = dma_map_single(greth->dev, @@ -910,11 +909,22 @@ static int greth_rx_gbit(struct net_device *dev, int limit) if (net_ratelimit()) dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n"); dev_kfree_skb(newskb); + /* reusing current skb, so it is a drop */ dev->stats.rx_dropped++; } + } else if (bad) { + /* Bad Frame transfer, the skb is reused */ + dev->stats.rx_dropped++; } else { + /* Failed Allocating a new skb. This is rather stupid + * but the current "filled" skb is reused, as if + * transfer failure. One could argue that RX descriptor + * table handling should be divided into cleaning and + * filling as the TX part of the driver + */ if (net_ratelimit()) dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n"); + /* reusing current skb, so it is a drop */ dev->stats.rx_dropped++; } |