cfg80211: fix refcount imbalance when wext is disabled
[safe/jmp/linux-2.6] / net / bluetooth / hci_event.c
index 963f966..28517ba 100644 (file)
@@ -866,8 +866,16 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
-       if (!conn)
-               goto unlock;
+       if (!conn) {
+               if (ev->link_type != SCO_LINK)
+                       goto unlock;
+
+               conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
+               if (!conn)
+                       goto unlock;
+
+               conn->type = SCO_LINK;
+       }
 
        if (!ev->status) {
                conn->handle = __le16_to_cpu(ev->handle);
@@ -875,9 +883,11 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
                if (conn->type == ACL_LINK) {
                        conn->state = BT_CONFIG;
                        hci_conn_hold(conn);
+                       conn->disc_timeout = HCI_DISCONN_TIMEOUT;
                } else
                        conn->state = BT_CONNECTED;
 
+               hci_conn_hold_device(conn);
                hci_conn_add_sysfs(conn);
 
                if (test_bit(HCI_AUTH, &hdev->flags))
@@ -1055,9 +1065,14 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
                                hci_proto_connect_cfm(conn, ev->status);
                                hci_conn_put(conn);
                        }
-               } else
+               } else {
                        hci_auth_cfm(conn, ev->status);
 
+                       hci_conn_hold(conn);
+                       conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+                       hci_conn_put(conn);
+               }
+
                if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
                        if (!ev->status) {
                                struct hci_cp_set_conn_encrypt cp;
@@ -1305,7 +1320,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
        if (ev->ncmd) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))
-                       hci_sched_cmd(hdev);
+                       tasklet_schedule(&hdev->cmd_task);
        }
 }
 
@@ -1371,7 +1386,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (ev->ncmd) {
                atomic_set(&hdev->cmd_cnt, 1);
                if (!skb_queue_empty(&hdev->cmd_q))
-                       hci_sched_cmd(hdev);
+                       tasklet_schedule(&hdev->cmd_task);
        }
 }
 
@@ -1439,7 +1454,7 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
                }
        }
 
-       hci_sched_tx(hdev);
+       tasklet_schedule(&hdev->tx_task);
 
        tasklet_enable(&hdev->tx_task);
 }
@@ -1471,7 +1486,21 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
 
 static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
+       struct hci_ev_pin_code_req *ev = (void *) skb->data;
+       struct hci_conn *conn;
+
        BT_DBG("%s", hdev->name);
+
+       hci_dev_lock(hdev);
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+       if (conn && conn->state == BT_CONNECTED) {
+               hci_conn_hold(conn);
+               conn->disc_timeout = HCI_PAIRING_TIMEOUT;
+               hci_conn_put(conn);
+       }
+
+       hci_dev_unlock(hdev);
 }
 
 static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1481,7 +1510,21 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
 
 static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
+       struct hci_ev_link_key_notify *ev = (void *) skb->data;
+       struct hci_conn *conn;
+
        BT_DBG("%s", hdev->name);
+
+       hci_dev_lock(hdev);
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+       if (conn) {
+               hci_conn_hold(conn);
+               conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+               hci_conn_put(conn);
+       }
+
+       hci_dev_unlock(hdev);
 }
 
 static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1651,6 +1694,7 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu
                conn->handle = __le16_to_cpu(ev->handle);
                conn->state  = BT_CONNECTED;
 
+               hci_conn_hold_device(conn);
                hci_conn_add_sysfs(conn);
                break;