net: bluetooth: Hold wakelock until BT idle timer kicks in.
Source: 7e394e2551
This commit is contained in:
parent
664e118857
commit
d4595be826
@ -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
|
||||
@ -183,10 +183,11 @@ struct hci_conn {
|
||||
|
||||
struct timer_list disc_timer;
|
||||
struct timer_list idle_timer;
|
||||
struct timer_list auto_accept_timer;
|
||||
|
||||
struct work_struct work_add;
|
||||
struct work_struct work_del;
|
||||
|
||||
struct wake_lock idle_lock;
|
||||
struct device dev;
|
||||
atomic_t devref;
|
||||
|
||||
@ -246,6 +247,7 @@ enum {
|
||||
HCI_CONN_ENCRYPT_PEND,
|
||||
HCI_CONN_RSWITCH_PEND,
|
||||
HCI_CONN_MODE_CHANGE_PEND,
|
||||
HCI_CONN_SCO_SETUP_PEND,
|
||||
};
|
||||
|
||||
static inline void hci_conn_hash_init(struct hci_dev *hdev)
|
||||
@ -326,6 +328,7 @@ void hci_acl_connect(struct hci_conn *conn);
|
||||
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
|
||||
void hci_add_sco(struct hci_conn *conn, __u16 handle);
|
||||
void hci_setup_sync(struct hci_conn *conn, __u16 handle);
|
||||
void hci_sco_setup(struct hci_conn *conn, __u8 status);
|
||||
|
||||
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
|
||||
__u16 pkt_type, bdaddr_t *dst);
|
||||
|
@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
|
||||
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
/* Device _must_ be locked */
|
||||
void hci_sco_setup(struct hci_conn *conn, __u8 status)
|
||||
{
|
||||
struct hci_conn *sco = conn->link;
|
||||
|
||||
BT_DBG("%p", conn);
|
||||
|
||||
if (!sco)
|
||||
return;
|
||||
|
||||
if (!status) {
|
||||
if (lmp_esco_capable(conn->hdev))
|
||||
hci_setup_sync(sco, conn->handle);
|
||||
else
|
||||
hci_add_sco(sco, conn->handle);
|
||||
} else {
|
||||
hci_proto_connect_cfm(sco, status);
|
||||
hci_conn_del(sco);
|
||||
}
|
||||
}
|
||||
|
||||
static void hci_conn_timeout(unsigned long arg)
|
||||
{
|
||||
struct hci_conn *conn = (void *) arg;
|
||||
@ -216,6 +237,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
|
||||
|
||||
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:
|
||||
@ -271,9 +293,11 @@ int hci_conn_del(struct hci_conn *conn)
|
||||
|
||||
BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
|
||||
|
||||
/* 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->auto_accept_timer);
|
||||
|
||||
if (conn->type == ACL_LINK) {
|
||||
struct hci_conn *sco = conn->link;
|
||||
@ -521,9 +545,11 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter sniff mode */
|
||||
|
@ -1482,6 +1482,12 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
|
||||
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);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
Loading…
x
Reference in New Issue
Block a user