aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2009-06-17 13:27:25 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-18 03:46:14 -0400
commitcb2107be43d2fc5eadec58b92b54bf32c00bfff3 (patch)
treedd04fda143a4a7d71b32b79b508a0566450c22c6 /drivers/net/netxen
parentd173346040af497af22818dfc48cff369e67cf50 (diff)
netxen: fix tx ring accounting
This forces every update of tx ring producer to check for availability of space for next full TSO command. Earlier firmware control commands didn't care to pause tx queue. Stop the tx queue if there's not enough space to transmit one full LSO command left on the tx ring after current transmit. This avoids returning NETDEV_TX_BUSY after checking distance between producer and consumer on every cpu. Restart the tx queue only if we have cleaned up enough tx descriptors. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r--drivers/net/netxen/netxen_nic.h11
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c2
-rw-r--r--drivers/net/netxen/netxen_nic_init.c11
-rw-r--r--drivers/net/netxen/netxen_nic_main.c32
4 files changed, 35 insertions, 21 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index ab11c2b3f0fe..970cedeb5f37 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -169,6 +169,7 @@
169#define MAX_NUM_CARDS 4 169#define MAX_NUM_CARDS 4
170 170
171#define MAX_BUFFERS_PER_CMD 32 171#define MAX_BUFFERS_PER_CMD 32
172#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4)
172 173
173/* 174/*
174 * Following are the states of the Phantom. Phantom will set them and 175 * Following are the states of the Phantom. Phantom will set them and
@@ -1436,7 +1437,7 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p);
1436struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); 1437struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
1437 1438
1438void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, 1439void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
1439 struct nx_host_tx_ring *tx_ring, uint32_t crb_producer); 1440 struct nx_host_tx_ring *tx_ring);
1440 1441
1441/* 1442/*
1442 * NetXen Board information 1443 * NetXen Board information
@@ -1538,6 +1539,14 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
1538} 1539}
1539 1540
1540 1541
1542static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring)
1543{
1544 smp_mb();
1545 return find_diff_among(tx_ring->producer,
1546 tx_ring->sw_consumer, tx_ring->num_desc);
1547
1548}
1549
1541int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); 1550int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
1542int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); 1551int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac);
1543extern void netxen_change_ringparam(struct netxen_adapter *adapter); 1552extern void netxen_change_ringparam(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 9702509ce3c5..ce3b89d2cbb6 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -488,7 +488,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
488 488
489 tx_ring->producer = producer; 489 tx_ring->producer = producer;
490 490
491 netxen_nic_update_cmd_producer(adapter, tx_ring, producer); 491 netxen_nic_update_cmd_producer(adapter, tx_ring);
492 492
493 netif_tx_unlock_bh(adapter->netdev); 493 netif_tx_unlock_bh(adapter->netdev);
494 494
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 6f77ad58e3b3..bdb143d2b5c7 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1292,7 +1292,6 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
1292 return 1; 1292 return 1;
1293 1293
1294 sw_consumer = tx_ring->sw_consumer; 1294 sw_consumer = tx_ring->sw_consumer;
1295 barrier(); /* hw_consumer can change underneath */
1296 hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); 1295 hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
1297 1296
1298 while (sw_consumer != hw_consumer) { 1297 while (sw_consumer != hw_consumer) {
@@ -1319,14 +1318,15 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
1319 break; 1318 break;
1320 } 1319 }
1321 1320
1322 tx_ring->sw_consumer = sw_consumer;
1323
1324 if (count && netif_running(netdev)) { 1321 if (count && netif_running(netdev)) {
1322 tx_ring->sw_consumer = sw_consumer;
1323
1325 smp_mb(); 1324 smp_mb();
1325
1326 if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { 1326 if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
1327 netif_tx_lock(netdev); 1327 netif_tx_lock(netdev);
1328 netif_wake_queue(netdev); 1328 if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
1329 smp_mb(); 1329 netif_wake_queue(netdev);
1330 netif_tx_unlock(netdev); 1330 netif_tx_unlock(netdev);
1331 } 1331 }
1332 } 1332 }
@@ -1343,7 +1343,6 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
1343 * There is still a possible race condition and the host could miss an 1343 * There is still a possible race condition and the host could miss an
1344 * interrupt. The card has to take care of this. 1344 * interrupt. The card has to take care of this.
1345 */ 1345 */
1346 barrier(); /* hw_consumer can change underneath */
1347 hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); 1346 hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
1348 done = (sw_consumer == hw_consumer); 1347 done = (sw_consumer == hw_consumer);
1349 spin_unlock(&adapter->tx_clean_lock); 1348 spin_unlock(&adapter->tx_clean_lock);
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 98737ef72936..71daa3d5f114 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -107,9 +107,14 @@ static uint32_t crb_cmd_producer[4] = {
107 107
108void 108void
109netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, 109netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
110 struct nx_host_tx_ring *tx_ring, u32 producer) 110 struct nx_host_tx_ring *tx_ring)
111{ 111{
112 NXWR32(adapter, tx_ring->crb_cmd_producer, producer); 112 NXWR32(adapter, tx_ring->crb_cmd_producer, tx_ring->producer);
113
114 if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) {
115 netif_stop_queue(adapter->netdev);
116 smp_mb();
117 }
113} 118}
114 119
115static uint32_t crb_cmd_consumer[4] = { 120static uint32_t crb_cmd_consumer[4] = {
@@ -119,9 +124,9 @@ static uint32_t crb_cmd_consumer[4] = {
119 124
120static inline void 125static inline void
121netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, 126netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
122 struct nx_host_tx_ring *tx_ring, u32 consumer) 127 struct nx_host_tx_ring *tx_ring)
123{ 128{
124 NXWR32(adapter, tx_ring->crb_cmd_consumer, consumer); 129 NXWR32(adapter, tx_ring->crb_cmd_consumer, tx_ring->sw_consumer);
125} 130}
126 131
127static uint32_t msi_tgt_status[8] = { 132static uint32_t msi_tgt_status[8] = {
@@ -900,8 +905,11 @@ netxen_nic_attach(struct netxen_adapter *adapter)
900 tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum]; 905 tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
901 tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum]; 906 tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
902 907
903 netxen_nic_update_cmd_producer(adapter, tx_ring, 0); 908 tx_ring->producer = 0;
904 netxen_nic_update_cmd_consumer(adapter, tx_ring, 0); 909 tx_ring->sw_consumer = 0;
910
911 netxen_nic_update_cmd_producer(adapter, tx_ring);
912 netxen_nic_update_cmd_consumer(adapter, tx_ring);
905 } 913 }
906 914
907 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 915 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
@@ -1362,7 +1370,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1362 dma_addr_t temp_dma; 1370 dma_addr_t temp_dma;
1363 int i, k; 1371 int i, k;
1364 1372
1365 u32 producer, consumer; 1373 u32 producer;
1366 int frag_count, no_of_desc; 1374 int frag_count, no_of_desc;
1367 u32 num_txd = tx_ring->num_desc; 1375 u32 num_txd = tx_ring->num_desc;
1368 bool is_tso = false; 1376 bool is_tso = false;
@@ -1372,15 +1380,13 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1372 /* 4 fragments per cmd des */ 1380 /* 4 fragments per cmd des */
1373 no_of_desc = (frag_count + 3) >> 2; 1381 no_of_desc = (frag_count + 3) >> 2;
1374 1382
1375 producer = tx_ring->producer; 1383 if (unlikely(no_of_desc + 2) > netxen_tx_avail(tx_ring)) {
1376 smp_mb();
1377 consumer = tx_ring->sw_consumer;
1378 if ((no_of_desc+2) >= find_diff_among(producer, consumer, num_txd)) {
1379 netif_stop_queue(netdev); 1384 netif_stop_queue(netdev);
1380 smp_mb();
1381 return NETDEV_TX_BUSY; 1385 return NETDEV_TX_BUSY;
1382 } 1386 }
1383 1387
1388 producer = tx_ring->producer;
1389
1384 hwdesc = &tx_ring->desc_head[producer]; 1390 hwdesc = &tx_ring->desc_head[producer];
1385 netxen_clear_cmddesc((u64 *)hwdesc); 1391 netxen_clear_cmddesc((u64 *)hwdesc);
1386 pbuf = &tx_ring->cmd_buf_arr[producer]; 1392 pbuf = &tx_ring->cmd_buf_arr[producer];
@@ -1493,7 +1499,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1493 tx_ring->producer = producer; 1499 tx_ring->producer = producer;
1494 adapter->stats.txbytes += skb->len; 1500 adapter->stats.txbytes += skb->len;
1495 1501
1496 netxen_nic_update_cmd_producer(adapter, tx_ring, producer); 1502 netxen_nic_update_cmd_producer(adapter, tx_ring);
1497 1503
1498 adapter->stats.xmitcalled++; 1504 adapter->stats.xmitcalled++;
1499 1505