Bluetooth: Fix printing errors if LE Connection times out

This fixes errors like bellow when LE Connection times out since that
is actually not a controller error:

 Bluetooth: hci0: Opcode 0x200d failed: -110
 Bluetooth: hci0: request failed to create LE connection: err -110

Instead the code shall properly detect if -ETIMEDOUT is returned and
send HCI_OP_LE_CREATE_CONN_CANCEL to give up on the connection.

Link: https://github.com/bluez/bluez/issues/340
Fixes: 8e8b92ee ("Bluetooth: hci_sync: Add hci_le_create_conn_sync")
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 19cf60bf
...@@ -954,6 +954,7 @@ enum { ...@@ -954,6 +954,7 @@ enum {
HCI_CONN_STK_ENCRYPT, HCI_CONN_STK_ENCRYPT,
HCI_CONN_AUTH_INITIATOR, HCI_CONN_AUTH_INITIATOR,
HCI_CONN_DROP, HCI_CONN_DROP,
HCI_CONN_CANCEL,
HCI_CONN_PARAM_REMOVAL_PEND, HCI_CONN_PARAM_REMOVAL_PEND,
HCI_CONN_NEW_LINK_KEY, HCI_CONN_NEW_LINK_KEY,
HCI_CONN_SCANNING, HCI_CONN_SCANNING,
......
...@@ -1233,6 +1233,8 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err) ...@@ -1233,6 +1233,8 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
{ {
struct hci_conn *conn = data; struct hci_conn *conn = data;
bt_dev_dbg(hdev, "err %d", err);
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!err) { if (!err) {
...@@ -1240,8 +1242,6 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err) ...@@ -1240,8 +1242,6 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
goto done; goto done;
} }
bt_dev_err(hdev, "request failed to create LE connection: err %d", err);
/* Check if connection is still pending */ /* Check if connection is still pending */
if (conn != hci_lookup_le_connect(hdev)) if (conn != hci_lookup_le_connect(hdev))
goto done; goto done;
...@@ -2771,6 +2771,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason) ...@@ -2771,6 +2771,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
{ {
int r = 0; int r = 0;
if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
return 0;
switch (conn->state) { switch (conn->state) {
case BT_CONNECTED: case BT_CONNECTED:
case BT_CONFIG: case BT_CONFIG:
......
...@@ -2881,16 +2881,6 @@ static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr, ...@@ -2881,16 +2881,6 @@ static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
conn->resp_addr_type = peer_addr_type; conn->resp_addr_type = peer_addr_type;
bacpy(&conn->resp_addr, peer_addr); bacpy(&conn->resp_addr, peer_addr);
/* We don't want the connection attempt to stick around
* indefinitely since LE doesn't have a page timeout concept
* like BR/EDR. Set a timer for any connection that doesn't use
* the accept list for connecting.
*/
if (filter_policy == HCI_LE_USE_PEER_ADDR)
queue_delayed_work(conn->hdev->workqueue,
&conn->le_conn_timeout,
conn->conn_timeout);
} }
static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
...@@ -5902,6 +5892,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, ...@@ -5902,6 +5892,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
if (status) if (status)
goto unlock; goto unlock;
/* Drop the connection if it has been aborted */
if (test_bit(HCI_CONN_CANCEL, &conn->flags)) {
hci_conn_drop(conn);
goto unlock;
}
if (conn->dst_type == ADDR_LE_DEV_PUBLIC) if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
addr_type = BDADDR_LE_PUBLIC; addr_type = BDADDR_LE_PUBLIC;
else else
......
...@@ -246,8 +246,9 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen, ...@@ -246,8 +246,9 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk); skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
if (IS_ERR(skb)) { if (IS_ERR(skb)) {
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode, if (!event)
PTR_ERR(skb)); bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
PTR_ERR(skb));
return PTR_ERR(skb); return PTR_ERR(skb);
} }
...@@ -5126,8 +5127,11 @@ static int hci_le_connect_cancel_sync(struct hci_dev *hdev, ...@@ -5126,8 +5127,11 @@ static int hci_le_connect_cancel_sync(struct hci_dev *hdev,
if (test_bit(HCI_CONN_SCANNING, &conn->flags)) if (test_bit(HCI_CONN_SCANNING, &conn->flags))
return 0; return 0;
if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
return 0;
return __hci_cmd_sync_status(hdev, HCI_OP_LE_CREATE_CONN_CANCEL, return __hci_cmd_sync_status(hdev, HCI_OP_LE_CREATE_CONN_CANCEL,
6, &conn->dst, HCI_CMD_TIMEOUT); 0, NULL, HCI_CMD_TIMEOUT);
} }
static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn) static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn)
...@@ -6102,6 +6106,9 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn) ...@@ -6102,6 +6106,9 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
conn->conn_timeout, NULL); conn->conn_timeout, NULL);
done: done:
if (err == -ETIMEDOUT)
hci_le_connect_cancel_sync(hdev, conn);
/* Re-enable advertising after the connection attempt is finished. */ /* Re-enable advertising after the connection attempt is finished. */
hci_resume_advertising_sync(hdev); hci_resume_advertising_sync(hdev);
return err; return err;
......
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