summaryrefslogtreecommitdiff
path: root/drivers/net/macb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-12-23 13:05:46 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-12-23 13:05:46 -0800
commit2634d064c16cc897bc850a109bbea781b50d1ad5 (patch)
tree89021349a41791a53eacb96839440a84b9388f4a /drivers/net/macb.c
parentc63f702068a445f682d7590c5fadfc266785a071 (diff)
parentbdcba1511b98f2e728b3a910b8771a0d3fce5bf3 (diff)
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: MACB: clear transmit buffers properly on transmit underrun 3c359 endianness annotations and fixes fec_mpc52xx: write in C... 3c574 and 3c589 endianness fixes (.24?) rrunner: use offsetof() instead of homegrown insanity r8169 endianness dl2k endianness fixes (.24 fodder?) yellowfin: annotations and fixes (.24 fodder?) asix fixes cycx: annotations and fixes (.24 fodder?) typhoon: trivial endianness annotations typhoon: memory corruptor on big-endian if TSO is enabled typhoon: missed rx overruns on big-endian typhoon: set_settings broken on big-endian typhoon: missing le32_to_cpu() in get_drvinfo typhoon: endianness bug in tx/rx byte counters ipw2200: prevent alloc of unspecified size on stack iwlwifi: fix possible priv->mutex deadlock during suspend p54: add Kconfig description rtl8187: Add USB ID for Sitecom WL-168 v1 001
Diffstat (limited to 'drivers/net/macb.c')
-rw-r--r--drivers/net/macb.c25
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;
}