|
@@ -1617,6 +1617,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
|
|
cancel_delayed_work(&hdev->service_cache);
|
|
|
|
|
|
cancel_delayed_work_sync(&hdev->le_scan_disable);
|
|
|
+ cancel_delayed_work_sync(&hdev->le_scan_restart);
|
|
|
|
|
|
if (test_bit(HCI_MGMT, &hdev->dev_flags))
|
|
|
cancel_delayed_work_sync(&hdev->rpa_expired);
|
|
@@ -2830,6 +2831,8 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ hdev->discovery.scan_start = 0;
|
|
|
+
|
|
|
switch (hdev->discovery.type) {
|
|
|
case DISCOV_TYPE_LE:
|
|
|
hci_dev_lock(hdev);
|
|
@@ -2869,6 +2872,8 @@ static void le_scan_disable_work(struct work_struct *work)
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
+ cancel_delayed_work_sync(&hdev->le_scan_restart);
|
|
|
+
|
|
|
hci_req_init(&req, hdev);
|
|
|
|
|
|
hci_req_add_le_scan_disable(&req);
|
|
@@ -2878,6 +2883,74 @@ static void le_scan_disable_work(struct work_struct *work)
|
|
|
BT_ERR("Disable LE scanning request failed: err %d", err);
|
|
|
}
|
|
|
|
|
|
+static void le_scan_restart_work_complete(struct hci_dev *hdev, u8 status,
|
|
|
+ u16 opcode)
|
|
|
+{
|
|
|
+ unsigned long timeout, duration, scan_start, now;
|
|
|
+
|
|
|
+ BT_DBG("%s", hdev->name);
|
|
|
+
|
|
|
+ if (status) {
|
|
|
+ BT_ERR("Failed to restart LE scan: status %d", status);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) ||
|
|
|
+ !hdev->discovery.scan_start)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* When the scan was started, hdev->le_scan_disable has been queued
|
|
|
+ * after duration from scan_start. During scan restart this job
|
|
|
+ * has been canceled, and we need to queue it again after proper
|
|
|
+ * timeout, to make sure that scan does not run indefinitely.
|
|
|
+ */
|
|
|
+ duration = hdev->discovery.scan_duration;
|
|
|
+ scan_start = hdev->discovery.scan_start;
|
|
|
+ now = jiffies;
|
|
|
+ if (now - scan_start <= duration) {
|
|
|
+ int elapsed;
|
|
|
+
|
|
|
+ if (now >= scan_start)
|
|
|
+ elapsed = now - scan_start;
|
|
|
+ else
|
|
|
+ elapsed = ULONG_MAX - scan_start + now;
|
|
|
+
|
|
|
+ timeout = duration - elapsed;
|
|
|
+ } else {
|
|
|
+ timeout = 0;
|
|
|
+ }
|
|
|
+ queue_delayed_work(hdev->workqueue,
|
|
|
+ &hdev->le_scan_disable, timeout);
|
|
|
+}
|
|
|
+
|
|
|
+static void le_scan_restart_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct hci_dev *hdev = container_of(work, struct hci_dev,
|
|
|
+ le_scan_restart.work);
|
|
|
+ struct hci_request req;
|
|
|
+ struct hci_cp_le_set_scan_enable cp;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ BT_DBG("%s", hdev->name);
|
|
|
+
|
|
|
+ /* If controller is not scanning we are done. */
|
|
|
+ if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
|
|
|
+ return;
|
|
|
+
|
|
|
+ hci_req_init(&req, hdev);
|
|
|
+
|
|
|
+ hci_req_add_le_scan_disable(&req);
|
|
|
+
|
|
|
+ memset(&cp, 0, sizeof(cp));
|
|
|
+ cp.enable = LE_SCAN_ENABLE;
|
|
|
+ cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
|
|
|
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp);
|
|
|
+
|
|
|
+ err = hci_req_run(&req, le_scan_restart_work_complete);
|
|
|
+ if (err)
|
|
|
+ BT_ERR("Restart LE scan request failed: err %d", err);
|
|
|
+}
|
|
|
+
|
|
|
/* Copy the Identity Address of the controller.
|
|
|
*
|
|
|
* If the controller has a public BD_ADDR, then by default use that one.
|
|
@@ -2974,6 +3047,7 @@ struct hci_dev *hci_alloc_dev(void)
|
|
|
INIT_DELAYED_WORK(&hdev->power_off, hci_power_off);
|
|
|
INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off);
|
|
|
INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work);
|
|
|
+ INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work);
|
|
|
|
|
|
skb_queue_head_init(&hdev->rx_q);
|
|
|
skb_queue_head_init(&hdev->cmd_q);
|