diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-06-17 13:27:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-18 03:46:14 -0400 |
commit | cb2107be43d2fc5eadec58b92b54bf32c00bfff3 (patch) | |
tree | dd04fda143a4a7d71b32b79b508a0566450c22c6 /drivers/net/netxen/netxen_nic_main.c | |
parent | d173346040af497af22818dfc48cff369e67cf50 (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/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 32 |
1 files changed, 19 insertions, 13 deletions
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 | ||
108 | void | 108 | void |
109 | netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, | 109 | netxen_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 | ||
115 | static uint32_t crb_cmd_consumer[4] = { | 120 | static uint32_t crb_cmd_consumer[4] = { |
@@ -119,9 +124,9 @@ static uint32_t crb_cmd_consumer[4] = { | |||
119 | 124 | ||
120 | static inline void | 125 | static inline void |
121 | netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, | 126 | netxen_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 | ||
127 | static uint32_t msi_tgt_status[8] = { | 132 | static 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 | ||