Commit 60e2e8b3 authored by Don Fry's avatar Don Fry Committed by David S. Miller

pcnet32: fix reallocation error

pcnet32_realloc_rx_ring() only worked on the first log2 number of
entries in the receive ring instead of the all the entries.
Replaced "1 << size" with more descriptive variable.
This is my original bug from 2006.  Found while testing another problem.
Tested on 79C972 and 79C976.
Signed-off-by: default avatarDon Fry <pcnet32@frontier.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1e8d6421
...@@ -549,35 +549,36 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, ...@@ -549,35 +549,36 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
struct pcnet32_rx_head *new_rx_ring; struct pcnet32_rx_head *new_rx_ring;
struct sk_buff **new_skb_list; struct sk_buff **new_skb_list;
int new, overlap; int new, overlap;
unsigned int entries = 1 << size;
new_rx_ring = pci_alloc_consistent(lp->pci_dev, new_rx_ring = pci_alloc_consistent(lp->pci_dev,
sizeof(struct pcnet32_rx_head) * sizeof(struct pcnet32_rx_head) *
(1 << size), entries,
&new_ring_dma_addr); &new_ring_dma_addr);
if (new_rx_ring == NULL) { if (new_rx_ring == NULL) {
netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); netif_err(lp, drv, dev, "Consistent memory allocation failed\n");
return; return;
} }
memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size)); memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * entries);
new_dma_addr_list = kcalloc(1 << size, sizeof(dma_addr_t), GFP_ATOMIC); new_dma_addr_list = kcalloc(entries, sizeof(dma_addr_t), GFP_ATOMIC);
if (!new_dma_addr_list) if (!new_dma_addr_list)
goto free_new_rx_ring; goto free_new_rx_ring;
new_skb_list = kcalloc(1 << size, sizeof(struct sk_buff *), new_skb_list = kcalloc(entries, sizeof(struct sk_buff *),
GFP_ATOMIC); GFP_ATOMIC);
if (!new_skb_list) if (!new_skb_list)
goto free_new_lists; goto free_new_lists;
/* first copy the current receive buffers */ /* first copy the current receive buffers */
overlap = min(size, lp->rx_ring_size); overlap = min(entries, lp->rx_ring_size);
for (new = 0; new < overlap; new++) { for (new = 0; new < overlap; new++) {
new_rx_ring[new] = lp->rx_ring[new]; new_rx_ring[new] = lp->rx_ring[new];
new_dma_addr_list[new] = lp->rx_dma_addr[new]; new_dma_addr_list[new] = lp->rx_dma_addr[new];
new_skb_list[new] = lp->rx_skbuff[new]; new_skb_list[new] = lp->rx_skbuff[new];
} }
/* now allocate any new buffers needed */ /* now allocate any new buffers needed */
for (; new < size; new++) { for (; new < entries; new++) {
struct sk_buff *rx_skbuff; struct sk_buff *rx_skbuff;
new_skb_list[new] = netdev_alloc_skb(dev, PKT_BUF_SKB); new_skb_list[new] = netdev_alloc_skb(dev, PKT_BUF_SKB);
rx_skbuff = new_skb_list[new]; rx_skbuff = new_skb_list[new];
...@@ -612,7 +613,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, ...@@ -612,7 +613,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
lp->rx_ring_size, lp->rx_ring, lp->rx_ring_size, lp->rx_ring,
lp->rx_ring_dma_addr); lp->rx_ring_dma_addr);
lp->rx_ring_size = (1 << size); lp->rx_ring_size = entries;
lp->rx_mod_mask = lp->rx_ring_size - 1; lp->rx_mod_mask = lp->rx_ring_size - 1;
lp->rx_len_bits = (size << 4); lp->rx_len_bits = (size << 4);
lp->rx_ring = new_rx_ring; lp->rx_ring = new_rx_ring;
...@@ -634,8 +635,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, ...@@ -634,8 +635,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
kfree(new_dma_addr_list); kfree(new_dma_addr_list);
free_new_rx_ring: free_new_rx_ring:
pci_free_consistent(lp->pci_dev, pci_free_consistent(lp->pci_dev,
sizeof(struct pcnet32_rx_head) * sizeof(struct pcnet32_rx_head) * entries,
(1 << size),
new_rx_ring, new_rx_ring,
new_ring_dma_addr); new_ring_dma_addr);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment