@@ -427,6 +427,7 @@ enum {
#define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */
+#define HCI_ACL_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
#define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
#define HCI_LE_AUTOCONN_TIMEOUT msecs_to_jiffies(4000) /* 4 seconds */
@@ -229,11 +229,12 @@ static void hci_connect_le_scan_remove(struct hci_conn *conn)
schedule_work(&conn->le_scan_cleanup);
}
-static void hci_acl_create_connection(struct hci_conn *conn)
+static int hci_acl_create_connection_sync(struct hci_dev *hdev, void *data)
{
- struct hci_dev *hdev = conn->hdev;
+ struct hci_conn *conn = data;
struct inquiry_entry *ie;
struct hci_cp_create_conn cp;
+ int err;
BT_DBG("hcon %p", conn);
@@ -246,12 +247,10 @@ static void hci_acl_create_connection(struct hci_conn *conn)
* request for discovery again when this flag becomes false.
*/
if (test_bit(HCI_INQUIRY, &hdev->flags)) {
- /* Put this connection to "pending" state so that it will be
- * executed after the inquiry cancel command complete event.
- */
- conn->state = BT_CONNECT2;
- hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
- return;
+ err = __hci_cmd_sync_status(hdev, HCI_OP_INQUIRY_CANCEL, 0,
+ NULL, HCI_CMD_TIMEOUT);
+ if (err)
+ bt_dev_warn(hdev, "Failed to cancel inquiry %d", err);
}
conn->state = BT_CONNECT;
@@ -284,7 +283,15 @@ static void hci_acl_create_connection(struct hci_conn *conn)
else
cp.role_switch = 0x00;
- hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
+ err = __hci_cmd_sync_status_sk(hdev, HCI_OP_CREATE_CONN,
+ sizeof(cp), &cp,
+ HCI_EV_CONN_COMPLETE,
+ HCI_ACL_CONN_TIMEOUT, NULL);
+
+ if (err == -ETIMEDOUT)
+ hci_abort_conn(conn, HCI_ERROR_LOCAL_HOST_TERM);
+
+ return err;
}
int hci_disconnect(struct hci_conn *conn, __u8 reason)
@@ -1622,10 +1629,18 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
acl->conn_reason = conn_reason;
if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
+ int err;
+
acl->sec_level = BT_SECURITY_LOW;
acl->pending_sec_level = sec_level;
acl->auth_type = auth_type;
- hci_acl_create_connection(acl);
+
+ err = hci_cmd_sync_queue(hdev, hci_acl_create_connection_sync,
+ acl, NULL);
+ if (err) {
+ hci_conn_del(acl);
+ return ERR_PTR(err);
+ }
}
return acl;
@@ -2530,7 +2545,7 @@ void hci_conn_check_pending(struct hci_dev *hdev)
conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
if (conn)
- hci_acl_create_connection(conn);
+ hci_cmd_sync_queue(hdev, hci_acl_create_connection_sync, conn, NULL);
hci_dev_unlock(hdev);
}