Skip to content

Commit

Permalink
net: macb: Fix race between HW and driver
Browse files Browse the repository at this point in the history
Under "heavy" RX load, the driver cannot handle the descriptors fast
enough. In detail, when a descriptor is consumed, its used flag is
cleared and once the RX budget is consumed all descriptors with a
cleared used flag are prepared to receive more data. Under load though,
the HW may constantly receive more data and use those descriptors with a
cleared used flag before they are actually prepared for next usage.

The head and tail pointers into the RX-ring should always be valid and
we can omit clearing and checking of the used flag.

Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Soren Brinkmann authored and David S. Miller committed May 5, 2014
1 parent 504ad98 commit c8ea5a2
Showing 1 changed file with 0 additions and 10 deletions.
10 changes: 0 additions & 10 deletions drivers/net/ethernet/cadence/macb.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,25 +599,16 @@ static void gem_rx_refill(struct macb *bp)
{
unsigned int entry;
struct sk_buff *skb;
struct macb_dma_desc *desc;
dma_addr_t paddr;

while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) {
u32 addr, ctrl;

entry = macb_rx_ring_wrap(bp->rx_prepared_head);
desc = &bp->rx_ring[entry];

/* Make hw descriptor updates visible to CPU */
rmb();

addr = desc->addr;
ctrl = desc->ctrl;
bp->rx_prepared_head++;

if ((addr & MACB_BIT(RX_USED)))
continue;

if (bp->rx_skbuff[entry] == NULL) {
/* allocate sk_buff for this free entry in ring */
skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size);
Expand Down Expand Up @@ -698,7 +689,6 @@ static int gem_rx(struct macb *bp, int budget)
if (!(addr & MACB_BIT(RX_USED)))
break;

desc->addr &= ~MACB_BIT(RX_USED);
bp->rx_tail++;
count++;

Expand Down

0 comments on commit c8ea5a2

Please sign in to comment.