Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9489eca4 authored by Johan Hedberg's avatar Johan Hedberg Committed by Marcel Holtmann
Browse files

Bluetooth: Add timeout for LE connection attempts



LE connection attempts do not have a controller side timeout in the same
way as BR/EDR has (in form of the page timeout). Since we always do
scanning before initiating connections the attempts are always expected
to succeed in some reasonable time.

This patch adds a timer which forces a cancellation of the connection
attempt within 20 seconds if it has not been successful by then. This
way we e.g. ensure that mgmt_pair_device times out eventually and gives
an error response.

Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent a7139edd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -183,6 +183,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_LE_CONN_TIMEOUT	msecs_to_jiffies(20000)	/* 20 seconds */

/* HCI data types */
#define HCI_COMMAND_PKT		0x01
+1 −0
Original line number Diff line number Diff line
@@ -375,6 +375,7 @@ struct hci_conn {
	struct delayed_work disc_work;
	struct delayed_work auto_accept_work;
	struct delayed_work idle_work;
	struct delayed_work le_conn_timeout;

	struct device	dev;

+13 −0
Original line number Diff line number Diff line
@@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work)
		     &conn->dst);
}

static void le_conn_timeout(struct work_struct *work)
{
	struct hci_conn *conn = container_of(work, struct hci_conn,
					     le_conn_timeout.work);

	BT_DBG("");

	hci_le_create_connection_cancel(conn);
}

struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
{
	struct hci_conn *conn;
@@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
	INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
	INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
	INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle);
	INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);

	atomic_set(&conn->refcnt, 0);

@@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn)
		/* Unacked frames */
		hdev->acl_cnt += conn->sent;
	} else if (conn->type == LE_LINK) {
		cancel_delayed_work_sync(&conn->le_conn_timeout);

		if (hdev->le_pkts)
			hdev->le_cnt += conn->sent;
		else
+12 −0
Original line number Diff line number Diff line
@@ -1678,6 +1678,16 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
	conn->resp_addr_type = cp->peer_addr_type;
	bacpy(&conn->resp_addr, &cp->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 white list for connecting.
	 */
	if (cp->filter_policy == HCI_LE_USE_PEER_ADDR)
		queue_delayed_work(conn->hdev->workqueue,
				   &conn->le_conn_timeout,
				   HCI_LE_CONN_TIMEOUT);

unlock:
	hci_dev_unlock(hdev);
}
@@ -3794,6 +3804,8 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
			conn->init_addr_type = ev->bdaddr_type;
			bacpy(&conn->init_addr, &ev->bdaddr);
		}
	} else {
		cancel_delayed_work(&conn->le_conn_timeout);
	}

	/* Ensure that the hci_conn contains the identity address type