diff options
Diffstat (limited to 'drivers/net/macb.c')
-rw-r--r-- | drivers/net/macb.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 047ea7be4850..e10528ed9081 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -307,8 +307,31 @@ static void macb_tx(struct macb *bp) (unsigned long)status); if (status & MACB_BIT(UND)) { + int i; printk(KERN_ERR "%s: TX underrun, resetting buffers\n", - bp->dev->name); + bp->dev->name); + + head = bp->tx_head; + + /*Mark all the buffer as used to avoid sending a lost buffer*/ + for (i = 0; i < TX_RING_SIZE; i++) + bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); + + /* free transmit buffer in upper layer*/ + for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { + struct ring_info *rp = &bp->tx_skb[tail]; + struct sk_buff *skb = rp->skb; + + BUG_ON(skb == NULL); + + rmb(); + + dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, + DMA_TO_DEVICE); + rp->skb = NULL; + dev_kfree_skb_irq(skb); + } + bp->tx_head = bp->tx_tail = 0; } |