Re: [PATCH] Bluetooth: hci_sync: scan unfiltered for host-resolved RPAs

From: Luiz Augusto von Dentz

Date: Tue Oct 13 2026 - 13:52:01 EST


Hi Kyle,

On Mon, Oct 12, 2026 at 11:13 PM Kyle Pepper <cochcoder@xxxxxxxxx> wrote:
>
> On controllers without LL Privacy, the accept list cannot match a bonded
> peer identity against the peer Resolvable Private Address. Background
> scans using the accept-list filter therefore hide those advertisements
> from host-side address resolution and auto-connect never starts.
>
> When a pending peer has an IRK but controller-side resolution is
> unavailable, use unfiltered scanning while the host is awake. Keep
> accept-list filtering during suspend, where host-side resolution cannot
> run.
>
> Assisted-by: OpenCode:gpt-6.1-sol
> Signed-off-by: Kyle Pepper <cochcoder@xxxxxxxxx>
> ---
> Submission review notes (not part of the commit message):
> The downstream N8/UB500 recovers an ACL link after range loss.
> No patch-off comparison or changed-RPA necessity test was supplied.
> Do not equate link reconnection with automatic audio/application resume.
> Privacy-capable and suspend/wake regressions remain coverage gaps.
>
> net/bluetooth/hci_sync.c | 27 +++++++++++++++++++++++++++
> 1 file changed, 27 insertions(+)
>
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> index efbd2e538..d0fbb3e08 100644
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -2907,6 +2907,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
> struct bdaddr_list *b, *t;
> u8 num_entries = 0;
> bool pend_conn, pend_report;
> + bool rpa_no_llp = false;
> u8 filter_policy;
> size_t i, n;
> int err;
> @@ -3025,6 +3026,17 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
> kvfree(params);
> goto done;
> }
> +
> + /* A bonded peer that advertises with a Resolvable Private
> + * Address can only be matched by the controller's accept list
> + * if the controller can resolve addresses itself (LL Privacy).
> + * When it cannot, note the peer so the scan below can fall back
> + * to host-side resolution instead of accept list filtering.
> + */
> + if (!ll_privacy_capable(hdev) &&
> + hci_find_irk_by_addr(hdev, &params[i].addr,
> + params[i].addr_type))
> + rpa_no_llp = true;
> }
>
> kvfree(params);
> @@ -3047,6 +3059,11 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
> kvfree(params);
> goto done;
> }
> +
> + if (!ll_privacy_capable(hdev) &&
> + hci_find_irk_by_addr(hdev, &params[i].addr,
> + params[i].addr_type))
> + rpa_no_llp = true;
> }
>
> kvfree(params);
> @@ -3061,6 +3078,16 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
> hdev->interleave_scan_state != INTERLEAVE_SCAN_ALLOWLIST)
> err = -EINVAL;
>
> + /* If a pending peer advertises with an RPA but the controller cannot
> + * resolve addresses (no LL Privacy), accept list filtering would drop
> + * its resolvable adverts and it could never be reconnected. Scan
> + * unfiltered instead so the host resolves the RPA in software and
> + * triggers the connection (see process_adv_report()). Skipped while
> + * suspended, where host-side resolution is not available.
> + */
> + if (rpa_no_llp && !hdev->suspended)
> + err = -EINVAL;

Weird, I thought we already captured this case. Perhaps there is a bug
in the code if AI is still flagging it as unsupported. Anyway we need
to mgmt-tester to confirm it.

> done:
> filter_policy = err ? 0x00 : 0x01;
>
>
> base-commit: 964430c038967fd06643e866f68115664e1a1bd1
>


--
Luiz Augusto von Dentz