diff mbox series

[5/5] Bluetooth: hci_event: Try reconnecting on more kinds of errors

Message ID 20240102185933.64179-6-verdre@v0yd.nl (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Bluetooth: Improve retrying of connection attempts | expand

Checks

Context Check Description
netdev/series_format warning Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1135 this patch: 1135
netdev/cc_maintainers warning 3 maintainers not CCed: edumazet@google.com kuba@kernel.org pabeni@redhat.com
netdev/build_clang success Errors and warnings before: 1140 this patch: 1140
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1162 this patch: 1162
netdev/checkpatch warning WARNING: else is not generally useful after a break or return WARNING: line length of 86 exceeds 80 columns WARNING: quoted string split across lines
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Jonas Dreßler Jan. 2, 2024, 6:59 p.m. UTC
While some hardware seems to return "HCI Command Disallowed" errors when
trying to connect to too many devices at once, other hardware (eg. the
BCM4378 found in M1 macbooks) returns "HCI Hardware Failure" in this case.

And the Marvell 88W8897 in various Microsoft Surface devices behaves
different again: Here the "HCI Create Connection" succeeds, but later
a "HCI Connection Complete" event with status "Rejected Limited Resources"
comes in.

Handle all these cases as expected by userspace and reuse the existing
BT_CONNECT2 logic to try "HCI Create Connection" again after the ongoing
connection attempts have been completed.

Signed-off-by: Jonas Dreßler <verdre@v0yd.nl>
---
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_event.c   | 26 +++++++++++++++++++++++---
 2 files changed, 24 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index fef723afd..23890f53e 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -637,6 +637,7 @@  enum {
 
 /* ---- HCI Error Codes ---- */
 #define HCI_ERROR_UNKNOWN_CONN_ID	0x02
+#define HCI_ERROR_HARDWARE_FAILURE	0x03
 #define HCI_ERROR_AUTH_FAILURE		0x05
 #define HCI_ERROR_PIN_OR_KEY_MISSING	0x06
 #define HCI_ERROR_MEMORY_EXCEEDED	0x07
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 1376092c5..46b6d7e27 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2323,13 +2323,14 @@  static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
 
 	if (status) {
 		if (conn && conn->state == BT_CONNECT) {
-			/* If the request failed with "Command Disallowed", the
+			/* If the request failed with a certain status, the
 			 * card is either using all its available "slots" for
 			 * attempting new connections, or it's currently
 			 * doing an HCI Inquiry. In these cases we'll try to
 			 * do the "Create Connection" request again later.
 			 */
-			if (status == HCI_ERROR_COMMAND_DISALLOWED) {
+			if (status == HCI_ERROR_COMMAND_DISALLOWED ||
+			    status == HCI_ERROR_HARDWARE_FAILURE) {
 				conn->state = BT_CONNECT2;
 
 				if (!hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT) &&
@@ -3254,7 +3255,26 @@  static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
 
 done:
 	if (status) {
-		hci_conn_failed(conn, status);
+		if (status == HCI_ERROR_REJ_LIMITED_RESOURCES) {
+			conn->state = BT_CONNECT2;
+
+			if (!hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT) &&
+			    !test_bit(HCI_INQUIRY, &hdev->flags)) {
+				bt_dev_err(hdev,
+					   "\"Connect Complete\" event with error "
+					   "(0x%2.2x) indicating to try again, but "
+					   "there's no concurrent \"Create "
+					   "Connection\" nor an ongoing inquiry",
+					   status);
+
+				hci_conn_failed(conn, status);
+			}
+
+			hci_dev_unlock(hdev);
+			return;
+		} else {
+			hci_conn_failed(conn, status);
+		}
 	} else if (ev->link_type == SCO_LINK) {
 		switch (conn->setting & SCO_AIRMODE_MASK) {
 		case SCO_AIRMODE_CVSD: