Skip to content

Commit

Permalink
Bluetooth: MGMT: Fix Add Device to responding before completing
Browse files Browse the repository at this point in the history
Add Device with LE type requires updating resolving/accept list which
requires quite a number of commands to complete and each of them may
fail, so instead of pretending it would always work this checks the
return of hci_update_passive_scan_sync which indicates if everything
worked as intended.

Fixes: e8907f7 ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Luiz Augusto von Dentz committed Jan 8, 2025
1 parent c2994b0 commit a182d9c
Showing 1 changed file with 36 additions and 2 deletions.
38 changes: 36 additions & 2 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7655,6 +7655,24 @@ static void device_added(struct sock *sk, struct hci_dev *hdev,
mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
}

static void add_device_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_device *cp = cmd->param;

if (!err) {
device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type,
cp->action);
device_flags_changed(NULL, hdev, &cp->addr.bdaddr,
cp->addr.type, hdev->conn_flags,
PTR_UINT(cmd->user_data));
}

mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE,
mgmt_status(err), &cp->addr, sizeof(cp->addr));
mgmt_pending_free(cmd);
}

static int add_device_sync(struct hci_dev *hdev, void *data)
{
return hci_update_passive_scan_sync(hdev);
Expand All @@ -7663,6 +7681,7 @@ static int add_device_sync(struct hci_dev *hdev, void *data)
static int add_device(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_pending_cmd *cmd;
struct mgmt_cp_add_device *cp = data;
u8 auto_conn, addr_type;
struct hci_conn_params *params;
Expand Down Expand Up @@ -7743,9 +7762,24 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
current_flags = params->flags;
}

err = hci_cmd_sync_queue(hdev, add_device_sync, NULL, NULL);
if (err < 0)
cmd = mgmt_pending_new(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}

cmd->user_data = UINT_PTR(current_flags);

err = hci_cmd_sync_queue(hdev, add_device_sync, cmd,
add_device_complete);
if (err < 0) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_FAILED, &cp->addr,
sizeof(cp->addr));
mgmt_pending_free(cmd);
}

goto unlock;

added:
device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
Expand Down

0 comments on commit a182d9c

Please sign in to comment.