diff options
author | Olof Johansson <olof@lixom.net> | 2007-08-22 10:13:11 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:50:58 -0400 |
commit | 021fa22e01d3d0425d3d15df48f523b69a3a11c4 (patch) | |
tree | 6526993ff713b963d5c95acc9775f49dd135ff41 /drivers/net | |
parent | 02df6cfa09c2ccebe685bfd54a708e1f50b00a81 (diff) |
pasemi_mac: Fix TX ring wrap checking
The old logic didn't detect full (tx) ring cases properly, causing
overruns and general badness. Clean it up a bit and abstract out the
ring size checks, always making sure to leave 1 slot open.
Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/pasemi_mac.c | 25 | ||||
-rw-r--r-- | drivers/net/pasemi_mac.h | 2 |
2 files changed, 15 insertions, 12 deletions
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 4836d405cd5d..dc710a0826b2 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c | |||
@@ -69,6 +69,10 @@ | |||
69 | #define RX_DESC_INFO(mac, num) ((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)]) | 69 | #define RX_DESC_INFO(mac, num) ((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)]) |
70 | #define RX_BUFF(mac, num) ((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)]) | 70 | #define RX_BUFF(mac, num) ((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)]) |
71 | 71 | ||
72 | #define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \ | ||
73 | & ((ring)->size - 1)) | ||
74 | #define RING_AVAIL(ring) ((ring->size) - RING_USED(ring)) | ||
75 | |||
72 | #define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ | 76 | #define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ |
73 | 77 | ||
74 | MODULE_LICENSE("GPL"); | 78 | MODULE_LICENSE("GPL"); |
@@ -174,6 +178,7 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev) | |||
174 | 178 | ||
175 | spin_lock_init(&ring->lock); | 179 | spin_lock_init(&ring->lock); |
176 | 180 | ||
181 | ring->size = RX_RING_SIZE; | ||
177 | ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) * | 182 | ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) * |
178 | RX_RING_SIZE, GFP_KERNEL); | 183 | RX_RING_SIZE, GFP_KERNEL); |
179 | 184 | ||
@@ -253,6 +258,7 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev) | |||
253 | 258 | ||
254 | spin_lock_init(&ring->lock); | 259 | spin_lock_init(&ring->lock); |
255 | 260 | ||
261 | ring->size = TX_RING_SIZE; | ||
256 | ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) * | 262 | ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) * |
257 | TX_RING_SIZE, GFP_KERNEL); | 263 | TX_RING_SIZE, GFP_KERNEL); |
258 | if (!ring->desc_info) | 264 | if (!ring->desc_info) |
@@ -281,7 +287,7 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev) | |||
281 | PAS_DMA_TXCHAN_CFG_UP | | 287 | PAS_DMA_TXCHAN_CFG_UP | |
282 | PAS_DMA_TXCHAN_CFG_WT(2)); | 288 | PAS_DMA_TXCHAN_CFG_WT(2)); |
283 | 289 | ||
284 | ring->next_to_use = 0; | 290 | ring->next_to_fill = 0; |
285 | ring->next_to_clean = 0; | 291 | ring->next_to_clean = 0; |
286 | 292 | ||
287 | snprintf(ring->irq_name, sizeof(ring->irq_name), | 293 | snprintf(ring->irq_name, sizeof(ring->irq_name), |
@@ -376,9 +382,7 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev) | |||
376 | int start = mac->rx->next_to_fill; | 382 | int start = mac->rx->next_to_fill; |
377 | unsigned int limit, count; | 383 | unsigned int limit, count; |
378 | 384 | ||
379 | limit = (mac->rx->next_to_clean + RX_RING_SIZE - | 385 | limit = RING_AVAIL(mac->rx); |
380 | mac->rx->next_to_fill) & (RX_RING_SIZE - 1); | ||
381 | |||
382 | /* Check to see if we're doing first-time setup */ | 386 | /* Check to see if we're doing first-time setup */ |
383 | if (unlikely(mac->rx->next_to_clean == 0 && mac->rx->next_to_fill == 0)) | 387 | if (unlikely(mac->rx->next_to_clean == 0 && mac->rx->next_to_fill == 0)) |
384 | limit = RX_RING_SIZE; | 388 | limit = RX_RING_SIZE; |
@@ -562,7 +566,7 @@ restart: | |||
562 | spin_lock_irqsave(&mac->tx->lock, flags); | 566 | spin_lock_irqsave(&mac->tx->lock, flags); |
563 | 567 | ||
564 | start = mac->tx->next_to_clean; | 568 | start = mac->tx->next_to_clean; |
565 | limit = min(mac->tx->next_to_use, start+32); | 569 | limit = min(mac->tx->next_to_fill, start+32); |
566 | 570 | ||
567 | count = 0; | 571 | count = 0; |
568 | 572 | ||
@@ -1004,14 +1008,13 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) | |||
1004 | 1008 | ||
1005 | spin_lock_irqsave(&txring->lock, flags); | 1009 | spin_lock_irqsave(&txring->lock, flags); |
1006 | 1010 | ||
1007 | if (txring->next_to_clean - txring->next_to_use == TX_RING_SIZE) { | 1011 | if (RING_AVAIL(txring) <= 1) { |
1008 | spin_unlock_irqrestore(&txring->lock, flags); | 1012 | spin_unlock_irqrestore(&txring->lock, flags); |
1009 | pasemi_mac_clean_tx(mac); | 1013 | pasemi_mac_clean_tx(mac); |
1010 | pasemi_mac_restart_tx_intr(mac); | 1014 | pasemi_mac_restart_tx_intr(mac); |
1011 | spin_lock_irqsave(&txring->lock, flags); | 1015 | spin_lock_irqsave(&txring->lock, flags); |
1012 | 1016 | ||
1013 | if (txring->next_to_clean - txring->next_to_use == | 1017 | if (RING_AVAIL(txring) <= 1) { |
1014 | TX_RING_SIZE) { | ||
1015 | /* Still no room -- stop the queue and wait for tx | 1018 | /* Still no room -- stop the queue and wait for tx |
1016 | * intr when there's room. | 1019 | * intr when there's room. |
1017 | */ | 1020 | */ |
@@ -1020,15 +1023,15 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) | |||
1020 | } | 1023 | } |
1021 | } | 1024 | } |
1022 | 1025 | ||
1023 | dp = &TX_DESC(mac, txring->next_to_use); | 1026 | dp = &TX_DESC(mac, txring->next_to_fill); |
1024 | info = &TX_DESC_INFO(mac, txring->next_to_use); | 1027 | info = &TX_DESC_INFO(mac, txring->next_to_fill); |
1025 | 1028 | ||
1026 | dp->mactx = mactx; | 1029 | dp->mactx = mactx; |
1027 | dp->ptr = ptr; | 1030 | dp->ptr = ptr; |
1028 | info->dma = map; | 1031 | info->dma = map; |
1029 | info->skb = skb; | 1032 | info->skb = skb; |
1030 | 1033 | ||
1031 | txring->next_to_use++; | 1034 | txring->next_to_fill++; |
1032 | mac->stats.tx_packets++; | 1035 | mac->stats.tx_packets++; |
1033 | mac->stats.tx_bytes += skb->len; | 1036 | mac->stats.tx_bytes += skb->len; |
1034 | 1037 | ||
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h index fbbc17a31db7..c5b0adbc182e 100644 --- a/drivers/net/pasemi_mac.h +++ b/drivers/net/pasemi_mac.h | |||
@@ -31,7 +31,7 @@ struct pasemi_mac_txring { | |||
31 | struct pas_dma_xct_descr *desc; | 31 | struct pas_dma_xct_descr *desc; |
32 | dma_addr_t dma; | 32 | dma_addr_t dma; |
33 | unsigned int size; | 33 | unsigned int size; |
34 | unsigned int next_to_use; | 34 | unsigned int next_to_fill; |
35 | unsigned int next_to_clean; | 35 | unsigned int next_to_clean; |
36 | struct pasemi_mac_buffer *desc_info; | 36 | struct pasemi_mac_buffer *desc_info; |
37 | char irq_name[10]; /* "eth%d tx" */ | 37 | char irq_name[10]; /* "eth%d tx" */ |