[BNX2]: remove atomics in tx
authorMichael Chan <mchan@broadcom.com>
Thu, 25 Aug 2005 22:36:58 +0000 (15:36 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 23:10:38 +0000 (16:10 -0700)
Remove atomic operations in the fast tx path. Expensive atomic
operations were used to keep track of the number of available tx
descriptors. The new code uses the difference between the consumer
and producer index to determine the number of free tx descriptors.

As suggested by Jeff Garzik, the name of the inline function is
changed to all lower case.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bnx2.c
drivers/net/bnx2.h

index 015ff7906601661fdbf1dc9cc09cafc1259242fc..da903b3ebfb006784d05fbfb6cb7ff3de31d9700 100644 (file)
@@ -107,6 +107,15 @@ static struct flash_spec flash_table[] =
 
 MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 
+static inline u32 bnx2_tx_avail(struct bnx2 *bp)
+{
+       u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
+
+       if (diff > MAX_TX_DESC_CNT)
+               diff = (diff & MAX_TX_DESC_CNT) - 1;
+       return (bp->tx_ring_size - diff);
+}
+
 static u32
 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
 {
@@ -1338,22 +1347,19 @@ bnx2_tx_int(struct bnx2 *bp)
                }
        }
 
-       atomic_add(tx_free_bd, &bp->tx_avail_bd);
+       bp->tx_cons = sw_cons;
 
        if (unlikely(netif_queue_stopped(bp->dev))) {
                unsigned long flags;
 
                spin_lock_irqsave(&bp->tx_lock, flags);
                if ((netif_queue_stopped(bp->dev)) &&
-                       (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)) {
+                   (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
 
                        netif_wake_queue(bp->dev);
                }
                spin_unlock_irqrestore(&bp->tx_lock, flags);
        }
-
-       bp->tx_cons = sw_cons;
-
 }
 
 static inline void
@@ -2971,7 +2977,6 @@ bnx2_init_tx_ring(struct bnx2 *bp)
        bp->tx_prod = 0;
        bp->tx_cons = 0;
        bp->tx_prod_bseq = 0;
-       atomic_set(&bp->tx_avail_bd, bp->tx_ring_size);
        
        val = BNX2_L2CTX_TYPE_TYPE_L2;
        val |= BNX2_L2CTX_TYPE_SIZE_L2;
@@ -4057,9 +4062,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u16 prod, ring_prod;
        int i;
 
-       if (unlikely(atomic_read(&bp->tx_avail_bd) <
-               (skb_shinfo(skb)->nr_frags + 1))) {
-
+       if (unlikely(bnx2_tx_avail(bp) < (skb_shinfo(skb)->nr_frags + 1))) {
                netif_stop_queue(dev);
                printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
                        dev->name);
@@ -4156,8 +4159,6 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        prod = NEXT_TX_BD(prod);
        bp->tx_prod_bseq += skb->len;
 
-       atomic_sub(last_frag + 1, &bp->tx_avail_bd);
-
        REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
        REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
 
@@ -4166,16 +4167,14 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        bp->tx_prod = prod;
        dev->trans_start = jiffies;
 
-       if (unlikely(atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS)) {
+       if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
                unsigned long flags;
 
                spin_lock_irqsave(&bp->tx_lock, flags);
-               if (atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS) {
-                       netif_stop_queue(dev);
-
-                       if (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)
-                               netif_wake_queue(dev);
-               }
+               netif_stop_queue(dev);
+               
+               if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
+                       netif_wake_queue(dev);
                spin_unlock_irqrestore(&bp->tx_lock, flags);
        }
 
index e1fb099acbf2c83f8746968bfaa024d1aed93ec8..9ad3f5740cd8ee450a3aa96b2996b4d8c8882fca 100644 (file)
@@ -3841,12 +3841,12 @@ struct bnx2 {
        struct status_block     *status_blk;
        u32                     last_status_idx;
 
-       atomic_t                tx_avail_bd;
        struct tx_bd            *tx_desc_ring;
        struct sw_bd            *tx_buf_ring;
        u32                     tx_prod_bseq;
        u16                     tx_prod;
        u16                     tx_cons;
+       int                     tx_ring_size;
 
 #ifdef BCM_VLAN 
        struct                  vlan_group *vlgrp;
@@ -3929,7 +3929,6 @@ struct bnx2 {
        u16                     fw_wr_seq;
        u16                     fw_drv_pulse_wr_seq;
 
-       int                     tx_ring_size;
        dma_addr_t              tx_desc_mapping;