Attached is a patch to fix the soft lockup problem when removing the netconsole module.

It looks different than the original patch I posted because the context had to change to maintain 80 column code. For reference the original e-mail + patch was "[BUG] 2.6.21 hang in cancel_rearming_delayed_workqueue()" sent on 5/25/07.

Jason.


>From 102a018d601e954f658d272d4daeef139ae40e0e Mon Sep 17 00:00:00 2001
From: Jason Wessel <[EMAIL PROTECTED]>
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 <[EMAIL PROTECTED]>
---
 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

Reply via email to