diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-11-10 09:11:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-11 22:03:35 -0500 |
commit | 836cf7faf8c75743477ed6ed341cce491f3183fb (patch) | |
tree | e4a8dff4c36bd53080af4dbe1014b91381b79850 /drivers/net/gianfar.c | |
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>
Diffstat (limited to 'drivers/net/gianfar.c')
-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 a5b0038a8d98..fde430a0b84b 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) | |||
2943 | if (events & IEVENT_CRL) | 2943 | if (events & IEVENT_CRL) |
2944 | dev->stats.tx_aborted_errors++; | 2944 | dev->stats.tx_aborted_errors++; |
2945 | if (events & IEVENT_XFUN) { | 2945 | if (events & IEVENT_XFUN) { |
2946 | unsigned long flags; | ||
2947 | |||
2946 | if (netif_msg_tx_err(priv)) | 2948 | if (netif_msg_tx_err(priv)) |
2947 | printk(KERN_DEBUG "%s: TX FIFO underrun, " | 2949 | printk(KERN_DEBUG "%s: TX FIFO underrun, " |
2948 | "packet dropped.\n", dev->name); | 2950 | "packet dropped.\n", dev->name); |
2949 | dev->stats.tx_dropped++; | 2951 | dev->stats.tx_dropped++; |
2950 | priv->extra_stats.tx_underrun++; | 2952 | priv->extra_stats.tx_underrun++; |
2951 | 2953 | ||
2954 | local_irq_save(flags); | ||
2955 | lock_tx_qs(priv); | ||
2956 | |||
2952 | /* Reactivate the Tx Queues */ | 2957 | /* Reactivate the Tx Queues */ |
2953 | gfar_write(®s->tstat, gfargrp->tstat); | 2958 | gfar_write(®s->tstat, gfargrp->tstat); |
2959 | |||
2960 | unlock_tx_qs(priv); | ||
2961 | local_irq_restore(flags); | ||
2954 | } | 2962 | } |
2955 | if (netif_msg_tx_err(priv)) | 2963 | if (netif_msg_tx_err(priv)) |
2956 | printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); | 2964 | printk(KERN_DEBUG "%s: Transmit Error\n", dev->name); |