mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
Bluetooth: Rework le_scan_restart for hci_sync
le_scan_restart delayed work queue was running as a deprecated hci_request instead of on the newer thread-safe hci_sync mechanism. Signed-off-by: Brian Gix <brian.gix@intel.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
8ffde2a73f
commit
27d54b778a
2 changed files with 75 additions and 89 deletions
|
@ -1975,92 +1975,6 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int le_scan_restart(struct hci_request *req, unsigned long opt)
|
|
||||||
{
|
|
||||||
struct hci_dev *hdev = req->hdev;
|
|
||||||
|
|
||||||
/* If controller is not scanning we are done. */
|
|
||||||
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (hdev->scanning_paused) {
|
|
||||||
bt_dev_dbg(hdev, "Scanning is paused for suspend");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_req_add_le_scan_disable(req, false);
|
|
||||||
|
|
||||||
if (use_ext_scan(hdev)) {
|
|
||||||
struct hci_cp_le_set_ext_scan_enable ext_enable_cp;
|
|
||||||
|
|
||||||
memset(&ext_enable_cp, 0, sizeof(ext_enable_cp));
|
|
||||||
ext_enable_cp.enable = LE_SCAN_ENABLE;
|
|
||||||
ext_enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
|
|
||||||
|
|
||||||
hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_ENABLE,
|
|
||||||
sizeof(ext_enable_cp), &ext_enable_cp);
|
|
||||||
} else {
|
|
||||||
struct hci_cp_le_set_scan_enable cp;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void le_scan_restart_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
|
||||||
le_scan_restart.work);
|
|
||||||
unsigned long timeout, duration, scan_start, now;
|
|
||||||
u8 status;
|
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "");
|
|
||||||
|
|
||||||
hci_req_sync(hdev, le_scan_restart, 0, HCI_CMD_TIMEOUT, &status);
|
|
||||||
if (status) {
|
|
||||||
bt_dev_err(hdev, "failed to restart LE scan: status %d",
|
|
||||||
status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
|
||||||
|
|
||||||
if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) ||
|
|
||||||
!hdev->discovery.scan_start)
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
/* 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->req_workqueue,
|
|
||||||
&hdev->le_scan_disable, timeout);
|
|
||||||
|
|
||||||
unlock:
|
|
||||||
hci_dev_unlock(hdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hci_req_stop_discovery(struct hci_request *req)
|
bool hci_req_stop_discovery(struct hci_request *req)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = req->hdev;
|
struct hci_dev *hdev = req->hdev;
|
||||||
|
@ -2158,7 +2072,6 @@ error:
|
||||||
|
|
||||||
void hci_request_setup(struct hci_dev *hdev)
|
void hci_request_setup(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work);
|
|
||||||
INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
|
INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
|
||||||
INIT_DELAYED_WORK(&hdev->interleave_scan, interleave_scan_work);
|
INIT_DELAYED_WORK(&hdev->interleave_scan, interleave_scan_work);
|
||||||
}
|
}
|
||||||
|
@ -2167,8 +2080,6 @@ void hci_request_cancel_all(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
__hci_cmd_sync_cancel(hdev, ENODEV);
|
__hci_cmd_sync_cancel(hdev, ENODEV);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&hdev->le_scan_restart);
|
|
||||||
|
|
||||||
if (hdev->adv_instance_timeout) {
|
if (hdev->adv_instance_timeout) {
|
||||||
cancel_delayed_work_sync(&hdev->adv_instance_expire);
|
cancel_delayed_work_sync(&hdev->adv_instance_expire);
|
||||||
hdev->adv_instance_timeout = 0;
|
hdev->adv_instance_timeout = 0;
|
||||||
|
|
|
@ -392,6 +392,79 @@ _return:
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hci_le_set_scan_enable_sync(struct hci_dev *hdev, u8 val,
|
||||||
|
u8 filter_dup);
|
||||||
|
static int hci_le_scan_restart_sync(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
/* If controller is not scanning we are done. */
|
||||||
|
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (hdev->scanning_paused) {
|
||||||
|
bt_dev_dbg(hdev, "Scanning is paused for suspend");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_le_set_scan_enable_sync(hdev, LE_SCAN_DISABLE, 0x00);
|
||||||
|
return hci_le_set_scan_enable_sync(hdev, LE_SCAN_ENABLE,
|
||||||
|
LE_SCAN_FILTER_DUP_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int le_scan_restart_sync(struct hci_dev *hdev, void *data)
|
||||||
|
{
|
||||||
|
return hci_le_scan_restart_sync(hdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void le_scan_restart(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct hci_dev *hdev = container_of(work, struct hci_dev,
|
||||||
|
le_scan_restart.work);
|
||||||
|
unsigned long timeout, duration, scan_start, now;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
bt_dev_dbg(hdev, "");
|
||||||
|
|
||||||
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
|
status = hci_cmd_sync_queue(hdev, le_scan_restart_sync, NULL, NULL);
|
||||||
|
if (status) {
|
||||||
|
bt_dev_err(hdev, "failed to restart LE scan: status %d",
|
||||||
|
status);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) ||
|
||||||
|
!hdev->discovery.scan_start)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
/* 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->req_workqueue,
|
||||||
|
&hdev->le_scan_disable, timeout);
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
hci_dev_unlock(hdev);
|
||||||
|
}
|
||||||
|
|
||||||
void hci_cmd_sync_init(struct hci_dev *hdev)
|
void hci_cmd_sync_init(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
|
INIT_WORK(&hdev->cmd_sync_work, hci_cmd_sync_work);
|
||||||
|
@ -400,6 +473,7 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
|
||||||
|
|
||||||
INIT_WORK(&hdev->cmd_sync_cancel_work, hci_cmd_sync_cancel_work);
|
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_disable, le_scan_disable);
|
||||||
|
INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_cmd_sync_clear(struct hci_dev *hdev)
|
void hci_cmd_sync_clear(struct hci_dev *hdev)
|
||||||
|
@ -4488,6 +4562,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
|
||||||
cancel_delayed_work(&hdev->power_off);
|
cancel_delayed_work(&hdev->power_off);
|
||||||
cancel_delayed_work(&hdev->ncmd_timer);
|
cancel_delayed_work(&hdev->ncmd_timer);
|
||||||
cancel_delayed_work(&hdev->le_scan_disable);
|
cancel_delayed_work(&hdev->le_scan_disable);
|
||||||
|
cancel_delayed_work(&hdev->le_scan_restart);
|
||||||
|
|
||||||
hci_request_cancel_all(hdev);
|
hci_request_cancel_all(hdev);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue