Bluetooth: Hold wakelock until BT idle timer kicks in.
Holding a wakelock avoids suspend power collapse, which
allow the BT idle timer to kick in, which eventually
initiates BT low power modes.
CRs-Fixed: 361067
Change-Id: I93e3950b6f854e70dbce092a5529120ec008c2b8
Signed-off-by: Rahul Kashyap <rkashyap@codeaurora.org>
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5749293..47b856c 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -26,7 +26,7 @@
#define __HCI_CORE_H
#include <net/bluetooth/hci.h>
-
+#include <linux/wakelock.h>
/* HCI upper protocols */
#define HCI_PROTO_L2CAP 0
#define HCI_PROTO_SCO 1
@@ -326,7 +326,7 @@
struct work_struct work_add;
struct work_struct work_del;
-
+ struct wake_lock idle_lock;
struct device dev;
atomic_t devref;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 25b559b1..02ea082 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -448,6 +448,7 @@
conn->power_save = 1;
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+ wake_lock_init(&conn->idle_lock, WAKE_LOCK_SUSPEND, "bt_idle");
switch (type) {
case ACL_LINK:
@@ -521,6 +522,7 @@
/* Make sure no timers are running */
del_timer(&conn->idle_timer);
+ wake_lock_destroy(&conn->idle_lock);
del_timer(&conn->disc_timer);
del_timer(&conn->smp_timer);
__cancel_delayed_work(&conn->rssi_update_work);
@@ -962,9 +964,11 @@
}
timer:
- if (hdev->idle_timeout > 0)
+ if (hdev->idle_timeout > 0) {
mod_timer(&conn->idle_timer,
jiffies + msecs_to_jiffies(hdev->idle_timeout));
+ wake_lock(&conn->idle_lock);
+ }
}
static inline void hci_conn_stop_rssi_timer(struct hci_conn *conn)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 395a95c..9e545f3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2556,6 +2556,9 @@
else
conn->power_save = 0;
}
+ if (conn->mode == HCI_CM_SNIFF)
+ if (wake_lock_active(&conn->idle_lock))
+ wake_unlock(&conn->idle_lock);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, ev->status);