aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJoseph Hwang <josephsih@chromium.org>2020-03-11 19:20:14 -0700
committerMarcel Holtmann <marcel@holtmann.org>2020-03-12 08:21:15 +0100
commitb8d290525e3972b5e876b2649a42bf4081d753fe (patch)
tree107aa62255523663a4a7f10cd12df434a4fca3d4 /net/bluetooth
parentBluetooth: Pause discovery and advertising during suspend (diff)
downloadwireguard-linux-b8d290525e3972b5e876b2649a42bf4081d753fe.tar.xz
wireguard-linux-b8d290525e3972b5e876b2649a42bf4081d753fe.zip
Bluetooth: clean up connection in hci_cs_disconnect
In bluetooth core specification 4.2, Vol 2, Part E, 7.8.9 LE Set Advertise Enable Command, it says The Controller shall continue advertising until ... or until a connection is created or ... In these cases, advertising is then disabled. Hence, advertising would be disabled before a connection is established. In current kernel implementation, advertising would be re-enabled when all connections are terminated. The correct disconnection flow looks like < HCI Command: Disconnect > HCI Event: Command Status Status: Success > HCI Event: Disconnect Complete Status: Success Specifically, the last Disconnect Complete Event would trigger a callback function hci_event.c:hci_disconn_complete_evt() to cleanup the connection and re-enable advertising when proper. However, sometimes, there might occur an exception in the controller when disconnection is being executed. The disconnection flow might then look like < HCI Command: Disconnect > HCI Event: Command Status Status: Unknown Connection Identifier Note that "> HCI Event: Disconnect Complete" is missing when such an exception occurs. This would result in advertising staying disabled forever since the connection in question is not cleaned up correctly. To fix the controller exception issue, we need to do some connection cleanup when the disconnect command status indicates an error. Signed-off-by: Joseph Hwang <josephsih@chromium.org> Signed-off-by: Manish Mandlik <mmandlik@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_event.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0908eaa7cacf..20408d386268 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2233,10 +2233,22 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
- if (conn)
+ if (conn) {
+ u8 type = conn->type;
+
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, status);
+ /* If the disconnection failed for any reason, the upper layer
+ * does not retry to disconnect in current implementation.
+ * Hence, we need to do some basic cleanup here and re-enable
+ * advertising if necessary.
+ */
+ hci_conn_del(conn);
+ if (type == LE_LINK)
+ hci_req_reenable_advertising(hdev);
+ }
+
hci_dev_unlock(hdev);
}