Răsfoiți Sursa

[BNX2]: remove atomics in tx

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>
Michael Chan 20 ani în urmă
părinte
comite
e89bbf1049
2 a modificat fișierele cu 18 adăugiri și 20 ștergeri
  1. 17 18
      drivers/net/bnx2.c
  2. 1 2
      drivers/net/bnx2.h

+ 17 - 18
drivers/net/bnx2.c

@@ -107,6 +107,15 @@ static struct flash_spec flash_table[] =
 
 
 MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 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
 static u32
 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
 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))) {
 	if (unlikely(netif_queue_stopped(bp->dev))) {
 		unsigned long flags;
 		unsigned long flags;
 
 
 		spin_lock_irqsave(&bp->tx_lock, flags);
 		spin_lock_irqsave(&bp->tx_lock, flags);
 		if ((netif_queue_stopped(bp->dev)) &&
 		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);
 			netif_wake_queue(bp->dev);
 		}
 		}
 		spin_unlock_irqrestore(&bp->tx_lock, flags);
 		spin_unlock_irqrestore(&bp->tx_lock, flags);
 	}
 	}
-
-	bp->tx_cons = sw_cons;
-
 }
 }
 
 
 static inline void
 static inline void
@@ -2971,7 +2977,6 @@ bnx2_init_tx_ring(struct bnx2 *bp)
 	bp->tx_prod = 0;
 	bp->tx_prod = 0;
 	bp->tx_cons = 0;
 	bp->tx_cons = 0;
 	bp->tx_prod_bseq = 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_TYPE_L2;
 	val |= BNX2_L2CTX_TYPE_SIZE_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;
 	u16 prod, ring_prod;
 	int i;
 	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);
 		netif_stop_queue(dev);
 		printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
 		printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
 			dev->name);
 			dev->name);
@@ -4156,8 +4159,6 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	prod = NEXT_TX_BD(prod);
 	prod = NEXT_TX_BD(prod);
 	bp->tx_prod_bseq += skb->len;
 	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_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);
 	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;
 	bp->tx_prod = prod;
 	dev->trans_start = jiffies;
 	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;
 		unsigned long flags;
 
 
 		spin_lock_irqsave(&bp->tx_lock, 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);
 		spin_unlock_irqrestore(&bp->tx_lock, flags);
 	}
 	}
 
 

+ 1 - 2
drivers/net/bnx2.h

@@ -3841,12 +3841,12 @@ struct bnx2 {
 	struct status_block	*status_blk;
 	struct status_block	*status_blk;
 	u32 			last_status_idx;
 	u32 			last_status_idx;
 
 
-	atomic_t		tx_avail_bd;
 	struct tx_bd		*tx_desc_ring;
 	struct tx_bd		*tx_desc_ring;
 	struct sw_bd		*tx_buf_ring;
 	struct sw_bd		*tx_buf_ring;
 	u32			tx_prod_bseq;
 	u32			tx_prod_bseq;
 	u16			tx_prod;
 	u16			tx_prod;
 	u16			tx_cons;
 	u16			tx_cons;
+	int			tx_ring_size;
 
 
 #ifdef BCM_VLAN 
 #ifdef BCM_VLAN 
 	struct			vlan_group *vlgrp;
 	struct			vlan_group *vlgrp;
@@ -3929,7 +3929,6 @@ struct bnx2 {
 	u16			fw_wr_seq;
 	u16			fw_wr_seq;
 	u16			fw_drv_pulse_wr_seq;
 	u16			fw_drv_pulse_wr_seq;
 
 
-	int			tx_ring_size;
 	dma_addr_t		tx_desc_mapping;
 	dma_addr_t		tx_desc_mapping;