Patchwork [3.5.y.z,extended,stable] Patch "Bluetooth: btmrvl: fix thread stopping race" has been added to staging queue

mail settings
Submitter Luis Henriques
Date July 1, 2013, 10 a.m.
Message ID <>
Download mbox | patch
Permalink /patch/256046/
State New
Headers show


Luis Henriques - July 1, 2013, 10 a.m.
This is a note to let you know that I have just added a patch titled

    Bluetooth: btmrvl: fix thread stopping race

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From 95d7da8707b525251cfc5d23fb7cb548da9245a4 Mon Sep 17 00:00:00 2001
From: Daniel Drake <>
Date: Tue, 11 Jun 2013 15:40:20 -0400
Subject: [PATCH] Bluetooth: btmrvl: fix thread stopping race

commit ea05fea9042620ac3b8ab9a3e5e4d2ed80c89244 upstream.

There is currently a race condition in the btmrvl_remove_card() which
is causing hangs on suspend for OLPC. When the race occurs,
kthread_stop() never returns.

The problem is that btmrvl_service_main_thread() calls kthread_should_stop()
and then does a fair number of things before restarting the loop and

If the thread gets stopped after kthread_should_stop() is checked, but
before the sleep happens, the thread will go to sleep and won't necessarily
be woken up.

Move the kthread_should_stop() check into a race-free place.

Signed-off-by: Daniel Drake <>
Signed-off-by: Gustavo Padovan <>
Signed-off-by: John W. Linville <>
Cc: Jonghwan Choi <>
Signed-off-by: Luis Henriques <>
 drivers/bluetooth/btmrvl_main.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)



diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index dc304de..2c63a21 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -496,6 +496,10 @@  static int btmrvl_service_main_thread(void *data)
 		add_wait_queue(&thread->wait_q, &wait);

+		if (kthread_should_stop()) {
+			BT_DBG("main_thread: break from main thread");
+			break;
+		}

 		if (adapter->wakeup_tries ||
 				((!adapter->int_count) &&
@@ -511,11 +515,6 @@  static int btmrvl_service_main_thread(void *data)

 		BT_DBG("main_thread woke up");

-		if (kthread_should_stop()) {
-			BT_DBG("main_thread: break from main thread");
-			break;
-		}
 		spin_lock_irqsave(&priv->driver_lock, flags);
 		if (adapter->int_count) {
 			adapter->int_count = 0;