Skip to content

Commit

Permalink
Bluetooth: hci_sync: Add helper functions to manipulate cmd_sync queue
Browse files Browse the repository at this point in the history
This adds functions to queue, dequeue and lookup into the cmd_sync
list.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Luiz Augusto von Dentz committed Mar 6, 2024
1 parent 5f641f0 commit 505ea2b
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 8 deletions.
12 changes: 12 additions & 0 deletions include/net/bluetooth/hci_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy);
int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy);
struct hci_cmd_sync_work_entry *
hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy);
int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy);
void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
struct hci_cmd_sync_work_entry *entry);
bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy);
bool hci_cmd_sync_dequeue_once(struct hci_dev *hdev,
hci_cmd_sync_work_func_t func, void *data,
hci_cmd_sync_work_destroy_t destroy);

int hci_update_eir_sync(struct hci_dev *hdev);
int hci_update_class_sync(struct hci_dev *hdev);
Expand Down
132 changes: 124 additions & 8 deletions net/bluetooth/hci_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,17 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
}

static void _hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
struct hci_cmd_sync_work_entry *entry,
int err)
{
if (entry->destroy)
entry->destroy(hdev, entry->data, err);

list_del(&entry->list);
kfree(entry);
}

void hci_cmd_sync_clear(struct hci_dev *hdev)
{
struct hci_cmd_sync_work_entry *entry, *tmp;
Expand All @@ -574,13 +585,8 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
cancel_work_sync(&hdev->reenable_adv_work);

mutex_lock(&hdev->cmd_sync_work_lock);
list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
if (entry->destroy)
entry->destroy(hdev, entry->data, -ECANCELED);

list_del(&entry->list);
kfree(entry);
}
list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list)
_hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
mutex_unlock(&hdev->cmd_sync_work_lock);
}

Expand Down Expand Up @@ -669,6 +675,115 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
}
EXPORT_SYMBOL(hci_cmd_sync_queue);

static struct hci_cmd_sync_work_entry *
_hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
struct hci_cmd_sync_work_entry *entry, *tmp;

list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
if (func && entry->func != func)
continue;

if (data && entry->data != data)
continue;

if (destroy && entry->destroy != destroy)
continue;

return entry;
}

return NULL;
}

/* Queue HCI command entry once:
*
* - Lookup if an entry already exist and only if it doesn't creates a new entry
* and queue it.
*/
int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy))
return 0;

return hci_cmd_sync_queue(hdev, func, data, destroy);
}
EXPORT_SYMBOL(hci_cmd_sync_queue_once);

/* Lookup HCI command entry:
*
* - Return first entry that matches by function callback or data or
* destroy callback.
*/
struct hci_cmd_sync_work_entry *
hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
struct hci_cmd_sync_work_entry *entry;

mutex_lock(&hdev->cmd_sync_work_lock);
entry = _hci_cmd_sync_lookup_entry(hdev, func, data, destroy);
mutex_unlock(&hdev->cmd_sync_work_lock);

return entry;
}
EXPORT_SYMBOL(hci_cmd_sync_lookup_entry);

/* Cancel HCI command entry */
void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
struct hci_cmd_sync_work_entry *entry)
{
mutex_lock(&hdev->cmd_sync_work_lock);
_hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
mutex_unlock(&hdev->cmd_sync_work_lock);
}
EXPORT_SYMBOL(hci_cmd_sync_cancel_entry);

/* Dequeue one HCI command entry:
*
* - Lookup and cancel first entry that matches.
*/
bool hci_cmd_sync_dequeue_once(struct hci_dev *hdev,
hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
struct hci_cmd_sync_work_entry *entry;

entry = hci_cmd_sync_lookup_entry(hdev, func, data, destroy);
if (!entry)
return false;

hci_cmd_sync_cancel_entry(hdev, entry);

return true;
}
EXPORT_SYMBOL(hci_cmd_sync_dequeue_once);

/* Dequeue HCI command entry:
*
* - Lookup and cancel any entry that matches by function callback or data or
* destroy callback.
*/
bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
void *data, hci_cmd_sync_work_destroy_t destroy)
{
struct hci_cmd_sync_work_entry *entry;
bool ret = false;

mutex_lock(&hdev->cmd_sync_work_lock);
while ((entry = _hci_cmd_sync_lookup_entry(hdev, func, data,
destroy))) {
_hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
ret = true;
}
mutex_unlock(&hdev->cmd_sync_work_lock);

return ret;
}
EXPORT_SYMBOL(hci_cmd_sync_dequeue);

int hci_update_eir_sync(struct hci_dev *hdev)
{
struct hci_cp_write_eir cp;
Expand Down Expand Up @@ -2881,7 +2996,8 @@ int hci_update_passive_scan(struct hci_dev *hdev)
hci_dev_test_flag(hdev, HCI_UNREGISTER))
return 0;

return hci_cmd_sync_queue(hdev, update_passive_scan_sync, NULL, NULL);
return hci_cmd_sync_queue_once(hdev, update_passive_scan_sync, NULL,
NULL);
}

int hci_write_sc_support_sync(struct hci_dev *hdev, u8 val)
Expand Down

0 comments on commit 505ea2b

Please sign in to comment.