2023-04-26 18:45:07

by Raul Cheleguini

[permalink] [raw]
Subject: [PATCH] Bluetooth: Fix unexpected SMP command errors for ATS2851

Fix unexpected SMP 0x08 and 0x09 command errors when connecting and pairing
devices using ATS2851 based constrollers.

The errors are a result of a race condition in which the host receives the
commands (without prior authorization by SMP functions) in the moment host
is sending WRITE_AUTH_PAYLOAD_TIMEOUT command.

In such a situation, a disconnect event occurs, and the device cannot
connect or pair.

To address this issue, we add a condition that skips the
WRITE_AUTH_PAYLOAD_TIMEOUT command for ATS2851, enabling the SMP
functions to prepare for commands 0x08 and 0x09 in a timely manner.

Signed-off-by: Raul Cheleguini <[email protected]>
---
- Note that this patch depends on the broken extended create connection
quirk sent in [1].
[1]. https://marc.info/?l=linux-bluetooth&m=168244024503639&w=2

drivers/bluetooth/btusb.c | 1 +
include/net/bluetooth/hci.h | 7 +++++++
net/bluetooth/hci_event.c | 7 +++++++
net/bluetooth/hci_sync.c | 5 ++++-
4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 1cf104feaf85..972ca94de6de 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -4374,6 +4374,7 @@ static int btusb_probe(struct usb_interface *intf,
set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
set_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &hdev->quirks);
+ set_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, &hdev->quirks);
}

if (!reset)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index d5d0e44bf0b6..625c100a74ad 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -316,6 +316,13 @@ enum {
* based controllers, which erroneously claims to support it.
*/
HCI_QUIRK_BROKEN_EXT_CREATE_CONN,
+
+ /*
+ * When this quirk is set, the command WRITE_AUTH_PAYLOAD_TIMEOUT is
+ * skipped. This is required for the Actions Semiconductor ATS2851
+ * based controllers, due to a race condition in pairing process.
+ */
+ HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT,
};

/* HCI device flags */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d00ef6e3fc45..2077a7c921f1 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3655,6 +3655,13 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
goto unlock;
}

+ /* We skip the WRITE_AUTH_PAYLOAD_TIMEOUT for ATS2851 based controllers
+ * to avoid unexpected SMP command errors when pairing.
+ */
+ if (test_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT,
+ &hdev->quirks))
+ goto notify;
+
/* Set the default Authenticated Payload Timeout after
* an LE Link is established. As per Core Spec v5.0, Vol 2, Part B
* Section 3.3, the HCI command WRITE_AUTH_PAYLOAD_TIMEOUT should be
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 26ab4deb6d52..ecd18c611122 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -4581,7 +4581,10 @@ static const struct {
"advertised, but not supported."),
HCI_QUIRK_BROKEN(EXT_CREATE_CONN,
"HCI LE Extended Create Connection command is "
- "advertised, but not supported.")
+ "advertised, but not supported."),
+ HCI_QUIRK_BROKEN(WRITE_AUTH_PAYLOAD_TIMEOUT,
+ "HCI WRITE AUTH PAYLOAD TIMEOUT command leads "
+ "to unexpected SMP errors when pairing.")
};

/* This function handles hdev setup stage:
--
2.39.2