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
...@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = { ...@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
}; };
/* This function requires the caller holds hdev->lock */ /* 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_conn_params *params;
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
...@@ -88,9 +88,28 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn) ...@@ -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, params = hci_pend_le_action_lookup(&hdev->pend_le_conns, bdaddr,
bdaddr_type); bdaddr_type);
if (!params || !params->explicit_connect) if (!params)
return; 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 /* The connection attempt was doing scan for new RPA, and is
* in scan phase. If params are not associated with any other * in scan phase. If params are not associated with any other
* autoconnect action, remove them completely. If they are, just unmark * autoconnect action, remove them completely. If they are, just unmark
...@@ -178,7 +197,7 @@ static void le_scan_cleanup(struct work_struct *work) ...@@ -178,7 +197,7 @@ static void le_scan_cleanup(struct work_struct *work)
rcu_read_unlock(); rcu_read_unlock();
if (c == conn) { if (c == conn) {
hci_connect_le_scan_cleanup(conn); hci_connect_le_scan_cleanup(conn, 0x00);
hci_conn_cleanup(conn); hci_conn_cleanup(conn);
} }
...@@ -1179,31 +1198,8 @@ EXPORT_SYMBOL(hci_get_route); ...@@ -1179,31 +1198,8 @@ EXPORT_SYMBOL(hci_get_route);
static void hci_le_conn_failed(struct hci_conn *conn, u8 status) static void hci_le_conn_failed(struct hci_conn *conn, u8 status)
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
struct hci_conn_params *params;
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst, hci_connect_le_scan_cleanup(conn, status);
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);
/* Enable advertising in case this was a failed connection /* Enable advertising in case this was a failed connection
* attempt as a peripheral. * attempt as a peripheral.
...@@ -1240,7 +1236,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err) ...@@ -1240,7 +1236,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!err) { if (!err) {
hci_connect_le_scan_cleanup(conn); hci_connect_le_scan_cleanup(conn, 0x00);
goto done; goto done;
} }
......
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