Commit 0cab9c80 authored by Johan Hedberg's avatar Johan Hedberg Committed by Gustavo Padovan

Bluetooth: Fix busy condition testing for EIR and class updates

The add/remove_uuid and set_dev_class mgmt commands can trigger both EIR
and class HCI commands, so testing just for a pending class command is
enough. The simplest way to monitor conflicts that should trigger "busy"
error returns is to check for any pending mgmt command that can trigger
these HCI commands. This patch adds a helper function for this
(pending_eir_or_class) and uses it instead of the old HCI_PENDING_CLASS
flag to test for busy conditions.
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
parent 229ab39c
......@@ -1336,6 +1336,29 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
return err;
}
/* This is a helper function to test for pending mgmt commands that can
* cause CoD or EIR HCI commands. We can only allow one such pending
* mgmt command at a time since otherwise we cannot easily track what
* the current values are, will be, and based on that calculate if a new
* HCI command needs to be sent and if yes with what value.
*/
static bool pending_eir_or_class(struct hci_dev *hdev)
{
struct pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
switch (cmd->opcode) {
case MGMT_OP_ADD_UUID:
case MGMT_OP_REMOVE_UUID:
case MGMT_OP_SET_DEV_CLASS:
case MGMT_OP_SET_POWERED:
return true;
}
}
return false;
}
static const u8 bluetooth_base_uuid[] = {
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
......@@ -1367,7 +1390,7 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_dev_lock(hdev);
if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
if (pending_eir_or_class(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
MGMT_STATUS_BUSY);
goto failed;
......@@ -1439,7 +1462,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) {
if (pending_eir_or_class(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
MGMT_STATUS_BUSY);
goto unlock;
......@@ -1515,15 +1538,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_NOT_SUPPORTED);
if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_BUSY);
hci_dev_lock(hdev);
if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0)
return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_INVALID_PARAMS);
if (pending_eir_or_class(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_BUSY);
goto unlock;
}
hci_dev_lock(hdev);
if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
hdev->major_class = cp->major;
hdev->minor_class = cp->minor;
......
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