summaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_init.c
diff options
context:
space:
mode:
authorDhananjay Phadke2009-06-17 19:27:25 +0200
committerDavid S. Miller2009-06-18 09:46:14 +0200
commitcb2107be43d2fc5eadec58b92b54bf32c00bfff3 (patch)
treedd04fda143a4a7d71b32b79b508a0566450c22c6 /drivers/net/netxen/netxen_nic_init.c
parentnetxen: fix detection of cut-thru firmware mode (diff)
downloadkernel-qcow2-linux-cb2107be43d2fc5eadec58b92b54bf32c00bfff3.tar.gz
kernel-qcow2-linux-cb2107be43d2fc5eadec58b92b54bf32c00bfff3.tar.xz
kernel-qcow2-linux-cb2107be43d2fc5eadec58b92b54bf32c00bfff3.zip
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_init.c')
-rw-r--r--drivers/net/netxen/netxen_nic_init.c11
1 files changed, 5 insertions, 6 deletions
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)
return 1;
sw_consumer = tx_ring->sw_consumer;
- barrier(); /* hw_consumer can change underneath */
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
while (sw_consumer != hw_consumer) {
@@ -1319,14 +1318,15 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
break;
}
- tx_ring->sw_consumer = sw_consumer;
-
if (count && netif_running(netdev)) {
+ tx_ring->sw_consumer = sw_consumer;
+
smp_mb();
+
if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
netif_tx_lock(netdev);
- netif_wake_queue(netdev);
- smp_mb();
+ if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
+ netif_wake_queue(netdev);
netif_tx_unlock(netdev);
}
}
@@ -1343,7 +1343,6 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
* There is still a possible race condition and the host could miss an
* interrupt. The card has to take care of this.
*/
- barrier(); /* hw_consumer can change underneath */
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
done = (sw_consumer == hw_consumer);
spin_unlock(&adapter->tx_clean_lock);