aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-03-15 18:06:54 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-03-18 13:02:00 -0400
commit0cab9c80ffc5006bf0f6922d805a7540e4949877 (patch)
treeb4bdd16acdf3ee8b9f2d56e36084f2536ecb2114 /net/bluetooth
parent229ab39caf8c1321527e408725c1350f7c9aaa84 (diff)
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: Johan Hedberg <johan.hedberg@intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/mgmt.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index bf17a62a1bef..367837d0da2d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1336,6 +1336,29 @@ unlock:
1336 return err; 1336 return err;
1337} 1337}
1338 1338
1339/* This is a helper function to test for pending mgmt commands that can
1340 * cause CoD or EIR HCI commands. We can only allow one such pending
1341 * mgmt command at a time since otherwise we cannot easily track what
1342 * the current values are, will be, and based on that calculate if a new
1343 * HCI command needs to be sent and if yes with what value.
1344 */
1345static bool pending_eir_or_class(struct hci_dev *hdev)
1346{
1347 struct pending_cmd *cmd;
1348
1349 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
1350 switch (cmd->opcode) {
1351 case MGMT_OP_ADD_UUID:
1352 case MGMT_OP_REMOVE_UUID:
1353 case MGMT_OP_SET_DEV_CLASS:
1354 case MGMT_OP_SET_POWERED:
1355 return true;
1356 }
1357 }
1358
1359 return false;
1360}
1361
1339static const u8 bluetooth_base_uuid[] = { 1362static const u8 bluetooth_base_uuid[] = {
1340 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 1363 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
1341 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1364 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)
1367 1390
1368 hci_dev_lock(hdev); 1391 hci_dev_lock(hdev);
1369 1392
1370 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { 1393 if (pending_eir_or_class(hdev)) {
1371 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID, 1394 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
1372 MGMT_STATUS_BUSY); 1395 MGMT_STATUS_BUSY);
1373 goto failed; 1396 goto failed;
@@ -1439,7 +1462,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
1439 1462
1440 hci_dev_lock(hdev); 1463 hci_dev_lock(hdev);
1441 1464
1442 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) { 1465 if (pending_eir_or_class(hdev)) {
1443 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID, 1466 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
1444 MGMT_STATUS_BUSY); 1467 MGMT_STATUS_BUSY);
1445 goto unlock; 1468 goto unlock;
@@ -1515,15 +1538,19 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
1515 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 1538 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
1516 MGMT_STATUS_NOT_SUPPORTED); 1539 MGMT_STATUS_NOT_SUPPORTED);
1517 1540
1518 if (test_bit(HCI_PENDING_CLASS, &hdev->dev_flags)) 1541 hci_dev_lock(hdev);
1519 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
1520 MGMT_STATUS_BUSY);
1521 1542
1522 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) 1543 if (pending_eir_or_class(hdev)) {
1523 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 1544 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
1524 MGMT_STATUS_INVALID_PARAMS); 1545 MGMT_STATUS_BUSY);
1546 goto unlock;
1547 }
1525 1548
1526 hci_dev_lock(hdev); 1549 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
1550 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
1551 MGMT_STATUS_INVALID_PARAMS);
1552 goto unlock;
1553 }
1527 1554
1528 hdev->major_class = cp->major; 1555 hdev->major_class = cp->major;
1529 hdev->minor_class = cp->minor; 1556 hdev->minor_class = cp->minor;