Commit 19cf60bf authored by Luiz Augusto von Dentz's avatar Luiz Augusto von Dentz
Browse files

Bluetooth: hci_conn: Fix not cleaning up on LE Connection failure



hci_connect_le_scan_cleanup shall always be invoked to cleanup the
states and re-enable passive scanning if necessary, otherwise it may
cause the pending action to stay active causing multiple attempts to
connect.

Fixes: 9b3628d7 ("Bluetooth: hci_sync: Cleanup hci_conn if it cannot be aborted")
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent b9881d9a
Loading
Loading
Loading
Loading
+24 −28
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
};

/* This function requires the caller holds hdev->lock */
static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
{
	struct hci_conn_params *params;
	struct hci_dev *hdev = conn->hdev;
@@ -88,9 +88,28 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn)

	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, bdaddr,
					   bdaddr_type);
	if (!params || !params->explicit_connect)
	if (!params)
		return;

	if (params->conn) {
		hci_conn_drop(params->conn);
		hci_conn_put(params->conn);
		params->conn = NULL;
	}

	if (!params->explicit_connect)
		return;

	/* If the status indicates successful cancellation of
	 * the attempt (i.e. Unknown Connection Id) there's no point of
	 * notifying failure since we'll go back to keep trying to
	 * connect. The only exception is explicit connect requests
	 * where a timeout + cancel does indicate an actual failure.
	 */
	if (status && status != HCI_ERROR_UNKNOWN_CONN_ID)
		mgmt_connect_failed(hdev, &conn->dst, conn->type,
				    conn->dst_type, status);

	/* The connection attempt was doing scan for new RPA, and is
	 * in scan phase. If params are not associated with any other
	 * autoconnect action, remove them completely. If they are, just unmark
@@ -178,7 +197,7 @@ static void le_scan_cleanup(struct work_struct *work)
	rcu_read_unlock();

	if (c == conn) {
		hci_connect_le_scan_cleanup(conn);
		hci_connect_le_scan_cleanup(conn, 0x00);
		hci_conn_cleanup(conn);
	}

@@ -1179,31 +1198,8 @@ EXPORT_SYMBOL(hci_get_route);
static void hci_le_conn_failed(struct hci_conn *conn, u8 status)
{
	struct hci_dev *hdev = conn->hdev;
	struct hci_conn_params *params;

	params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
					   conn->dst_type);
	if (params && params->conn) {
		hci_conn_drop(params->conn);
		hci_conn_put(params->conn);
		params->conn = NULL;
	}

	/* If the status indicates successful cancellation of
	 * the attempt (i.e. Unknown Connection Id) there's no point of
	 * notifying failure since we'll go back to keep trying to
	 * connect. The only exception is explicit connect requests
	 * where a timeout + cancel does indicate an actual failure.
	 */
	if (status != HCI_ERROR_UNKNOWN_CONN_ID ||
	    (params && params->explicit_connect))
		mgmt_connect_failed(hdev, &conn->dst, conn->type,
				    conn->dst_type, status);

	/* Since we may have temporarily stopped the background scanning in
	 * favor of connection establishment, we should restart it.
	 */
	hci_update_passive_scan(hdev);
	hci_connect_le_scan_cleanup(conn, status);

	/* Enable advertising in case this was a failed connection
	 * attempt as a peripheral.
@@ -1240,7 +1236,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
	hci_dev_lock(hdev);

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