Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v5 1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume
@ 2026-09-18 11:03 Valentin Kindschi
  2026-09-18 11:03 ` [PATCH v5 2/2] Bluetooth: hci_sync: pause advertising for the scan address update Valentin Kindschi
  2026-09-18 14:44 ` [v5,1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume bluez.test.bot
  0 siblings, 2 replies; 3+ messages in thread
From: Valentin Kindschi @ 2026-09-18 11:03 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: marcel, johan.hedberg, luiz.dentz, linux-kernel,
	Valentin Kindschi, stable

hci_resume_advertising_sync() never re-enables advertising on a
controller without extended advertising.

It restores HCI_ADVERTISING from advertising_old_state, then calls
hci_schedule_adv_instance_sync(), which starts with:

  if (hci_dev_test_flag(hdev, HCI_ADVERTISING) && !ext_adv_capable(hdev))
          return -EPERM;

The flag it tests was set a few lines earlier by the resume itself, so
the call returns -EPERM without sending anything. The return value is
discarded by every caller, so the failure is silent: advertising_paused
is cleared, HCI_ADVERTISING is set, and the controller is not
advertising.

Observed on a BCM43455 (no extended advertising) after an active scan:
btmon shows the pause disabling advertising and no re-enable in the ten
seconds that follow, the device does not appear in another controller's
scan, and btmgmt info still reports "advertising" in current settings.

Enable instance 0x00 directly in that case, the way reenable_adv_sync()
already does for the same situation. Instances continue to go through
hci_schedule_adv_instance_sync() so the software rotation loop is
rearmed.

This affects every caller of hci_resume_advertising_sync(), not only the
scan path: address resolution changes, accept list updates, discovery
stop, suspend/resume and the end of an LE connection attempt all leave
advertising disabled on such a controller today.

err is initialised because the extended branch leaves it unset when
adv_instances is empty and HCI_LE_ADV_0 is clear.

Fixes: ad383c2c65a5 ("Bluetooth: hci_sync: Enable advertising when LL privacy is enabled")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5 btmon
Signed-off-by: Valentin Kindschi <valentin.kindschi@fiveco.ch>
---
Changes in v5:
- New patch. v4 of the scan fix resumed advertising through
  hci_schedule_adv_instance_sync(), which refuses HCI_ADVERTISING on a
  controller without extended advertising, so the resume never sent
  anything. Patch 2 depends on this.

 net/bluetooth/hci_sync.c | 10 ++++++++---
 1 file changed, 7 insertions(+), 3 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
@@ -2679,7 +2679,7 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
 static int hci_resume_advertising_sync(struct hci_dev *hdev)
 {
 	struct adv_info *adv, *tmp;
-	int err;
+	int err = 0;
 
 	/* If advertising has not been paused there is nothing  to do. */
 	if (!hdev->advertising_paused)
@@ -2712,13 +2712,18 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
 		 */
 		if (hci_dev_test_and_clear_flag(hdev, HCI_LE_ADV_0))
 			err = hci_enable_ext_advertising_sync(hdev, 0x00);
-	} else {
+	} else if (hdev->cur_adv_instance) {
 		/* Schedule for most recent instance to be restarted and begin
 		 * the software rotation loop
 		 */
 		err = hci_schedule_adv_instance_sync(hdev,
 						     hdev->cur_adv_instance,
 						     true);
+	} else {
+		/* hci_schedule_adv_instance_sync() rejects instance 0x00 while
+		 * HCI_ADVERTISING is set, so enable it directly.
+		 */
+		err = hci_start_adv_sync(hdev, 0x00);
 	}
 
 	hdev->advertising_paused = false;
--
2.34.1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v5 2/2] Bluetooth: hci_sync: pause advertising for the scan address update
  2026-09-18 11:03 [PATCH v5 1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume Valentin Kindschi
@ 2026-09-18 11:03 ` Valentin Kindschi
  2026-09-18 14:44 ` [v5,1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume bluez.test.bot
  1 sibling, 0 replies; 3+ messages in thread
From: Valentin Kindschi @ 2026-09-18 11:03 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: marcel, johan.hedberg, luiz.dentz, linux-kernel,
	Valentin Kindschi, stable

hci_active_scan_sync() programs a non-resolvable private address with LE
Set Random Address on every active scan start.

BLUETOOTH CORE SPECIFICATION Vol 4, Part E, 7.8.4 says the controller
shall return Command Disallowed (0x0C) for that command while legacy
advertising or scanning is enabled. hci_pause_addr_resolution(), called
just above, only stops advertising when LL privacy is in use, so on a
controller without it the command is issued while advertising is still
on:

  Bluetooth: hci0: Opcode 0x2005 failed: -16

It does not converge either. hdev->random_addr is only set on a
successful command complete, so it stays BDADDR_ANY, and the deferral
added by commit c2994b008492 ("Bluetooth: hci_sync: Fix not setting
Random Address when required") requires it to be set. Unlike the
resolvable address a few lines above, which is reused while rpa_valid(),
the non-resolvable one is regenerated and rewritten on every call, so a
controller that refuses the write is asked again at the scan restart
period of about 10 s, for as long as discovery keeps restarting.
Observed on a BCM43455, which has no LL privacy and no extended
advertising, 190 rejections in one capture, every one retrying the same
address:

  < 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

Pause advertising for the address update, and resume it once the update
is done and before the scan is started. The pause does not outlive the
function: it is taken only when nothing else holds it, and released on
every exit. A failed pause returns before marking anything paused, so
the error path is a no-op.

The resume in the error path is no longer guarded by ll_privacy_capable().
That guard matched a pause taken only under LL privacy; the pause added
here is unconditional, and hci_resume_advertising_sync() returns early
when nothing was paused.

One caveat this widens, raised on the previous posting. When
HCI_ADVERTISING is set, hci_pause_advertising_sync() also clears
HCI_DISCOVERABLE and HCI_LIMITED_DISCOVERABLE and zeroes discov_timeout,
and hci_resume_advertising_sync() restores only HCI_ADVERTISING, so the
discoverable state is lost. It reproduces today on an LL privacy
controller through hci_pause_addr_resolution(); the unconditional pause
makes it reachable without LL privacy as well. hci_suspend_sync() also
pauses unconditionally, so a device that suspends loses the same state
on any controller today. That asymmetry is pre-existing and is left
alone here rather than folded into a scan path fix.

Legacy controllers have one random address register, shared by the
scanner and the advertiser. Restoring the advertiser here can reprogram
it when the advertiser is non-connectable, so the scan then uses that
address rather than the one generated for it. Both are non-resolvable
and neither is linkable to the identity address. With privacy enabled
both roles already share one resolvable address the same way.

With the patch, on the same hardware:

  < LE Set Advertising Enable    Enable: 0x00              Success
  < LE Set Random Address                                  Success
  < LE Set Advertising Parameters                          Success
  < LE Set Advertising Enable    Enable: 0x01              Success
  < LE Set Scan Parameters                                 Success
  < LE Set Scan Enable           Enable: 0x01              Success

The address write is accepted, and advertising is restored before the
scan is started.

Over 119369 btmon records and about 12 minutes of the normal workload of
that device, alternating active and passive scanning with ten outgoing
connection attempts, every LE Set Random Address succeeded and there were
no Command Disallowed responses of any opcode, against one per scan
restart before.

Patch 1 is required: without it the resume added here returns -EPERM on
the controllers this fixes and leaves advertising disabled.

Fixes: 3c44a431d62b ("Bluetooth: hci_sync: Resume adv with no RPA when active scan")
Cc: stable@vger.kernel.org # depends on "Bluetooth: hci_sync: re-enable legacy advertising on resume"
Assisted-by: Claude:claude-opus-5 btmon
Signed-off-by: Valentin Kindschi <valentin.kindschi@fiveco.ch>
---
Changes in v5:
- Split into two patches. v4's resume was reached through
  hci_schedule_adv_instance_sync(), which refuses HCI_ADVERTISING on a
  controller without extended advertising, so advertising was never
  re-enabled. Patch 1 fixes that and is a prerequisite for this one.
- Do not resume on the success path. hci_resume_advertising_sync()
  reaches hci_update_random_address_sync(), which for a non-connectable
  advertiser programs a fresh address, and doing that with the scan
  already enabled is refused the same way. Resume before the scan is
  started instead.
- Take the pause only when nothing else holds it and release it on every
  exit, so it cannot be released by another user of
  hdev->advertising_paused.
- v4 claimed the resume commands in the capture were issued with the scan
  already running and succeeded. That capture came from a build whose
  resume ran elsewhere; the claim is dropped. The capture above is from
  this version, on the device, under its normal workload.
- Fixes: now points at 3c44a431d62b, where the pause became conditional
  on LL privacy, rather than at the introduction of the scan function.

Changes in v4:
- Report the HCI_DISCOVERABLE asymmetry raised in review rather than fix
  it, with a reproducer in the commit message.
- Keep the explicit return on the success path, so the resume runs there
  and the function no longer falls through into failed:.
- Shorten the added comments to one line each.

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 | 16 ++++++++++++----
 1 file changed, 12 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
@@ -6246,6 +6246,7 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
 	u8 filter_policy = 0x00;
 	/* Default is to enable duplicates filter */
 	u8 filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
+	bool paused;
 	int err;
 
 	bt_dev_dbg(hdev, "");
@@ -6269,6 +6270,12 @@ 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. */
+	paused = !hdev->advertising_paused;
+	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.
@@ -6278,6 +6285,9 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
 	if (err < 0)
 		own_addr_type = ADDR_LE_DEV_PUBLIC;
 
+	if (paused)
+		hci_resume_advertising_sync(hdev);
+
 	if (hci_is_adv_monitoring(hdev) ||
 	    (hci_test_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER) &&
 	    hdev->discovery.result_filtering)) {
@@ -6301,9 +6311,8 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
 		return err;
 
 failed:
-	/* Resume advertising if it was paused */
-	if (ll_privacy_capable(hdev))
-		hci_resume_advertising_sync(hdev);
+	/* No-op when advertising was not paused. */
+	hci_resume_advertising_sync(hdev);
 
 	/* Resume passive scanning */
 	hci_update_passive_scan_sync(hdev);
--
2.34.1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [v5,1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume
  2026-09-18 11:03 [PATCH v5 1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume Valentin Kindschi
  2026-09-18 11:03 ` [PATCH v5 2/2] Bluetooth: hci_sync: pause advertising for the scan address update Valentin Kindschi
@ 2026-09-18 14:44 ` bluez.test.bot
  1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-09-18 14:44 UTC (permalink / raw)
  To: linux-bluetooth, valentin.kindschi

[-- Attachment #1: Type: text/plain, Size: 2879 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1168573/

---Test result---

Test Summary:
CheckPatch                    PASS      1.23 seconds
VerifyFixes                   PASS      0.11 seconds
VerifySignedoff               PASS      0.11 seconds
GitLint                       FAIL      0.57 seconds
SubjectPrefix                 PASS      0.21 seconds
BuildKernel                   PASS      25.25 seconds
CheckAllWarning               PASS      31.29 seconds
CheckSparse                   PASS      30.37 seconds
BuildKernel32                 PASS      25.23 seconds
CheckKernelLLVM               PASS      29.88 seconds
TestRunnerSetup               PASS      621.61 seconds
TestRunner_l2cap-tester       FAIL      17.20 seconds
TestRunner_iso-tester         PASS      25.84 seconds
TestRunner_bnep-tester        PASS      2.82 seconds
TestRunner_mgmt-tester        FAIL      57.60 seconds
TestRunner_rfcomm-tester      PASS      4.05 seconds
TestRunner_sco-tester         PASS      7.19 seconds
TestRunner_ioctl-tester       PASS      5.64 seconds
TestRunner_mesh-tester        FAIL      9.10 seconds
TestRunner_smp-tester         PASS      4.01 seconds
TestRunner_userchan-tester    PASS      3.61 seconds
TestRunner_6lowpan-tester     PASS      13.41 seconds
IncrementalBuild              PASS      29.35 seconds

Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v5,2/2] Bluetooth: hci_sync: pause advertising for the scan address update

82: B1 Line exceeds max length (101>80): "Cc: stable@vger.kernel.org # depends on "Bluetooth: hci_sync: re-enable legacy advertising on resume""
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
Total: 111, Passed: 109 (98.2%), Failed: 2, Not Run: 0

Failed Test Cases
L2CAP LE Client, Direct Advertising - Success        Failed       2.018 seconds
L2CAP Ext-Flowctl Client, Direct Advertising - Success Failed       2.046 seconds
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 501, Passed: 496 (99.0%), Failed: 1, Not Run: 4

Failed Test Cases
Read Exp Feature - Success                           Failed       0.019 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0

Failed Test Cases
Mesh - Send cancel - 1                               Timed out    2.601 seconds
Mesh - Send cancel - 2                               Timed out    1.996 seconds


https://github.com/bluez/bluetooth-next/pull/792

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-18 14:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-18 11:03 [PATCH v5 1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume Valentin Kindschi
2026-09-18 11:03 ` [PATCH v5 2/2] Bluetooth: hci_sync: pause advertising for the scan address update Valentin Kindschi
2026-09-18 14:44 ` [v5,1/2] Bluetooth: hci_sync: re-enable legacy advertising on resume bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox