[PATCH] Bluetooth: find an RPA peer's connection parameters by its identity

From: Radek Podgorny

Date: Sun Nov 01 2026 - 12:21:23 EST


hci_le_create_conn_sync() looks up the peer's connection parameters by
conn->dst. Those parameters are stored under the identity address, but
hci_connect_le() puts the peer's cached RPA in conn->dst, and
__hci_conn_add() no longer converts it back when the controller cannot
translate an identity address.

The lookup then misses, and the connection is created with the
controller-wide defaults in hdev instead of the peer's interval, latency
and supervision timeout.

Resolve an RPA to its identity before the lookup, as
hci_connect_le_scan_cleanup() does. The other lookups by conn->dst run
after le_conn_complete_evt() has resolved it, so they are not affected.

Measured with btmon on a BCM4345C0 against a bonded peer that rotates
RPAs, with stored parameters of interval 12, latency 0 and timeout 600,
over six forced reconnects each way on v7.3.1:

before after
requested interval 30.00-50.00 ms 15.00-15.00 ms
requested timeout 420 ms 6000 ms
link interval 48.75 ms 15.00 ms
link timeout 420 ms 6000 ms

Fixes: 4914c4998961 ("Bluetooth: put the peer's on-air address on air when we cannot resolve")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Radek Podgorny <radek@xxxxxxxxxxx>
---
This is the follow-up to the on-air address patch that Luiz said could
be done on top:
https://lore.kernel.org/linux-bluetooth/CABBYNZ+5zV8xzhHZKTUQYT4tLHaZAO7iiKOEsKuT8aA+YNLjPQ@xxxxxxxxxxxxxx/

What this does not establish:
- tested on v7.3.1, not on bluetooth-next; the patch applies to both
and bluetooth-next was only build-tested
- it shows the stored parameters now reach the controller. It does not
show that links are more reliable: all twelve reconnects succeeded,
with or without the patch

Per Documentation/process/generated-content.rst: the patch, this message
and the btmon test runs were done with the Claude coding assistant
(model as in the Assisted-by trailer). The prompts asked it to fix the
lookup miss named in the on-air address review, then to measure the
result on the author's van, with and without the patch. The author
directed the work and reviewed the result.
---
net/bluetooth/hci_sync.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 9d829c20c31604..810d6f5143342a 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -7018,6 +7018,7 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
{
struct hci_cp_le_create_conn cp;
struct hci_conn_params *params;
+ struct smp_irk *irk;
u8 own_addr_type;
int err;
struct hci_conn *conn = data;
@@ -7057,7 +7058,16 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)

hci_dev_lock(hdev);

- params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+ /* conn->dst may hold the peer's RPA, but connection parameters are
+ * stored under its identity address.
+ */
+ irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
+ if (irk)
+ params = hci_conn_params_lookup(hdev, &irk->bdaddr,
+ irk->addr_type);
+ else
+ params = hci_conn_params_lookup(hdev, &conn->dst,
+ conn->dst_type);
if (params) {
conn->le_conn_min_interval = params->conn_min_interval;
conn->le_conn_max_interval = params->conn_max_interval;

---
base-commit: 42b8c2d729268a65a2d98064e8dc59ff53646b14
change-id: 20261101-for-upstream-le-conn-params-rpa-f2334fb5dda7

--
Radek Podgorny <radek@xxxxxxxxxxx>