>From 102a018d601e954f658d272d4daeef139ae40e0e Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Wed, 30 May 2007 08:03:52 -0500 Subject: [PATCH] The netpoll_cleanup handler can hang the kernel if there is no work in the work queue because a call to cancel_rearming_delayed_work() with no work goes into an infinite loop. The typical case where this is a problem is on removing a kernel module such as the netconsole driver or kgdboe. To maintain 80 column code, the function had to have one level of braces dropped. Signed-off-by: Jason Wessel --- net/core/netpoll.c | 36 +++++++++++++++++++----------------- 1 files changed, 19 insertions(+), 17 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 4581ece..28fa50e 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -766,30 +766,32 @@ void netpoll_cleanup(struct netpoll *np) struct netpoll_info *npinfo; unsigned long flags; - if (np->dev) { - npinfo = np->dev->npinfo; - if (npinfo) { - if (npinfo->rx_np == np) { - spin_lock_irqsave(&npinfo->rx_lock, flags); - npinfo->rx_np = NULL; - npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - } + if (!np->dev) + return; + + npinfo = np->dev->npinfo; + if (npinfo) { + if (npinfo->rx_np == np) { + spin_lock_irqsave(&npinfo->rx_lock, flags); + npinfo->rx_np = NULL; + npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; + spin_unlock_irqrestore(&npinfo->rx_lock, flags); + } - np->dev->npinfo = NULL; - if (atomic_dec_and_test(&npinfo->refcnt)) { - skb_queue_purge(&npinfo->arp_tx); - skb_queue_purge(&npinfo->txq); + np->dev->npinfo = NULL; + if (atomic_dec_and_test(&npinfo->refcnt)) { + skb_queue_purge(&npinfo->arp_tx); + skb_queue_purge(&npinfo->txq); + if (delayed_work_pending(&npinfo->tx_work)) { cancel_rearming_delayed_work(&npinfo->tx_work); flush_scheduled_work(); - - kfree(npinfo); } - } - dev_put(np->dev); + kfree(npinfo); + } } + dev_put(np->dev); np->dev = NULL; } -- 1.5.0.6