aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2007-08-22 10:13:11 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:58 -0400
commit021fa22e01d3d0425d3d15df48f523b69a3a11c4 (patch)
tree6526993ff713b963d5c95acc9775f49dd135ff41
parent02df6cfa09c2ccebe685bfd54a708e1f50b00a81 (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>
-rw-r--r--drivers/net/pasemi_mac.c25
-rw-r--r--drivers/net/pasemi_mac.h2
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
74MODULE_LICENSE("GPL"); 78MODULE_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" */