Skip to content

Commit

Permalink
[BNX2]: remove atomics in tx
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael Chan authored and David S. Miller committed Aug 29, 2005
1 parent cd339a0 commit e89bbf1
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 20 deletions.
35 changes: 17 additions & 18 deletions drivers/net/bnx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand All @@ -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);
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/net/bnx2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;


Expand Down

0 comments on commit e89bbf1

Please sign in to comment.