Skip to content

Commit

Permalink
Bluetooth: Fix printing errors if LE Connection times out
Browse files Browse the repository at this point in the history
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: bluez/bluez#340
Fixes: 8e8b92e ("Bluetooth: hci_sync: Add hci_le_create_conn_sync")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Vudentz committed Apr 10, 2023
1 parent 19cf60b commit b62e722
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 15 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,7 @@ enum {
HCI_CONN_STK_ENCRYPT,
HCI_CONN_AUTH_INITIATOR,
HCI_CONN_DROP,
HCI_CONN_CANCEL,
HCI_CONN_PARAM_REMOVAL_PEND,
HCI_CONN_NEW_LINK_KEY,
HCI_CONN_SCANNING,
Expand Down
7 changes: 5 additions & 2 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,15 +1233,15 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
{
struct hci_conn *conn = data;

bt_dev_dbg(hdev, "err %d", err);

hci_dev_lock(hdev);

if (!err) {
hci_connect_le_scan_cleanup(conn, 0x00);
goto done;
}

bt_dev_err(hdev, "request failed to create LE connection: err %d", err);

/* Check if connection is still pending */
if (conn != hci_lookup_le_connect(hdev))
goto done;
Expand Down Expand Up @@ -2771,6 +2771,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
{
int r = 0;

if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
return 0;

switch (conn->state) {
case BT_CONNECTED:
case BT_CONFIG:
Expand Down
16 changes: 6 additions & 10 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
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)
Expand Down Expand Up @@ -5902,6 +5892,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
if (status)
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)
addr_type = BDADDR_LE_PUBLIC;
else
Expand Down
13 changes: 10 additions & 3 deletions net/bluetooth/hci_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
PTR_ERR(skb));
if (!event)
bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
PTR_ERR(skb));
return PTR_ERR(skb);
}

Expand Down Expand Up @@ -5126,8 +5127,11 @@ static int hci_le_connect_cancel_sync(struct hci_dev *hdev,
if (test_bit(HCI_CONN_SCANNING, &conn->flags))
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,
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)
Expand Down Expand Up @@ -6102,6 +6106,9 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
conn->conn_timeout, NULL);

done:
if (err == -ETIMEDOUT)
hci_le_connect_cancel_sync(hdev, conn);

/* Re-enable advertising after the connection attempt is finished. */
hci_resume_advertising_sync(hdev);
return err;
Expand Down

0 comments on commit b62e722

Please sign in to comment.