Bluetooth: Validate hci conn validity before refering wakelock.

Found in a rare case there is possibility that remote device
sent disconnect on a connection and DUT is trying send data
on the same. In that case accessing some released wakelock
is causing issue. The current changes are to use locking
mechanism to validate the connection before acting on the
wake lock.

CRs-Fixed: 394651
Change-Id: I6a4188a7d0d05a8cfbe66d3680473d549157917a
Signed-off-by: Srinivas Krovvidi <skrovvid@codeaurora.org>
(cherry picked from commit 6aadc41fcbd28dc3899a4b5d098e5f316588a029)

Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
This commit is contained in:
Srinivas Krovvidi 2012-09-03 18:47:50 +05:30 committed by Stephen Boyd
parent 14585a7c95
commit cdd13e5bfd
3 changed files with 14 additions and 7 deletions

View file

@ -354,6 +354,7 @@ struct hci_conn {
__u8 auth;
void *smp_conn;
struct timer_list smp_timer;
__u8 conn_valid;
void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);

View file

@ -393,9 +393,7 @@ static void hci_conn_idle(unsigned long arg)
BT_DBG("conn %p mode %d", conn, conn->mode);
hci_dev_lock(conn->hdev);
hci_conn_enter_sniff_mode(conn);
hci_dev_unlock(conn->hdev);
}
static void hci_conn_rssi_update(struct work_struct *work)
@ -450,6 +448,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
conn->power_save = 1;
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
conn->conn_valid = true;
spin_lock_init(&conn->lock);
wake_lock_init(&conn->idle_lock, WAKE_LOCK_SUSPEND, "bt_idle");
switch (type) {
@ -522,6 +522,10 @@ int hci_conn_del(struct hci_conn *conn)
BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
spin_lock_bh(&conn->lock);
conn->conn_valid = false; /* conn data is being released */
spin_unlock_bh(&conn->lock);
/* Make sure no timers are running */
del_timer(&conn->idle_timer);
wake_lock_destroy(&conn->idle_lock);
@ -981,9 +985,13 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
timer:
if (hdev->idle_timeout > 0) {
mod_timer(&conn->idle_timer,
jiffies + msecs_to_jiffies(hdev->idle_timeout));
wake_lock(&conn->idle_lock);
spin_lock_bh(&conn->lock);
if (conn->conn_valid) {
mod_timer(&conn->idle_timer,
jiffies + msecs_to_jiffies(hdev->idle_timeout));
wake_lock(&conn->idle_lock);
}
spin_unlock_bh(&conn->lock);
}
}

View file

@ -2285,7 +2285,6 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
if (count > hdev->acl_cnt)
return;
hci_dev_lock(hdev);
hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
hci_send_frame(skb);
@ -2295,7 +2294,6 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
quote -= count;
conn->sent += count;
hci_dev_unlock(hdev);
}
}
}