static int hci_update_event_filter_sync(struct hci_dev *hdev)
{
struct bdaddr_list_with_flags *b;
+ bdaddr_t *accept_list;
+ size_t i, num_entries = 0;
u8 scan = SCAN_DISABLED;
bool scanning = test_bit(HCI_PSCAN, &hdev->flags);
int err;
/* Always clear event filter when starting */
hci_clear_event_filter_sync(hdev);
- list_for_each_entry(b, &hdev->accept_list, list) {
- if (!(b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP))
- continue;
+ hci_dev_lock(hdev);
+
+ list_for_each_entry(b, &hdev->accept_list, list)
+ if (b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP)
+ num_entries++;
- bt_dev_dbg(hdev, "Adding event filters for %pMR", &b->bdaddr);
+ if (!num_entries) {
+ hci_dev_unlock(hdev);
+ goto update_scan;
+ }
- err = hci_set_event_filter_sync(hdev, HCI_FLT_CONN_SETUP,
- HCI_CONN_SETUP_ALLOW_BDADDR,
- &b->bdaddr,
- HCI_CONN_SETUP_AUTO_ON);
+ accept_list = kmalloc_array(num_entries, sizeof(*accept_list),
+ GFP_KERNEL);
+ if (!accept_list) {
+ hci_dev_unlock(hdev);
+ return -ENOMEM;
+ }
+
+ i = 0;
+ list_for_each_entry(b, &hdev->accept_list, list)
+ if (b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP)
+ bacpy(&accept_list[i++], &b->bdaddr);
+
+ hci_dev_unlock(hdev);
+
+ for (i = 0; i < num_entries; i++) {
+ bt_dev_dbg(hdev, "Adding event filters for %pMR",
+ &accept_list[i]);
+
+ err = hci_set_event_filter_sync(hdev, HCI_FLT_CONN_SETUP,
+ HCI_CONN_SETUP_ALLOW_BDADDR,
+ &accept_list[i],
+ HCI_CONN_SETUP_AUTO_ON);
if (err)
bt_dev_err(hdev, "Failed to set event filter for %pMR",
- &b->bdaddr);
+ &accept_list[i]);
else
scan = SCAN_PAGE;
}
+ kfree(accept_list);
+
+update_scan:
if (scan && !scanning)
hci_write_scan_enable_sync(hdev, scan);
else if (!scan && scanning)