diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-03-17 00:01:26 +0300 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-03-23 08:48:33 +0300 |
commit | e3a1b99fb60dab1b39d5022d1d8f47bebfe6d8c6 (patch) | |
tree | 3cacd444ae5b08ad30dd9cf1facbaf41d315913c /drivers/net/skge.c | |
parent | 12998096cc48563a04ca751965ba17c3f73a5461 (diff) | |
download | linux-e3a1b99fb60dab1b39d5022d1d8f47bebfe6d8c6.tar.xz |
skge: deadlock on tx timeout
The skge driver will deadlock if gets a transmit timeout
because the netif_tx_lock() is already held.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 8fecf1b817f7..fad189e01ec6 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2576,7 +2576,11 @@ static int skge_down(struct net_device *dev) skge_led(skge, LED_MODE_OFF); netif_poll_disable(dev); + + netif_tx_lock_bh(dev); skge_tx_clean(dev); + netif_tx_unlock_bh(dev); + skge_rx_clean(skge); kfree(skge->rx_ring.start); @@ -2721,7 +2725,6 @@ static void skge_tx_clean(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_element *e; - netif_tx_lock_bh(dev); for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { struct skge_tx_desc *td = e->desc; skge_tx_free(skge, e, td->control); @@ -2730,7 +2733,6 @@ static void skge_tx_clean(struct net_device *dev) skge->tx_ring.to_clean = e; netif_wake_queue(dev); - netif_tx_unlock_bh(dev); } static void skge_tx_timeout(struct net_device *dev) |