Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6.git] / net / bluetooth / hci_core.c
index 2ac6036..815269b 100644 (file)
@@ -586,9 +586,6 @@ static int hci_dev_do_close(struct hci_dev *hdev)
        hci_req_cancel(hdev, ENODEV);
        hci_req_lock(hdev);
 
-       /* Stop timer, it might be running */
-       del_timer_sync(&hdev->cmd_timer);
-
        if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
                del_timer_sync(&hdev->cmd_timer);
                hci_req_unlock(hdev);
@@ -629,6 +626,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
        /* Drop last sent command */
        if (hdev->sent_cmd) {
+               del_timer_sync(&hdev->cmd_timer);
                kfree_skb(hdev->sent_cmd);
                hdev->sent_cmd = NULL;
        }
@@ -1062,7 +1060,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
                                bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
        struct link_key *key, *old_key;
-       u8 old_key_type;
+       u8 old_key_type, persistent;
 
        old_key = hci_find_link_key(hdev, bdaddr);
        if (old_key) {
@@ -1083,25 +1081,32 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
         * previous key */
        if (type == HCI_LK_CHANGED_COMBINATION &&
                                        (!conn || conn->remote_auth == 0xff) &&
-                                       old_key_type == 0xff)
+                                       old_key_type == 0xff) {
                type = HCI_LK_COMBINATION;
-
-       if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) {
-               list_del(&key->list);
-               kfree(key);
-               return 0;
+               if (conn)
+                       conn->key_type = type;
        }
 
        bacpy(&key->bdaddr, bdaddr);
        memcpy(key->val, val, 16);
-       key->type = type;
        key->pin_len = pin_len;
 
-       if (new_key)
-               mgmt_new_key(hdev->id, key, old_key_type);
-
        if (type == HCI_LK_CHANGED_COMBINATION)
                key->type = old_key_type;
+       else
+               key->type = type;
+
+       if (!new_key)
+               return 0;
+
+       persistent = hci_persistent_key(hdev, conn, type, old_key_type);
+
+       mgmt_new_key(hdev->id, key, persistent);
+
+       if (!persistent) {
+               list_del(&key->list);
+               kfree(key);
+       }
 
        return 0;
 }
@@ -1999,7 +2004,7 @@ static void hci_tx_task(unsigned long arg)
        read_unlock(&hci_task_lock);
 }
 
-/* ----- HCI RX task (incoming data proccessing) ----- */
+/* ----- HCI RX task (incoming data processing) ----- */
 
 /* ACL data packet */
 static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)