Linux bluetooth development
 help / color / mirror / Atom feed
From: Valentin Kindschi <valentin.kindschi@fiveco.ch>
To: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: "linux-bluetooth@vger.kernel.org"
	<linux-bluetooth@vger.kernel.org>,
	"marcel@holtmann.org" <marcel@holtmann.org>,
	"johan.hedberg@gmail.com" <johan.hedberg@gmail.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"stable@vger.kernel.org" <stable@vger.kernel.org>
Subject: RE: [PATCH v3] Bluetooth: hci_sync: pause advertising for the scan address update
Date: Wed, 2 Sep 2026 12:19:04 +0000	[thread overview]
Message-ID: <f80fffba2aa048ffa4b649bf5eab88a3@fiveco.ch> (raw)
In-Reply-To: <CABBYNZKp=a8+YQDj_b=jcmA1tVxW8HJG8yvsCFQHuDghZPmFzw@mail.gmail.com>

Hi Luiz,

On Mon, Aug 31, 2026 at 5:03 AM Luiz Augusto von Dentz wrote:
> Sashiko flagged this, so I think we need to fix it; otherwise, the
> controller will not be considered discoverable upon resume

Agreed, and it is worse than my caveat paragraph said: on this hardware
the patch introduces the problem rather than widening it.
le_features[0] is 0x3f here, so LL Privacy (bit 6) is clear and
hci_pause_addr_resolution() returns at its first line - without this
patch hci_pause_advertising_sync() is never reached from the scan path
at all.

Reproduced in two commands with the patch applied:

  btmgmt -i hci0 connectable yes
  btmgmt -i hci0 advertising on
  btmgmt -i hci0 discov yes
    current settings: powered connectable discoverable le advertising ...
  btmgmt -i hci0 find -l      # ~10 s
    current settings: powered connectable le advertising ...

discoverable is gone and does not come back. Advertising itself did
resume, for what it is worth.

So v4 as a 2 patch series, unless you would rather see it differently:

1/2 hci_sync: restore discoverable state when resuming advertising

    Save HCI_DISCOVERABLE, HCI_LIMITED_DISCOVERABLE and discov_timeout
    in hci_pause_advertising_sync() next to advertising_old_state, and
    restore them in hci_resume_advertising_sync(). This is a fix in its
    own right - an LL privacy controller loses discoverability the same
    way today, via hci_pause_addr_resolution().

2/2 this patch, caveat paragraph dropped.

Two things I would like your call on.

hci_sync.c never cancels hdev->discov_off, so the pending work still
fires on its original deadline. I read the discoverable window as a
wall clock promise to the mgmt caller that an internal pause should not
extend, so resume restores the flags and discov_timeout but does not
re-arm anything. Does that match your intent for discov_timeout?

If discov_off fires during the pause it clears the flags and zeroes
discov_timeout, and resume would then set them back from the saved
copy, outliving the deadline. I was going to clear the saved state in
discov_off; resume checking delayed_work_pending() would also work.

Thanks,
Valentin

-----Message d'origine-----
De : Luiz Augusto von Dentz <luiz.dentz@gmail.com> 
Envoyé : mardi, 1 septembre 2026 16:52
À : Valentin Kindschi <valentin.kindschi@fiveco.ch>
Cc : linux-bluetooth@vger.kernel.org; marcel@holtmann.org; johan.hedberg@gmail.com; linux-kernel@vger.kernel.org; stable@vger.kernel.org
Objet : Re: [PATCH v3] Bluetooth: hci_sync: pause advertising for the scan address update

Hi Valentin,

On Mon, Aug 31, 2026 at 5:03 AM Valentin Kindschi <valentin.kindschi@fiveco.ch> wrote:
>
> hci_active_scan_sync() calls hci_update_random_address_sync() with 
> require_privacy set on every active scan start, which generates a 
> non-resolvable private address and programs it with LE Set Random 
> Address.
>
> BLUETOOTH CORE SPECIFICATION Vol 4, Part E, 7.8.4 states the 
> controller shall return Command Disallowed (0x0C) for LE Set Random 
> Address while legacy advertising or scanning is enabled.
>
> Advertising is only stopped beforehand when LL privacy is in use.
> hci_pause_addr_resolution(), called just above, returns early when 
> !use_ll_privacy(hdev), so its hci_pause_advertising_sync() never runs.
> On a device that advertises while active scanning - a peripheral that 
> is also a central - every scan start therefore issues a command the 
> host can already know will be rejected:
>
>   Bluetooth: hci0: Opcode 0x2005 failed: -16
>
> The address write is not retried either: hci_set_random_addr_sync() 
> defers only when hdev->random_addr is already set, and it never 
> becomes set because the write keeps failing, so HCI_RPA_EXPIRED is not used here.
>
> Observed on a BCM43455 with Privacy=off, one advertising instance and 
> continuous active discovery, at the scan restart period (~10 s):
>
>   < LE Set Random Address  Address: 02:16:91:90:F1:D4 (Non-Resolvable)
>   > Command Complete       LE Set Random Address, Command Disallowed
>   < LE Set Random Address  Address: 26:90:57:96:9A:3E (Non-Resolvable)
>   > Command Complete       LE Set Random Address, Command Disallowed
>   < LE Set Random Address  Address: 16:32:01:BC:B5:CE (Non-Resolvable)
>   > Command Complete       LE Set Random Address, Command Disallowed
>
> Pause advertising for the address update regardless of privacy, and 
> resume it on every exit path. Previously the resume was guarded by
> use_ll_privacy() and only reached on the error path, which matched the 
> pause being privacy-only.
>
> One caveat this widens: when HCI_ADVERTISING is set,
> hci_pause_advertising_sync() also clears HCI_DISCOVERABLE and zeroes 
> discov_timeout, and hci_resume_advertising_sync() restores only 
> HCI_ADVERTISING. That side effect previously happened only with LL 
> privacy; it is now reachable on every active scan start, so a device 
> made discoverable through mgmt while repeatedly running active 
> discovery would lose discoverability. Restoring it belongs in the 
> pause/resume pair rather than here, but it is worth flagging.

Sashiko flagged this, so I think we need to fix it; otherwise, the controller will not be considered discoverable upon resume:

https://sashiko.dev/#/patchset/20260831090232.1726063-1-valentin.kindschi%40fiveco.ch

> With the patch, the same scan restart on the same hardware:
>
>   < LE Set Advertising Enable                            Success
>   < LE Set Random Address                                Success
>   < LE Set Scan Parameters                               Success
>   < LE Set Scan Enable                                   Success
>   < LE Set Advertising Parameters                        Success
>   < LE Set Advertising Enable                            Success
>
> Over 35425 records / ~4 min of btmon with continuous active discovery 
> and advertising enabled there were no Command Disallowed responses of 
> any kind, against one per scan restart before. A central could still 
> connect to the device, confirming advertising is restored after the pause.
>
> A second capture on the same device, 221 s with an out-of-range peer 
> causing two cancelled outgoing connections, shows the same result 
> under a different mix of traffic: 2 LE Set Random Address, both 
> Success, and no Command Disallowed of any opcode.
>
> Tooling disclosure (Documentation/process/generated-content.rst): an 
> AI coding assistant was used to investigate this and to draft the 
> change; the patch text and code are its output, reviewed by me. Inputs 
> were btmon captures and kernel logs from the affected device, with the 
> request to identify what re-issues LE Set Random Address every ~10 s and to fix it.
> Three earlier explanations it proposed were discarded after being 
> checked against the captures: bluetoothd restarting service discovery; 
> RPA rotation (excluded, Privacy=off); and the static-address branch of
> hci_update_random_address_sync() (excluded, both random_address and 
> static_address read 00:00:00:00:00:00). The cause was only established 
> after decoding the command payloads, which showed a freshly generated 
> non-resolvable address per attempt. Testing is as described above, on 
> the device, using btmon and a second device to confirm connectability.
>
> Fixes: abfeea476c68 ("Bluetooth: hci_sync: Convert 
> MGMT_OP_START_DISCOVERY")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-5 btmon
> Signed-off-by: Valentin Kindschi <valentin.kindschi@fiveco.ch>
> ---
> Changes in v3:
> - Resend, no code change; v2 had no reply. Rechecked that it still applies
>   to bluetooth-next.
> - Added the second capture described above, taken with the two patches from
>   the "endless adv params retry" series applied, since in bluetooth-next,
>   confirming the fix holds with cancelled outgoing connections in the mix.
>
> Changes in v2:
> - Rebased onto bluetooth-next: mainline renamed use_ll_privacy() to
>   ll_privacy_capable(). No functional change.
>  net/bluetooth/hci_sync.c | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> --- a/net/bluetooth/hci_sync.c
> +++ b/net/bluetooth/hci_sync.c
> @@ -6244,6 +6244,14 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
>         if (err)
>                 goto failed;
>
> +       /* LE Set Random Address is disallowed while advertising is enabled, so
> +        * pause it for the address update. hci_pause_addr_resolution() above
> +        * only does this when LL privacy is in use.
> +        */
> +       err = hci_pause_advertising_sync(hdev);
> +       if (err)
> +               goto failed;
> +
>         /* All active scans will be done with either a resolvable private
>          * address (when privacy feature has been enabled) or non-resolvable
>          * private address.
> @@ -6272,13 +6280,18 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
>         err = hci_start_scan_sync(hdev, LE_SCAN_ACTIVE, interval,
>                                   hdev->le_scan_window_discovery,
>                                   own_addr_type, filter_policy, filter_dup);
> -       if (!err)
> +       if (!err) {
> +               /* Advertising was paused for the address update above. */
> +               hci_resume_advertising_sync(hdev);
>                 return err;
> +       }
>
>  failed:
> -       /* Resume advertising if it was paused */
> -       if (ll_privacy_capable(hdev))
> -               hci_resume_advertising_sync(hdev);
> +       /* Resume advertising if it was paused. hci_resume_advertising_sync()
> +        * is a no-op when hdev->advertising_paused is not set, so this covers
> +        * both the privacy and the address-update pause.
> +        */
> +       hci_resume_advertising_sync(hdev);
>
>         /* Resume passive scanning */
>         hci_update_passive_scan_sync(hdev);
> --
> 2.34.1
>


--
Luiz Augusto von Dentz

      reply	other threads:[~2026-09-02 12:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31  9:02 [PATCH v3] Bluetooth: hci_sync: pause advertising for the scan address update Valentin Kindschi
2026-08-31 12:44 ` [v3] " bluez.test.bot
2026-09-01 14:51 ` [PATCH v3] " Luiz Augusto von Dentz
2026-09-02 12:19   ` Valentin Kindschi [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f80fffba2aa048ffa4b649bf5eab88a3@fiveco.ch \
    --to=valentin.kindschi@fiveco.ch \
    --cc=johan.hedberg@gmail.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luiz.dentz@gmail.com \
    --cc=marcel@holtmann.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox