diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-11-10 14:11:08 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-11 19:03:35 -0800 |
commit | 836cf7faf8c75743477ed6ed341cce491f3183fb (patch) | |
tree | e4a8dff4c36bd53080af4dbe1014b91381b79850 | |
parent | 499428ed28d800eb5cf25889bb1e026637d99dfc (diff) |
gianfar: Fix race between gfar_error() and gfar_start_xmit()
gfar_error() can arrive at the middle of gfar_start_xmit() processing,
and so it can trigger transfers of BDs that we don't yet expect to
be transmitted.
Fix this by locking the tx queues in gfar_error().
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/gianfar.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a5b0038a8d9..fde430a0b84 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2943,14 +2943,22 @@ static irqreturn_t gfar_error(int irq, void *grp_id) if (events & IEVENT_CRL) dev->stats.tx_aborted_errors++; if (events & IEVENT_XFUN) { + unsigned long flags; + if (netif_msg_tx_err(priv)) printk(KERN_DEBUG "%s: TX FIFO underrun, " "packet dropped.\n", dev->name); dev->stats.tx_dropped++; priv->extra_stats.tx_underrun++; + local_irq_save(flags); + lock_tx_qs(priv); + /* Reactivate the Tx Queues */ gfar_write(®s->tstat, gfargrp->tstat); + + unlock_tx_qs(priv); + local_irq_restore(flags); } if (netif_msg_tx_err(priv)) printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); |