2022-05-25 01:06:49

by Manish Mandlik

[permalink] [raw]
Subject: [PATCH 1/2] Bluetooth: hci_sync: Refactor add Adv Monitor

Make use of hci_cmd_sync_queue for adding an advertisement monitor.

Signed-off-by: Manish Mandlik <[email protected]>
Reviewed-by: Miao-chen Chou <[email protected]>
---

include/net/bluetooth/hci_core.h | 5 +-
net/bluetooth/hci_core.c | 47 ++++-----
net/bluetooth/mgmt.c | 121 +++++++----------------
net/bluetooth/msft.c | 161 ++++++++-----------------------
4 files changed, 98 insertions(+), 236 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5a52a2018b56..59953a7a6328 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1410,10 +1410,8 @@ bool hci_adv_instance_is_scannable(struct hci_dev *hdev, u8 instance);

void hci_adv_monitors_clear(struct hci_dev *hdev);
void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
-int hci_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
-bool hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
- int *err);
+int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
bool hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle, int *err);
bool hci_remove_all_adv_monitor(struct hci_dev *hdev, int *err);
bool hci_is_adv_monitoring(struct hci_dev *hdev);
@@ -1875,7 +1873,6 @@ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
u8 instance);
void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle);
int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
-int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
bdaddr_t *bdaddr, u8 addr_type);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5abb2ca5b129..bbbbe3203130 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1873,11 +1873,6 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
kfree(monitor);
}

-int hci_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status)
-{
- return mgmt_add_adv_patterns_monitor_complete(hdev, status);
-}
-
int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
{
return mgmt_remove_adv_monitor_complete(hdev, status);
@@ -1885,49 +1880,49 @@ int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)

/* Assigns handle to a monitor, and if offloading is supported and power is on,
* also attempts to forward the request to the controller.
- * Returns true if request is forwarded (result is pending), false otherwise.
- * This function requires the caller holds hdev->lock.
*/
-bool hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
- int *err)
+int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
{
int min, max, handle;
+ int status = 0;

- *err = 0;
+ if (!monitor)
+ return -EINVAL;

- if (!monitor) {
- *err = -EINVAL;
- return false;
- }
+ hci_dev_lock(hdev);

min = HCI_MIN_ADV_MONITOR_HANDLE;
max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES;
handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max,
GFP_KERNEL);
- if (handle < 0) {
- *err = handle;
- return false;
- }
+
+ hci_dev_unlock(hdev);
+
+ if (handle < 0)
+ return handle;

monitor->handle = handle;

if (!hdev_is_powered(hdev))
- return false;
+ return status;

switch (hci_get_adv_monitor_offload_ext(hdev)) {
case HCI_ADV_MONITOR_EXT_NONE:
- hci_update_passive_scan(hdev);
- bt_dev_dbg(hdev, "%s add monitor status %d", hdev->name, *err);
+ bt_dev_dbg(hdev, "%s add monitor %d status %d", hdev->name,
+ monitor->handle, status);
/* Message was not forwarded to controller - not an error */
- return false;
+ break;
+
case HCI_ADV_MONITOR_EXT_MSFT:
- *err = msft_add_monitor_pattern(hdev, monitor);
- bt_dev_dbg(hdev, "%s add monitor msft status %d", hdev->name,
- *err);
+ hci_req_sync_lock(hdev);
+ status = msft_add_monitor_pattern(hdev, monitor);
+ hci_req_sync_unlock(hdev);
+ bt_dev_dbg(hdev, "%s add monitor %d msft status %d", hdev->name,
+ monitor->handle, status);
break;
}

- return (*err == 0);
+ return status;
}

/* Attempts to tell the controller and free the monitor. If somehow the
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 74937a834648..d04f90698a87 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4653,75 +4653,21 @@ static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
return err;
}

-int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status)
-{
- struct mgmt_rp_add_adv_patterns_monitor rp;
- struct mgmt_pending_cmd *cmd;
- struct adv_monitor *monitor;
- int err = 0;
-
- hci_dev_lock(hdev);
-
- cmd = pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev);
- if (!cmd) {
- cmd = pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev);
- if (!cmd)
- goto done;
- }
-
- monitor = cmd->user_data;
- rp.monitor_handle = cpu_to_le16(monitor->handle);
-
- if (!status) {
- mgmt_adv_monitor_added(cmd->sk, hdev, monitor->handle);
- hdev->adv_monitors_cnt++;
- if (monitor->state == ADV_MONITOR_STATE_NOT_REGISTERED)
- monitor->state = ADV_MONITOR_STATE_REGISTERED;
- hci_update_passive_scan(hdev);
- }
-
- err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
- mgmt_status(status), &rp, sizeof(rp));
- mgmt_pending_remove(cmd);
-
-done:
- hci_dev_unlock(hdev);
- bt_dev_dbg(hdev, "add monitor %d complete, status %u",
- rp.monitor_handle, status);
-
- return err;
-}
-
static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
- struct adv_monitor *m, u8 status,
- void *data, u16 len, u16 op)
+ struct adv_monitor *m, void *data,
+ u16 len, u16 op)
{
struct mgmt_rp_add_adv_patterns_monitor rp;
- struct mgmt_pending_cmd *cmd;
+ u8 status = MGMT_STATUS_SUCCESS;
int err;
- bool pending;
-
- hci_dev_lock(hdev);
-
- if (status)
- goto unlock;

if (pending_find(MGMT_OP_SET_LE, hdev) ||
- pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
- pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) ||
pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
status = MGMT_STATUS_BUSY;
- goto unlock;
- }
-
- cmd = mgmt_pending_add(sk, op, hdev, data, len);
- if (!cmd) {
- status = MGMT_STATUS_NO_RESOURCES;
- goto unlock;
+ goto done;
}

- cmd->user_data = m;
- pending = hci_add_adv_monitor(hdev, m, &err);
+ err = hci_add_adv_monitor(hdev, m);
if (err) {
if (err == -ENOSPC || err == -ENOMEM)
status = MGMT_STATUS_NO_RESOURCES;
@@ -4730,30 +4676,29 @@ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
else
status = MGMT_STATUS_FAILED;

- mgmt_pending_remove(cmd);
- goto unlock;
+ goto done;
}

- if (!pending) {
- mgmt_pending_remove(cmd);
- rp.monitor_handle = cpu_to_le16(m->handle);
- mgmt_adv_monitor_added(sk, hdev, m->handle);
- m->state = ADV_MONITOR_STATE_REGISTERED;
- hdev->adv_monitors_cnt++;
+ hci_dev_lock(hdev);

- hci_dev_unlock(hdev);
- return mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_SUCCESS,
- &rp, sizeof(rp));
- }
+ rp.monitor_handle = cpu_to_le16(m->handle);
+ mgmt_adv_monitor_added(sk, hdev, m->handle);
+ if (m->state == ADV_MONITOR_STATE_NOT_REGISTERED)
+ m->state = ADV_MONITOR_STATE_REGISTERED;
+ hdev->adv_monitors_cnt++;
+ hci_update_passive_scan(hdev);

hci_dev_unlock(hdev);

- return 0;
+done:
+ bt_dev_dbg(hdev, "add monitor %d complete, status %u", m->handle,
+ status);

-unlock:
- hci_free_adv_monitor(hdev, m);
- hci_dev_unlock(hdev);
- return mgmt_cmd_status(sk, hdev->id, op, status);
+ if (status)
+ return mgmt_cmd_status(sk, hdev->id, op, status);
+
+ return mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_SUCCESS, &rp,
+ sizeof(rp));
}

static void parse_adv_monitor_rssi(struct adv_monitor *m,
@@ -4817,7 +4762,7 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
{
struct mgmt_cp_add_adv_patterns_monitor *cp = data;
struct adv_monitor *m = NULL;
- u8 status = MGMT_STATUS_SUCCESS;
+ int status = MGMT_STATUS_SUCCESS;
size_t expected_size = sizeof(*cp);

BT_DBG("request for %s", hdev->name);
@@ -4843,10 +4788,14 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,

parse_adv_monitor_rssi(m, NULL);
status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
+ if (status)
+ goto done;
+
+ status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR);

done:
- return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
- MGMT_OP_ADD_ADV_PATTERNS_MONITOR);
+ return status;
}

static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
@@ -4854,7 +4803,7 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
{
struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = data;
struct adv_monitor *m = NULL;
- u8 status = MGMT_STATUS_SUCCESS;
+ int status = MGMT_STATUS_SUCCESS;
size_t expected_size = sizeof(*cp);

BT_DBG("request for %s", hdev->name);
@@ -4880,10 +4829,14 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,

parse_adv_monitor_rssi(m, &cp->rssi);
status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
+ if (status)
+ goto done;

-done:
- return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
+ status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI);
+
+done:
+ return status;
}

int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
@@ -4933,9 +4886,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev);

if (pending_find(MGMT_OP_SET_LE, hdev) ||
- pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) ||
- pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
- pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) {
+ pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
status = MGMT_STATUS_BUSY;
goto unlock;
}
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index f43994523b1f..9abea16c4305 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -106,8 +106,6 @@ struct msft_data {
__u8 filter_enabled;
};

-static int __msft_add_monitor_pattern(struct hci_dev *hdev,
- struct adv_monitor *monitor);
static int __msft_remove_monitor(struct hci_dev *hdev,
struct adv_monitor *monitor, u16 handle);

@@ -164,34 +162,6 @@ static bool read_supported_features(struct hci_dev *hdev,
return false;
}

-static void reregister_monitor(struct hci_dev *hdev, int handle)
-{
- struct adv_monitor *monitor;
- struct msft_data *msft = hdev->msft_data;
- int err;
-
- while (1) {
- monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
- if (!monitor) {
- /* All monitors have been resumed */
- msft->resuming = false;
- hci_update_passive_scan(hdev);
- return;
- }
-
- msft->pending_add_handle = (u16)handle;
- err = __msft_add_monitor_pattern(hdev, monitor);
-
- /* If success, we return and wait for monitor added callback */
- if (!err)
- return;
-
- /* Otherwise remove the monitor and keep registering */
- hci_free_adv_monitor(hdev, monitor);
- handle++;
- }
-}
-
/* is_mgmt = true matches the handle exposed to userspace via mgmt.
* is_mgmt = false matches the handle used by the msft controller.
* This function requires the caller holds hdev->lock
@@ -243,14 +213,14 @@ static int msft_monitor_device_del(struct hci_dev *hdev, __u16 mgmt_handle,
return count;
}

-static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
- u8 status, u16 opcode,
- struct sk_buff *skb)
+static int msft_le_monitor_advertisement_cb(struct hci_dev *hdev, u16 opcode,
+ struct sk_buff *skb)
{
struct msft_rp_le_monitor_advertisement *rp;
struct adv_monitor *monitor;
struct msft_monitor_advertisement_handle_data *handle_data;
struct msft_data *msft = hdev->msft_data;
+ int status = 0;

hci_dev_lock(hdev);

@@ -262,15 +232,16 @@ static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
goto unlock;
}

- if (status)
- goto unlock;
-
rp = (struct msft_rp_le_monitor_advertisement *)skb->data;
if (skb->len < sizeof(*rp)) {
status = HCI_ERROR_UNSPECIFIED;
goto unlock;
}

+ status = rp->status;
+ if (status)
+ goto unlock;
+
handle_data = kmalloc(sizeof(*handle_data), GFP_KERNEL);
if (!handle_data) {
status = HCI_ERROR_UNSPECIFIED;
@@ -290,8 +261,7 @@ static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,

hci_dev_unlock(hdev);

- if (!msft->resuming)
- hci_add_adv_patterns_monitor_complete(hdev, status);
+ return status;
}

static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
@@ -463,7 +433,7 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
ptrdiff_t offset = 0;
u8 pattern_count = 0;
struct sk_buff *skb;
- u8 status;
+ struct msft_data *msft = hdev->msft_data;

if (!msft_monitor_pattern_valid(monitor))
return -EINVAL;
@@ -505,20 +475,40 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
if (IS_ERR(skb))
return PTR_ERR(skb);

- status = skb->data[0];
- skb_pull(skb, 1);
+ msft->pending_add_handle = monitor->handle;

- msft_le_monitor_advertisement_cb(hdev, status, hdev->msft_opcode, skb);
+ return msft_le_monitor_advertisement_cb(hdev, hdev->msft_opcode, skb);
+}

- return status;
+static void reregister_monitor(struct hci_dev *hdev)
+{
+ struct adv_monitor *monitor;
+ struct msft_data *msft = hdev->msft_data;
+ int handle = 0;
+
+ if (!msft)
+ return;
+
+ msft->resuming = true;
+
+ while (1) {
+ monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
+ if (!monitor)
+ break;
+
+ msft_add_monitor_sync(hdev, monitor);
+
+ handle++;
+ }
+
+ /* All monitors have been reregistered */
+ msft->resuming = false;
}

/* This function requires the caller holds hci_req_sync_lock */
int msft_resume_sync(struct hci_dev *hdev)
{
struct msft_data *msft = hdev->msft_data;
- struct adv_monitor *monitor;
- int handle = 0;

if (!msft || !msft_monitor_supported(hdev))
return 0;
@@ -533,24 +523,12 @@ int msft_resume_sync(struct hci_dev *hdev)

hci_dev_unlock(hdev);

- msft->resuming = true;
-
- while (1) {
- monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
- if (!monitor)
- break;
-
- msft_add_monitor_sync(hdev, monitor);
-
- handle++;
- }
-
- /* All monitors have been resumed */
- msft->resuming = false;
+ reregister_monitor(hdev);

return 0;
}

+/* This function requires the caller holds hci_req_sync_lock */
void msft_do_open(struct hci_dev *hdev)
{
struct msft_data *msft = hdev->msft_data;
@@ -583,7 +561,7 @@ void msft_do_open(struct hci_dev *hdev)
/* Monitors get removed on power off, so we need to explicitly
* tell the controller to re-monitor.
*/
- reregister_monitor(hdev, 0);
+ reregister_monitor(hdev);
}
}

@@ -829,66 +807,7 @@ static void msft_le_set_advertisement_filter_enable_cb(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}

-/* This function requires the caller holds hdev->lock */
-static int __msft_add_monitor_pattern(struct hci_dev *hdev,
- struct adv_monitor *monitor)
-{
- struct msft_cp_le_monitor_advertisement *cp;
- struct msft_le_monitor_advertisement_pattern_data *pattern_data;
- struct msft_le_monitor_advertisement_pattern *pattern;
- struct adv_pattern *entry;
- struct hci_request req;
- struct msft_data *msft = hdev->msft_data;
- size_t total_size = sizeof(*cp) + sizeof(*pattern_data);
- ptrdiff_t offset = 0;
- u8 pattern_count = 0;
- int err = 0;
-
- if (!msft_monitor_pattern_valid(monitor))
- return -EINVAL;
-
- list_for_each_entry(entry, &monitor->patterns, list) {
- pattern_count++;
- total_size += sizeof(*pattern) + entry->length;
- }
-
- cp = kmalloc(total_size, GFP_KERNEL);
- if (!cp)
- return -ENOMEM;
-
- cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT;
- cp->rssi_high = monitor->rssi.high_threshold;
- cp->rssi_low = monitor->rssi.low_threshold;
- cp->rssi_low_interval = (u8)monitor->rssi.low_threshold_timeout;
- cp->rssi_sampling_period = monitor->rssi.sampling_period;
-
- cp->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN;
-
- pattern_data = (void *)cp->data;
- pattern_data->count = pattern_count;
-
- list_for_each_entry(entry, &monitor->patterns, list) {
- pattern = (void *)(pattern_data->data + offset);
- /* the length also includes data_type and offset */
- pattern->length = entry->length + 2;
- pattern->data_type = entry->ad_type;
- pattern->start_byte = entry->offset;
- memcpy(pattern->pattern, entry->value, entry->length);
- offset += sizeof(*pattern) + entry->length;
- }
-
- hci_req_init(&req, hdev);
- hci_req_add(&req, hdev->msft_opcode, total_size, cp);
- err = hci_req_run_skb(&req, msft_le_monitor_advertisement_cb);
- kfree(cp);
-
- if (!err)
- msft->pending_add_handle = monitor->handle;
-
- return err;
-}
-
-/* This function requires the caller holds hdev->lock */
+/* This function requires the caller holds hci_req_sync_lock */
int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
{
struct msft_data *msft = hdev->msft_data;
@@ -899,7 +818,7 @@ int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
if (msft->resuming || msft->suspending)
return -EBUSY;

- return __msft_add_monitor_pattern(hdev, monitor);
+ return msft_add_monitor_sync(hdev, monitor);
}

/* This function requires the caller holds hdev->lock */
--
2.36.1.124.g0e6072fb45-goog



2022-05-25 08:27:16

by Manish Mandlik

[permalink] [raw]
Subject: [PATCH 2/2] Bluetooth: hci_sync: Refactor remove Adv Monitor

Make use of hci_cmd_sync_queue for removing an advertisement monitor.

Signed-off-by: Manish Mandlik <[email protected]>
Reviewed-by: Miao-chen Chou <[email protected]>
---

include/net/bluetooth/hci_core.h | 6 +--
net/bluetooth/hci_core.c | 87 ++++++++++----------------------
net/bluetooth/mgmt.c | 67 ++++++------------------
net/bluetooth/msft.c | 87 +++++++-------------------------
net/bluetooth/msft.h | 6 +--
5 files changed, 63 insertions(+), 190 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 59953a7a6328..7a1e48d794ea 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1410,10 +1410,9 @@ bool hci_adv_instance_is_scannable(struct hci_dev *hdev, u8 instance);

void hci_adv_monitors_clear(struct hci_dev *hdev);
void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
-int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
-bool hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle, int *err);
-bool hci_remove_all_adv_monitor(struct hci_dev *hdev, int *err);
+int hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle);
+int hci_remove_all_adv_monitor(struct hci_dev *hdev);
bool hci_is_adv_monitoring(struct hci_dev *hdev);
int hci_get_adv_monitor_offload_ext(struct hci_dev *hdev);

@@ -1873,7 +1872,6 @@ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
u8 instance);
void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle);
int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
-int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
bdaddr_t *bdaddr, u8 addr_type);

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index bbbbe3203130..c233844a3fc4 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1873,11 +1873,6 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
kfree(monitor);
}

-int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
-{
- return mgmt_remove_adv_monitor_complete(hdev, status);
-}
-
/* Assigns handle to a monitor, and if offloading is supported and power is on,
* also attempts to forward the request to the controller.
*/
@@ -1927,92 +1922,64 @@ int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)

/* Attempts to tell the controller and free the monitor. If somehow the
* controller doesn't have a corresponding handle, remove anyway.
- * Returns true if request is forwarded (result is pending), false otherwise.
- * This function requires the caller holds hdev->lock.
*/
-static bool hci_remove_adv_monitor(struct hci_dev *hdev,
- struct adv_monitor *monitor,
- u16 handle, int *err)
+static int hci_remove_adv_monitor(struct hci_dev *hdev,
+ struct adv_monitor *monitor)
{
- *err = 0;
+ int status = 0;

switch (hci_get_adv_monitor_offload_ext(hdev)) {
case HCI_ADV_MONITOR_EXT_NONE: /* also goes here when powered off */
- goto free_monitor;
+ hci_free_adv_monitor(hdev, monitor);
+ bt_dev_dbg(hdev, "%s remove monitor %d status %d", hdev->name,
+ monitor->handle, status);
+ break;
+
case HCI_ADV_MONITOR_EXT_MSFT:
- *err = msft_remove_monitor(hdev, monitor, handle);
+ hci_req_sync_lock(hdev);
+ status = msft_remove_monitor(hdev, monitor);
+ hci_req_sync_unlock(hdev);
+ bt_dev_dbg(hdev, "%s remove monitor %d msft status %d",
+ hdev->name, monitor->handle, status);
break;
}

- /* In case no matching handle registered, just free the monitor */
- if (*err == -ENOENT)
- goto free_monitor;
-
- return (*err == 0);
-
-free_monitor:
- if (*err == -ENOENT)
+ if (status == -ENOENT)
bt_dev_warn(hdev, "Removing monitor with no matching handle %d",
monitor->handle);
- hci_free_adv_monitor(hdev, monitor);

- *err = 0;
- return false;
+ return status;
}

-/* Returns true if request is forwarded (result is pending), false otherwise.
- * This function requires the caller holds hdev->lock.
- */
-bool hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle, int *err)
+int hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle)
{
struct adv_monitor *monitor = idr_find(&hdev->adv_monitors_idr, handle);
- bool pending;
-
- if (!monitor) {
- *err = -EINVAL;
- return false;
- }

- pending = hci_remove_adv_monitor(hdev, monitor, handle, err);
- if (!*err && !pending)
- hci_update_passive_scan(hdev);
-
- bt_dev_dbg(hdev, "%s remove monitor handle %d, status %d, %spending",
- hdev->name, handle, *err, pending ? "" : "not ");
+ if (!monitor)
+ return -EINVAL;

- return pending;
+ return hci_remove_adv_monitor(hdev, monitor);
}

-/* Returns true if request is forwarded (result is pending), false otherwise.
- * This function requires the caller holds hdev->lock.
- */
-bool hci_remove_all_adv_monitor(struct hci_dev *hdev, int *err)
+int hci_remove_all_adv_monitor(struct hci_dev *hdev)
{
struct adv_monitor *monitor;
int idr_next_id = 0;
- bool pending = false;
- bool update = false;
-
- *err = 0;
+ int status = 0;

- while (!*err && !pending) {
+ while (1) {
monitor = idr_get_next(&hdev->adv_monitors_idr, &idr_next_id);
if (!monitor)
break;

- pending = hci_remove_adv_monitor(hdev, monitor, 0, err);
+ status = hci_remove_adv_monitor(hdev, monitor);
+ if (status)
+ return status;

- if (!*err && !pending)
- update = true;
+ idr_next_id++;
}

- if (update)
- hci_update_passive_scan(hdev);
-
- bt_dev_dbg(hdev, "%s remove all monitors status %d, %spending",
- hdev->name, *err, pending ? "" : "not ");
-
- return pending;
+ return status;
}

/* This function requires the caller holds hdev->lock */
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index d04f90698a87..12d91cd87ff0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4839,37 +4839,6 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
return status;
}

-int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
-{
- struct mgmt_rp_remove_adv_monitor rp;
- struct mgmt_cp_remove_adv_monitor *cp;
- struct mgmt_pending_cmd *cmd;
- int err = 0;
-
- hci_dev_lock(hdev);
-
- cmd = pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev);
- if (!cmd)
- goto done;
-
- cp = cmd->param;
- rp.monitor_handle = cp->monitor_handle;
-
- if (!status)
- hci_update_passive_scan(hdev);
-
- err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
- mgmt_status(status), &rp, sizeof(rp));
- mgmt_pending_remove(cmd);
-
-done:
- hci_dev_unlock(hdev);
- bt_dev_dbg(hdev, "remove monitor %d complete, status %u",
- rp.monitor_handle, status);
-
- return err;
-}
-
static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
@@ -4877,11 +4846,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
struct mgmt_rp_remove_adv_monitor rp;
struct mgmt_pending_cmd *cmd;
u16 handle = __le16_to_cpu(cp->monitor_handle);
- int err, status;
- bool pending;
-
- BT_DBG("request for %s", hdev->name);
- rp.monitor_handle = cp->monitor_handle;
+ int err, status = MGMT_STATUS_SUCCESS;

hci_dev_lock(hdev);

@@ -4897,15 +4862,19 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}

+ hci_dev_unlock(hdev);
+
if (handle)
- pending = hci_remove_single_adv_monitor(hdev, handle, &err);
+ err = hci_remove_single_adv_monitor(hdev, handle);
else
- pending = hci_remove_all_adv_monitor(hdev, &err);
+ err = hci_remove_all_adv_monitor(hdev);

- if (err) {
- mgmt_pending_remove(cmd);
+ hci_dev_lock(hdev);
+
+ mgmt_pending_remove(cmd);

- if (err == -ENOENT)
+ if (err) {
+ if (err == -ENOENT || err == -EINVAL)
status = MGMT_STATUS_INVALID_INDEX;
else
status = MGMT_STATUS_FAILED;
@@ -4913,19 +4882,13 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}

- /* monitor can be removed without forwarding request to controller */
- if (!pending) {
- mgmt_pending_remove(cmd);
- hci_dev_unlock(hdev);
-
- return mgmt_cmd_complete(sk, hdev->id,
- MGMT_OP_REMOVE_ADV_MONITOR,
- MGMT_STATUS_SUCCESS,
- &rp, sizeof(rp));
- }
+ rp.monitor_handle = cp->monitor_handle;
+ hci_update_passive_scan(hdev);

hci_dev_unlock(hdev);
- return 0;
+
+ return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_ADV_MONITOR,
+ MGMT_STATUS_SUCCESS, &rp, sizeof(rp));

unlock:
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
index 9abea16c4305..0d3378e707db 100644
--- a/net/bluetooth/msft.c
+++ b/net/bluetooth/msft.c
@@ -106,9 +106,6 @@ struct msft_data {
__u8 filter_enabled;
};

-static int __msft_remove_monitor(struct hci_dev *hdev,
- struct adv_monitor *monitor, u16 handle);
-
bool msft_monitor_supported(struct hci_dev *hdev)
{
return !!(msft_get_features(hdev) & MSFT_FEATURE_MASK_LE_ADV_MONITOR);
@@ -264,20 +261,16 @@ static int msft_le_monitor_advertisement_cb(struct hci_dev *hdev, u16 opcode,
return status;
}

-static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
- u8 status, u16 opcode,
- struct sk_buff *skb)
+static int msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
+ u16 opcode,
+ struct sk_buff *skb)
{
struct msft_cp_le_cancel_monitor_advertisement *cp;
struct msft_rp_le_cancel_monitor_advertisement *rp;
struct adv_monitor *monitor;
struct msft_monitor_advertisement_handle_data *handle_data;
struct msft_data *msft = hdev->msft_data;
- int err;
- bool pending;
-
- if (status)
- goto done;
+ int status = 0;

rp = (struct msft_rp_le_cancel_monitor_advertisement *)skb->data;
if (skb->len < sizeof(*rp)) {
@@ -285,6 +278,10 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
goto done;
}

+ status = rp->status;
+ if (status)
+ goto done;
+
hci_dev_lock(hdev);

cp = hci_sent_cmd_data(hdev, hdev->msft_opcode);
@@ -312,26 +309,10 @@ static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
kfree(handle_data);
}

- /* If remove all monitors is required, we need to continue the process
- * here because the earlier it was paused when waiting for the
- * response from controller.
- */
- if (msft->pending_remove_handle == 0) {
- pending = hci_remove_all_adv_monitor(hdev, &err);
- if (pending) {
- hci_dev_unlock(hdev);
- return;
- }
-
- if (err)
- status = HCI_ERROR_UNSPECIFIED;
- }
-
hci_dev_unlock(hdev);

done:
- if (!msft->suspending)
- hci_remove_adv_monitor_complete(hdev, status);
+ return status;
}

static int msft_remove_monitor_sync(struct hci_dev *hdev,
@@ -340,13 +321,14 @@ static int msft_remove_monitor_sync(struct hci_dev *hdev,
struct msft_cp_le_cancel_monitor_advertisement cp;
struct msft_monitor_advertisement_handle_data *handle_data;
struct sk_buff *skb;
- u8 status;

handle_data = msft_find_handle_data(hdev, monitor->handle, true);

/* If no matched handle, just remove without telling controller */
- if (!handle_data)
+ if (!handle_data) {
+ hci_free_adv_monitor(hdev, monitor);
return -ENOENT;
+ }

cp.sub_opcode = MSFT_OP_LE_CANCEL_MONITOR_ADVERTISEMENT;
cp.handle = handle_data->msft_handle;
@@ -356,13 +338,8 @@ static int msft_remove_monitor_sync(struct hci_dev *hdev,
if (IS_ERR(skb))
return PTR_ERR(skb);

- status = skb->data[0];
- skb_pull(skb, 1);
-
- msft_le_cancel_monitor_advertisement_cb(hdev, status, hdev->msft_opcode,
- skb);
-
- return status;
+ return msft_le_cancel_monitor_advertisement_cb(hdev, hdev->msft_opcode,
+ skb);
}

/* This function requires the caller holds hci_req_sync_lock */
@@ -821,38 +798,8 @@ int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
return msft_add_monitor_sync(hdev, monitor);
}

-/* This function requires the caller holds hdev->lock */
-static int __msft_remove_monitor(struct hci_dev *hdev,
- struct adv_monitor *monitor, u16 handle)
-{
- struct msft_cp_le_cancel_monitor_advertisement cp;
- struct msft_monitor_advertisement_handle_data *handle_data;
- struct hci_request req;
- struct msft_data *msft = hdev->msft_data;
- int err = 0;
-
- handle_data = msft_find_handle_data(hdev, monitor->handle, true);
-
- /* If no matched handle, just remove without telling controller */
- if (!handle_data)
- return -ENOENT;
-
- cp.sub_opcode = MSFT_OP_LE_CANCEL_MONITOR_ADVERTISEMENT;
- cp.handle = handle_data->msft_handle;
-
- hci_req_init(&req, hdev);
- hci_req_add(&req, hdev->msft_opcode, sizeof(cp), &cp);
- err = hci_req_run_skb(&req, msft_le_cancel_monitor_advertisement_cb);
-
- if (!err)
- msft->pending_remove_handle = handle;
-
- return err;
-}
-
-/* This function requires the caller holds hdev->lock */
-int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
- u16 handle)
+/* This function requires the caller holds hci_req_sync_lock */
+int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
{
struct msft_data *msft = hdev->msft_data;

@@ -862,7 +809,7 @@ int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
if (msft->resuming || msft->suspending)
return -EBUSY;

- return __msft_remove_monitor(hdev, monitor, handle);
+ return msft_remove_monitor_sync(hdev, monitor);
}

void msft_req_add_set_filter_enable(struct hci_request *req, bool enable)
diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
index afcaf7d3b1cb..2a63205b377b 100644
--- a/net/bluetooth/msft.h
+++ b/net/bluetooth/msft.h
@@ -20,8 +20,7 @@ void msft_do_close(struct hci_dev *hdev);
void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb);
__u64 msft_get_features(struct hci_dev *hdev);
int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor);
-int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
- u16 handle);
+int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
void msft_req_add_set_filter_enable(struct hci_request *req, bool enable);
int msft_set_filter_enable(struct hci_dev *hdev, bool enable);
int msft_suspend_sync(struct hci_dev *hdev);
@@ -49,8 +48,7 @@ static inline int msft_add_monitor_pattern(struct hci_dev *hdev,
}

static inline int msft_remove_monitor(struct hci_dev *hdev,
- struct adv_monitor *monitor,
- u16 handle)
+ struct adv_monitor *monitor)
{
return -EOPNOTSUPP;
}
--
2.36.1.124.g0e6072fb45-goog


2022-05-25 09:03:35

by bluez.test.bot

[permalink] [raw]
Subject: RE: [1/2] Bluetooth: hci_sync: Refactor add Adv Monitor

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=644760

---Test result---

Test Summary:
CheckPatch FAIL 2.59 seconds
GitLint PASS 2.26 seconds
SubjectPrefix PASS 1.84 seconds
BuildKernel PASS 40.42 seconds
BuildKernel32 PASS 35.72 seconds
Incremental Build with patchesPASS 82.96 seconds
TestRunner: Setup PASS 597.82 seconds
TestRunner: l2cap-tester PASS 19.89 seconds
TestRunner: bnep-tester PASS 7.36 seconds
TestRunner: mgmt-tester PASS 122.66 seconds
TestRunner: rfcomm-tester PASS 11.60 seconds
TestRunner: sco-tester PASS 11.25 seconds
TestRunner: smp-tester PASS 11.21 seconds
TestRunner: userchan-tester PASS 7.72 seconds

Details
##############################
Test: CheckPatch - FAIL - 2.59 seconds
Run checkpatch.pl script with rule in .checkpatch.conf
[1/2] Bluetooth: hci_sync: Refactor add Adv Monitor\CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#383: FILE: net/bluetooth/mgmt.c:4836:
+ status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI);

total: 0 errors, 0 warnings, 1 checks, 533 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12860520.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.




---
Regards,
Linux Bluetooth

2022-05-26 03:02:44

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH 1/2] Bluetooth: hci_sync: Refactor add Adv Monitor

Hi Manish,

On Tue, May 24, 2022 at 1:14 PM Manish Mandlik <[email protected]> wrote:
>
> Make use of hci_cmd_sync_queue for adding an advertisement monitor.

Im a little lost here, it seems you end up not really using
hci_cmd_sync_queue are you assuming these functions are already run
from a safe context?

> Signed-off-by: Manish Mandlik <[email protected]>
> Reviewed-by: Miao-chen Chou <[email protected]>
> ---
>
> include/net/bluetooth/hci_core.h | 5 +-
> net/bluetooth/hci_core.c | 47 ++++-----
> net/bluetooth/mgmt.c | 121 +++++++----------------
> net/bluetooth/msft.c | 161 ++++++++-----------------------
> 4 files changed, 98 insertions(+), 236 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 5a52a2018b56..59953a7a6328 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -1410,10 +1410,8 @@ bool hci_adv_instance_is_scannable(struct hci_dev *hdev, u8 instance);
>
> void hci_adv_monitors_clear(struct hci_dev *hdev);
> void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
> -int hci_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
> int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
> -bool hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
> - int *err);
> +int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
> bool hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle, int *err);
> bool hci_remove_all_adv_monitor(struct hci_dev *hdev, int *err);
> bool hci_is_adv_monitoring(struct hci_dev *hdev);
> @@ -1875,7 +1873,6 @@ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
> u8 instance);
> void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle);
> int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
> -int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
> int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
> void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
> bdaddr_t *bdaddr, u8 addr_type);
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 5abb2ca5b129..bbbbe3203130 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -1873,11 +1873,6 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
> kfree(monitor);
> }
>
> -int hci_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status)
> -{
> - return mgmt_add_adv_patterns_monitor_complete(hdev, status);
> -}
> -
> int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
> {
> return mgmt_remove_adv_monitor_complete(hdev, status);
> @@ -1885,49 +1880,49 @@ int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
>
> /* Assigns handle to a monitor, and if offloading is supported and power is on,
> * also attempts to forward the request to the controller.
> - * Returns true if request is forwarded (result is pending), false otherwise.
> - * This function requires the caller holds hdev->lock.
> */
> -bool hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
> - int *err)
> +int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
> {
> int min, max, handle;
> + int status = 0;
>
> - *err = 0;
> + if (!monitor)
> + return -EINVAL;
>
> - if (!monitor) {
> - *err = -EINVAL;
> - return false;
> - }
> + hci_dev_lock(hdev);
>
> min = HCI_MIN_ADV_MONITOR_HANDLE;
> max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES;
> handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max,
> GFP_KERNEL);
> - if (handle < 0) {
> - *err = handle;
> - return false;
> - }
> +
> + hci_dev_unlock(hdev);
> +
> + if (handle < 0)
> + return handle;
>
> monitor->handle = handle;
>
> if (!hdev_is_powered(hdev))
> - return false;
> + return status;
>
> switch (hci_get_adv_monitor_offload_ext(hdev)) {
> case HCI_ADV_MONITOR_EXT_NONE:
> - hci_update_passive_scan(hdev);
> - bt_dev_dbg(hdev, "%s add monitor status %d", hdev->name, *err);
> + bt_dev_dbg(hdev, "%s add monitor %d status %d", hdev->name,
> + monitor->handle, status);
> /* Message was not forwarded to controller - not an error */
> - return false;
> + break;
> +
> case HCI_ADV_MONITOR_EXT_MSFT:
> - *err = msft_add_monitor_pattern(hdev, monitor);
> - bt_dev_dbg(hdev, "%s add monitor msft status %d", hdev->name,
> - *err);
> + hci_req_sync_lock(hdev);
> + status = msft_add_monitor_pattern(hdev, monitor);
> + hci_req_sync_unlock(hdev);
> + bt_dev_dbg(hdev, "%s add monitor %d msft status %d", hdev->name,
> + monitor->handle, status);
> break;
> }
>
> - return (*err == 0);
> + return status;
> }
>
> /* Attempts to tell the controller and free the monitor. If somehow the
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 74937a834648..d04f90698a87 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -4653,75 +4653,21 @@ static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
> return err;
> }
>
> -int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status)
> -{
> - struct mgmt_rp_add_adv_patterns_monitor rp;
> - struct mgmt_pending_cmd *cmd;
> - struct adv_monitor *monitor;
> - int err = 0;
> -
> - hci_dev_lock(hdev);
> -
> - cmd = pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev);
> - if (!cmd) {
> - cmd = pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev);
> - if (!cmd)
> - goto done;
> - }
> -
> - monitor = cmd->user_data;
> - rp.monitor_handle = cpu_to_le16(monitor->handle);
> -
> - if (!status) {
> - mgmt_adv_monitor_added(cmd->sk, hdev, monitor->handle);
> - hdev->adv_monitors_cnt++;
> - if (monitor->state == ADV_MONITOR_STATE_NOT_REGISTERED)
> - monitor->state = ADV_MONITOR_STATE_REGISTERED;
> - hci_update_passive_scan(hdev);
> - }
> -
> - err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
> - mgmt_status(status), &rp, sizeof(rp));
> - mgmt_pending_remove(cmd);
> -
> -done:
> - hci_dev_unlock(hdev);
> - bt_dev_dbg(hdev, "add monitor %d complete, status %u",
> - rp.monitor_handle, status);
> -
> - return err;
> -}
> -
> static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
> - struct adv_monitor *m, u8 status,
> - void *data, u16 len, u16 op)
> + struct adv_monitor *m, void *data,
> + u16 len, u16 op)
> {
> struct mgmt_rp_add_adv_patterns_monitor rp;
> - struct mgmt_pending_cmd *cmd;
> + u8 status = MGMT_STATUS_SUCCESS;
> int err;
> - bool pending;
> -
> - hci_dev_lock(hdev);
> -
> - if (status)
> - goto unlock;
>
> if (pending_find(MGMT_OP_SET_LE, hdev) ||
> - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
> - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) ||
> pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
> status = MGMT_STATUS_BUSY;
> - goto unlock;
> - }
> -
> - cmd = mgmt_pending_add(sk, op, hdev, data, len);
> - if (!cmd) {
> - status = MGMT_STATUS_NO_RESOURCES;
> - goto unlock;
> + goto done;
> }
>
> - cmd->user_data = m;
> - pending = hci_add_adv_monitor(hdev, m, &err);
> + err = hci_add_adv_monitor(hdev, m);
> if (err) {
> if (err == -ENOSPC || err == -ENOMEM)
> status = MGMT_STATUS_NO_RESOURCES;
> @@ -4730,30 +4676,29 @@ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
> else
> status = MGMT_STATUS_FAILED;
>
> - mgmt_pending_remove(cmd);
> - goto unlock;
> + goto done;
> }
>
> - if (!pending) {
> - mgmt_pending_remove(cmd);
> - rp.monitor_handle = cpu_to_le16(m->handle);
> - mgmt_adv_monitor_added(sk, hdev, m->handle);
> - m->state = ADV_MONITOR_STATE_REGISTERED;
> - hdev->adv_monitors_cnt++;
> + hci_dev_lock(hdev);
>
> - hci_dev_unlock(hdev);
> - return mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_SUCCESS,
> - &rp, sizeof(rp));
> - }
> + rp.monitor_handle = cpu_to_le16(m->handle);
> + mgmt_adv_monitor_added(sk, hdev, m->handle);
> + if (m->state == ADV_MONITOR_STATE_NOT_REGISTERED)
> + m->state = ADV_MONITOR_STATE_REGISTERED;
> + hdev->adv_monitors_cnt++;
> + hci_update_passive_scan(hdev);
>
> hci_dev_unlock(hdev);
>
> - return 0;
> +done:
> + bt_dev_dbg(hdev, "add monitor %d complete, status %u", m->handle,
> + status);
>
> -unlock:
> - hci_free_adv_monitor(hdev, m);
> - hci_dev_unlock(hdev);
> - return mgmt_cmd_status(sk, hdev->id, op, status);
> + if (status)
> + return mgmt_cmd_status(sk, hdev->id, op, status);
> +
> + return mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_SUCCESS, &rp,
> + sizeof(rp));
> }
>
> static void parse_adv_monitor_rssi(struct adv_monitor *m,
> @@ -4817,7 +4762,7 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
> {
> struct mgmt_cp_add_adv_patterns_monitor *cp = data;
> struct adv_monitor *m = NULL;
> - u8 status = MGMT_STATUS_SUCCESS;
> + int status = MGMT_STATUS_SUCCESS;
> size_t expected_size = sizeof(*cp);
>
> BT_DBG("request for %s", hdev->name);
> @@ -4843,10 +4788,14 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
>
> parse_adv_monitor_rssi(m, NULL);
> status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
> + if (status)
> + goto done;
> +
> + status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
> + MGMT_OP_ADD_ADV_PATTERNS_MONITOR);
>
> done:
> - return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
> - MGMT_OP_ADD_ADV_PATTERNS_MONITOR);
> + return status;
> }
>
> static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
> @@ -4854,7 +4803,7 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
> {
> struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = data;
> struct adv_monitor *m = NULL;
> - u8 status = MGMT_STATUS_SUCCESS;
> + int status = MGMT_STATUS_SUCCESS;
> size_t expected_size = sizeof(*cp);
>
> BT_DBG("request for %s", hdev->name);
> @@ -4880,10 +4829,14 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
>
> parse_adv_monitor_rssi(m, &cp->rssi);
> status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
> + if (status)
> + goto done;
>
> -done:
> - return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
> + status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
> MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI);
> +
> +done:
> + return status;
> }
>
> int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
> @@ -4933,9 +4886,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
> hci_dev_lock(hdev);
>
> if (pending_find(MGMT_OP_SET_LE, hdev) ||
> - pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) ||
> - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
> - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) {
> + pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
> status = MGMT_STATUS_BUSY;
> goto unlock;
> }
> diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
> index f43994523b1f..9abea16c4305 100644
> --- a/net/bluetooth/msft.c
> +++ b/net/bluetooth/msft.c
> @@ -106,8 +106,6 @@ struct msft_data {
> __u8 filter_enabled;
> };
>
> -static int __msft_add_monitor_pattern(struct hci_dev *hdev,
> - struct adv_monitor *monitor);
> static int __msft_remove_monitor(struct hci_dev *hdev,
> struct adv_monitor *monitor, u16 handle);
>
> @@ -164,34 +162,6 @@ static bool read_supported_features(struct hci_dev *hdev,
> return false;
> }
>
> -static void reregister_monitor(struct hci_dev *hdev, int handle)
> -{
> - struct adv_monitor *monitor;
> - struct msft_data *msft = hdev->msft_data;
> - int err;
> -
> - while (1) {
> - monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
> - if (!monitor) {
> - /* All monitors have been resumed */
> - msft->resuming = false;
> - hci_update_passive_scan(hdev);
> - return;
> - }
> -
> - msft->pending_add_handle = (u16)handle;
> - err = __msft_add_monitor_pattern(hdev, monitor);
> -
> - /* If success, we return and wait for monitor added callback */
> - if (!err)
> - return;
> -
> - /* Otherwise remove the monitor and keep registering */
> - hci_free_adv_monitor(hdev, monitor);
> - handle++;
> - }
> -}
> -
> /* is_mgmt = true matches the handle exposed to userspace via mgmt.
> * is_mgmt = false matches the handle used by the msft controller.
> * This function requires the caller holds hdev->lock
> @@ -243,14 +213,14 @@ static int msft_monitor_device_del(struct hci_dev *hdev, __u16 mgmt_handle,
> return count;
> }
>
> -static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
> - u8 status, u16 opcode,
> - struct sk_buff *skb)
> +static int msft_le_monitor_advertisement_cb(struct hci_dev *hdev, u16 opcode,
> + struct sk_buff *skb)
> {
> struct msft_rp_le_monitor_advertisement *rp;
> struct adv_monitor *monitor;
> struct msft_monitor_advertisement_handle_data *handle_data;
> struct msft_data *msft = hdev->msft_data;
> + int status = 0;
>
> hci_dev_lock(hdev);
>
> @@ -262,15 +232,16 @@ static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
> goto unlock;
> }
>
> - if (status)
> - goto unlock;
> -
> rp = (struct msft_rp_le_monitor_advertisement *)skb->data;
> if (skb->len < sizeof(*rp)) {
> status = HCI_ERROR_UNSPECIFIED;
> goto unlock;
> }
>
> + status = rp->status;
> + if (status)
> + goto unlock;
> +
> handle_data = kmalloc(sizeof(*handle_data), GFP_KERNEL);
> if (!handle_data) {
> status = HCI_ERROR_UNSPECIFIED;
> @@ -290,8 +261,7 @@ static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
>
> hci_dev_unlock(hdev);
>
> - if (!msft->resuming)
> - hci_add_adv_patterns_monitor_complete(hdev, status);
> + return status;
> }
>
> static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
> @@ -463,7 +433,7 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
> ptrdiff_t offset = 0;
> u8 pattern_count = 0;
> struct sk_buff *skb;
> - u8 status;
> + struct msft_data *msft = hdev->msft_data;
>
> if (!msft_monitor_pattern_valid(monitor))
> return -EINVAL;
> @@ -505,20 +475,40 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
> if (IS_ERR(skb))
> return PTR_ERR(skb);
>
> - status = skb->data[0];
> - skb_pull(skb, 1);
> + msft->pending_add_handle = monitor->handle;
>
> - msft_le_monitor_advertisement_cb(hdev, status, hdev->msft_opcode, skb);
> + return msft_le_monitor_advertisement_cb(hdev, hdev->msft_opcode, skb);
> +}
>
> - return status;
> +static void reregister_monitor(struct hci_dev *hdev)
> +{
> + struct adv_monitor *monitor;
> + struct msft_data *msft = hdev->msft_data;
> + int handle = 0;
> +
> + if (!msft)
> + return;
> +
> + msft->resuming = true;
> +
> + while (1) {
> + monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
> + if (!monitor)
> + break;
> +
> + msft_add_monitor_sync(hdev, monitor);
> +
> + handle++;
> + }
> +
> + /* All monitors have been reregistered */
> + msft->resuming = false;
> }
>
> /* This function requires the caller holds hci_req_sync_lock */
> int msft_resume_sync(struct hci_dev *hdev)
> {
> struct msft_data *msft = hdev->msft_data;
> - struct adv_monitor *monitor;
> - int handle = 0;
>
> if (!msft || !msft_monitor_supported(hdev))
> return 0;
> @@ -533,24 +523,12 @@ int msft_resume_sync(struct hci_dev *hdev)
>
> hci_dev_unlock(hdev);
>
> - msft->resuming = true;
> -
> - while (1) {
> - monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
> - if (!monitor)
> - break;
> -
> - msft_add_monitor_sync(hdev, monitor);
> -
> - handle++;
> - }
> -
> - /* All monitors have been resumed */
> - msft->resuming = false;
> + reregister_monitor(hdev);
>
> return 0;
> }
>
> +/* This function requires the caller holds hci_req_sync_lock */
> void msft_do_open(struct hci_dev *hdev)
> {
> struct msft_data *msft = hdev->msft_data;
> @@ -583,7 +561,7 @@ void msft_do_open(struct hci_dev *hdev)
> /* Monitors get removed on power off, so we need to explicitly
> * tell the controller to re-monitor.
> */
> - reregister_monitor(hdev, 0);
> + reregister_monitor(hdev);
> }
> }
>
> @@ -829,66 +807,7 @@ static void msft_le_set_advertisement_filter_enable_cb(struct hci_dev *hdev,
> hci_dev_unlock(hdev);
> }
>
> -/* This function requires the caller holds hdev->lock */
> -static int __msft_add_monitor_pattern(struct hci_dev *hdev,
> - struct adv_monitor *monitor)
> -{
> - struct msft_cp_le_monitor_advertisement *cp;
> - struct msft_le_monitor_advertisement_pattern_data *pattern_data;
> - struct msft_le_monitor_advertisement_pattern *pattern;
> - struct adv_pattern *entry;
> - struct hci_request req;
> - struct msft_data *msft = hdev->msft_data;
> - size_t total_size = sizeof(*cp) + sizeof(*pattern_data);
> - ptrdiff_t offset = 0;
> - u8 pattern_count = 0;
> - int err = 0;
> -
> - if (!msft_monitor_pattern_valid(monitor))
> - return -EINVAL;
> -
> - list_for_each_entry(entry, &monitor->patterns, list) {
> - pattern_count++;
> - total_size += sizeof(*pattern) + entry->length;
> - }
> -
> - cp = kmalloc(total_size, GFP_KERNEL);
> - if (!cp)
> - return -ENOMEM;
> -
> - cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT;
> - cp->rssi_high = monitor->rssi.high_threshold;
> - cp->rssi_low = monitor->rssi.low_threshold;
> - cp->rssi_low_interval = (u8)monitor->rssi.low_threshold_timeout;
> - cp->rssi_sampling_period = monitor->rssi.sampling_period;
> -
> - cp->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN;
> -
> - pattern_data = (void *)cp->data;
> - pattern_data->count = pattern_count;
> -
> - list_for_each_entry(entry, &monitor->patterns, list) {
> - pattern = (void *)(pattern_data->data + offset);
> - /* the length also includes data_type and offset */
> - pattern->length = entry->length + 2;
> - pattern->data_type = entry->ad_type;
> - pattern->start_byte = entry->offset;
> - memcpy(pattern->pattern, entry->value, entry->length);
> - offset += sizeof(*pattern) + entry->length;
> - }
> -
> - hci_req_init(&req, hdev);
> - hci_req_add(&req, hdev->msft_opcode, total_size, cp);
> - err = hci_req_run_skb(&req, msft_le_monitor_advertisement_cb);
> - kfree(cp);
> -
> - if (!err)
> - msft->pending_add_handle = monitor->handle;
> -
> - return err;
> -}
> -
> -/* This function requires the caller holds hdev->lock */
> +/* This function requires the caller holds hci_req_sync_lock */
> int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
> {
> struct msft_data *msft = hdev->msft_data;
> @@ -899,7 +818,7 @@ int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
> if (msft->resuming || msft->suspending)
> return -EBUSY;
>
> - return __msft_add_monitor_pattern(hdev, monitor);
> + return msft_add_monitor_sync(hdev, monitor);
> }
>
> /* This function requires the caller holds hdev->lock */
> --
> 2.36.1.124.g0e6072fb45-goog
>


--
Luiz Augusto von Dentz

2022-06-08 07:01:51

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH 1/2] Bluetooth: hci_sync: Refactor add Adv Monitor

Hi Manish,

On Tue, Jun 7, 2022 at 9:57 AM Manish Mandlik <[email protected]> wrote:
>
> Hi Luiz,
>
> On Thu, May 26, 2022 at 7:01 PM Manish Mandlik <[email protected]> wrote:
>>
>> Hi Luiz,
>>
>>
>> On Wed, May 25, 2022 at 5:46 PM Luiz Augusto von Dentz <[email protected]> wrote:
>>>
>>> Hi Manish,
>>>
>>> On Tue, May 24, 2022 at 1:14 PM Manish Mandlik <[email protected]> wrote:
>>> >
>>> > Make use of hci_cmd_sync_queue for adding an advertisement monitor.
>>>
>>> Im a little lost here, it seems you end up not really using
>>> hci_cmd_sync_queue are you assuming these functions are already run
>>> from a safe context?
>>
>> Not sure if I understand the question. But I am using msft_add_monitor_sync() to send a monitor to the controller which uses hci_cmd_sync_queue. It requires the caller to hold hci_req_sync_lock, which I have used at the appropriate places. Let me know if that looks correct.

It sounds like you are doing the hci_req_sync_lock from any thread
instead of using hci_cmd_sync_queue and then from its callback call
msft_add_monitor_sync, that way we guarantee only one task is
scheduling HCI traffic.

>>
>>>
>>> > Signed-off-by: Manish Mandlik <[email protected]>
>>> > Reviewed-by: Miao-chen Chou <[email protected]>
>>> > ---
>>> >
>>> > include/net/bluetooth/hci_core.h | 5 +-
>>> > net/bluetooth/hci_core.c | 47 ++++-----
>>> > net/bluetooth/mgmt.c | 121 +++++++----------------
>>> > net/bluetooth/msft.c | 161 ++++++++-----------------------
>>> > 4 files changed, 98 insertions(+), 236 deletions(-)
>>> >
>>> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
>>> > index 5a52a2018b56..59953a7a6328 100644
>>> > --- a/include/net/bluetooth/hci_core.h
>>> > +++ b/include/net/bluetooth/hci_core.h
>>> > @@ -1410,10 +1410,8 @@ bool hci_adv_instance_is_scannable(struct hci_dev *hdev, u8 instance);
>>> >
>>> > void hci_adv_monitors_clear(struct hci_dev *hdev);
>>> > void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
>>> > -int hci_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
>>> > int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
>>> > -bool hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
>>> > - int *err);
>>> > +int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor);
>>> > bool hci_remove_single_adv_monitor(struct hci_dev *hdev, u16 handle, int *err);
>>> > bool hci_remove_all_adv_monitor(struct hci_dev *hdev, int *err);
>>> > bool hci_is_adv_monitoring(struct hci_dev *hdev);
>>> > @@ -1875,7 +1873,6 @@ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
>>> > u8 instance);
>>> > void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle);
>>> > int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip);
>>> > -int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status);
>>> > int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status);
>>> > void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
>>> > bdaddr_t *bdaddr, u8 addr_type);
>>> > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
>>> > index 5abb2ca5b129..bbbbe3203130 100644
>>> > --- a/net/bluetooth/hci_core.c
>>> > +++ b/net/bluetooth/hci_core.c
>>> > @@ -1873,11 +1873,6 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
>>> > kfree(monitor);
>>> > }
>>> >
>>> > -int hci_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status)
>>> > -{
>>> > - return mgmt_add_adv_patterns_monitor_complete(hdev, status);
>>> > -}
>>> > -
>>> > int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
>>> > {
>>> > return mgmt_remove_adv_monitor_complete(hdev, status);
>>> > @@ -1885,49 +1880,49 @@ int hci_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
>>> >
>>> > /* Assigns handle to a monitor, and if offloading is supported and power is on,
>>> > * also attempts to forward the request to the controller.
>>> > - * Returns true if request is forwarded (result is pending), false otherwise.
>>> > - * This function requires the caller holds hdev->lock.
>>> > */
>>> > -bool hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor,
>>> > - int *err)
>>> > +int hci_add_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor)
>>> > {
>>> > int min, max, handle;
>>> > + int status = 0;
>>> >
>>> > - *err = 0;
>>> > + if (!monitor)
>>> > + return -EINVAL;
>>> >
>>> > - if (!monitor) {
>>> > - *err = -EINVAL;
>>> > - return false;
>>> > - }
>>> > + hci_dev_lock(hdev);
>>> >
>>> > min = HCI_MIN_ADV_MONITOR_HANDLE;
>>> > max = HCI_MIN_ADV_MONITOR_HANDLE + HCI_MAX_ADV_MONITOR_NUM_HANDLES;
>>> > handle = idr_alloc(&hdev->adv_monitors_idr, monitor, min, max,
>>> > GFP_KERNEL);
>>> > - if (handle < 0) {
>>> > - *err = handle;
>>> > - return false;
>>> > - }
>>> > +
>>> > + hci_dev_unlock(hdev);
>>> > +
>>> > + if (handle < 0)
>>> > + return handle;
>>> >
>>> > monitor->handle = handle;
>>> >
>>> > if (!hdev_is_powered(hdev))
>>> > - return false;
>>> > + return status;
>>> >
>>> > switch (hci_get_adv_monitor_offload_ext(hdev)) {
>>> > case HCI_ADV_MONITOR_EXT_NONE:
>>> > - hci_update_passive_scan(hdev);
>>> > - bt_dev_dbg(hdev, "%s add monitor status %d", hdev->name, *err);
>>> > + bt_dev_dbg(hdev, "%s add monitor %d status %d", hdev->name,
>>> > + monitor->handle, status);
>>> > /* Message was not forwarded to controller - not an error */
>>> > - return false;
>>> > + break;
>>> > +
>>> > case HCI_ADV_MONITOR_EXT_MSFT:
>>> > - *err = msft_add_monitor_pattern(hdev, monitor);
>>> > - bt_dev_dbg(hdev, "%s add monitor msft status %d", hdev->name,
>>> > - *err);
>>> > + hci_req_sync_lock(hdev);
>>> > + status = msft_add_monitor_pattern(hdev, monitor);
>>> > + hci_req_sync_unlock(hdev);
>>> > + bt_dev_dbg(hdev, "%s add monitor %d msft status %d", hdev->name,
>>> > + monitor->handle, status);
>>> > break;
>>> > }
>>> >
>>> > - return (*err == 0);
>>> > + return status;
>>> > }
>>> >
>>> > /* Attempts to tell the controller and free the monitor. If somehow the
>>> > diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
>>> > index 74937a834648..d04f90698a87 100644
>>> > --- a/net/bluetooth/mgmt.c
>>> > +++ b/net/bluetooth/mgmt.c
>>> > @@ -4653,75 +4653,21 @@ static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
>>> > return err;
>>> > }
>>> >
>>> > -int mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, u8 status)
>>> > -{
>>> > - struct mgmt_rp_add_adv_patterns_monitor rp;
>>> > - struct mgmt_pending_cmd *cmd;
>>> > - struct adv_monitor *monitor;
>>> > - int err = 0;
>>> > -
>>> > - hci_dev_lock(hdev);
>>> > -
>>> > - cmd = pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev);
>>> > - if (!cmd) {
>>> > - cmd = pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev);
>>> > - if (!cmd)
>>> > - goto done;
>>> > - }
>>> > -
>>> > - monitor = cmd->user_data;
>>> > - rp.monitor_handle = cpu_to_le16(monitor->handle);
>>> > -
>>> > - if (!status) {
>>> > - mgmt_adv_monitor_added(cmd->sk, hdev, monitor->handle);
>>> > - hdev->adv_monitors_cnt++;
>>> > - if (monitor->state == ADV_MONITOR_STATE_NOT_REGISTERED)
>>> > - monitor->state = ADV_MONITOR_STATE_REGISTERED;
>>> > - hci_update_passive_scan(hdev);
>>> > - }
>>> > -
>>> > - err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
>>> > - mgmt_status(status), &rp, sizeof(rp));
>>> > - mgmt_pending_remove(cmd);
>>> > -
>>> > -done:
>>> > - hci_dev_unlock(hdev);
>>> > - bt_dev_dbg(hdev, "add monitor %d complete, status %u",
>>> > - rp.monitor_handle, status);
>>> > -
>>> > - return err;
>>> > -}
>>> > -
>>> > static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
>>> > - struct adv_monitor *m, u8 status,
>>> > - void *data, u16 len, u16 op)
>>> > + struct adv_monitor *m, void *data,
>>> > + u16 len, u16 op)
>>> > {
>>> > struct mgmt_rp_add_adv_patterns_monitor rp;
>>> > - struct mgmt_pending_cmd *cmd;
>>> > + u8 status = MGMT_STATUS_SUCCESS;
>>> > int err;
>>> > - bool pending;
>>> > -
>>> > - hci_dev_lock(hdev);
>>> > -
>>> > - if (status)
>>> > - goto unlock;
>>> >
>>> > if (pending_find(MGMT_OP_SET_LE, hdev) ||
>>> > - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
>>> > - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) ||
>>> > pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
>>> > status = MGMT_STATUS_BUSY;
>>> > - goto unlock;
>>> > - }
>>> > -
>>> > - cmd = mgmt_pending_add(sk, op, hdev, data, len);
>>> > - if (!cmd) {
>>> > - status = MGMT_STATUS_NO_RESOURCES;
>>> > - goto unlock;
>>> > + goto done;
>>> > }
>>> >
>>> > - cmd->user_data = m;
>>> > - pending = hci_add_adv_monitor(hdev, m, &err);
>>> > + err = hci_add_adv_monitor(hdev, m);
>>> > if (err) {
>>> > if (err == -ENOSPC || err == -ENOMEM)
>>> > status = MGMT_STATUS_NO_RESOURCES;
>>> > @@ -4730,30 +4676,29 @@ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
>>> > else
>>> > status = MGMT_STATUS_FAILED;
>>> >
>>> > - mgmt_pending_remove(cmd);
>>> > - goto unlock;
>>> > + goto done;
>>> > }
>>> >
>>> > - if (!pending) {
>>> > - mgmt_pending_remove(cmd);
>>> > - rp.monitor_handle = cpu_to_le16(m->handle);
>>> > - mgmt_adv_monitor_added(sk, hdev, m->handle);
>>> > - m->state = ADV_MONITOR_STATE_REGISTERED;
>>> > - hdev->adv_monitors_cnt++;
>>> > + hci_dev_lock(hdev);
>>> >
>>> > - hci_dev_unlock(hdev);
>>> > - return mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_SUCCESS,
>>> > - &rp, sizeof(rp));
>>> > - }
>>> > + rp.monitor_handle = cpu_to_le16(m->handle);
>>> > + mgmt_adv_monitor_added(sk, hdev, m->handle);
>>> > + if (m->state == ADV_MONITOR_STATE_NOT_REGISTERED)
>>> > + m->state = ADV_MONITOR_STATE_REGISTERED;
>>> > + hdev->adv_monitors_cnt++;
>>> > + hci_update_passive_scan(hdev);
>>> >
>>> > hci_dev_unlock(hdev);
>>> >
>>> > - return 0;
>>> > +done:
>>> > + bt_dev_dbg(hdev, "add monitor %d complete, status %u", m->handle,
>>> > + status);
>>> >
>>> > -unlock:
>>> > - hci_free_adv_monitor(hdev, m);
>>> > - hci_dev_unlock(hdev);
>>> > - return mgmt_cmd_status(sk, hdev->id, op, status);
>>> > + if (status)
>>> > + return mgmt_cmd_status(sk, hdev->id, op, status);
>>> > +
>>> > + return mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_SUCCESS, &rp,
>>> > + sizeof(rp));
>>> > }
>>> >
>>> > static void parse_adv_monitor_rssi(struct adv_monitor *m,
>>> > @@ -4817,7 +4762,7 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
>>> > {
>>> > struct mgmt_cp_add_adv_patterns_monitor *cp = data;
>>> > struct adv_monitor *m = NULL;
>>> > - u8 status = MGMT_STATUS_SUCCESS;
>>> > + int status = MGMT_STATUS_SUCCESS;
>>> > size_t expected_size = sizeof(*cp);
>>> >
>>> > BT_DBG("request for %s", hdev->name);
>>> > @@ -4843,10 +4788,14 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
>>> >
>>> > parse_adv_monitor_rssi(m, NULL);
>>> > status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
>>> > + if (status)
>>> > + goto done;
>>> > +
>>> > + status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
>>> > + MGMT_OP_ADD_ADV_PATTERNS_MONITOR);
>>> >
>>> > done:
>>> > - return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
>>> > - MGMT_OP_ADD_ADV_PATTERNS_MONITOR);
>>> > + return status;
>>> > }
>>> >
>>> > static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
>>> > @@ -4854,7 +4803,7 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
>>> > {
>>> > struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = data;
>>> > struct adv_monitor *m = NULL;
>>> > - u8 status = MGMT_STATUS_SUCCESS;
>>> > + int status = MGMT_STATUS_SUCCESS;
>>> > size_t expected_size = sizeof(*cp);
>>> >
>>> > BT_DBG("request for %s", hdev->name);
>>> > @@ -4880,10 +4829,14 @@ static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
>>> >
>>> > parse_adv_monitor_rssi(m, &cp->rssi);
>>> > status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
>>> > + if (status)
>>> > + goto done;
>>> >
>>> > -done:
>>> > - return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
>>> > + status = __add_adv_patterns_monitor(sk, hdev, m, data, len,
>>> > MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI);
>>> > +
>>> > +done:
>>> > + return status;
>>> > }
>>> >
>>> > int mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, u8 status)
>>> > @@ -4933,9 +4886,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
>>> > hci_dev_lock(hdev);
>>> >
>>> > if (pending_find(MGMT_OP_SET_LE, hdev) ||
>>> > - pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) ||
>>> > - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
>>> > - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) {
>>> > + pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
>>> > status = MGMT_STATUS_BUSY;
>>> > goto unlock;
>>> > }
>>> > diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
>>> > index f43994523b1f..9abea16c4305 100644
>>> > --- a/net/bluetooth/msft.c
>>> > +++ b/net/bluetooth/msft.c
>>> > @@ -106,8 +106,6 @@ struct msft_data {
>>> > __u8 filter_enabled;
>>> > };
>>> >
>>> > -static int __msft_add_monitor_pattern(struct hci_dev *hdev,
>>> > - struct adv_monitor *monitor);
>>> > static int __msft_remove_monitor(struct hci_dev *hdev,
>>> > struct adv_monitor *monitor, u16 handle);
>>> >
>>> > @@ -164,34 +162,6 @@ static bool read_supported_features(struct hci_dev *hdev,
>>> > return false;
>>> > }
>>> >
>>> > -static void reregister_monitor(struct hci_dev *hdev, int handle)
>>> > -{
>>> > - struct adv_monitor *monitor;
>>> > - struct msft_data *msft = hdev->msft_data;
>>> > - int err;
>>> > -
>>> > - while (1) {
>>> > - monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
>>> > - if (!monitor) {
>>> > - /* All monitors have been resumed */
>>> > - msft->resuming = false;
>>> > - hci_update_passive_scan(hdev);
>>> > - return;
>>> > - }
>>> > -
>>> > - msft->pending_add_handle = (u16)handle;
>>> > - err = __msft_add_monitor_pattern(hdev, monitor);
>>> > -
>>> > - /* If success, we return and wait for monitor added callback */
>>> > - if (!err)
>>> > - return;
>>> > -
>>> > - /* Otherwise remove the monitor and keep registering */
>>> > - hci_free_adv_monitor(hdev, monitor);
>>> > - handle++;
>>> > - }
>>> > -}
>>> > -
>>> > /* is_mgmt = true matches the handle exposed to userspace via mgmt.
>>> > * is_mgmt = false matches the handle used by the msft controller.
>>> > * This function requires the caller holds hdev->lock
>>> > @@ -243,14 +213,14 @@ static int msft_monitor_device_del(struct hci_dev *hdev, __u16 mgmt_handle,
>>> > return count;
>>> > }
>>> >
>>> > -static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
>>> > - u8 status, u16 opcode,
>>> > - struct sk_buff *skb)
>>> > +static int msft_le_monitor_advertisement_cb(struct hci_dev *hdev, u16 opcode,
>>> > + struct sk_buff *skb)
>>> > {
>>> > struct msft_rp_le_monitor_advertisement *rp;
>>> > struct adv_monitor *monitor;
>>> > struct msft_monitor_advertisement_handle_data *handle_data;
>>> > struct msft_data *msft = hdev->msft_data;
>>> > + int status = 0;
>>> >
>>> > hci_dev_lock(hdev);
>>> >
>>> > @@ -262,15 +232,16 @@ static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
>>> > goto unlock;
>>> > }
>>> >
>>> > - if (status)
>>> > - goto unlock;
>>> > -
>>> > rp = (struct msft_rp_le_monitor_advertisement *)skb->data;
>>> > if (skb->len < sizeof(*rp)) {
>>> > status = HCI_ERROR_UNSPECIFIED;
>>> > goto unlock;
>>> > }
>>> >
>>> > + status = rp->status;
>>> > + if (status)
>>> > + goto unlock;
>>> > +
>>> > handle_data = kmalloc(sizeof(*handle_data), GFP_KERNEL);
>>> > if (!handle_data) {
>>> > status = HCI_ERROR_UNSPECIFIED;
>>> > @@ -290,8 +261,7 @@ static void msft_le_monitor_advertisement_cb(struct hci_dev *hdev,
>>> >
>>> > hci_dev_unlock(hdev);
>>> >
>>> > - if (!msft->resuming)
>>> > - hci_add_adv_patterns_monitor_complete(hdev, status);
>>> > + return status;
>>> > }
>>> >
>>> > static void msft_le_cancel_monitor_advertisement_cb(struct hci_dev *hdev,
>>> > @@ -463,7 +433,7 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
>>> > ptrdiff_t offset = 0;
>>> > u8 pattern_count = 0;
>>> > struct sk_buff *skb;
>>> > - u8 status;
>>> > + struct msft_data *msft = hdev->msft_data;
>>> >
>>> > if (!msft_monitor_pattern_valid(monitor))
>>> > return -EINVAL;
>>> > @@ -505,20 +475,40 @@ static int msft_add_monitor_sync(struct hci_dev *hdev,
>>> > if (IS_ERR(skb))
>>> > return PTR_ERR(skb);
>>> >
>>> > - status = skb->data[0];
>>> > - skb_pull(skb, 1);
>>> > + msft->pending_add_handle = monitor->handle;
>>> >
>>> > - msft_le_monitor_advertisement_cb(hdev, status, hdev->msft_opcode, skb);
>>> > + return msft_le_monitor_advertisement_cb(hdev, hdev->msft_opcode, skb);
>>> > +}
>>> >
>>> > - return status;
>>> > +static void reregister_monitor(struct hci_dev *hdev)
>>> > +{
>>> > + struct adv_monitor *monitor;
>>> > + struct msft_data *msft = hdev->msft_data;
>>> > + int handle = 0;
>>> > +
>>> > + if (!msft)
>>> > + return;
>>> > +
>>> > + msft->resuming = true;
>>> > +
>>> > + while (1) {
>>> > + monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
>>> > + if (!monitor)
>>> > + break;
>>> > +
>>> > + msft_add_monitor_sync(hdev, monitor);
>>> > +
>>> > + handle++;
>>> > + }
>>> > +
>>> > + /* All monitors have been reregistered */
>>> > + msft->resuming = false;
>>> > }
>>> >
>>> > /* This function requires the caller holds hci_req_sync_lock */
>>> > int msft_resume_sync(struct hci_dev *hdev)
>>> > {
>>> > struct msft_data *msft = hdev->msft_data;
>>> > - struct adv_monitor *monitor;
>>> > - int handle = 0;
>>> >
>>> > if (!msft || !msft_monitor_supported(hdev))
>>> > return 0;
>>> > @@ -533,24 +523,12 @@ int msft_resume_sync(struct hci_dev *hdev)
>>> >
>>> > hci_dev_unlock(hdev);
>>> >
>>> > - msft->resuming = true;
>>> > -
>>> > - while (1) {
>>> > - monitor = idr_get_next(&hdev->adv_monitors_idr, &handle);
>>> > - if (!monitor)
>>> > - break;
>>> > -
>>> > - msft_add_monitor_sync(hdev, monitor);
>>> > -
>>> > - handle++;
>>> > - }
>>> > -
>>> > - /* All monitors have been resumed */
>>> > - msft->resuming = false;
>>> > + reregister_monitor(hdev);
>>> >
>>> > return 0;
>>> > }
>>> >
>>> > +/* This function requires the caller holds hci_req_sync_lock */
>>> > void msft_do_open(struct hci_dev *hdev)
>>> > {
>>> > struct msft_data *msft = hdev->msft_data;
>>> > @@ -583,7 +561,7 @@ void msft_do_open(struct hci_dev *hdev)
>>> > /* Monitors get removed on power off, so we need to explicitly
>>> > * tell the controller to re-monitor.
>>> > */
>>> > - reregister_monitor(hdev, 0);
>>> > + reregister_monitor(hdev);
>>> > }
>>> > }
>>> >
>>> > @@ -829,66 +807,7 @@ static void msft_le_set_advertisement_filter_enable_cb(struct hci_dev *hdev,
>>> > hci_dev_unlock(hdev);
>>> > }
>>> >
>>> > -/* This function requires the caller holds hdev->lock */
>>> > -static int __msft_add_monitor_pattern(struct hci_dev *hdev,
>>> > - struct adv_monitor *monitor)
>>> > -{
>>> > - struct msft_cp_le_monitor_advertisement *cp;
>>> > - struct msft_le_monitor_advertisement_pattern_data *pattern_data;
>>> > - struct msft_le_monitor_advertisement_pattern *pattern;
>>> > - struct adv_pattern *entry;
>>> > - struct hci_request req;
>>> > - struct msft_data *msft = hdev->msft_data;
>>> > - size_t total_size = sizeof(*cp) + sizeof(*pattern_data);
>>> > - ptrdiff_t offset = 0;
>>> > - u8 pattern_count = 0;
>>> > - int err = 0;
>>> > -
>>> > - if (!msft_monitor_pattern_valid(monitor))
>>> > - return -EINVAL;
>>> > -
>>> > - list_for_each_entry(entry, &monitor->patterns, list) {
>>> > - pattern_count++;
>>> > - total_size += sizeof(*pattern) + entry->length;
>>> > - }
>>> > -
>>> > - cp = kmalloc(total_size, GFP_KERNEL);
>>> > - if (!cp)
>>> > - return -ENOMEM;
>>> > -
>>> > - cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT;
>>> > - cp->rssi_high = monitor->rssi.high_threshold;
>>> > - cp->rssi_low = monitor->rssi.low_threshold;
>>> > - cp->rssi_low_interval = (u8)monitor->rssi.low_threshold_timeout;
>>> > - cp->rssi_sampling_period = monitor->rssi.sampling_period;
>>> > -
>>> > - cp->cond_type = MSFT_MONITOR_ADVERTISEMENT_TYPE_PATTERN;
>>> > -
>>> > - pattern_data = (void *)cp->data;
>>> > - pattern_data->count = pattern_count;
>>> > -
>>> > - list_for_each_entry(entry, &monitor->patterns, list) {
>>> > - pattern = (void *)(pattern_data->data + offset);
>>> > - /* the length also includes data_type and offset */
>>> > - pattern->length = entry->length + 2;
>>> > - pattern->data_type = entry->ad_type;
>>> > - pattern->start_byte = entry->offset;
>>> > - memcpy(pattern->pattern, entry->value, entry->length);
>>> > - offset += sizeof(*pattern) + entry->length;
>>> > - }
>>> > -
>>> > - hci_req_init(&req, hdev);
>>> > - hci_req_add(&req, hdev->msft_opcode, total_size, cp);
>>> > - err = hci_req_run_skb(&req, msft_le_monitor_advertisement_cb);
>>> > - kfree(cp);
>>> > -
>>> > - if (!err)
>>> > - msft->pending_add_handle = monitor->handle;
>>> > -
>>> > - return err;
>>> > -}
>>> > -
>>> > -/* This function requires the caller holds hdev->lock */
>>> > +/* This function requires the caller holds hci_req_sync_lock */
>>> > int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
>>> > {
>>> > struct msft_data *msft = hdev->msft_data;
>>> > @@ -899,7 +818,7 @@ int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor)
>>> > if (msft->resuming || msft->suspending)
>>> > return -EBUSY;
>>> >
>>> > - return __msft_add_monitor_pattern(hdev, monitor);
>>> > + return msft_add_monitor_sync(hdev, monitor);
>>> > }
>>> >
>>> > /* This function requires the caller holds hdev->lock */
>>> > --
>>> > 2.36.1.124.g0e6072fb45-goog
>>> >
>>>
>>>
>>> --
>>> Luiz Augusto von Dentz
>>
>>
>> Regards,
>> Manish.
>
>
> Friendly ping to review this..
>
> Regards,
> Manish.



--
Luiz Augusto von Dentz