Bluetooth: Add hci_request support for hci_update_background_scan
authorJohan Hedberg <johan.hedberg@intel.com>
Fri, 19 Dec 2014 20:26:00 +0000 (22:26 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 19 Dec 2014 21:06:37 +0000 (22:06 +0100)
Many places using hci_update_background_scan() try to synchronize
whatever they're doing with the help of hci_request callbacks. However,
since the hci_update_background_scan() function hasn't so far accepted a
hci_request pointer any commands triggered by it have been left out by
the synchronization. This patch modifies the API in a similar way as was
done for hci_update_page_scan, i.e. there's a variant that takes a
hci_request and another one that takes a hci_dev.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/hci_request.c
net/bluetooth/hci_request.h
net/bluetooth/mgmt.c

index 93066f70f8ab2c32285bfaf34a6a675dc6422592..8eccdf02950095ee612eb4d707a56fe3b3762952 100644 (file)
@@ -930,8 +930,6 @@ struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
                                                  bdaddr_t *addr,
                                                  u8 addr_type);
 
-void hci_update_background_scan(struct hci_dev *hdev);
-
 void hci_uuids_clear(struct hci_dev *hdev);
 
 void hci_link_keys_clear(struct hci_dev *hdev);
index 2cfaaa6acb04c45b2a43eb93ae18948a0f870e36..def6fba01b458262b91d221472b2552ccbede18e 100644 (file)
@@ -5312,95 +5312,6 @@ static void hci_cmd_work(struct work_struct *work)
        }
 }
 
-static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
-{
-       if (status)
-               BT_DBG("HCI request failed to update background scanning: "
-                      "status 0x%2.2x", status);
-}
-
-/* This function controls the background scanning based on hdev->pend_le_conns
- * list. If there are pending LE connection we start the background scanning,
- * otherwise we stop it.
- *
- * This function requires the caller holds hdev->lock.
- */
-void hci_update_background_scan(struct hci_dev *hdev)
-{
-       struct hci_request req;
-       struct hci_conn *conn;
-       int err;
-
-       if (!test_bit(HCI_UP, &hdev->flags) ||
-           test_bit(HCI_INIT, &hdev->flags) ||
-           test_bit(HCI_SETUP, &hdev->dev_flags) ||
-           test_bit(HCI_CONFIG, &hdev->dev_flags) ||
-           test_bit(HCI_AUTO_OFF, &hdev->dev_flags) ||
-           test_bit(HCI_UNREGISTER, &hdev->dev_flags))
-               return;
-
-       /* No point in doing scanning if LE support hasn't been enabled */
-       if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
-               return;
-
-       /* If discovery is active don't interfere with it */
-       if (hdev->discovery.state != DISCOVERY_STOPPED)
-               return;
-
-       /* Reset RSSI and UUID filters when starting background scanning
-        * since these filters are meant for service discovery only.
-        *
-        * The Start Discovery and Start Service Discovery operations
-        * ensure to set proper values for RSSI threshold and UUID
-        * filter list. So it is safe to just reset them here.
-        */
-       hci_discovery_filter_clear(hdev);
-
-       hci_req_init(&req, hdev);
-
-       if (list_empty(&hdev->pend_le_conns) &&
-           list_empty(&hdev->pend_le_reports)) {
-               /* If there is no pending LE connections or devices
-                * to be scanned for, we should stop the background
-                * scanning.
-                */
-
-               /* If controller is not scanning we are done. */
-               if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
-                       return;
-
-               hci_req_add_le_scan_disable(&req);
-
-               BT_DBG("%s stopping background scanning", hdev->name);
-       } else {
-               /* If there is at least one pending LE connection, we should
-                * keep the background scan running.
-                */
-
-               /* If controller is connecting, we should not start scanning
-                * since some controllers are not able to scan and connect at
-                * the same time.
-                */
-               conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
-               if (conn)
-                       return;
-
-               /* If controller is currently scanning, we stop it to ensure we
-                * don't miss any advertising (due to duplicates filter).
-                */
-               if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
-                       hci_req_add_le_scan_disable(&req);
-
-               hci_req_add_le_passive_scan(&req);
-
-               BT_DBG("%s starting background scanning", hdev->name);
-       }
-
-       err = hci_req_run(&req, update_background_scan_complete);
-       if (err)
-               BT_ERR("Failed to run HCI request: err %d", err);
-}
-
 static bool disconnected_whitelist_entries(struct hci_dev *hdev)
 {
        struct bdaddr_list *b;
index eba83a2a65565f3170ce89254b8cb52bef6b13b0..e49f682f15506e360846a4e89b3c41db94efdaa5 100644 (file)
@@ -395,3 +395,99 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy,
 
        return 0;
 }
+
+/* This function controls the background scanning based on hdev->pend_le_conns
+ * list. If there are pending LE connection we start the background scanning,
+ * otherwise we stop it.
+ *
+ * This function requires the caller holds hdev->lock.
+ */
+void __hci_update_background_scan(struct hci_request *req)
+{
+       struct hci_dev *hdev = req->hdev;
+       struct hci_conn *conn;
+
+       if (!test_bit(HCI_UP, &hdev->flags) ||
+           test_bit(HCI_INIT, &hdev->flags) ||
+           test_bit(HCI_SETUP, &hdev->dev_flags) ||
+           test_bit(HCI_CONFIG, &hdev->dev_flags) ||
+           test_bit(HCI_AUTO_OFF, &hdev->dev_flags) ||
+           test_bit(HCI_UNREGISTER, &hdev->dev_flags))
+               return;
+
+       /* No point in doing scanning if LE support hasn't been enabled */
+       if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+               return;
+
+       /* If discovery is active don't interfere with it */
+       if (hdev->discovery.state != DISCOVERY_STOPPED)
+               return;
+
+       /* Reset RSSI and UUID filters when starting background scanning
+        * since these filters are meant for service discovery only.
+        *
+        * The Start Discovery and Start Service Discovery operations
+        * ensure to set proper values for RSSI threshold and UUID
+        * filter list. So it is safe to just reset them here.
+        */
+       hci_discovery_filter_clear(hdev);
+
+       if (list_empty(&hdev->pend_le_conns) &&
+           list_empty(&hdev->pend_le_reports)) {
+               /* If there is no pending LE connections or devices
+                * to be scanned for, we should stop the background
+                * scanning.
+                */
+
+               /* If controller is not scanning we are done. */
+               if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+                       return;
+
+               hci_req_add_le_scan_disable(req);
+
+               BT_DBG("%s stopping background scanning", hdev->name);
+       } else {
+               /* If there is at least one pending LE connection, we should
+                * keep the background scan running.
+                */
+
+               /* If controller is connecting, we should not start scanning
+                * since some controllers are not able to scan and connect at
+                * the same time.
+                */
+               conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
+               if (conn)
+                       return;
+
+               /* If controller is currently scanning, we stop it to ensure we
+                * don't miss any advertising (due to duplicates filter).
+                */
+               if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
+                       hci_req_add_le_scan_disable(req);
+
+               hci_req_add_le_passive_scan(req);
+
+               BT_DBG("%s starting background scanning", hdev->name);
+       }
+}
+
+static void update_background_scan_complete(struct hci_dev *hdev, u8 status)
+{
+       if (status)
+               BT_DBG("HCI request failed to update background scanning: "
+                      "status 0x%2.2x", status);
+}
+
+void hci_update_background_scan(struct hci_dev *hdev)
+{
+       int err;
+       struct hci_request req;
+
+       hci_req_init(&req, hdev);
+
+       __hci_update_background_scan(&req);
+
+       err = hci_req_run(&req, update_background_scan_complete);
+       if (err && err != -ENODATA)
+               BT_ERR("Failed to run HCI request: err %d", err);
+}
index 1793a46fea6573081cea37a3a2bbb286be10d297..adf074d33544083ca74f9dd3f22123a84bd8b527 100644 (file)
@@ -49,3 +49,6 @@ void __hci_update_page_scan(struct hci_request *req);
 
 int hci_update_random_address(struct hci_request *req, bool require_privacy,
                              u8 *own_addr_type);
+
+void hci_update_background_scan(struct hci_dev *hdev);
+void __hci_update_background_scan(struct hci_request *req);
index 95473e96670369359b78002264ed92d045972206..3afe1e175eb87aff6225bff9ea6326b55c684e5d 100644 (file)
@@ -2228,9 +2228,8 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status)
                hci_req_init(&req, hdev);
                update_adv_data(&req);
                update_scan_rsp_data(&req);
+               __hci_update_background_scan(&req);
                hci_req_run(&req, NULL);
-
-               hci_update_background_scan(hdev);
        }
 
 unlock:
@@ -6038,8 +6037,9 @@ void mgmt_index_removed(struct hci_dev *hdev)
 }
 
 /* This function requires the caller holds hdev->lock */
-static void restart_le_actions(struct hci_dev *hdev)
+static void restart_le_actions(struct hci_request *req)
 {
+       struct hci_dev *hdev = req->hdev;
        struct hci_conn_params *p;
 
        list_for_each_entry(p, &hdev->le_conn_params, list) {
@@ -6061,7 +6061,7 @@ static void restart_le_actions(struct hci_dev *hdev)
                }
        }
 
-       hci_update_background_scan(hdev);
+       __hci_update_background_scan(req);
 }
 
 static void powered_complete(struct hci_dev *hdev, u8 status)
@@ -6072,8 +6072,6 @@ static void powered_complete(struct hci_dev *hdev, u8 status)
 
        hci_dev_lock(hdev);
 
-       restart_le_actions(hdev);
-
        mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
 
        new_settings(hdev, match.sk);
@@ -6131,6 +6129,8 @@ static int powered_update_hci(struct hci_dev *hdev)
 
                if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
                        enable_advertising(&req);
+
+               restart_le_actions(&req);
        }
 
        link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);