diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-03-16 17:01:26 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-03-23 01:48:33 -0400 |
commit | e3a1b99fb60dab1b39d5022d1d8f47bebfe6d8c6 (patch) | |
tree | 3cacd444ae5b08ad30dd9cf1facbaf41d315913c /drivers/net/skge.c | |
parent | 12998096cc48563a04ca751965ba17c3f73a5461 (diff) |
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) | |||
2576 | skge_led(skge, LED_MODE_OFF); | 2576 | skge_led(skge, LED_MODE_OFF); |
2577 | 2577 | ||
2578 | netif_poll_disable(dev); | 2578 | netif_poll_disable(dev); |
2579 | |||
2580 | netif_tx_lock_bh(dev); | ||
2579 | skge_tx_clean(dev); | 2581 | skge_tx_clean(dev); |
2582 | netif_tx_unlock_bh(dev); | ||
2583 | |||
2580 | skge_rx_clean(skge); | 2584 | skge_rx_clean(skge); |
2581 | 2585 | ||
2582 | kfree(skge->rx_ring.start); | 2586 | kfree(skge->rx_ring.start); |
@@ -2721,7 +2725,6 @@ static void skge_tx_clean(struct net_device *dev) | |||
2721 | struct skge_port *skge = netdev_priv(dev); | 2725 | struct skge_port *skge = netdev_priv(dev); |
2722 | struct skge_element *e; | 2726 | struct skge_element *e; |
2723 | 2727 | ||
2724 | netif_tx_lock_bh(dev); | ||
2725 | for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { | 2728 | for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { |
2726 | struct skge_tx_desc *td = e->desc; | 2729 | struct skge_tx_desc *td = e->desc; |
2727 | skge_tx_free(skge, e, td->control); | 2730 | skge_tx_free(skge, e, td->control); |
@@ -2730,7 +2733,6 @@ static void skge_tx_clean(struct net_device *dev) | |||
2730 | 2733 | ||
2731 | skge->tx_ring.to_clean = e; | 2734 | skge->tx_ring.to_clean = e; |
2732 | netif_wake_queue(dev); | 2735 | netif_wake_queue(dev); |
2733 | netif_tx_unlock_bh(dev); | ||
2734 | } | 2736 | } |
2735 | 2737 | ||
2736 | static void skge_tx_timeout(struct net_device *dev) | 2738 | static void skge_tx_timeout(struct net_device *dev) |