aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bsd_comp.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-08-15 04:39:10 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-08-17 19:29:51 -0400
commit2f8af120a159a843948749ea88bcacda9779b132 (patch)
treee633037a72db856b8078e814e3451dd8f44c14de /drivers/net/bsd_comp.c
parentfb33f82568d32016b3b3c00819574f9526e52be3 (diff)
[BNX2]: Fix tx race condition.
Fix a subtle race condition between bnx2_start_xmit() and bnx2_tx_int() similar to the one in tg3 discovered by Herbert Xu: CPU0 CPU1 bnx2_start_xmit() if (tx_ring_full) { tx_lock bnx2_tx() if (!netif_queue_stopped) netif_stop_queue() if (!tx_ring_full) update_tx_ring netif_wake_queue() tx_unlock } Even though tx_ring is updated before the if statement in bnx2_tx_int() in program order, it can be re-ordered by the CPU as shown above. This scenario can cause the tx queue to be stopped forever if bnx2_tx_int() has just freed up the entire tx_ring. The possibility of this happening should be very rare though. The following changes are made, very much identical to the tg3 fix: 1. Add memory barrier to fix the above race condition. 2. Eliminate the private tx_lock altogether and rely solely on netif_tx_lock. This eliminates one spinlock in bnx2_start_xmit() when the ring is full. 3. Because of 2, use netif_tx_lock in bnx2_tx_int() before calling netif_wake_queue(). 4. Add memory barrier to bnx2_tx_avail(). 5. Add bp->tx_wake_thresh which is set to half the tx ring size. 6. Check for the full wake queue condition before getting netif_tx_lock in tg3_tx(). This reduces the number of unnecessary spinlocks when the tx ring is full in a steady-state condition. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bsd_comp.c')
0 files changed, 0 insertions, 0 deletions