Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-2.6-microblaze.git] / net / bluetooth / hci_sync.c
index 9ba2a1a..af7ea8a 100644 (file)
@@ -276,40 +276,37 @@ EXPORT_SYMBOL(__hci_cmd_sync_status);
 static void hci_cmd_sync_work(struct work_struct *work)
 {
        struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_sync_work);
-       struct hci_cmd_sync_work_entry *entry;
-       hci_cmd_sync_work_func_t func;
-       hci_cmd_sync_work_destroy_t destroy;
-       void *data;
 
        bt_dev_dbg(hdev, "");
 
-       mutex_lock(&hdev->cmd_sync_work_lock);
-       entry = list_first_entry(&hdev->cmd_sync_work_list,
-                                struct hci_cmd_sync_work_entry, list);
-       if (entry) {
-               list_del(&entry->list);
-               func = entry->func;
-               data = entry->data;
-               destroy = entry->destroy;
-               kfree(entry);
-       } else {
-               func = NULL;
-               data = NULL;
-               destroy = NULL;
-       }
-       mutex_unlock(&hdev->cmd_sync_work_lock);
+       /* Dequeue all entries and run them */
+       while (1) {
+               struct hci_cmd_sync_work_entry *entry;
 
-       if (func) {
-               int err;
+               mutex_lock(&hdev->cmd_sync_work_lock);
+               entry = list_first_entry_or_null(&hdev->cmd_sync_work_list,
+                                                struct hci_cmd_sync_work_entry,
+                                                list);
+               if (entry)
+                       list_del(&entry->list);
+               mutex_unlock(&hdev->cmd_sync_work_lock);
 
-               hci_req_sync_lock(hdev);
+               if (!entry)
+                       break;
+
+               bt_dev_dbg(hdev, "entry %p", entry);
 
-               err = func(hdev, data);
+               if (entry->func) {
+                       int err;
 
-               if (destroy)
-                       destroy(hdev, data, err);
+                       hci_req_sync_lock(hdev);
+                       err = entry->func(hdev, entry->data);
+                       if (entry->destroy)
+                               entry->destroy(hdev, entry->data, err);
+                       hci_req_sync_unlock(hdev);
+               }
 
-               hci_req_sync_unlock(hdev);
+               kfree(entry);
        }
 }
 
@@ -382,6 +379,9 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
 {
        struct hci_cmd_sync_work_entry *entry;
 
+       if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
+               return -ENODEV;
+
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return -ENOMEM;
@@ -4425,7 +4425,7 @@ static int hci_disconnect_all_sync(struct hci_dev *hdev, u8 reason)
                        return err;
        }
 
-       return err;
+       return 0;
 }
 
 /* This function perform power off HCI command sequence as follows:
@@ -5143,8 +5143,8 @@ static void set_ext_conn_params(struct hci_conn *conn,
        p->max_ce_len = cpu_to_le16(0x0000);
 }
 
-int hci_le_ext_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn,
-                               u8 own_addr_type)
+static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
+                                      struct hci_conn *conn, u8 own_addr_type)
 {
        struct hci_cp_le_ext_create_conn *cp;
        struct hci_cp_le_ext_conn_param *p;