net: bluetooth: Hold wakelock until BT idle timer kicks in.

Source: 7e394e2551
This commit is contained in:
tytung 2012-06-29 02:04:58 +08:00
parent 664e118857
commit d4595be826
3 changed files with 39 additions and 4 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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);