libertas: don't exit worker thread until kthread_stop() is called
authorDavid Woodhouse <dwmw2@infradead.org>
Fri, 14 Dec 2007 02:48:00 +0000 (21:48 -0500)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 23:07:26 +0000 (15:07 -0800)
The kthread code can't cope with a thread exiting of its own accord and
then someone calling kthread_stop() for it. When the thread detects that
it needs to die, make it wait for kthread_stop() to be called.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/libertas/main.c

index 5d2bf539d4b92a87a2cdb48321795f37869a1330..b51513fb59ecd80f902a01c4b82ca2eb3e932aa4 100644 (file)
@@ -662,8 +662,10 @@ static int lbs_thread(void *data)
                set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_irq(&priv->driver_lock);
 
-               if (priv->surpriseremoved)
+               if (kthread_should_stop())
                        shouldsleep = 0;        /* Bye */
+               else if (priv->surpriseremoved)
+                       shouldsleep = 1;        /* We need to wait until we're _told_ to die */
                else if (priv->psstate == PS_STATE_SLEEP)
                        shouldsleep = 1;        /* Sleep mode. Nothing we can do till it wakes */
                else if (priv->intcounter)
@@ -699,12 +701,15 @@ static int lbs_thread(void *data)
                lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
                               priv->intcounter, priv->currenttxskb, priv->dnld_sent);
 
-               if (kthread_should_stop() || priv->surpriseremoved) {
-                       lbs_deb_thread("main-thread: break from main thread: surpriseremoved=0x%x\n",
-                                      priv->surpriseremoved);
+               if (kthread_should_stop()) {
+                       lbs_deb_thread("main-thread: break from main thread\n");
                        break;
                }
 
+               if (priv->surpriseremoved) {
+                       lbs_deb_thread("adapter removed; waiting to die...\n");
+                       continue;
+               }
 
                spin_lock_irq(&priv->driver_lock);