Skip to content

Commit

Permalink
macb: avoid lockup when TGO during underrun
Browse files Browse the repository at this point in the history
In rare cases when an underrun occur, all macb buffers where consumed
and the netif_queue was stopped infinitely. This happens then the TGO
(transfer ongoing) bit in the TSR is set (and UND). It seems like
clening up after the underrun makes the driver and the macb hardware
end up in an inconsistent state. The result of this is that in the
following calls to macb_tx no TX buffers are released -> the
netif_queue was stopped, and never woken up again.

The solution is to disable the transmitter, if TGO is set, before
clening up after the underrun, and re-enable the transmitter when the
cleaning up is done.

Signed-off-by: Richard Röjfors <richard.rojfors@endian.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Richard Röjfors authored and David S. Miller committed Jan 20, 2009
1 parent 24e94de commit 39eddb4
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/net/macb.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ static void macb_tx(struct macb *bp)
printk(KERN_ERR "%s: TX underrun, resetting buffers\n",
bp->dev->name);

/* Transfer ongoing, disable transmitter, to avoid confusion */
if (status & MACB_BIT(TGO))
macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE));

head = bp->tx_head;

/*Mark all the buffer as used to avoid sending a lost buffer*/
Expand All @@ -343,6 +347,10 @@ static void macb_tx(struct macb *bp)
}

bp->tx_head = bp->tx_tail = 0;

/* Enable the transmitter again */
if (status & MACB_BIT(TGO))
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
}

if (!(status & MACB_BIT(COMP)))
Expand Down

0 comments on commit 39eddb4

Please sign in to comment.