aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-12-19 15:26:02 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-12-19 16:06:37 -0500
commit5a154e6f71dfd41c7b5cf96a13c83fca91e7df7f (patch)
tree26ae6a6727b3750b5960134b21b7f6a9e26fda6a /net
parent51ef3ebe7bcc212f4cbbeac48bda26ee90a6edbe (diff)
Bluetooth: Fix Add Device to wait for HCI before sending cmd_complete
This patch updates the Add Device mgmt command handler to use a hci_request to wait for HCI command completion before notifying user space of the mgmt command completion. To do this we need to add an extra hci_request parameter to the hci_conn_params_set function. Since this function has no other users besides mgmt.c it's moved there as a static function. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/hci_core.c58
-rw-r--r--net/bluetooth/mgmt.c119
2 files changed, 109 insertions, 68 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index def6fba01b45..ee2096c7ec2c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -3660,23 +3660,6 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
3660 return NULL; 3660 return NULL;
3661} 3661}
3662 3662
3663static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
3664{
3665 struct hci_conn *conn;
3666
3667 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
3668 if (!conn)
3669 return false;
3670
3671 if (conn->dst_type != type)
3672 return false;
3673
3674 if (conn->state != BT_CONNECTED)
3675 return false;
3676
3677 return true;
3678}
3679
3680/* This function requires the caller holds hdev->lock */ 3663/* This function requires the caller holds hdev->lock */
3681struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list, 3664struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
3682 bdaddr_t *addr, u8 addr_type) 3665 bdaddr_t *addr, u8 addr_type)
@@ -3732,47 +3715,6 @@ struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
3732 return params; 3715 return params;
3733} 3716}
3734 3717
3735/* This function requires the caller holds hdev->lock */
3736int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type,
3737 u8 auto_connect)
3738{
3739 struct hci_conn_params *params;
3740
3741 params = hci_conn_params_add(hdev, addr, addr_type);
3742 if (!params)
3743 return -EIO;
3744
3745 if (params->auto_connect == auto_connect)
3746 return 0;
3747
3748 list_del_init(&params->action);
3749
3750 switch (auto_connect) {
3751 case HCI_AUTO_CONN_DISABLED:
3752 case HCI_AUTO_CONN_LINK_LOSS:
3753 hci_update_background_scan(hdev);
3754 break;
3755 case HCI_AUTO_CONN_REPORT:
3756 list_add(&params->action, &hdev->pend_le_reports);
3757 hci_update_background_scan(hdev);
3758 break;
3759 case HCI_AUTO_CONN_DIRECT:
3760 case HCI_AUTO_CONN_ALWAYS:
3761 if (!is_connected(hdev, addr, addr_type)) {
3762 list_add(&params->action, &hdev->pend_le_conns);
3763 hci_update_background_scan(hdev);
3764 }
3765 break;
3766 }
3767
3768 params->auto_connect = auto_connect;
3769
3770 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
3771 auto_connect);
3772
3773 return 0;
3774}
3775
3776static void hci_conn_params_free(struct hci_conn_params *params) 3718static void hci_conn_params_free(struct hci_conn_params *params)
3777{ 3719{
3778 if (params->conn) { 3720 if (params->conn) {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6b925733c6f8..ec7c0ec3d8d3 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5425,6 +5425,65 @@ unlock:
5425 return err; 5425 return err;
5426} 5426}
5427 5427
5428static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5429{
5430 struct hci_conn *conn;
5431
5432 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5433 if (!conn)
5434 return false;
5435
5436 if (conn->dst_type != type)
5437 return false;
5438
5439 if (conn->state != BT_CONNECTED)
5440 return false;
5441
5442 return true;
5443}
5444
5445/* This function requires the caller holds hdev->lock */
5446static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5447 u8 addr_type, u8 auto_connect)
5448{
5449 struct hci_dev *hdev = req->hdev;
5450 struct hci_conn_params *params;
5451
5452 params = hci_conn_params_add(hdev, addr, addr_type);
5453 if (!params)
5454 return -EIO;
5455
5456 if (params->auto_connect == auto_connect)
5457 return 0;
5458
5459 list_del_init(&params->action);
5460
5461 switch (auto_connect) {
5462 case HCI_AUTO_CONN_DISABLED:
5463 case HCI_AUTO_CONN_LINK_LOSS:
5464 __hci_update_background_scan(req);
5465 break;
5466 case HCI_AUTO_CONN_REPORT:
5467 list_add(&params->action, &hdev->pend_le_reports);
5468 __hci_update_background_scan(req);
5469 break;
5470 case HCI_AUTO_CONN_DIRECT:
5471 case HCI_AUTO_CONN_ALWAYS:
5472 if (!is_connected(hdev, addr, addr_type)) {
5473 list_add(&params->action, &hdev->pend_le_conns);
5474 __hci_update_background_scan(req);
5475 }
5476 break;
5477 }
5478
5479 params->auto_connect = auto_connect;
5480
5481 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5482 auto_connect);
5483
5484 return 0;
5485}
5486
5428static void device_added(struct sock *sk, struct hci_dev *hdev, 5487static void device_added(struct sock *sk, struct hci_dev *hdev,
5429 bdaddr_t *bdaddr, u8 type, u8 action) 5488 bdaddr_t *bdaddr, u8 type, u8 action)
5430{ 5489{
@@ -5437,10 +5496,31 @@ static void device_added(struct sock *sk, struct hci_dev *hdev,
5437 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk); 5496 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5438} 5497}
5439 5498
5499static void add_device_complete(struct hci_dev *hdev, u8 status)
5500{
5501 struct pending_cmd *cmd;
5502
5503 BT_DBG("status 0x%02x", status);
5504
5505 hci_dev_lock(hdev);
5506
5507 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5508 if (!cmd)
5509 goto unlock;
5510
5511 cmd->cmd_complete(cmd, mgmt_status(status));
5512 mgmt_pending_remove(cmd);
5513
5514unlock:
5515 hci_dev_unlock(hdev);
5516}
5517
5440static int add_device(struct sock *sk, struct hci_dev *hdev, 5518static int add_device(struct sock *sk, struct hci_dev *hdev,
5441 void *data, u16 len) 5519 void *data, u16 len)
5442{ 5520{
5443 struct mgmt_cp_add_device *cp = data; 5521 struct mgmt_cp_add_device *cp = data;
5522 struct pending_cmd *cmd;
5523 struct hci_request req;
5444 u8 auto_conn, addr_type; 5524 u8 auto_conn, addr_type;
5445 int err; 5525 int err;
5446 5526
@@ -5457,14 +5537,24 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5457 MGMT_STATUS_INVALID_PARAMS, 5537 MGMT_STATUS_INVALID_PARAMS,
5458 &cp->addr, sizeof(cp->addr)); 5538 &cp->addr, sizeof(cp->addr));
5459 5539
5540 hci_req_init(&req, hdev);
5541
5460 hci_dev_lock(hdev); 5542 hci_dev_lock(hdev);
5461 5543
5544 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5545 if (!cmd) {
5546 err = -ENOMEM;
5547 goto unlock;
5548 }
5549
5550 cmd->cmd_complete = addr_cmd_complete;
5551
5462 if (cp->addr.type == BDADDR_BREDR) { 5552 if (cp->addr.type == BDADDR_BREDR) {
5463 /* Only incoming connections action is supported for now */ 5553 /* Only incoming connections action is supported for now */
5464 if (cp->action != 0x01) { 5554 if (cp->action != 0x01) {
5465 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5555 err = 0;
5466 MGMT_STATUS_INVALID_PARAMS, 5556 cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS);
5467 &cp->addr, sizeof(cp->addr)); 5557 mgmt_pending_remove(cmd);
5468 goto unlock; 5558 goto unlock;
5469 } 5559 }
5470 5560
@@ -5473,7 +5563,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5473 if (err) 5563 if (err)
5474 goto unlock; 5564 goto unlock;
5475 5565
5476 hci_update_page_scan(hdev); 5566 __hci_update_page_scan(&req);
5477 5567
5478 goto added; 5568 goto added;
5479 } 5569 }
@@ -5493,19 +5583,28 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
5493 /* If the connection parameters don't exist for this device, 5583 /* If the connection parameters don't exist for this device,
5494 * they will be created and configured with defaults. 5584 * they will be created and configured with defaults.
5495 */ 5585 */
5496 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type, 5586 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
5497 auto_conn) < 0) { 5587 auto_conn) < 0) {
5498 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5588 err = 0;
5499 MGMT_STATUS_FAILED, 5589 cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
5500 &cp->addr, sizeof(cp->addr)); 5590 mgmt_pending_remove(cmd);
5501 goto unlock; 5591 goto unlock;
5502 } 5592 }
5503 5593
5504added: 5594added:
5505 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action); 5595 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5506 5596
5507 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, 5597 err = hci_req_run(&req, add_device_complete);
5508 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr)); 5598 if (err < 0) {
5599 /* ENODATA means no HCI commands were needed (e.g. if
5600 * the adapter is powered off).
5601 */
5602 if (err == -ENODATA) {
5603 cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
5604 err = 0;
5605 }
5606 mgmt_pending_remove(cmd);
5607 }
5509 5608
5510unlock: 5609unlock:
5511 hci_dev_unlock(hdev); 5610 hci_dev_unlock(hdev);