]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.16.3/bluetooth-btmrvl-wait-for-host_sleep_enable-event-in-suspend.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.16.3 / bluetooth-btmrvl-wait-for-host_sleep_enable-event-in-suspend.patch
1 From 396e04f4bb9afefb0744715dc76d9abe18ee5fb0 Mon Sep 17 00:00:00 2001
2 From: Chin-Ran Lo <crlo@marvell.com>
3 Date: Tue, 1 Jul 2014 14:00:14 -0700
4 Subject: Bluetooth: btmrvl: wait for HOST_SLEEP_ENABLE event in suspend
5
6 From: Chin-Ran Lo <crlo@marvell.com>
7
8 commit 396e04f4bb9afefb0744715dc76d9abe18ee5fb0 upstream.
9
10 After BT_CMD_HOST_SLEEP_ENABLE command finishes, driver should
11 wait until getting BT_EVENT_HOST_SLEEP_ENABLE event to complete
12 suspend procedure.
13 Without this patch the suspend handler would return success
14 earlier. By the time when the BT_EVENT_HOST_SLEEP_ENABLE event
15 comes in the controller driver could have already turned off the
16 bus clock. This causes kernel crash or system reboot eventually.
17
18 Signed-off-by: Chin-Ran Lo <crlo@marvell.com>
19 Signed-off-by: Jeff CF Chen <jeffc@marvell.com>
20 Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
21 Signed-off-by: Bing Zhao <bzhao@marvell.com>
22 Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
23 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24
25 ---
26 drivers/bluetooth/btmrvl_drv.h | 1 +
27 drivers/bluetooth/btmrvl_main.c | 25 ++++++++++++++++++++++++-
28 2 files changed, 25 insertions(+), 1 deletion(-)
29
30 --- a/drivers/bluetooth/btmrvl_drv.h
31 +++ b/drivers/bluetooth/btmrvl_drv.h
32 @@ -68,6 +68,7 @@ struct btmrvl_adapter {
33 u8 hs_state;
34 u8 wakeup_tries;
35 wait_queue_head_t cmd_wait_q;
36 + wait_queue_head_t event_hs_wait_q;
37 u8 cmd_complete;
38 bool is_suspended;
39 };
40 --- a/drivers/bluetooth/btmrvl_main.c
41 +++ b/drivers/bluetooth/btmrvl_main.c
42 @@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_p
43 adapter->hs_state = HS_ACTIVATED;
44 if (adapter->psmode)
45 adapter->ps_state = PS_SLEEP;
46 + wake_up_interruptible(&adapter->event_hs_wait_q);
47 BT_DBG("HS ACTIVATED!");
48 } else {
49 BT_DBG("HS Enable failed");
50 @@ -253,11 +254,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
51
52 int btmrvl_enable_hs(struct btmrvl_private *priv)
53 {
54 + struct btmrvl_adapter *adapter = priv->adapter;
55 int ret;
56
57 ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
58 - if (ret)
59 + if (ret) {
60 BT_ERR("Host sleep enable command failed\n");
61 + return ret;
62 + }
63 +
64 + ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q,
65 + adapter->hs_state,
66 + msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED));
67 + if (ret < 0) {
68 + BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d",
69 + ret, adapter->hs_state, adapter->ps_state,
70 + adapter->wakeup_tries);
71 + } else if (!ret) {
72 + BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state,
73 + adapter->ps_state, adapter->wakeup_tries);
74 + ret = -ETIMEDOUT;
75 + } else {
76 + BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state,
77 + adapter->ps_state, adapter->wakeup_tries);
78 + ret = 0;
79 + }
80
81 return ret;
82 }
83 @@ -358,6 +379,7 @@ static void btmrvl_init_adapter(struct b
84 }
85
86 init_waitqueue_head(&priv->adapter->cmd_wait_q);
87 + init_waitqueue_head(&priv->adapter->event_hs_wait_q);
88 }
89
90 static void btmrvl_free_adapter(struct btmrvl_private *priv)
91 @@ -666,6 +688,7 @@ int btmrvl_remove_card(struct btmrvl_pri
92 hdev = priv->btmrvl_dev.hcidev;
93
94 wake_up_interruptible(&priv->adapter->cmd_wait_q);
95 + wake_up_interruptible(&priv->adapter->event_hs_wait_q);
96
97 kthread_stop(priv->main_thread.task);
98