Skip to content

Commit

Permalink
[BNX2]: Fix bug when rx ring is full
Browse files Browse the repository at this point in the history
Fix the rx code path that does not handle the full rx ring correctly.

When the rx ring is set to the max. size (i.e. 255), the consumer and
producer indices will be the same when completing an rx packet. Fix
the rx code to handle this condition properly.

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 Mar 21, 2006
1 parent 244ac4f commit 236b639
Showing 1 changed file with 25 additions and 16 deletions.
41 changes: 25 additions & 16 deletions drivers/net/bnx2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1656,23 +1656,30 @@ static inline void
bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
u16 cons, u16 prod)
{
struct sw_bd *cons_rx_buf = &bp->rx_buf_ring[cons];
struct sw_bd *prod_rx_buf = &bp->rx_buf_ring[prod];
struct rx_bd *cons_bd = &bp->rx_desc_ring[cons];
struct rx_bd *prod_bd = &bp->rx_desc_ring[prod];
struct sw_bd *cons_rx_buf, *prod_rx_buf;
struct rx_bd *cons_bd, *prod_bd;

cons_rx_buf = &bp->rx_buf_ring[cons];
prod_rx_buf = &bp->rx_buf_ring[prod];

pci_dma_sync_single_for_device(bp->pdev,
pci_unmap_addr(cons_rx_buf, mapping),
bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);

prod_rx_buf->skb = cons_rx_buf->skb;
pci_unmap_addr_set(prod_rx_buf, mapping,
pci_unmap_addr(cons_rx_buf, mapping));
bp->rx_prod_bseq += bp->rx_buf_use_size;

memcpy(prod_bd, cons_bd, 8);
prod_rx_buf->skb = skb;

bp->rx_prod_bseq += bp->rx_buf_use_size;
if (cons == prod)
return;

pci_unmap_addr_set(prod_rx_buf, mapping,
pci_unmap_addr(cons_rx_buf, mapping));

cons_bd = &bp->rx_desc_ring[cons];
prod_bd = &bp->rx_desc_ring[prod];
prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
}

static int
Expand All @@ -1699,14 +1706,19 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
u32 status;
struct sw_bd *rx_buf;
struct sk_buff *skb;
dma_addr_t dma_addr;

sw_ring_cons = RX_RING_IDX(sw_cons);
sw_ring_prod = RX_RING_IDX(sw_prod);

rx_buf = &bp->rx_buf_ring[sw_ring_cons];
skb = rx_buf->skb;
pci_dma_sync_single_for_cpu(bp->pdev,
pci_unmap_addr(rx_buf, mapping),

rx_buf->skb = NULL;

dma_addr = pci_unmap_addr(rx_buf, mapping);

pci_dma_sync_single_for_cpu(bp->pdev, dma_addr,
bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);

rx_hdr = (struct l2_fhdr *) skb->data;
Expand Down Expand Up @@ -1747,8 +1759,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
skb = new_skb;
}
else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) {
pci_unmap_single(bp->pdev,
pci_unmap_addr(rx_buf, mapping),
pci_unmap_single(bp->pdev, dma_addr,
bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);

skb_reserve(skb, bp->rx_offset);
Expand Down Expand Up @@ -1794,8 +1805,6 @@ bnx2_rx_int(struct bnx2 *bp, int budget)
rx_pkt++;

next_rx:
rx_buf->skb = NULL;

sw_cons = NEXT_RX_BD(sw_cons);
sw_prod = NEXT_RX_BD(sw_prod);

Expand Down Expand Up @@ -3360,7 +3369,7 @@ bnx2_init_rx_ring(struct bnx2 *bp)
val = (u64) bp->rx_desc_mapping & 0xffffffff;
CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);

for ( ;ring_prod < bp->rx_ring_size; ) {
for (i = 0; i < bp->rx_ring_size; i++) {
if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
break;
}
Expand Down

0 comments on commit 236b639

Please sign in to comment.