Commit 2e77551c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'for-net-2022-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - Fix regression with scanning not working in some systems.

* tag 'for-net-2022-03-01' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: Fix not checking MGMT cmd pending queue
====================

Link: https://lore.kernel.org/r/20220302004330.125536-1-luiz.dentz@gmail.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4761df52 275f3f64
...@@ -1218,7 +1218,13 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip) ...@@ -1218,7 +1218,13 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip)
static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err) static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
{ {
struct mgmt_pending_cmd *cmd = data; struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param; struct mgmt_mode *cp;
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
return;
cp = cmd->param;
bt_dev_dbg(hdev, "err %d", err); bt_dev_dbg(hdev, "err %d", err);
...@@ -1242,7 +1248,7 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err) ...@@ -1242,7 +1248,7 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
mgmt_status(err)); mgmt_status(err));
} }
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
} }
static int set_powered_sync(struct hci_dev *hdev, void *data) static int set_powered_sync(struct hci_dev *hdev, void *data)
...@@ -1281,7 +1287,7 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1281,7 +1287,7 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed; goto failed;
} }
cmd = mgmt_pending_new(sk, MGMT_OP_SET_POWERED, hdev, data, len); cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
if (!cmd) { if (!cmd) {
err = -ENOMEM; err = -ENOMEM;
goto failed; goto failed;
...@@ -1290,6 +1296,9 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1290,6 +1296,9 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
err = hci_cmd_sync_queue(hdev, set_powered_sync, cmd, err = hci_cmd_sync_queue(hdev, set_powered_sync, cmd,
mgmt_set_powered_complete); mgmt_set_powered_complete);
if (err < 0)
mgmt_pending_remove(cmd);
failed: failed:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return err; return err;
...@@ -1383,6 +1392,10 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, ...@@ -1383,6 +1392,10 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
bt_dev_dbg(hdev, "err %d", err); bt_dev_dbg(hdev, "err %d", err);
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (err) { if (err) {
...@@ -1402,7 +1415,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, ...@@ -1402,7 +1415,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
new_settings(hdev, cmd->sk); new_settings(hdev, cmd->sk);
done: done:
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -1511,7 +1524,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1511,7 +1524,7 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed; goto failed;
} }
cmd = mgmt_pending_new(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len); cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
if (!cmd) { if (!cmd) {
err = -ENOMEM; err = -ENOMEM;
goto failed; goto failed;
...@@ -1538,6 +1551,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1538,6 +1551,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
err = hci_cmd_sync_queue(hdev, set_discoverable_sync, cmd, err = hci_cmd_sync_queue(hdev, set_discoverable_sync, cmd,
mgmt_set_discoverable_complete); mgmt_set_discoverable_complete);
if (err < 0)
mgmt_pending_remove(cmd);
failed: failed:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return err; return err;
...@@ -1550,6 +1566,10 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, ...@@ -1550,6 +1566,10 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
bt_dev_dbg(hdev, "err %d", err); bt_dev_dbg(hdev, "err %d", err);
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (err) { if (err) {
...@@ -1562,7 +1582,9 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, ...@@ -1562,7 +1582,9 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
new_settings(hdev, cmd->sk); new_settings(hdev, cmd->sk);
done: done:
mgmt_pending_free(cmd); if (cmd)
mgmt_pending_remove(cmd);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -1634,7 +1656,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1634,7 +1656,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed; goto failed;
} }
cmd = mgmt_pending_new(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len); cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
if (!cmd) { if (!cmd) {
err = -ENOMEM; err = -ENOMEM;
goto failed; goto failed;
...@@ -1654,6 +1676,9 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1654,6 +1676,9 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
err = hci_cmd_sync_queue(hdev, set_connectable_sync, cmd, err = hci_cmd_sync_queue(hdev, set_connectable_sync, cmd,
mgmt_set_connectable_complete); mgmt_set_connectable_complete);
if (err < 0)
mgmt_pending_remove(cmd);
failed: failed:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return err; return err;
...@@ -1774,6 +1799,10 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) ...@@ -1774,6 +1799,10 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
u8 enable = cp->val; u8 enable = cp->val;
bool changed; bool changed;
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_SSP, hdev))
return;
if (err) { if (err) {
u8 mgmt_err = mgmt_status(err); u8 mgmt_err = mgmt_status(err);
...@@ -3321,6 +3350,9 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err) ...@@ -3321,6 +3350,9 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
bt_dev_dbg(hdev, "err %d", err); bt_dev_dbg(hdev, "err %d", err);
if (cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
return;
if (status) { if (status) {
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
status); status);
...@@ -3493,6 +3525,9 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err) ...@@ -3493,6 +3525,9 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
struct sk_buff *skb = cmd->skb; struct sk_buff *skb = cmd->skb;
u8 status = mgmt_status(err); u8 status = mgmt_status(err);
if (cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
return;
if (!status) { if (!status) {
if (!skb) if (!skb)
status = MGMT_STATUS_FAILED; status = MGMT_STATUS_FAILED;
...@@ -3759,13 +3794,6 @@ static int set_wideband_speech(struct sock *sk, struct hci_dev *hdev, ...@@ -3759,13 +3794,6 @@ static int set_wideband_speech(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (pending_find(MGMT_OP_SET_WIDEBAND_SPEECH, hdev)) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_WIDEBAND_SPEECH,
MGMT_STATUS_BUSY);
goto unlock;
}
if (hdev_is_powered(hdev) && if (hdev_is_powered(hdev) &&
!!cp->val != hci_dev_test_flag(hdev, !!cp->val != hci_dev_test_flag(hdev,
HCI_WIDEBAND_SPEECH_ENABLED)) { HCI_WIDEBAND_SPEECH_ENABLED)) {
...@@ -5036,12 +5064,6 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, ...@@ -5036,12 +5064,6 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
goto unlock; goto unlock;
} }
if (pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_BUSY);
goto unlock;
}
cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0); cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
if (!cmd) if (!cmd)
err = -ENOMEM; err = -ENOMEM;
...@@ -5261,11 +5283,16 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err) ...@@ -5261,11 +5283,16 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
{ {
struct mgmt_pending_cmd *cmd = data; struct mgmt_pending_cmd *cmd = data;
if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) &&
cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) &&
cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
return;
bt_dev_dbg(hdev, "err %d", err); bt_dev_dbg(hdev, "err %d", err);
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
cmd->param, 1); cmd->param, 1);
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED: hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED:
DISCOVERY_FINDING); DISCOVERY_FINDING);
...@@ -5327,7 +5354,7 @@ static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev, ...@@ -5327,7 +5354,7 @@ static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
else else
hdev->discovery.limited = false; hdev->discovery.limited = false;
cmd = mgmt_pending_new(sk, op, hdev, data, len); cmd = mgmt_pending_add(sk, op, hdev, data, len);
if (!cmd) { if (!cmd) {
err = -ENOMEM; err = -ENOMEM;
goto failed; goto failed;
...@@ -5336,7 +5363,7 @@ static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev, ...@@ -5336,7 +5363,7 @@ static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
err = hci_cmd_sync_queue(hdev, start_discovery_sync, cmd, err = hci_cmd_sync_queue(hdev, start_discovery_sync, cmd,
start_discovery_complete); start_discovery_complete);
if (err < 0) { if (err < 0) {
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -5430,7 +5457,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -5430,7 +5457,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
goto failed; goto failed;
} }
cmd = mgmt_pending_new(sk, MGMT_OP_START_SERVICE_DISCOVERY, cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
hdev, data, len); hdev, data, len);
if (!cmd) { if (!cmd) {
err = -ENOMEM; err = -ENOMEM;
...@@ -5463,7 +5490,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -5463,7 +5490,7 @@ static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
err = hci_cmd_sync_queue(hdev, start_discovery_sync, cmd, err = hci_cmd_sync_queue(hdev, start_discovery_sync, cmd,
start_discovery_complete); start_discovery_complete);
if (err < 0) { if (err < 0) {
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -5495,11 +5522,14 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err) ...@@ -5495,11 +5522,14 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
{ {
struct mgmt_pending_cmd *cmd = data; struct mgmt_pending_cmd *cmd = data;
if (cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
return;
bt_dev_dbg(hdev, "err %d", err); bt_dev_dbg(hdev, "err %d", err);
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
cmd->param, 1); cmd->param, 1);
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
if (!err) if (!err)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED); hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
...@@ -5535,7 +5565,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5535,7 +5565,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
goto unlock; goto unlock;
} }
cmd = mgmt_pending_new(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len); cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
if (!cmd) { if (!cmd) {
err = -ENOMEM; err = -ENOMEM;
goto unlock; goto unlock;
...@@ -5544,7 +5574,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -5544,7 +5574,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
err = hci_cmd_sync_queue(hdev, stop_discovery_sync, cmd, err = hci_cmd_sync_queue(hdev, stop_discovery_sync, cmd,
stop_discovery_complete); stop_discovery_complete);
if (err < 0) { if (err < 0) {
mgmt_pending_free(cmd); mgmt_pending_remove(cmd);
goto unlock; goto unlock;
} }
...@@ -7474,6 +7504,9 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data, ...@@ -7474,6 +7504,9 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
u8 status = mgmt_status(err); u8 status = mgmt_status(err);
u16 eir_len; u16 eir_len;
if (cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
return;
if (!status) { if (!status) {
if (!skb) if (!skb)
status = MGMT_STATUS_FAILED; status = MGMT_STATUS_FAILED;
...@@ -7969,11 +8002,7 @@ static bool requested_adv_flags_are_valid(struct hci_dev *hdev, u32 adv_flags) ...@@ -7969,11 +8002,7 @@ static bool requested_adv_flags_are_valid(struct hci_dev *hdev, u32 adv_flags)
static bool adv_busy(struct hci_dev *hdev) static bool adv_busy(struct hci_dev *hdev)
{ {
return (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) || return pending_find(MGMT_OP_SET_LE, hdev);
pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
pending_find(MGMT_OP_SET_LE, hdev) ||
pending_find(MGMT_OP_ADD_EXT_ADV_PARAMS, hdev) ||
pending_find(MGMT_OP_ADD_EXT_ADV_DATA, hdev));
} }
static void add_adv_complete(struct hci_dev *hdev, struct sock *sk, u8 instance, static void add_adv_complete(struct hci_dev *hdev, struct sock *sk, u8 instance,
...@@ -8563,9 +8592,7 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev, ...@@ -8563,9 +8592,7 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
goto unlock; goto unlock;
} }
if (pending_find(MGMT_OP_ADD_ADVERTISING, hdev) || if (pending_find(MGMT_OP_SET_LE, hdev)) {
pending_find(MGMT_OP_REMOVE_ADVERTISING, hdev) ||
pending_find(MGMT_OP_SET_LE, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING, err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY);
goto unlock; goto unlock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment