Bluetooth: Move Adv Instance timer to hci_sync
authorBrian Gix <brian.gix@intel.com>
Fri, 5 Aug 2022 23:42:32 +0000 (16:42 -0700)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 25 Aug 2022 23:19:37 +0000 (16:19 -0700)
The Advertising Instance expiration timer adv_instance_expire was
handled with the deprecated hci_request mechanism, rather than it's
replacement: hci_sync.

Signed-off-by: Brian Gix <brian.gix@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/hci_sync.h
net/bluetooth/hci_request.c
net/bluetooth/hci_request.h
net/bluetooth/hci_sync.c
net/bluetooth/mgmt.c

index 3843f5060c73750509ae6566856b5f8a09fd0413..aea950440b9dad27809e389bb5a4350cf6f333cd 100644 (file)
@@ -72,7 +72,8 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len,
 int hci_remove_advertising_sync(struct hci_dev *hdev, struct sock *sk,
                                u8 instance, bool force);
 int hci_disable_advertising_sync(struct hci_dev *hdev);
-
+int hci_clear_adv_instance_sync(struct hci_dev *hdev, struct sock *sk,
+                               u8 instance, bool force);
 int hci_update_passive_scan_sync(struct hci_dev *hdev);
 int hci_update_passive_scan(struct hci_dev *hdev);
 int hci_read_rssi_sync(struct hci_dev *hdev, __le16 handle);
index d14e50951aec045e5ff6d3f3258963a05a0b0fbf..be32fb0f5557192b4520c825a3a01fe2771e90a0 100644 (file)
@@ -811,14 +811,6 @@ void hci_req_add_le_passive_scan(struct hci_request *req)
                           addr_resolv);
 }
 
-static void cancel_adv_timeout(struct hci_dev *hdev)
-{
-       if (hdev->adv_instance_timeout) {
-               hdev->adv_instance_timeout = 0;
-               cancel_delayed_work(&hdev->adv_instance_expire);
-       }
-}
-
 static bool adv_cur_instance_is_scannable(struct hci_dev *hdev)
 {
        return hci_adv_instance_is_scannable(hdev, hdev->cur_adv_instance);
@@ -1140,37 +1132,6 @@ void hci_req_reenable_advertising(struct hci_dev *hdev)
        hci_req_run(&req, adv_enable_complete);
 }
 
-static void adv_timeout_expire(struct work_struct *work)
-{
-       struct hci_dev *hdev = container_of(work, struct hci_dev,
-                                           adv_instance_expire.work);
-
-       struct hci_request req;
-       u8 instance;
-
-       bt_dev_dbg(hdev, "");
-
-       hci_dev_lock(hdev);
-
-       hdev->adv_instance_timeout = 0;
-
-       instance = hdev->cur_adv_instance;
-       if (instance == 0x00)
-               goto unlock;
-
-       hci_req_init(&req, hdev);
-
-       hci_req_clear_adv_instance(hdev, NULL, &req, instance, false);
-
-       if (list_empty(&hdev->adv_instances))
-               __hci_req_disable_advertising(&req);
-
-       hci_req_run(&req, NULL);
-
-unlock:
-       hci_dev_unlock(hdev);
-}
-
 static int hci_req_add_le_interleaved_scan(struct hci_request *req,
                                           unsigned long opt)
 {
@@ -1637,72 +1598,6 @@ int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
        return 0;
 }
 
-/* For a single instance:
- * - force == true: The instance will be removed even when its remaining
- *   lifetime is not zero.
- * - force == false: the instance will be deactivated but kept stored unless
- *   the remaining lifetime is zero.
- *
- * For instance == 0x00:
- * - force == true: All instances will be removed regardless of their timeout
- *   setting.
- * - force == false: Only instances that have a timeout will be removed.
- */
-void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
-                               struct hci_request *req, u8 instance,
-                               bool force)
-{
-       struct adv_info *adv_instance, *n, *next_instance = NULL;
-       int err;
-       u8 rem_inst;
-
-       /* Cancel any timeout concerning the removed instance(s). */
-       if (!instance || hdev->cur_adv_instance == instance)
-               cancel_adv_timeout(hdev);
-
-       /* Get the next instance to advertise BEFORE we remove
-        * the current one. This can be the same instance again
-        * if there is only one instance.
-        */
-       if (instance && hdev->cur_adv_instance == instance)
-               next_instance = hci_get_next_instance(hdev, instance);
-
-       if (instance == 0x00) {
-               list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances,
-                                        list) {
-                       if (!(force || adv_instance->timeout))
-                               continue;
-
-                       rem_inst = adv_instance->instance;
-                       err = hci_remove_adv_instance(hdev, rem_inst);
-                       if (!err)
-                               mgmt_advertising_removed(sk, hdev, rem_inst);
-               }
-       } else {
-               adv_instance = hci_find_adv_instance(hdev, instance);
-
-               if (force || (adv_instance && adv_instance->timeout &&
-                             !adv_instance->remaining_time)) {
-                       /* Don't advertise a removed instance. */
-                       if (next_instance &&
-                           next_instance->instance == instance)
-                               next_instance = NULL;
-
-                       err = hci_remove_adv_instance(hdev, instance);
-                       if (!err)
-                               mgmt_advertising_removed(sk, hdev, instance);
-               }
-       }
-
-       if (!req || !hdev_is_powered(hdev) ||
-           hci_dev_test_flag(hdev, HCI_ADVERTISING))
-               return;
-
-       if (next_instance && !ext_adv_capable(hdev))
-               __hci_req_schedule_adv_instance(req, next_instance->instance,
-                                               false);
-}
-
 int hci_update_random_address(struct hci_request *req, bool require_privacy,
                              bool use_rpa, u8 *own_addr_type)
 {
@@ -1977,7 +1872,6 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
 
 void hci_request_setup(struct hci_dev *hdev)
 {
-       INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
        INIT_DELAYED_WORK(&hdev->interleave_scan, interleave_scan_work);
 }
 
@@ -1985,10 +1879,5 @@ void hci_request_cancel_all(struct hci_dev *hdev)
 {
        __hci_cmd_sync_cancel(hdev, ENODEV);
 
-       if (hdev->adv_instance_timeout) {
-               cancel_delayed_work_sync(&hdev->adv_instance_expire);
-               hdev->adv_instance_timeout = 0;
-       }
-
        cancel_interleave_scan(hdev);
 }
index 41e0b84f20426dc1e3a8448e66289fb8077e1f72..3d1b3d97ccdd883161e4ff7772f56352fc19b224 100644 (file)
@@ -90,10 +90,6 @@ void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance);
 
 int __hci_req_schedule_adv_instance(struct hci_request *req, u8 instance,
                                    bool force);
-void hci_req_clear_adv_instance(struct hci_dev *hdev, struct sock *sk,
-                               struct hci_request *req, u8 instance,
-                               bool force);
-
 int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance);
 int __hci_req_setup_per_adv_instance(struct hci_request *req, u8 instance,
                                     u16 min_interval, u16 max_interval);
index 75e7c0a01ab18a9d9ea2c33a0216eb8a07126ccb..bc993dd2383df62ea9f6d6d5831b1217a22bbce5 100644 (file)
@@ -465,6 +465,121 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+static void cancel_adv_timeout(struct hci_dev *hdev)
+{
+       if (hdev->adv_instance_timeout) {
+               hdev->adv_instance_timeout = 0;
+               cancel_delayed_work(&hdev->adv_instance_expire);
+       }
+}
+
+/* For a single instance:
+ * - force == true: The instance will be removed even when its remaining
+ *   lifetime is not zero.
+ * - force == false: the instance will be deactivated but kept stored unless
+ *   the remaining lifetime is zero.
+ *
+ * For instance == 0x00:
+ * - force == true: All instances will be removed regardless of their timeout
+ *   setting.
+ * - force == false: Only instances that have a timeout will be removed.
+ */
+int hci_clear_adv_instance_sync(struct hci_dev *hdev, struct sock *sk,
+                               u8 instance, bool force)
+{
+       struct adv_info *adv_instance, *n, *next_instance = NULL;
+       int err;
+       u8 rem_inst;
+
+       /* Cancel any timeout concerning the removed instance(s). */
+       if (!instance || hdev->cur_adv_instance == instance)
+               cancel_adv_timeout(hdev);
+
+       /* Get the next instance to advertise BEFORE we remove
+        * the current one. This can be the same instance again
+        * if there is only one instance.
+        */
+       if (instance && hdev->cur_adv_instance == instance)
+               next_instance = hci_get_next_instance(hdev, instance);
+
+       if (instance == 0x00) {
+               list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances,
+                                        list) {
+                       if (!(force || adv_instance->timeout))
+                               continue;
+
+                       rem_inst = adv_instance->instance;
+                       err = hci_remove_adv_instance(hdev, rem_inst);
+                       if (!err)
+                               mgmt_advertising_removed(sk, hdev, rem_inst);
+               }
+       } else {
+               adv_instance = hci_find_adv_instance(hdev, instance);
+
+               if (force || (adv_instance && adv_instance->timeout &&
+                             !adv_instance->remaining_time)) {
+                       /* Don't advertise a removed instance. */
+                       if (next_instance &&
+                           next_instance->instance == instance)
+                               next_instance = NULL;
+
+                       err = hci_remove_adv_instance(hdev, instance);
+                       if (!err)
+                               mgmt_advertising_removed(sk, hdev, instance);
+               }
+       }
+
+       if (!hdev_is_powered(hdev) || hci_dev_test_flag(hdev, HCI_ADVERTISING))
+               return 0;
+
+       if (next_instance && !ext_adv_capable(hdev))
+               return hci_schedule_adv_instance_sync(hdev,
+                                                     next_instance->instance,
+                                                     false);
+
+       return 0;
+}
+
+static int adv_timeout_expire_sync(struct hci_dev *hdev, void *data)
+{
+       u8 instance = *(u8 *)data;
+
+       kfree(data);
+
+       hci_clear_adv_instance_sync(hdev, NULL, instance, false);
+
+       if (list_empty(&hdev->adv_instances))
+               return hci_disable_advertising_sync(hdev);
+
+       return 0;
+}
+
+static void adv_timeout_expire(struct work_struct *work)
+{
+       u8 *inst_ptr;
+       struct hci_dev *hdev = container_of(work, struct hci_dev,
+                                           adv_instance_expire.work);
+
+       bt_dev_dbg(hdev, "");
+
+       hci_dev_lock(hdev);
+
+       hdev->adv_instance_timeout = 0;
+
+       if (hdev->cur_adv_instance == 0x00)
+               goto unlock;
+
+       inst_ptr = kmalloc(1, GFP_KERNEL);
+       if (!inst_ptr)
+               goto unlock;
+
+       *inst_ptr = hdev->cur_adv_instance;
+       hci_cmd_sync_queue(hdev, adv_timeout_expire_sync, inst_ptr, NULL);
+
+unlock:
+       hci_dev_unlock(hdev);
+}
+
 void hci_cmd_sync_init(struct hci_dev *hdev)
 {
        INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
@@ -474,6 +589,7 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
        INIT_WORK(&hdev->cmd_sync_cancel_work, hci_cmd_sync_cancel_work);
        INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable);
        INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart);
+       INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
 }
 
 void hci_cmd_sync_clear(struct hci_dev *hdev)
@@ -1479,14 +1595,6 @@ int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason)
                                     sizeof(cp), &cp, HCI_CMD_TIMEOUT);
 }
 
-static void cancel_adv_timeout(struct hci_dev *hdev)
-{
-       if (hdev->adv_instance_timeout) {
-               hdev->adv_instance_timeout = 0;
-               cancel_delayed_work(&hdev->adv_instance_expire);
-       }
-}
-
 static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)
 {
        struct {
@@ -4566,6 +4674,11 @@ int hci_dev_close_sync(struct hci_dev *hdev)
 
        hci_request_cancel_all(hdev);
 
+       if (hdev->adv_instance_timeout) {
+               cancel_delayed_work_sync(&hdev->adv_instance_expire);
+               hdev->adv_instance_timeout = 0;
+       }
+
        if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
            !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
            test_bit(HCI_UP, &hdev->flags)) {
index 6e31023b84f5fc7d5fd6ae5587672940691303cc..df20e15a05daf2dd6f1a21469db766270f1fc568 100644 (file)
@@ -2058,6 +2058,8 @@ static int set_le_sync(struct hci_dev *hdev, void *data)
        int err;
 
        if (!val) {
+               hci_clear_adv_instance_sync(hdev, NULL, 0x00, true);
+
                if (hci_dev_test_flag(hdev, HCI_LE_ADV))
                        hci_disable_advertising_sync(hdev);
 
@@ -2131,9 +2133,6 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
        val = !!cp->val;
        enabled = lmp_host_le_capable(hdev);
 
-       if (!val)
-               hci_req_clear_adv_instance(hdev, NULL, NULL, 0x00, true);
-
        if (!hdev_is_powered(hdev) || val == enabled) {
                bool changed = false;