* Re: [v6,1/2] Bluetooth: hci_conn: Fix null ptr deref in hci_abort_conn()
From: Siwei Zhang @ 2026-06-16 15:33 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <6a3030a7.f732ad81.18cf48.63cc@mx.google.com>
Hi Luiz,
On Mon, Jun 15, 2026, at 1:04 PM, bluez.test.bot@gmail.com wrote:
> 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/project/bluetooth/list/?series=1111791
>
> ---Test result---
>
> Test Summary:
> CheckPatch PASS 1.82 seconds
> VerifyFixes PASS 0.09 seconds
> VerifySignedoff PASS 0.09 seconds
> GitLint PASS 0.47 seconds
> SubjectPrefix PASS 0.16 seconds
> BuildKernel PASS 26.58 seconds
> CheckAllWarning PASS 28.89 seconds
> CheckSparse PASS 27.60 seconds
> BuildKernel32 PASS 25.49 seconds
> TestRunnerSetup PASS 571.42 seconds
> TestRunner_l2cap-tester PASS 58.94 seconds
> TestRunner_iso-tester PASS 96.66 seconds
> TestRunner_bnep-tester PASS 30.75 seconds
> TestRunner_mgmt-tester FAIL 207.20 seconds
> TestRunner_rfcomm-tester PASS 30.92 seconds
> TestRunner_sco-tester PASS 31.50 seconds
> TestRunner_ioctl-tester PASS 26.69 seconds
> TestRunner_mesh-tester FAIL 25.83 seconds
> TestRunner_smp-tester PASS 22.80 seconds
> TestRunner_userchan-tester PASS 19.22 seconds
> TestRunner_6lowpan-tester FAIL 45.81 seconds
> IncrementalBuild PASS 43.45 seconds
>
> Details
> ##############################
> Test: TestRunner_mgmt-tester - FAIL
> Desc: Run mgmt-tester with test-runner
> Output:
> Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4
>
> Failed Test Cases
> Read Exp Feature - Success Failed 0.234 seconds
The mgmt.c is not modified in this patch.
> ##############################
> 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.808 seconds
> Mesh - Send cancel - 2 Timed out 1.989 seconds
Also, the mesh path does not allocate hci_conn nor related to the code path changed.
> ##############################
> Test: TestRunner_6lowpan-tester - FAIL
> Desc: Run 6lowpan-tester with test-runner
> Output:
> Total: 8, Passed: 3 (37.5%), Failed: 5, Not Run: 0
>
> Failed Test Cases
> Client Connect - Disconnect Timed out 5.480 seconds
> Client Recv Dgram - Success Timed out 4.991 seconds
> Client Recv Raw - Success Timed out 4.993 seconds
> Client Recv IPHC Dgram - Success Timed out 4.999 seconds
> Client Recv IPHC Raw - Success Timed out 4.993 seconds
>
>
Fixed by the recent commit d35e2950daaf8cd362beb4ecd42af2b0d9459136.
> https://github.com/bluez/bluetooth-next/pull/318
>
> ---
> Regards,
> Linux Bluetooth
Could you please review on this patch?
And also this patch I sent on Monday.
https://lore.kernel.org/linux-bluetooth/20260612143449.3045055-1-oss@fourdim.xyz/T/#t
Thanks.
Best,
Siwei
^ permalink raw reply
* [PATCH] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v3()
From: Maoyi Xie @ 2026-06-16 15:40 UTC (permalink / raw)
To: Amitkumar Karwar, Neeraj Kale, Marcel Holtmann,
Luiz Augusto von Dentz
Cc: Ilpo Järvinen, linux-bluetooth, linux-kernel
During the v3 firmware download the controller sends a v3_data_req with a
32 bit offset and a 16 bit len. nxp_recv_fw_req_v3() checks only the lower
bound of the offset and then sends firmware from that offset.
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v3_offset, len);
Nothing checks that fw_dnld_v3_offset + len stays within nxpdev->fw->size, so a
controller that asks for an offset or length past the firmware image makes the
driver read past the end of nxpdev->fw->data and send that memory back over
UART.
nxp_recv_fw_req_v1() already bounds the same write. Add the equivalent check to
the v3 path, reject the request when it falls outside the firmware image, and
zero len on the error path so the fw_v3_prev_sent bookkeeping at free_skb stays
consistent.
Fixes: 689ca16e5232 ("Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets")
Suggested-by: Neeraj Kale <neeraj.sanjaykale@nxp.com>
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
This is the fix for the out of bounds read I reported on linux-bluetooth. Neeraj
confirmed the bug and asked me to send it. The Suggested-by is for his suggestion
to zero len on the reject path, which keeps the fw_v3_prev_sent bookkeeping at
free_skb consistent.
drivers/bluetooth/btnxpuart.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index e7036a48ce48..6a1cffe08d5f 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1267,6 +1267,12 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
}
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
+ if (nxpdev->fw_dnld_v3_offset >= nxpdev->fw->size ||
+ len > nxpdev->fw->size - nxpdev->fw_dnld_v3_offset) {
+ bt_dev_err(hdev, "FW download out of bounds, ignoring request");
+ len = 0;
+ goto free_skb;
+ }
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v3_offset, len);
--
2.34.1
^ permalink raw reply related
* RE: [v2] Bluetooth: MGMT: Add management security level changed event
From: bluez.test.bot @ 2026-06-16 16:06 UTC (permalink / raw)
To: linux-bluetooth, frederic.danis
In-Reply-To: <20260616145855.342740-1-frederic.danis@collabora.com>
[-- Attachment #1: Type: text/plain, Size: 2469 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/project/bluetooth/list/?series=1112403
---Test result---
Test Summary:
CheckPatch PASS 1.45 seconds
VerifyFixes PASS 0.07 seconds
VerifySignedoff PASS 0.07 seconds
GitLint PASS 0.20 seconds
SubjectPrefix PASS 0.06 seconds
BuildKernel PASS 26.77 seconds
CheckAllWarning PASS 29.14 seconds
CheckSparse PASS 27.75 seconds
BuildKernel32 PASS 25.71 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 576.60 seconds
TestRunner_l2cap-tester PASS 58.98 seconds
TestRunner_iso-tester PASS 78.50 seconds
TestRunner_bnep-tester PASS 18.77 seconds
TestRunner_mgmt-tester FAIL 208.08 seconds
TestRunner_rfcomm-tester PASS 25.39 seconds
TestRunner_sco-tester PASS 32.28 seconds
TestRunner_ioctl-tester PASS 25.58 seconds
TestRunner_mesh-tester FAIL 24.95 seconds
TestRunner_smp-tester PASS 23.13 seconds
TestRunner_userchan-tester PASS 19.70 seconds
TestRunner_6lowpan-tester PASS 22.49 seconds
IncrementalBuild PASS 24.70 seconds
Details
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 488 (98.8%), Failed: 2, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.245 seconds
LL Privacy - Unpair 1 Timed out 1.853 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 1.826 seconds
Mesh - Send cancel - 2 Timed out 1.992 seconds
https://github.com/bluez/bluetooth-next/pull/320
---
Regards,
Linux Bluetooth
^ permalink raw reply
* [bluez/bluez] 4f34c4: shared/gatt: Fix gatt-db buffer overflow for clone...
From: fdanis-oss @ 2026-06-16 17:23 UTC (permalink / raw)
To: linux-bluetooth
Branch: refs/heads/1112321
Home: https://github.com/bluez/bluez
Commit: 4f34c4155f8ff852ab543ba8e4ca85fcc600530b
https://github.com/bluez/bluez/commit/4f34c4155f8ff852ab543ba8e4ca85fcc600530b
Author: Frédéric Danis <frederic.danis@collabora.com>
Date: 2026-06-16 (Tue, 16 Jun 2026)
Changed paths:
M src/shared/gatt-db.c
Log Message:
-----------
shared/gatt: Fix gatt-db buffer overflow for cloned db
On notify_service_changed() timeout, db_hash_update() is called but
for cloned db the last-handle has not been copied and only one slot is
allocated, ending in buffer overflow:
==288975==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5020000ac220 at pc 0x55f8b7e551bf bp 0x7ffcd6e9ddf0 sp 0x7ffcd6e9dde0
WRITE of size 8 at 0x5020000ac220 thread T0
#0 0x55f8b7e551be in gen_hash_m src/shared/gatt-db.c:415
#1 0x55f8b7e5d817 in gatt_db_service_foreach src/shared/gatt-db.c:1744
#2 0x55f8b7e5d817 in gatt_db_service_foreach src/shared/gatt-db.c:1722
#3 0x55f8b7e60c6c in foreach_service_in_range src/shared/gatt-db.c:1633
#4 0x55f8b7e60c6c in foreach_in_range src/shared/gatt-db.c:1656
#5 0x55f8b7dde002 in queue_foreach src/shared/queue.c:207
#6 0x55f8b7e5c435 in gatt_db_foreach_service_in_range src/shared/gatt-db.c:1698
#7 0x55f8b7e5c87c in db_hash_update src/shared/gatt-db.c:442
#8 0x55f8b7f15283 in timeout_callback src/shared/timeout-glib.c:25
#9 0x7fc1845154f1 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5e4f1) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
#10 0x7fc18451445d (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5d45d) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
#11 0x7fc184573976 (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0xbc976) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
#12 0x7fc184514f46 in g_main_loop_run (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5df46) (BuildId: 116e142b9b52c8a4dfd403e759e71ab8f95d8bb3)
#13 0x55f8b7f157e8 in mainloop_run src/shared/mainloop-glib.c:65
#14 0x55f8b7f16116 in mainloop_run_with_signal src/shared/mainloop-notify.c:196
#15 0x55f8b7af46df in main src/main.c:1709
#16 0x7fc18382a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#17 0x7fc18382a28a in __libc_start_main_impl ../csu/libc-start.c:360
#18 0x55f8b7af68b4 in _start (/home/fdanis/src/bluez/src/bluetoothd+0x6588b4) (BuildId: 89dc89ac5800f58cc305bae57a965b1185601a3e)
0x5020000ac220 is located 0 bytes after 16-byte region [0x5020000ac210,0x5020000ac220)
allocated by thread T0 here:
#0 0x7fc1846fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x55f8b7ddf2b6 in util_malloc src/shared/util.c:46
To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications
^ permalink raw reply
* RE: Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v3()
From: bluez.test.bot @ 2026-06-16 19:25 UTC (permalink / raw)
To: linux-bluetooth, maoyixie.tju
In-Reply-To: <178162441367.2434858.9590661629618538235@maoyixie.com>
[-- Attachment #1: Type: text/plain, Size: 2563 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/project/bluetooth/list/?series=1112441
---Test result---
Test Summary:
CheckPatch FAIL 0.44 seconds
VerifyFixes PASS 0.08 seconds
VerifySignedoff PASS 0.08 seconds
GitLint FAIL 0.21 seconds
SubjectPrefix PASS 0.07 seconds
BuildKernel PASS 16.91 seconds
CheckAllWarning PASS 20.08 seconds
CheckSparse PASS 18.00 seconds
BuildKernel32 PASS 16.75 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 329.06 seconds
IncrementalBuild PASS 16.02 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v3()
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#108:
Nothing checks that fw_dnld_v3_offset + len stays within nxpdev->fw->size, so a
total: 0 errors, 1 warnings, 12 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14631861.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v3()
7: B3 Line contains hard tab characters (\t): " nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;"
8: B3 Line contains hard tab characters (\t): " serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +"
9: B3 Line contains hard tab characters (\t): " nxpdev->fw_dnld_v3_offset, len);"
26: B1 Line exceeds max length (81>80): "confirmed the bug and asked me to send it. The Suggested-by is for his suggestion"
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
https://github.com/bluez/bluetooth-next/pull/321
---
Regards,
Linux Bluetooth
^ permalink raw reply
* [Bug 221660] New: btmtk (MT7921K / RZ608): BR/EDR outgoing connection always fails with Page Timeout (0x04); scan/receive works, same device pairs fine on Windows
From: bugzilla-daemon @ 2026-06-16 22:39 UTC (permalink / raw)
To: linux-bluetooth
https://bugzilla.kernel.org/show_bug.cgi?id=221660
Bug ID: 221660
Summary: btmtk (MT7921K / RZ608): BR/EDR outgoing connection
always fails with Page Timeout (0x04); scan/receive
works, same device pairs fine on Windows
Product: Drivers
Version: 2.5
Kernel Version: 7.0.12-arch1-1
Hardware: AMD
OS: Linux
Status: NEW
Severity: normal
Priority: P3
Component: Bluetooth
Assignee: linux-bluetooth@vger.kernel.org
Reporter: bynxmusic@gmail.com
Regression: No
Created attachment 310333
--> https://bugzilla.kernel.org/attachment.cgi?id=310333&action=edit
btmon HCI trace (binary + decoded) of the Page Timeout + system info
btmtk (MT7921K / RZ608): every BR/EDR outgoing connection fails with Page
Timeout (0x04). Scan/receive works, and the same device pairs fine on Windows.
HARDWARE
WiFi+BT combo: MediaTek MT7921K (RZ608) Wi-Fi 6E, PCI 14c3:0608, driver
mt7921e
Bluetooth function: USB 0e8d:0608 (MediaTek Inc. Wireless_Device), btusb +
btmtk
Motherboard onboard radio, AMD desktop platform
SOFTWARE
Kernel: 7.0.12-arch1-1 (x86_64), Arch Linux (rolling)
linux-firmware: 20260519-1 ; linux-firmware-mediatek: 20260519-1
BlueZ: 5.86
BT controller firmware: HW/SW Version 0x008a008a, Build Time 20260224111243
BT firmware blob loads OK: mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin
WHAT WORKS
Controller initializes cleanly every boot ("hci0: Device setup in ~160000
usecs", AOSP extensions v1.00). Inquiry/scan works: remote devices (a
Skullcandy Crusher Evo headset and a Samsung TV) are reliably discovered with
RSSI, so the RX path is fine.
THE BUG
Every outgoing connection (page) to any BR/EDR device times out. HCI Create
Connection is issued and accepted (Command Status: Success), but roughly 7.7
s
later the controller returns Connect Complete with Status: Page Timeout
(0x04).
BlueZ reports org.bluez.Error.ConnectionAttemptFailed. The remote device
never
registers a connection. The same headset on the same PC pairs and works
perfectly under Windows, so this is not dead hardware or a peripheral issue;
it is the btmtk/MT7921K outgoing-connection path on Linux.
KEY HCI TRACE (btmon), captured with the WiFi driver (mt7921e) UNLOADED, i.e.
WiFi/BT coexistence ruled out:
< HCI Command: Create Connection (0x01|0x0005) plen 13 #9 [hci0] 14.208614
Address: 88:08:94:13:8F:94 (Skullcandy)
Packet type: 0xcc18 (DM1/DH1/DM3/DH3 ...)
> HCI Event: Command Status (0x0f) plen 4 #10 [hci0] 14.209664
Create Connection (0x01|0x0005) ncmd 1
Status: Success (0x00)
> HCI Event: Connect Complete (0x03) plen 11 #11 [hci0] 21.899975
Status: Page Timeout (0x04)
Handle: 0
Address: 88:08:94:13:8F:94 (Skullcandy)
Link type: ACL (0x01)
Also seen intermittently in dmesg during attempts:
Bluetooth: hci0: ACL packet for unknown connection handle 3837
STEPS TO REPRODUCE
1. Boot with MT7921K onboard Bluetooth.
2. Put any BR/EDR device (e.g. a freshly factory-reset BT headset) in pairing
mode.
3. In bluetoothctl: scan on (device IS discovered), then pair <MAC>.
4. Pairing fails with org.bluez.Error.ConnectionAttemptFailed; btmon shows
Connect Complete: Page Timeout (0x04).
EXPECTED vs ACTUAL
Expected: Create Connection succeeds and pairing/bonding proceeds (as on
Windows).
Actual: every Create Connection ends in Page Timeout; no outgoing connection
ever completes.
ALREADY RULED OUT
- USB autosuspend: disabled via options btusb enable_autosuspend=0 (confirmed
power/control=on). No change.
- WiFi/BT coexistence: Page Timeout persists even with mt7921e fully unloaded
(modprobe -r mt7921e); the trace above is from that state. Also tested with
rfkill block wifi. No change.
- LE vs BR/EDR bearer: tested with and without Experimental, and with
ControllerMode = bredr. No change.
- Stale/half state: reproduced after a fresh cold boot (controller not
wedged).
- Remote device: Crusher Evo factory-reset; nothing else paired to it
(phone/TV BT off); works on Windows.
ATTACHMENTS
- bt-hci-trace.btsnoop: full binary btmon capture of one failed pairing.
- bt-bugreport.txt: full system diagnostic bundle (versions, lspci/lsusb,
dmesg).
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are the assignee for the bug.
^ permalink raw reply
* [bluetooth-next:master] BUILD SUCCESS cb20f6afc25b2b54c0fec61b45ac0ec9eb875d59
From: kernel test robot @ 2026-06-17 0:30 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
branch HEAD: cb20f6afc25b2b54c0fec61b45ac0ec9eb875d59 Bluetooth: MGMT: Fix UAF of hci_conn_params in add_device_complete
elapsed time: 986m
configs tested: 289
configs skipped: 3
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-16.1.0
alpha allyesconfig gcc-16.1.0
alpha defconfig gcc-16.1.0
arc allmodconfig clang-23
arc allmodconfig gcc-16.1.0
arc allnoconfig gcc-16.1.0
arc allyesconfig clang-23
arc defconfig gcc-16.1.0
arc randconfig-001-20260616 gcc-9.5.0
arc randconfig-001-20260617 gcc-16.1.0
arc randconfig-002-20260616 gcc-9.5.0
arc randconfig-002-20260617 gcc-16.1.0
arm allnoconfig clang-23
arm allnoconfig gcc-16.1.0
arm allyesconfig clang-23
arm allyesconfig gcc-16.1.0
arm defconfig gcc-16.1.0
arm lpc18xx_defconfig clang-23
arm randconfig-001-20260616 gcc-9.5.0
arm randconfig-001-20260617 gcc-16.1.0
arm randconfig-002-20260616 gcc-9.5.0
arm randconfig-002-20260617 gcc-16.1.0
arm randconfig-003-20260616 gcc-9.5.0
arm randconfig-003-20260617 gcc-16.1.0
arm randconfig-004-20260616 gcc-9.5.0
arm randconfig-004-20260617 gcc-16.1.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
arm64 defconfig gcc-16.1.0
arm64 randconfig-001-20260617 gcc-12.5.0
arm64 randconfig-002-20260617 gcc-12.5.0
arm64 randconfig-003-20260617 gcc-12.5.0
arm64 randconfig-004-20260617 gcc-12.5.0
csky allmodconfig gcc-16.1.0
csky allnoconfig gcc-16.1.0
csky defconfig gcc-16.1.0
csky randconfig-001-20260617 gcc-12.5.0
csky randconfig-002-20260617 gcc-12.5.0
hexagon allmodconfig clang-23
hexagon allmodconfig gcc-16.1.0
hexagon allnoconfig clang-23
hexagon allnoconfig gcc-16.1.0
hexagon defconfig gcc-16.1.0
hexagon randconfig-001-20260616 clang-23
hexagon randconfig-001-20260617 clang-17
hexagon randconfig-002-20260616 clang-23
hexagon randconfig-002-20260617 clang-17
i386 allmodconfig clang-22
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allnoconfig gcc-16.1.0
i386 allyesconfig clang-22
i386 buildonly-randconfig-001-20260616 gcc-14
i386 buildonly-randconfig-001-20260617 gcc-14
i386 buildonly-randconfig-002-20260616 clang-22
i386 buildonly-randconfig-002-20260617 gcc-14
i386 buildonly-randconfig-003-20260616 gcc-14
i386 buildonly-randconfig-003-20260617 gcc-14
i386 buildonly-randconfig-004-20260616 gcc-14
i386 buildonly-randconfig-004-20260617 gcc-14
i386 buildonly-randconfig-005-20260616 gcc-14
i386 buildonly-randconfig-005-20260617 gcc-14
i386 buildonly-randconfig-006-20260616 gcc-14
i386 buildonly-randconfig-006-20260617 gcc-14
i386 defconfig gcc-16.1.0
i386 randconfig-001-20260616 gcc-14
i386 randconfig-001-20260617 gcc-13
i386 randconfig-002-20260616 gcc-14
i386 randconfig-002-20260617 gcc-13
i386 randconfig-003-20260616 gcc-14
i386 randconfig-003-20260617 gcc-13
i386 randconfig-004-20260616 gcc-14
i386 randconfig-004-20260617 gcc-13
i386 randconfig-005-20260616 gcc-14
i386 randconfig-005-20260617 gcc-13
i386 randconfig-006-20260616 gcc-14
i386 randconfig-006-20260617 gcc-13
i386 randconfig-007-20260616 gcc-14
i386 randconfig-007-20260617 gcc-13
i386 randconfig-011-20260616 gcc-14
i386 randconfig-011-20260617 clang-22
i386 randconfig-012-20260616 gcc-14
i386 randconfig-012-20260617 clang-22
i386 randconfig-013-20260616 gcc-14
i386 randconfig-013-20260617 clang-22
i386 randconfig-014-20260616 gcc-14
i386 randconfig-014-20260617 clang-22
i386 randconfig-015-20260616 gcc-14
i386 randconfig-015-20260617 clang-22
i386 randconfig-016-20260616 clang-22
i386 randconfig-016-20260617 clang-22
i386 randconfig-017-20260616 clang-22
i386 randconfig-017-20260617 clang-22
loongarch allmodconfig clang-23
loongarch allnoconfig clang-20
loongarch allnoconfig gcc-16.1.0
loongarch defconfig clang-23
loongarch randconfig-001-20260616 clang-23
loongarch randconfig-001-20260617 clang-17
loongarch randconfig-002-20260616 clang-23
loongarch randconfig-002-20260617 clang-17
m68k allmodconfig gcc-16.1.0
m68k allnoconfig gcc-16.1.0
m68k allyesconfig clang-23
m68k allyesconfig gcc-16.1.0
m68k defconfig clang-23
m68k defconfig gcc-16.1.0
m68k hp300_defconfig gcc-16.1.0
microblaze allnoconfig gcc-16.1.0
microblaze allyesconfig gcc-16.1.0
microblaze defconfig clang-23
microblaze defconfig gcc-16.1.0
mips allmodconfig gcc-16.1.0
mips allnoconfig gcc-16.1.0
mips allyesconfig gcc-16.1.0
mips malta_kvm_defconfig gcc-16.1.0
nios2 allmodconfig clang-20
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig clang-23
nios2 defconfig clang-23
nios2 defconfig gcc-11.5.0
nios2 randconfig-001-20260616 clang-23
nios2 randconfig-001-20260617 clang-17
nios2 randconfig-002-20260616 clang-23
nios2 randconfig-002-20260617 clang-17
openrisc allmodconfig clang-20
openrisc allmodconfig gcc-16.1.0
openrisc allnoconfig clang-23
openrisc defconfig gcc-16.1.0
parisc allmodconfig gcc-16.1.0
parisc allnoconfig clang-23
parisc allyesconfig clang-17
parisc allyesconfig gcc-16.1.0
parisc defconfig gcc-16.1.0
parisc randconfig-001-20260617 gcc-15.2.0
parisc randconfig-002-20260617 gcc-15.2.0
parisc64 defconfig clang-23
parisc64 defconfig gcc-16.1.0
powerpc allmodconfig gcc-16.1.0
powerpc allnoconfig clang-23
powerpc randconfig-001-20260617 gcc-15.2.0
powerpc randconfig-002-20260617 gcc-15.2.0
powerpc64 randconfig-001-20260617 gcc-15.2.0
powerpc64 randconfig-002-20260617 gcc-15.2.0
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allyesconfig clang-23
riscv defconfig gcc-16.1.0
riscv randconfig-001 gcc-13.4.0
riscv randconfig-001-20260616 gcc-9.5.0
riscv randconfig-001-20260617 gcc-16.1.0
riscv randconfig-002 clang-23
riscv randconfig-002-20260616 clang-23
riscv randconfig-002-20260617 gcc-16.1.0
s390 allmodconfig clang-17
s390 allnoconfig clang-23
s390 allyesconfig gcc-16.1.0
s390 defconfig gcc-16.1.0
s390 randconfig-001 gcc-15.2.0
s390 randconfig-001-20260616 clang-23
s390 randconfig-001-20260617 gcc-16.1.0
s390 randconfig-002 clang-18
s390 randconfig-002-20260616 clang-18
s390 randconfig-002-20260617 gcc-16.1.0
sh allmodconfig gcc-16.1.0
sh allnoconfig clang-23
sh allyesconfig clang-17
sh allyesconfig gcc-16.1.0
sh defconfig gcc-14
sh randconfig-001 gcc-14.3.0
sh randconfig-001-20260616 gcc-16.1.0
sh randconfig-001-20260617 gcc-16.1.0
sh randconfig-002 gcc-9.5.0
sh randconfig-002-20260616 gcc-13.4.0
sh randconfig-002-20260617 gcc-16.1.0
sparc allnoconfig clang-23
sparc defconfig gcc-16.1.0
sparc randconfig-001-20260616 gcc-8.5.0
sparc randconfig-001-20260617 gcc-16.1.0
sparc randconfig-002-20260616 gcc-8.5.0
sparc randconfig-002-20260617 gcc-16.1.0
sparc64 allmodconfig clang-20
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260616 gcc-8.5.0
sparc64 randconfig-001-20260617 gcc-16.1.0
sparc64 randconfig-002-20260616 gcc-8.5.0
sparc64 randconfig-002-20260617 gcc-16.1.0
um allmodconfig clang-17
um allnoconfig clang-23
um allyesconfig gcc-14
um allyesconfig gcc-16.1.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260616 gcc-8.5.0
um randconfig-001-20260617 gcc-16.1.0
um randconfig-002-20260616 gcc-8.5.0
um randconfig-002-20260617 gcc-16.1.0
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-22
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-22
x86_64 buildonly-randconfig-001-20260616 gcc-14
x86_64 buildonly-randconfig-001-20260617 clang-22
x86_64 buildonly-randconfig-002-20260616 gcc-14
x86_64 buildonly-randconfig-002-20260617 clang-22
x86_64 buildonly-randconfig-003-20260616 gcc-12
x86_64 buildonly-randconfig-003-20260617 clang-22
x86_64 buildonly-randconfig-004-20260616 gcc-12
x86_64 buildonly-randconfig-004-20260617 clang-22
x86_64 buildonly-randconfig-005-20260616 gcc-14
x86_64 buildonly-randconfig-005-20260617 clang-22
x86_64 buildonly-randconfig-006-20260616 gcc-14
x86_64 buildonly-randconfig-006-20260617 clang-22
x86_64 defconfig gcc-14
x86_64 kexec clang-22
x86_64 randconfig-001-20260617 clang-22
x86_64 randconfig-002-20260617 clang-22
x86_64 randconfig-003-20260617 clang-22
x86_64 randconfig-004-20260617 clang-22
x86_64 randconfig-005-20260617 clang-22
x86_64 randconfig-006-20260617 clang-22
x86_64 randconfig-011 clang-22
x86_64 randconfig-011 gcc-14
x86_64 randconfig-011-20260616 clang-22
x86_64 randconfig-011-20260616 gcc-14
x86_64 randconfig-011-20260617 clang-22
x86_64 randconfig-012 clang-22
x86_64 randconfig-012 gcc-14
x86_64 randconfig-012-20260616 clang-22
x86_64 randconfig-012-20260616 gcc-14
x86_64 randconfig-012-20260617 clang-22
x86_64 randconfig-013 clang-22
x86_64 randconfig-013-20260616 clang-22
x86_64 randconfig-013-20260617 clang-22
x86_64 randconfig-014 clang-22
x86_64 randconfig-014 gcc-14
x86_64 randconfig-014-20260616 clang-22
x86_64 randconfig-014-20260617 clang-22
x86_64 randconfig-015 clang-22
x86_64 randconfig-015 gcc-14
x86_64 randconfig-015-20260616 clang-22
x86_64 randconfig-015-20260617 clang-22
x86_64 randconfig-016 clang-22
x86_64 randconfig-016-20260616 clang-22
x86_64 randconfig-016-20260616 gcc-14
x86_64 randconfig-016-20260617 clang-22
x86_64 randconfig-071 gcc-13
x86_64 randconfig-071 gcc-14
x86_64 randconfig-071-20260616 gcc-13
x86_64 randconfig-071-20260616 gcc-14
x86_64 randconfig-071-20260617 clang-22
x86_64 randconfig-072 gcc-13
x86_64 randconfig-072 gcc-14
x86_64 randconfig-072-20260616 clang-22
x86_64 randconfig-072-20260616 gcc-13
x86_64 randconfig-072-20260617 clang-22
x86_64 randconfig-073 clang-22
x86_64 randconfig-073 gcc-13
x86_64 randconfig-073-20260616 gcc-13
x86_64 randconfig-073-20260616 gcc-14
x86_64 randconfig-073-20260617 clang-22
x86_64 randconfig-074 gcc-13
x86_64 randconfig-074 gcc-14
x86_64 randconfig-074-20260616 gcc-13
x86_64 randconfig-074-20260616 gcc-14
x86_64 randconfig-074-20260617 clang-22
x86_64 randconfig-075 gcc-13
x86_64 randconfig-075-20260616 gcc-12
x86_64 randconfig-075-20260616 gcc-13
x86_64 randconfig-075-20260617 clang-22
x86_64 randconfig-076 clang-22
x86_64 randconfig-076 gcc-13
x86_64 randconfig-076-20260616 gcc-13
x86_64 randconfig-076-20260616 gcc-14
x86_64 randconfig-076-20260617 clang-22
x86_64 rhel-9.4 clang-22
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-22
x86_64 rhel-9.4-kselftests clang-22
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-22
xtensa allnoconfig clang-23
xtensa allyesconfig clang-20
xtensa allyesconfig gcc-16.1.0
xtensa randconfig-001-20260616 gcc-8.5.0
xtensa randconfig-001-20260617 gcc-16.1.0
xtensa randconfig-002-20260616 gcc-8.5.0
xtensa randconfig-002-20260617 gcc-16.1.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check
From: Sean Wang @ 2026-06-17 0:40 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Mark-yw Chen, Sean Wang,
Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
linux-mediatek, stable
In-Reply-To: <20260616111224.152140-2-senozhatsky@chromium.org>
Hi,
On Tue, Jun 16, 2026 at 6:15 AM Sergey Senozhatsky
<senozhatsky@chromium.org> wrote:
>
> The btmtksdio_txrx_work() loop is expected to be terminated if running
> for longer than 5*HZ. However the timeout check is reversed:
> time_is_before_jiffies(old_jiffies + 5*HZ) evaluates to true when
> old_jiffies + 5*HZ is in the past i.e. when a timeout has occurred.
> Using OR with time_is_before_jiffies(txrx_timeout) means that:
> - before the 5-second timeout: the condition is `int_status || false`,
> so it loops as long as there are pending interrupts.
> - after the 5-second timeout: the condition becomes `int_status || true`,
> which is always true.
>
> Fix loop termination condition to actually enforce a 5*HZ timeout.
>
> Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> ---
> drivers/bluetooth/btmtksdio.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
> index 5b0fab7b89b5..c6f80c419e90 100644
> --- a/drivers/bluetooth/btmtksdio.c
> +++ b/drivers/bluetooth/btmtksdio.c
> @@ -620,7 +620,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
> if (btmtksdio_rx_packet(bdev, rx_size) < 0)
> bdev->hdev->stat.err_rx++;
> }
> - } while (int_status || time_is_before_jiffies(txrx_timeout));
> + } while (int_status && time_is_after_jiffies(txrx_timeout));
>
This patch has already been merged, so I think the series should be
respun based on the latest code.
> /* Enable interrupt */
> if (bdev->func->irq_handler)
> --
> 2.54.0.1136.gdb2ca164c4-goog
>
>
^ permalink raw reply
* Re: [PATCH v2 3/3] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope
From: Sean Wang @ 2026-06-17 0:56 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Marcel Holtmann, Luiz Augusto von Dentz, Mark-yw Chen, Sean Wang,
Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
linux-mediatek, stable
In-Reply-To: <20260616111224.152140-4-senozhatsky@chromium.org>
Hi,
On Tue, Jun 16, 2026 at 6:15 AM Sergey Senozhatsky
<senozhatsky@chromium.org> wrote:
>
> cancel_work_sync() should be called outside of host lock scope
> in order to avoid circular locking scenario:
>
> CPU0 CPU1
> close()/reset()
> sdio_claim_host()
> txrx_work
> sdio_claim_host() // sleeps
> cancel_work_sync() // sleeps
>
> In addition, when txrx_work() runs concurrently with close()/reset()
> it better not to re-enable interrupts by testing for BTMTKSDIO_FUNC_ENABLED
> and not BTMTKSDIO_HW_RESET_ACTIVE before C_INT_EN_SET write. However,
> btmtksdio_close() clears the BTMTKSDIO_FUNC_ENABLED too late (after
> cancel_work_sync() call). Move BTMTKSDIO_FUNC_ENABLED bit-clear earlier
> so that txrx_work can see concurrent close().
>
> Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> ---
> drivers/bluetooth/btmtksdio.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
> index d8c8d2857527..207d04cc2282 100644
> --- a/drivers/bluetooth/btmtksdio.c
> +++ b/drivers/bluetooth/btmtksdio.c
> @@ -625,7 +625,9 @@ static void btmtksdio_txrx_work(struct work_struct *work)
> } while (int_status && time_is_after_jiffies(txrx_timeout));
>
> /* Enable interrupt */
> - if (bdev->func->irq_handler)
> + if (bdev->func->irq_handler &&
> + test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state) &&
> + !test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
> sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
>
> sdio_release_host(bdev->func);
> @@ -741,6 +743,8 @@ static int btmtksdio_close(struct hci_dev *hdev)
> if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
> return 0;
>
> + clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
> +
> sdio_claim_host(bdev->func);
>
> /* Disable interrupt */
> @@ -748,11 +752,12 @@ static int btmtksdio_close(struct hci_dev *hdev)
>
> sdio_release_irq(bdev->func);
>
> + sdio_release_host(bdev->func);
> cancel_work_sync(&bdev->txrx_work);
> + sdio_claim_host(bdev->func);
>
> btmtksdio_fw_pmctrl(bdev);
>
> - clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
> sdio_disable_func(bdev->func);
>
> sdio_release_host(bdev->func);
> @@ -1295,7 +1300,10 @@ static void btmtksdio_reset(struct hci_dev *hdev)
>
> sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
> skb_queue_purge(&bdev->txq);
> +
> + sdio_release_host(bdev->func);
> cancel_work_sync(&bdev->txrx_work);
> + sdio_claim_host(bdev->func);
>
> gpiod_set_value_cansleep(bdev->reset, 1);
> msleep(100);
The patch looks good to me. Inspired by your patch,
do you think should we add another patch to keep txrx_work out of the
reset window by rejecting TX during reset,
ignoring reset-time interrupts, and making queued workers exit early?
Some code like:
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -567,6 +567,8 @@ static void btmtksdio_txrx_work(struct work_struct *work)
pm_runtime_get_sync(bdev->dev);
sdio_claim_host(bdev->func);
+ if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
+ goto out;
/* Disable interrupt */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
@@ -628,6 +630,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
!test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
+out:
sdio_release_host(bdev->func);
pm_runtime_put_autosuspend(bdev->dev);
@@ -646,6 +649,9 @@ static void btmtksdio_interrupt(struct sdio_func *func)
/* Disable interrupt */
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
+ if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
+ return;
+
schedule_work(&bdev->txrx_work);
}
@@ -1250,6 +1256,9 @@ static int btmtksdio_send_frame(struct hci_dev
*hdev, struct sk_buff *skb)
{
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
+ if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
+ return -EBUSY;
+
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
> --
> 2.54.0.1136.gdb2ca164c4-goog
>
>
^ permalink raw reply
* Re: [PATCH v1] Bluetooth: btmtk: Add MT7928 support
From: Chris Lu (陸稚泓) @ 2026-06-17 1:53 UTC (permalink / raw)
To: luiz.dentz@gmail.com, johan.hedberg@gmail.com,
marcel@holtmann.org, pav@iki.fi
Cc: Sean Wang, linux-mediatek@lists.infradead.org,
SS Wu (巫憲欣),
Steve Lee (李視誠),
Will-CY Lee (李政穎),
linux-bluetooth@vger.kernel.org
In-Reply-To: <cb14eaa1c566ed30119ca66bff0484192f852e91.camel@iki.fi>
Hi Pauli,
On Tue, 2026-06-16 at 17:38 +0300, Pauli Virtanen wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Hi,
>
> ti, 2026-06-16 kello 11:01 +0800, Chris Lu kirjoitti:
> > Add support for MT7928 (device ID 0x7935) which requires additional
> > firmware (CBMCU firmware) loading before Bluetooth firmware.
> >
> > Implement two-phase CBMCU firmware download: Phase 1 loads
> > section with type 0x5 containing global descriptor,
> > section maps and signature data; Phase 2 loads remaining
> > firmware sections. Add retry mechanism for concurrent download
> > protection.
> >
> > After CBMCU firmware loads successfully, the driver continues
> > to load corresponding BT firmware based on device ID through
> > fallthrough to case 0x7922/0x7925.
> >
> > Signed-off-by: Chris Lu <chris.lu@mediatek.com>
> > ---
> [clip]
> > diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
> > index c83c24897c95..6d3bf6b74a1d 100644
> > --- a/drivers/bluetooth/btmtk.h
> > +++ b/drivers/bluetooth/btmtk.h
> > @@ -9,6 +9,8 @@
> > #define FIRMWARE_MT7961
> > "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
> > #define FIRMWARE_MT7925
> > "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
> > #define FIRMWARE_MT7927
> > "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"
> > +#define FIRMWARE_MT7928
> > "mediatek/mt7928/BT_RAM_CODE_MT7935_1_1_hdr.bin"
> > +#define FIRMWARE_MT7928_CBMCU
> > "mediatek/mt7928/CBMCU_CODE_MT7935_1_1.bin"
>
> Are these firmware names correct?
>
> The above names for MT7928 say MT79**35** not MT7928?
The naming is intentional,
MT7928 is the external/marketing name, while MT7935 is MediaTek's
internal codename for same chip. The firmware filename follows and
generate with internal codename. Windows PC paired with MT7928 also
follows this rule.
>
> >
> > #define HCI_EV_WMT 0xe4
> > #define HCI_WMT_MAX_EVENT_SIZE 64
> > @@ -54,6 +56,7 @@ enum {
> > BTMTK_WMT_RST = 0x7,
> > BTMTK_WMT_REGISTER = 0x8,
> > BTMTK_WMT_SEMAPHORE = 0x17,
> > + BTMTK_WMT_CBMCU_DWNLD = 0x58,
> > };
> >
> > enum {
>
> --
> Pauli Virtanen
Chris Lu
^ permalink raw reply
* Re: [PATCH v1] Bluetooth: btmtk: Add MT7928 support
From: Chris Lu (陸稚泓) @ 2026-06-17 2:16 UTC (permalink / raw)
To: pmenzel@molgen.mpg.de
Cc: Will-CY Lee (李政穎),
Steve Lee (李視誠), luiz.dentz@gmail.com,
marcel@holtmann.org, SS Wu (巫憲欣),
linux-kernel@vger.kernel.org, johan.hedberg@gmail.com, Sean Wang,
linux-bluetooth@vger.kernel.org,
linux-mediatek@lists.infradead.org
In-Reply-To: <6b29b553-d703-448d-9275-62912a62e356@molgen.mpg.de>
Hi Paul,
On Tue, 2026-06-16 at 12:24 +0200, Paul Menzel wrote:
>
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>
>
> Dear Chris,
>
>
> Thank you for your patch.
>
> Am 16.06.26 um 05:01 schrieb Chris Lu:
> > Add support for MT7928 (device ID 0x7935) which requires additional
> > firmware (CBMCU firmware) loading before Bluetooth firmware.
>
> Please detail what CBMCU firmware is.
CBMCU is a new component on MT7928 to handle common part shared across
the combo chip (Wi-Fi/Bluetooth's subsystem), providing a better user
experience through improved coordination between subsystems.
>
> > Implement two-phase CBMCU firmware download: Phase 1 loads
> > section with type 0x5 containing global descriptor,
> > section maps and signature data; Phase 2 loads remaining
> > firmware sections. Add retry mechanism for concurrent download
> > protection.
>
> What is type 0x5? How big is the firmware, and how long does it take?
>
> > After CBMCU firmware loads successfully, the driver continues
> > to load corresponding BT firmware based on device ID through
> > fallthrough to case 0x7922/0x7925.
>
> Please add the new log message to the commit message.
>
> > Signed-off-by: Chris Lu <chris.lu@mediatek.com>
> > ---
> > drivers/bluetooth/btmtk.c | 342
> > +++++++++++++++++++++++++++++++++++++-
> > drivers/bluetooth/btmtk.h | 3 +
> > 2 files changed, 344 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
> > index 02a96342e964..a68c67d1df4b 100644
> > --- a/drivers/bluetooth/btmtk.c
> > +++ b/drivers/bluetooth/btmtk.c
> > @@ -21,6 +21,7 @@
> > #define MTK_FW_ROM_PATCH_SEC_MAP_SIZE 64
> > #define MTK_SEC_MAP_COMMON_SIZE 12
> > #define MTK_SEC_MAP_NEED_SEND_SIZE 52
> > +#define MTK_SEC_MAP_LENGTH_SIZE 4
> >
> > /* It is for mt79xx iso data transmission setting */
> > #define MTK_ISO_THRESHOLD 264
> > @@ -120,6 +121,10 @@ void btmtk_fw_get_filename(char *buf, size_t
> > size, u32 dev_id, u32 fw_ver,
> > snprintf(buf, size,
> >
> > "mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
> > dev_id & 0xffff, dev_id & 0xffff, (fw_ver &
> > 0xff) + 1);
> > + else if (dev_id == 0x7935)
> > + snprintf(buf, size,
> > +
> > "mediatek/mt7928/BT_RAM_CODE_MT%04x_1_1_hdr.bin",
> > + dev_id & 0xffff);
> > else if (dev_id == 0x7961 && fw_flavor)
> > snprintf(buf, size,
> > "mediatek/BT_RAM_CODE_MT%04x_1a_%x_hdr.bin",
> > @@ -734,6 +739,7 @@ static int btmtk_usb_hci_wmt_sync(struct
> > hci_dev *hdev,
> > status = BTMTK_WMT_ON_UNDONE;
> > break;
> > case BTMTK_WMT_PATCH_DWNLD:
> > + case BTMTK_WMT_CBMCU_DWNLD:
> > if (wmt_evt->whdr.flag == 2)
> > status = BTMTK_WMT_PATCH_DONE;
> > else if (wmt_evt->whdr.flag == 1)
> > @@ -870,6 +876,329 @@ static u32 btmtk_usb_reset_done(struct
> > hci_dev *hdev)
> > return val & MTK_BT_RST_DONE;
> > }
> >
> > +static int btmtk_cbmcu_patch_status(struct hci_dev *hdev,
> > + wmt_cmd_sync_func_t wmt_cmd_sync,
> > + u8 *patch_status)
> > +{
> > + struct btmtk_hci_wmt_params wmt_params;
> > + int status, err, retry = 20;
> > +
> > + do {
> > + wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
> > + wmt_params.flag = 0xF0;
> > + wmt_params.dlen = 0;
> > + wmt_params.data = NULL;
> > + wmt_params.status = &status;
> > +
> > + err = wmt_cmd_sync(hdev, &wmt_params);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to query CBMCU patch
> > status (%d)", err);
> > + return err;
> > + }
> > +
> > + *patch_status = (u8)status;
> > +
> > + if (*patch_status == BTMTK_WMT_PATCH_PROGRESS) {
> > + msleep(100);
> > + retry--;
> > + } else {
> > + break;
> > + }
> > + } while (retry > 0);
> > +
> > + return 0;
> > +}
> > +
> > +static int btmtk_query_cbmcu_section(struct hci_dev *hdev,
> > + wmt_cmd_sync_func_t
> > wmt_cmd_sync,
> > + u8 cbmcu_type,
> > + const u8 *section_map,
> > + u32 cert_len)
> > +{
> > + struct btmtk_hci_wmt_params wmt_params;
> > + u8 cmd[64];
> > + int status, err;
> > +
> > + cmd[0] = 0;
> > + cmd[1] = cbmcu_type;
> > +
> > + if (cbmcu_type == 0)
> > + put_unaligned_le32(cert_len, &cmd[2]);
> > + else
> > + memcpy(&cmd[2], section_map,
> > MTK_SEC_MAP_NEED_SEND_SIZE);
> > +
> > + wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
> > + wmt_params.flag = 0;
> > + wmt_params.dlen = cbmcu_type ?
> > + MTK_SEC_MAP_NEED_SEND_SIZE + 2 :
> > + MTK_SEC_MAP_LENGTH_SIZE + 2;
> > + wmt_params.data = cmd;
> > + wmt_params.status = &status;
> > +
> > + err = wmt_cmd_sync(hdev, &wmt_params);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to query CBMCU section
> > (%d)", err);
> > + return err;
> > + }
> > +
> > + /* Query should return UNDONE status for successful section
> > query */
> > + if (status != BTMTK_WMT_PATCH_UNDONE) {
> > + bt_dev_err(hdev, "CBMCU section query status error
> > (%d)", status);
> > + return -EIO;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int btmtk_download_cbmcu_section(struct hci_dev *hdev,
> > + wmt_cmd_sync_func_t
> > wmt_cmd_sync,
> > + const u8 *fw_data,
> > + u32 dl_size)
> > +{
> > + struct btmtk_hci_wmt_params wmt_params;
> > + u32 sent_len, total_size = dl_size;
> > + int err;
> > +
> > + wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
> > + wmt_params.status = NULL;
> > +
> > + while (dl_size > 0) {
> > + sent_len = min_t(u32, 250, dl_size);
> > +
> > + if (dl_size == total_size)
> > + wmt_params.flag = 1;
> > + else if (dl_size == sent_len)
> > + wmt_params.flag = 3;
> > + else
> > + wmt_params.flag = 2;
> > +
> > + wmt_params.dlen = sent_len;
> > + wmt_params.data = fw_data;
> > +
> > + err = wmt_cmd_sync(hdev, &wmt_params);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to send CBMCU
> > section data (%d)", err);
> > + return err;
> > + }
> > +
> > + dl_size -= sent_len;
> > + fw_data += sent_len;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int btmtk_enable_cbmcu_patch(struct hci_dev *hdev,
> > + wmt_cmd_sync_func_t wmt_cmd_sync)
> > +{
> > + struct btmtk_hci_wmt_params wmt_params;
> > + int err;
> > +
> > + wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
> > + wmt_params.flag = 0xF1;
> > + wmt_params.dlen = 0;
> > + wmt_params.data = NULL;
> > + wmt_params.status = NULL;
> > +
> > + err = wmt_cmd_sync(hdev, &wmt_params);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to enable CBMCU patch (%d)",
> > err);
> > + return err;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int btmtk_load_cbmcu_firmware(struct hci_dev *hdev,
> > + const char *fwname,
> > + wmt_cmd_sync_func_t
> > wmt_cmd_sync)
> > +{
> > + struct btmtk_patch_header *hdr;
> > + struct btmtk_global_desc *globaldesc;
> > + struct btmtk_section_map *sectionmap;
> > + const struct firmware *fw;
> > + const u8 *fw_ptr;
> > + u8 *cert_buf = NULL;
> > + u32 section_num, section_offset, dl_size, cert_len;
> > + int i, err;
> > +
> > + err = request_firmware(&fw, fwname, &hdev->dev);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to load CBMCU firmware file
> > (%d)", err);
>
> Please add fwname to the error message.
>
> > + return err;
> > + }
> > +
> > + if (fw->size < MTK_FW_ROM_PATCH_HEADER_SIZE +
> > MTK_FW_ROM_PATCH_GD_SIZE) {
> > + bt_dev_err(hdev, "CBMCU firmware too small (%zu
> > bytes)", fw->size);
>
> Please add the limit to the error message.
>
> > + err = -EINVAL;
> > + goto err_release_fw;
> > + }
> > +
> > + fw_ptr = fw->data;
> > + hdr = (struct btmtk_patch_header *)fw_ptr;
> > + globaldesc = (struct btmtk_global_desc *)(fw_ptr +
> > MTK_FW_ROM_PATCH_HEADER_SIZE);
> > + section_num = le32_to_cpu(globaldesc->section_num);
> > +
> > + if (fw->size < MTK_FW_ROM_PATCH_HEADER_SIZE +
> > MTK_FW_ROM_PATCH_GD_SIZE +
> > + (size_t)MTK_FW_ROM_PATCH_SEC_MAP_SIZE *
> > section_num) {
> > + bt_dev_err(hdev, "CBMCU firmware truncated
> > (section_num=%u)", section_num);
>
> Please log the values from the if condition.
>
> > + err = -EINVAL;
> > + goto err_release_fw;
> > + }
> > +
> > + bt_dev_info(hdev, "CBMCU Version: 0x%04x%04x, Build Time:
> > %s",
> > + le16_to_cpu(hdr->hwver), le16_to_cpu(hdr->swver),
> > hdr->datetime);
> > +
> > + /* Phase 1: Download section type 0x5 */
>
> Please define a macro or enum for 0x5.
>
> > + for (i = 0; i < section_num; i++) {
> > + sectionmap = (struct btmtk_section_map *)
> > + (fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
> > + MTK_FW_ROM_PATCH_GD_SIZE +
> > + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
> > +
> > + /* Only process type 0x5 section in Phase 1 */
> > + if ((le32_to_cpu(sectionmap->sectype) & 0xFFFF) !=
> > 0x5)
> > + continue;
> > +
> > + section_offset = le32_to_cpu(sectionmap->secoffset);
> > + dl_size = le32_to_cpu(sectionmap->secsize);
> > +
> > + if (dl_size == 0)
> > + continue;
> > +
> > + if (section_offset > fw->size ||
> > + dl_size > fw->size - section_offset) {
> > + bt_dev_err(hdev, "CBMCU Phase 1 section out
> > of bounds");
> > + err = -EINVAL;
> > + goto err_release_fw;
> > + }
> > +
> > + cert_len = MTK_FW_ROM_PATCH_GD_SIZE +
> > + MTK_FW_ROM_PATCH_SEC_MAP_SIZE *
> > section_num +
> > + dl_size;
> > +
> > + /* Query cbmcu section */
> > + err = btmtk_query_cbmcu_section(hdev, wmt_cmd_sync,
> > 0, NULL,
> > + cert_len);
> > + if (err < 0)
> > + goto err_release_fw;
> > +
> > + cert_buf = kmalloc(cert_len, GFP_KERNEL);
> > + if (!cert_buf) {
> > + err = -ENOMEM;
> > + goto err_release_fw;
> > + }
> > +
> > + /* Copy Global Descriptor + All Section Maps */
> > + memcpy(cert_buf,
> > + fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE,
> > + MTK_FW_ROM_PATCH_GD_SIZE +
> > MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num);
> > +
> > + /* Copy Phase 1 section data */
> > + memcpy(cert_buf + MTK_FW_ROM_PATCH_GD_SIZE +
> > + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num,
> > + fw_ptr + section_offset,
> > + dl_size);
> > +
> > + /* Download Phase 1 section */
> > + err = btmtk_download_cbmcu_section(hdev,
> > wmt_cmd_sync,
> > + cert_buf,
> > cert_len);
> > + kfree(cert_buf);
> > + cert_buf = NULL;
> > +
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to download CBMCU
> > Phase 1 section (%d)", err);
> > + goto err_release_fw;
> > + }
> > +
> > + break;
> > + }
> > +
> > + /* Phase 2: Download other sections (type != 0x5) */
> > + for (i = 0; i < section_num; i++) {
> > + sectionmap = (struct btmtk_section_map *)
> > + (fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
> > + MTK_FW_ROM_PATCH_GD_SIZE +
> > + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
> > +
> > + /* Skip type 0x5 section in Phase 2 */
> > + if ((le32_to_cpu(sectionmap->sectype) & 0xFFFF) ==
> > 0x5)
> > + continue;
> > +
> > + section_offset = le32_to_cpu(sectionmap->secoffset);
> > + dl_size = le32_to_cpu(sectionmap-
> > >bin_info_spec.dlsize);
> > +
> > + if (dl_size == 0)
> > + continue;
> > +
> > + if (section_offset > fw->size ||
> > + dl_size > fw->size - section_offset) {
> > + bt_dev_err(hdev, "CBMCU Phase 2 section %d
> > out of bounds", i);
> > + err = -EINVAL;
> > + goto err_release_fw;
> > + }
> > +
> > + /* Query cbmcu section */
> > + err = btmtk_query_cbmcu_section(hdev, wmt_cmd_sync,
> > 1,
> > + (u8 *)§ionmap-
> > >bin_info_spec,
> > + 0);
> > + if (err < 0)
> > + goto err_release_fw;
> > +
> > + /* Download section data */
> > + err = btmtk_download_cbmcu_section(hdev,
> > wmt_cmd_sync,
> > + fw_ptr +
> > section_offset,
> > + dl_size);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to download CBMCU
> > section %d (%d)", i, err);
> > + goto err_release_fw;
> > + }
> > + }
> > +
> > + /* Wait for firmware activation */
> > + usleep_range(100000, 120000);
> > +
> > + bt_dev_info(hdev, "CBMCU firmware download completed");
> > +
> > +err_release_fw:
> > + release_firmware(fw);
> > + return err;
> > +}
> > +
> > +static int btmtk_setup_cbmcu_firmware(struct hci_dev *hdev,
> > + wmt_cmd_sync_func_t
> > wmt_cmd_sync,
> > + u32 dev_id)
> > +{
> > + char cbmcu_fwname[64];
> > + u8 patch_status;
> > + int err;
> > +
> > + err = btmtk_cbmcu_patch_status(hdev, wmt_cmd_sync,
> > &patch_status);
> > + if (err < 0)
> > + return err;
> > +
> > + bt_dev_dbg(hdev, "CBMCU patch status: 0x%02x", patch_status);
> > +
> > + if (patch_status != BTMTK_WMT_PATCH_UNDONE)
> > + return 0;
> > +
> > + snprintf(cbmcu_fwname, sizeof(cbmcu_fwname),
> > + "mediatek/mt7928/CBMCU_CODE_MT%04x_1_1.bin",
> > + dev_id & 0xffff);
> > +
> > + err = btmtk_load_cbmcu_firmware(hdev, cbmcu_fwname,
> > wmt_cmd_sync);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to download CBMCU firmware
> > (%d)", err);
> > + return err;
> > + }
> > +
> > + err = btmtk_enable_cbmcu_patch(hdev, wmt_cmd_sync);
> > + if (err < 0)
> > + return err;
> > +
> > + return 0;
> > +}
> > +
> > int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
> > {
> > u32 val;
> > @@ -894,7 +1223,7 @@ int btmtk_usb_subsys_reset(struct hci_dev
> > *hdev, u32 dev_id)
> > if (err < 0)
> > return err;
> > msleep(100);
> > - } else if (dev_id == 0x7925 || dev_id == 0x6639) {
> > + } else if (dev_id == 0x7925 || dev_id == 0x6639 || dev_id ==
> > 0x7935) {
> > err = btmtk_usb_uhw_reg_read(hdev,
> > MTK_BT_RESET_REG_CONNV3, &val);
> > if (err < 0)
> > return err;
> > @@ -1379,6 +1708,15 @@ int btmtk_usb_setup(struct hci_dev *hdev)
> > case 0x7668:
> > fwname = FIRMWARE_MT7668;
> > break;
> > + case 0x7935:
> > + /* Requires CBMCU firmware before BT firmware */
> > + err = btmtk_setup_cbmcu_firmware(hdev,
> > btmtk_usb_hci_wmt_sync,
> > + dev_id);
> > + if (err < 0) {
> > + bt_dev_err(hdev, "Failed to set up CBMCU
> > firmware (%d)", err);
> > + return err;
> > + }
> > + fallthrough;
> > case 0x7922:
> > case 0x7925:
> > /*
> > @@ -1596,3 +1934,5 @@ MODULE_FIRMWARE(FIRMWARE_MT7922);
> > MODULE_FIRMWARE(FIRMWARE_MT7961);
> > MODULE_FIRMWARE(FIRMWARE_MT7925);
> > MODULE_FIRMWARE(FIRMWARE_MT7927);
> > +MODULE_FIRMWARE(FIRMWARE_MT7928);
> > +MODULE_FIRMWARE(FIRMWARE_MT7928_CBMCU);
> > diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
> > index c83c24897c95..6d3bf6b74a1d 100644
> > --- a/drivers/bluetooth/btmtk.h
> > +++ b/drivers/bluetooth/btmtk.h
> > @@ -9,6 +9,8 @@
> > #define FIRMWARE_MT7961
> > "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
> > #define FIRMWARE_MT7925
> > "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
> > #define FIRMWARE_MT7927
> > "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"
> > +#define FIRMWARE_MT7928
> > "mediatek/mt7928/BT_RAM_CODE_MT7935_1_1_hdr.bin"
> > +#define FIRMWARE_MT7928_CBMCU
> > "mediatek/mt7928/CBMCU_CODE_MT7935_1_1.bin"
> >
> > #define HCI_EV_WMT 0xe4
> > #define HCI_WMT_MAX_EVENT_SIZE 64
> > @@ -54,6 +56,7 @@ enum {
> > BTMTK_WMT_RST = 0x7,
> > BTMTK_WMT_REGISTER = 0x8,
> > BTMTK_WMT_SEMAPHORE = 0x17,
> > + BTMTK_WMT_CBMCU_DWNLD = 0x58,
> > };
> >
> > enum {
>
>
> Kind regards,
>
> Paul
Thanks for the review, I'll revise the error message to be more
informative and replace the magic number with proper macro. A v2 will
be sent out shortly.
Chris Lu
^ permalink raw reply
* Re: [PATCH v2 3/3] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope
From: Sergey Senozhatsky @ 2026-06-17 3:41 UTC (permalink / raw)
To: Sean Wang
Cc: Sergey Senozhatsky, Marcel Holtmann, Luiz Augusto von Dentz,
Mark-yw Chen, Sean Wang, Tomasz Figa, linux-bluetooth,
linux-kernel, linux-arm-kernel, linux-mediatek, stable
In-Reply-To: <CAGp9LzqT4knwk9hONu43cGDr005Phs3xw6T+YexXa3X6JEBOpA@mail.gmail.com>
On (26/06/16 19:56), Sean Wang wrote:
> The patch looks good to me. Inspired by your patch,
> do you think should we add another patch to keep txrx_work out of the
> reset window by rejecting TX during reset,
> ignoring reset-time interrupts, and making queued workers exit early?
I honestly don't know, it's hard for to me judge as I'm not all that
familiar with the code. To make things more complex, I don't think we
see any crashes on reset path. My personal preference maybe would be
to keep things the way they are?
> Some code like:
>
> --- a/drivers/bluetooth/btmtksdio.c
> +++ b/drivers/bluetooth/btmtksdio.c
> @@ -567,6 +567,8 @@ static void btmtksdio_txrx_work(struct work_struct *work)
> pm_runtime_get_sync(bdev->dev);
>
> sdio_claim_host(bdev->func);
> + if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
> + goto out;
A nit: I think you can test_bit() outside of host lock scope.
Other than that I'm afraid I cannot be of much help here.
> /* Disable interrupt */
> sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
> @@ -628,6 +630,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
> !test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
> sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
>
> +out:
> sdio_release_host(bdev->func);
>
> pm_runtime_put_autosuspend(bdev->dev);
> @@ -646,6 +649,9 @@ static void btmtksdio_interrupt(struct sdio_func *func)
> /* Disable interrupt */
> sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
>
> + if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
> + return;
> +
> schedule_work(&bdev->txrx_work);
> }
>
> @@ -1250,6 +1256,9 @@ static int btmtksdio_send_frame(struct hci_dev
> *hdev, struct sk_buff *skb)
> {
> struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
>
> + if (test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
> + return -EBUSY;
> +
> switch (hci_skb_pkt_type(skb)) {
> case HCI_COMMAND_PKT:
> hdev->stat.cmd_tx++;
^ permalink raw reply
* Re: [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check
From: Sergey Senozhatsky @ 2026-06-17 3:43 UTC (permalink / raw)
To: Sean Wang
Cc: Sergey Senozhatsky, Marcel Holtmann, Luiz Augusto von Dentz,
Mark-yw Chen, Sean Wang, Tomasz Figa, linux-bluetooth,
linux-kernel, linux-arm-kernel, linux-mediatek, stable
In-Reply-To: <CAGp9LzpCMGr2hyVJRMehs_BD4Rk6mS2jAifWuCgBaANdqgtvqA@mail.gmail.com>
On (26/06/16 19:40), Sean Wang wrote:
> > The btmtksdio_txrx_work() loop is expected to be terminated if running
> > for longer than 5*HZ. However the timeout check is reversed:
> > time_is_before_jiffies(old_jiffies + 5*HZ) evaluates to true when
> > old_jiffies + 5*HZ is in the past i.e. when a timeout has occurred.
> > Using OR with time_is_before_jiffies(txrx_timeout) means that:
> > - before the 5-second timeout: the condition is `int_status || false`,
> > so it loops as long as there are pending interrupts.
> > - after the 5-second timeout: the condition becomes `int_status || true`,
> > which is always true.
> >
> > Fix loop termination condition to actually enforce a 5*HZ timeout.
> >
> > Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> > ---
> > drivers/bluetooth/btmtksdio.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
> > index 5b0fab7b89b5..c6f80c419e90 100644
> > --- a/drivers/bluetooth/btmtksdio.c
> > +++ b/drivers/bluetooth/btmtksdio.c
> > @@ -620,7 +620,7 @@ static void btmtksdio_txrx_work(struct work_struct *work)
> > if (btmtksdio_rx_packet(bdev, rx_size) < 0)
> > bdev->hdev->stat.err_rx++;
> > }
> > - } while (int_status || time_is_before_jiffies(txrx_timeout));
> > + } while (int_status && time_is_after_jiffies(txrx_timeout));
> >
>
> This patch has already been merged, so I think the series should be
> respun based on the latest code.
Oh, I see. Any chance it can be dropped from the tree or updated?
The patch is identical it's the commit message that has changed.
Otherwise, I can drop it from a v3 re-spin.
^ permalink raw reply
* [PATCH RFC] bluetooth: hci: Fix null-ptr-deref in hci_conn_timeout
From: Sungwoo Kim @ 2026-06-17 3:54 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: Sungwoo Kim, Dave Tian, Luiz Augusto von Dentz, linux-bluetooth,
linux-kernel
RFC only.
The hci_conn_timeout() function dereferences hdev->sent_cmd when handling
connection timeouts. However, an HCI_EV_HARDWARE_ERROR can trigger an
asynchronous reset sequence that sets hdev->sent_cmd to NULL via
hci_dev_close_sync().
hdev->sent_cmd is dereferenced when conn->disc_work timeout:
hci_conn_timeout()
hci_abort_conn()
switch (hci_skb_event(hdev->sent_cmd)) {
...
However, an HCI hardware error event (HCI_EV_HARDWARE_ERROR) resets the
hci device, setting hdev->sent_cmd = NULL asynchornously:
hci_hardware_error_evt()
hci_error_reset() (async)
hci_dev_do_close()
hci_dev_close_sync()
hdev->sent_cmd = NULL;
As a result, a race condition exists between conn->disc_work execution
and the reset path, which can lead to a NULL pointer dereference when
hci_abort_conn() accesses hdev->sent_cmd.
To fix this, this patch ensures that all pending conn->disc_work
instances are canceled and completed before hdev->sent_cmd is cleared
during the reset path.
This is a provisional fix. Better design suggestions are welcome.
Oops:
Bluetooth: hci4: hardware error 0x00
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000007: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000038-0x000000000000003f]
CPU: 2 UID: 0 PID: 408 Comm: kworker/u17:4 Not tainted 7.1.0-dirty #96 PREEMPT(lazy)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
Workqueue: hci1 hci_conn_timeout
RIP: 0010:hci_abort_conn+0x291/0x350 net/bluetooth/hci_conn.c:3196
Fixes: d0b137062b2d ("Bluetooth: hci_sync: Rework init stages")
Acked-by: Dave Tian <daveti@purdue.edu>
Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
---
net/bluetooth/hci_sync.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index df23245d6ccd..dab709448a02 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -5419,6 +5419,14 @@ int hci_dev_close_sync(struct hci_dev *hdev)
/* Drop last sent command */
if (hdev->sent_cmd) {
+ struct hci_conn *c;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(c, &hdev->conn_hash.list, list) {
+ cancel_delayed_work_sync(&c->disc_work);
+ }
+ rcu_read_unlock();
+
cancel_delayed_work_sync(&hdev->cmd_timer);
kfree_skb(hdev->sent_cmd);
hdev->sent_cmd = NULL;
--
2.47.3
^ permalink raw reply related
* [PATCH v2] Bluetooth: btmtk: Add MT7928 support
From: Chris Lu @ 2026-06-17 6:17 UTC (permalink / raw)
To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
linux-kernel, linux-mediatek, Chris Lu
Add support for MT7928 (device ID 0x7935) which requires additional
firmware (CBMCU firmware) loading before Bluetooth firmware.
Implement two-phase CBMCU firmware download: Phase 1 loads
section with type 0x5 containing global descriptor,
section maps and signature data; Phase 2 loads remaining
firmware sections. Add retry mechanism for concurrent download
protection.
After CBMCU firmware loads successfully, the driver continues
to load corresponding BT firmware based on device ID through
fallthrough to case 0x7922/0x7925.
MT7928 bringup kernel log:
[90.081868] usb 1-3: new high-speed USB device number 28 using xhci_hcd
[90.209995] usb 1-3: New USB device found, idVendor=0e8d, idProduct=7935, bcdDevice= 1.00
[90.210027] usb 1-3: New USB device strings: Mfr=5, Product=6, SerialNumber=7
[90.210046] usb 1-3: Product: Wireless_Device
[90.210060] usb 1-3: Manufacturer: MediaTek Inc.
[90.210075] usb 1-3: SerialNumber: 000000000
[90.223089] Bluetooth: hci1: CBMCU Version: 0x00000000, Build Time: 20260601T161751+0800
[90.664706] Bluetooth: hci1: CBMCU firmware download completed
[90.685424] Bluetooth: hci1: HW/SW Version: 0x00000000, Build Time: 20260527000816
[93.771612] Bluetooth: hci1: Device setup in 3467323 usecs
[93.771657] Bluetooth: hci1: HCI Enhanced Setup Synchronous
Connection command is advertised, but not supported.
[93.890840] Bluetooth: hci1: AOSP extensions version v2.00
[93.890887] Bluetooth: hci1: AOSP quality report is supported
[93.893444] Bluetooth: MGMT ver 1.23
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
v1->v2: Update error message; Use macro instead of magic number.
---
drivers/bluetooth/btmtk.c | 348 +++++++++++++++++++++++++++++++++++++-
drivers/bluetooth/btmtk.h | 3 +
2 files changed, 350 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..6bae0b0794dd 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -21,6 +21,8 @@
#define MTK_FW_ROM_PATCH_SEC_MAP_SIZE 64
#define MTK_SEC_MAP_COMMON_SIZE 12
#define MTK_SEC_MAP_NEED_SEND_SIZE 52
+#define MTK_SEC_MAP_LENGTH_SIZE 4
+#define MTK_SEC_CBMCU_DESC 0x5
/* It is for mt79xx iso data transmission setting */
#define MTK_ISO_THRESHOLD 264
@@ -120,6 +122,10 @@ void btmtk_fw_get_filename(char *buf, size_t size, u32 dev_id, u32 fw_ver,
snprintf(buf, size,
"mediatek/mt%04x/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
dev_id & 0xffff, dev_id & 0xffff, (fw_ver & 0xff) + 1);
+ else if (dev_id == 0x7935)
+ snprintf(buf, size,
+ "mediatek/mt7928/BT_RAM_CODE_MT%04x_1_1_hdr.bin",
+ dev_id & 0xffff);
else if (dev_id == 0x7961 && fw_flavor)
snprintf(buf, size,
"mediatek/BT_RAM_CODE_MT%04x_1a_%x_hdr.bin",
@@ -734,6 +740,7 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
status = BTMTK_WMT_ON_UNDONE;
break;
case BTMTK_WMT_PATCH_DWNLD:
+ case BTMTK_WMT_CBMCU_DWNLD:
if (wmt_evt->whdr.flag == 2)
status = BTMTK_WMT_PATCH_DONE;
else if (wmt_evt->whdr.flag == 1)
@@ -870,6 +877,334 @@ static u32 btmtk_usb_reset_done(struct hci_dev *hdev)
return val & MTK_BT_RST_DONE;
}
+static int btmtk_cbmcu_patch_status(struct hci_dev *hdev,
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ u8 *patch_status)
+{
+ struct btmtk_hci_wmt_params wmt_params;
+ int status, err, retry = 20;
+
+ do {
+ wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
+ wmt_params.flag = 0xF0;
+ wmt_params.dlen = 0;
+ wmt_params.data = NULL;
+ wmt_params.status = &status;
+
+ err = wmt_cmd_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to query CBMCU patch status (%d)", err);
+ return err;
+ }
+
+ *patch_status = (u8)status;
+
+ if (*patch_status == BTMTK_WMT_PATCH_PROGRESS) {
+ msleep(100);
+ retry--;
+ } else {
+ break;
+ }
+ } while (retry > 0);
+
+ return 0;
+}
+
+static int btmtk_query_cbmcu_section(struct hci_dev *hdev,
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ u8 cbmcu_type,
+ const u8 *section_map,
+ u32 cert_len)
+{
+ struct btmtk_hci_wmt_params wmt_params;
+ u8 cmd[64];
+ int status, err;
+
+ cmd[0] = 0;
+ cmd[1] = cbmcu_type;
+
+ if (cbmcu_type == 0)
+ put_unaligned_le32(cert_len, &cmd[2]);
+ else
+ memcpy(&cmd[2], section_map, MTK_SEC_MAP_NEED_SEND_SIZE);
+
+ wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
+ wmt_params.flag = 0;
+ wmt_params.dlen = cbmcu_type ?
+ MTK_SEC_MAP_NEED_SEND_SIZE + 2 :
+ MTK_SEC_MAP_LENGTH_SIZE + 2;
+ wmt_params.data = cmd;
+ wmt_params.status = &status;
+
+ err = wmt_cmd_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to query CBMCU section (%d)", err);
+ return err;
+ }
+
+ /* Query should return UNDONE status for successful section query */
+ if (status != BTMTK_WMT_PATCH_UNDONE) {
+ bt_dev_err(hdev, "CBMCU section query status error (%d)", status);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int btmtk_download_cbmcu_section(struct hci_dev *hdev,
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ const u8 *fw_data,
+ u32 dl_size)
+{
+ struct btmtk_hci_wmt_params wmt_params;
+ u32 sent_len, total_size = dl_size;
+ int err;
+
+ wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
+ wmt_params.status = NULL;
+
+ while (dl_size > 0) {
+ sent_len = min_t(u32, 250, dl_size);
+
+ if (dl_size == total_size)
+ wmt_params.flag = 1;
+ else if (dl_size == sent_len)
+ wmt_params.flag = 3;
+ else
+ wmt_params.flag = 2;
+
+ wmt_params.dlen = sent_len;
+ wmt_params.data = fw_data;
+
+ err = wmt_cmd_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to send CBMCU section data (%d)", err);
+ return err;
+ }
+
+ dl_size -= sent_len;
+ fw_data += sent_len;
+ }
+
+ return 0;
+}
+
+static int btmtk_enable_cbmcu_patch(struct hci_dev *hdev,
+ wmt_cmd_sync_func_t wmt_cmd_sync)
+{
+ struct btmtk_hci_wmt_params wmt_params;
+ int err;
+
+ wmt_params.op = BTMTK_WMT_CBMCU_DWNLD;
+ wmt_params.flag = 0xF1;
+ wmt_params.dlen = 0;
+ wmt_params.data = NULL;
+ wmt_params.status = NULL;
+
+ err = wmt_cmd_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to enable CBMCU patch (%d)", err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int btmtk_load_cbmcu_firmware(struct hci_dev *hdev,
+ const char *fwname,
+ wmt_cmd_sync_func_t wmt_cmd_sync)
+{
+ struct btmtk_patch_header *hdr;
+ struct btmtk_global_desc *globaldesc;
+ struct btmtk_section_map *sectionmap;
+ const struct firmware *fw;
+ const u8 *fw_ptr;
+ u8 *cert_buf = NULL;
+ u32 section_num, section_offset, dl_size, cert_len;
+ int i, err;
+
+ err = request_firmware(&fw, fwname, &hdev->dev);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to load CBMCU firmware file %s (%d)",
+ fwname, err);
+ return err;
+ }
+
+ if (fw->size < MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE) {
+ bt_dev_err(hdev, "CBMCU firmware too small (%zu bytes)", fw->size);
+ err = -EINVAL;
+ goto err_release_fw;
+ }
+
+ fw_ptr = fw->data;
+ hdr = (struct btmtk_patch_header *)fw_ptr;
+ globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
+ section_num = le32_to_cpu(globaldesc->section_num);
+
+ if (fw->size < MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE +
+ (size_t)MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num) {
+ bt_dev_err(hdev, "CBMCU firmware truncated: size=%zu, expected=%zu (section_num=%u)",
+ fw->size,
+ MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE +
+ (size_t)MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num,
+ section_num);
+ err = -EINVAL;
+ goto err_release_fw;
+ }
+
+ bt_dev_info(hdev, "CBMCU Version: 0x%04x%04x, Build Time: %s",
+ le16_to_cpu(hdr->hwver), le16_to_cpu(hdr->swver), hdr->datetime);
+
+ /* Phase 1: Download section type MTK_SEC_CBMCU_DESC */
+ for (i = 0; i < section_num; i++) {
+ sectionmap = (struct btmtk_section_map *)
+ (fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
+ MTK_FW_ROM_PATCH_GD_SIZE +
+ MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
+
+ /* Only process MTK_SEC_CBMCU_DESC section in Phase 1 */
+ if ((le32_to_cpu(sectionmap->sectype) & 0xFFFF) != MTK_SEC_CBMCU_DESC)
+ continue;
+
+ section_offset = le32_to_cpu(sectionmap->secoffset);
+ dl_size = le32_to_cpu(sectionmap->secsize);
+
+ if (dl_size == 0)
+ continue;
+
+ if (section_offset > fw->size ||
+ dl_size > fw->size - section_offset) {
+ bt_dev_err(hdev, "CBMCU Phase 1 section out of bounds");
+ err = -EINVAL;
+ goto err_release_fw;
+ }
+
+ cert_len = MTK_FW_ROM_PATCH_GD_SIZE +
+ MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num +
+ dl_size;
+
+ /* Query cbmcu section */
+ err = btmtk_query_cbmcu_section(hdev, wmt_cmd_sync, 0, NULL,
+ cert_len);
+ if (err < 0)
+ goto err_release_fw;
+
+ cert_buf = kmalloc(cert_len, GFP_KERNEL);
+ if (!cert_buf) {
+ err = -ENOMEM;
+ goto err_release_fw;
+ }
+
+ /* Copy Global Descriptor + All Section Maps */
+ memcpy(cert_buf,
+ fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE,
+ MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num);
+
+ /* Copy Phase 1 section data */
+ memcpy(cert_buf + MTK_FW_ROM_PATCH_GD_SIZE +
+ MTK_FW_ROM_PATCH_SEC_MAP_SIZE * section_num,
+ fw_ptr + section_offset,
+ dl_size);
+
+ /* Download Phase 1 section */
+ err = btmtk_download_cbmcu_section(hdev, wmt_cmd_sync,
+ cert_buf, cert_len);
+ kfree(cert_buf);
+ cert_buf = NULL;
+
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to download CBMCU Phase 1 section (%d)", err);
+ goto err_release_fw;
+ }
+
+ break;
+ }
+
+ /* Phase 2: Download other sections (type != MTK_SEC_CBMCU_DESC) */
+ for (i = 0; i < section_num; i++) {
+ sectionmap = (struct btmtk_section_map *)
+ (fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
+ MTK_FW_ROM_PATCH_GD_SIZE +
+ MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
+
+ /* Skip MTK_SEC_CBMCU_DESC section in Phase 2 */
+ if ((le32_to_cpu(sectionmap->sectype) & 0xFFFF) == MTK_SEC_CBMCU_DESC)
+ continue;
+
+ section_offset = le32_to_cpu(sectionmap->secoffset);
+ dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
+
+ if (dl_size == 0)
+ continue;
+
+ if (section_offset > fw->size ||
+ dl_size > fw->size - section_offset) {
+ bt_dev_err(hdev, "CBMCU Phase 2 section %d out of bounds", i);
+ err = -EINVAL;
+ goto err_release_fw;
+ }
+
+ /* Query cbmcu section */
+ err = btmtk_query_cbmcu_section(hdev, wmt_cmd_sync, 1,
+ (u8 *)§ionmap->bin_info_spec,
+ 0);
+ if (err < 0)
+ goto err_release_fw;
+
+ /* Download section data */
+ err = btmtk_download_cbmcu_section(hdev, wmt_cmd_sync,
+ fw_ptr + section_offset,
+ dl_size);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to download CBMCU section %d (%d)", i, err);
+ goto err_release_fw;
+ }
+ }
+
+ /* Wait for firmware activation */
+ usleep_range(100000, 120000);
+
+ bt_dev_info(hdev, "CBMCU firmware download completed");
+
+err_release_fw:
+ release_firmware(fw);
+ return err;
+}
+
+static int btmtk_setup_cbmcu_firmware(struct hci_dev *hdev,
+ wmt_cmd_sync_func_t wmt_cmd_sync,
+ u32 dev_id)
+{
+ char cbmcu_fwname[64];
+ u8 patch_status;
+ int err;
+
+ err = btmtk_cbmcu_patch_status(hdev, wmt_cmd_sync, &patch_status);
+ if (err < 0)
+ return err;
+
+ bt_dev_dbg(hdev, "CBMCU patch status: 0x%02x", patch_status);
+
+ if (patch_status != BTMTK_WMT_PATCH_UNDONE)
+ return 0;
+
+ snprintf(cbmcu_fwname, sizeof(cbmcu_fwname),
+ "mediatek/mt7928/CBMCU_CODE_MT%04x_1_1.bin",
+ dev_id & 0xffff);
+
+ err = btmtk_load_cbmcu_firmware(hdev, cbmcu_fwname, wmt_cmd_sync);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to download CBMCU firmware (%d)", err);
+ return err;
+ }
+
+ err = btmtk_enable_cbmcu_patch(hdev, wmt_cmd_sync);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
{
u32 val;
@@ -894,7 +1229,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
if (err < 0)
return err;
msleep(100);
- } else if (dev_id == 0x7925 || dev_id == 0x6639) {
+ } else if (dev_id == 0x7925 || dev_id == 0x6639 || dev_id == 0x7935) {
err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
if (err < 0)
return err;
@@ -1379,6 +1714,15 @@ int btmtk_usb_setup(struct hci_dev *hdev)
case 0x7668:
fwname = FIRMWARE_MT7668;
break;
+ case 0x7935:
+ /* Requires CBMCU firmware before BT firmware */
+ err = btmtk_setup_cbmcu_firmware(hdev, btmtk_usb_hci_wmt_sync,
+ dev_id);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to set up CBMCU firmware (%d)", err);
+ return err;
+ }
+ fallthrough;
case 0x7922:
case 0x7925:
/*
@@ -1596,3 +1940,5 @@ MODULE_FIRMWARE(FIRMWARE_MT7922);
MODULE_FIRMWARE(FIRMWARE_MT7961);
MODULE_FIRMWARE(FIRMWARE_MT7925);
MODULE_FIRMWARE(FIRMWARE_MT7927);
+MODULE_FIRMWARE(FIRMWARE_MT7928);
+MODULE_FIRMWARE(FIRMWARE_MT7928_CBMCU);
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index c83c24897c95..6d3bf6b74a1d 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -9,6 +9,8 @@
#define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
#define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
#define FIRMWARE_MT7927 "mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin"
+#define FIRMWARE_MT7928 "mediatek/mt7928/BT_RAM_CODE_MT7935_1_1_hdr.bin"
+#define FIRMWARE_MT7928_CBMCU "mediatek/mt7928/CBMCU_CODE_MT7935_1_1.bin"
#define HCI_EV_WMT 0xe4
#define HCI_WMT_MAX_EVENT_SIZE 64
@@ -54,6 +56,7 @@ enum {
BTMTK_WMT_RST = 0x7,
BTMTK_WMT_REGISTER = 0x8,
BTMTK_WMT_SEMAPHORE = 0x17,
+ BTMTK_WMT_CBMCU_DWNLD = 0x58,
};
enum {
--
2.45.2
^ permalink raw reply related
* [PATCH v3 0/2] Bluetooth: btmtksdio: teardown fixes
From: Sergey Senozhatsky @ 2026-06-17 6:45 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, Mark-yw Chen, Sean Wang
Cc: Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
linux-mediatek, Sergey Senozhatsky
This fixes several teardown issues:
INFO: task kworker/u17:0:189 blocked for more than 122 seconds.
__cancel_work_timer+0x3f4/0x460
cancel_work_sync+0x1c/0x2c
btmtksdio_flush+0x2c/0x40
hci_dev_open_sync+0x10c4/0x2190
[..]
close/flush can deadlock when run concurrently with btmtksdio_txrx_work().
In addition btmtksdio_txrx_work() re-enables interrupts regardless of
close/flush being executed on another CPU.
v2 -> v3:
- dropped infinite btmtksdio_txrx_work() loop fix (already merged)
Sergey Senozhatsky (2):
Bluetooth: btmtksdio: test for BUS IO errors in btmtksdio_txrx_work()
Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock
scope
drivers/bluetooth/btmtksdio.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply
* [PATCH v3 1/2] Bluetooth: btmtksdio: test for BUS IO errors in btmtksdio_txrx_work()
From: Sergey Senozhatsky @ 2026-06-17 6:45 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, Mark-yw Chen, Sean Wang
Cc: Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
linux-mediatek, Sergey Senozhatsky, stable
In-Reply-To: <20260617064543.574704-1-senozhatsky@chromium.org>
btmtksdio_txrx_work() loop termination condition checks for
int_status being non-zero, however, this evaluates to true
even when sdio_readl() encounters BUS I/O error (in which
case int_status is 0xffffffff). Break out of the loop if
sdio_readl() errors out.
Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
Cc: stable@vger.kernel.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/bluetooth/btmtksdio.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index c6f80c419e90..d8c8d2857527 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -574,7 +574,9 @@ static void btmtksdio_txrx_work(struct work_struct *work)
txrx_timeout = jiffies + 5 * HZ;
do {
- int_status = sdio_readl(bdev->func, MTK_REG_CHISR, NULL);
+ int_status = sdio_readl(bdev->func, MTK_REG_CHISR, &err);
+ if (err < 0 || int_status == 0xffffffff)
+ break;
/* Ack an interrupt as soon as possible before any operation on
* hardware.
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* [PATCH v3 2/2] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope
From: Sergey Senozhatsky @ 2026-06-17 6:45 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, Mark-yw Chen, Sean Wang
Cc: Tomasz Figa, linux-bluetooth, linux-kernel, linux-arm-kernel,
linux-mediatek, Sergey Senozhatsky, stable
In-Reply-To: <20260617064543.574704-1-senozhatsky@chromium.org>
cancel_work_sync() should be called outside of host lock scope
in order to avoid circular locking scenario:
CPU0 CPU1
close()/reset()
sdio_claim_host()
txrx_work
sdio_claim_host() // sleeps
cancel_work_sync() // sleeps
In addition, when txrx_work() runs concurrently with close()/reset()
it better not to re-enable interrupts by testing for BTMTKSDIO_FUNC_ENABLED
and not BTMTKSDIO_HW_RESET_ACTIVE before C_INT_EN_SET write. However,
btmtksdio_close() clears the BTMTKSDIO_FUNC_ENABLED too late (after
cancel_work_sync() call). Move BTMTKSDIO_FUNC_ENABLED bit-clear earlier
so that txrx_work can see concurrent close().
Fixes: 26270bc189ea4 ("Bluetooth: btmtksdio: move interrupt service to work")
Cc: stable@vger.kernel.org
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
---
drivers/bluetooth/btmtksdio.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index d8c8d2857527..207d04cc2282 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -625,7 +625,9 @@ static void btmtksdio_txrx_work(struct work_struct *work)
} while (int_status && time_is_after_jiffies(txrx_timeout));
/* Enable interrupt */
- if (bdev->func->irq_handler)
+ if (bdev->func->irq_handler &&
+ test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state) &&
+ !test_bit(BTMTKSDIO_HW_RESET_ACTIVE, &bdev->tx_state))
sdio_writel(bdev->func, C_INT_EN_SET, MTK_REG_CHLPCR, NULL);
sdio_release_host(bdev->func);
@@ -741,6 +743,8 @@ static int btmtksdio_close(struct hci_dev *hdev)
if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state))
return 0;
+ clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
+
sdio_claim_host(bdev->func);
/* Disable interrupt */
@@ -748,11 +752,12 @@ static int btmtksdio_close(struct hci_dev *hdev)
sdio_release_irq(bdev->func);
+ sdio_release_host(bdev->func);
cancel_work_sync(&bdev->txrx_work);
+ sdio_claim_host(bdev->func);
btmtksdio_fw_pmctrl(bdev);
- clear_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state);
sdio_disable_func(bdev->func);
sdio_release_host(bdev->func);
@@ -1295,7 +1300,10 @@ static void btmtksdio_reset(struct hci_dev *hdev)
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
skb_queue_purge(&bdev->txq);
+
+ sdio_release_host(bdev->func);
cancel_work_sync(&bdev->txrx_work);
+ sdio_claim_host(bdev->func);
gpiod_set_value_cansleep(bdev->reset, 1);
msleep(100);
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related
* Re: [PATCH v1] Bluetooth: btmtk: Add MT7928 support
From: Paul Menzel @ 2026-06-17 6:53 UTC (permalink / raw)
To: Chris Lu (陸稚泓)
Cc: Will-CY Lee (李政穎),
Steve Lee (李視誠), luiz.dentz, marcel,
SS Wu (巫憲欣), linux-kernel, johan.hedberg,
Sean Wang, linux-bluetooth, linux-mediatek
In-Reply-To: <03e0a6787272a445448a3189b4b575aa85396fb0.camel@mediatek.com>
Dear Chris,
Thank you for your answer, and sending in v2.
Am 17.06.26 um 04:16 schrieb Chris Lu (陸稚泓):
> On Tue, 2026-06-16 at 12:24 +0200, Paul Menzel wrote:
>> Am 16.06.26 um 05:01 schrieb Chris Lu:
>>> Add support for MT7928 (device ID 0x7935) which requires additional
>>> firmware (CBMCU firmware) loading before Bluetooth firmware.
>>
>> Please detail what CBMCU firmware is.
>
> CBMCU is a new component on MT7928 to handle common part shared across
> the combo chip (Wi-Fi/Bluetooth's subsystem), providing a better user
> experience through improved coordination between subsystems.
Thank you, but please add it to the commit message.
>>> Implement two-phase CBMCU firmware download: Phase 1 loads
>>> section with type 0x5 containing global descriptor,
>>> section maps and signature data; Phase 2 loads remaining
>>> firmware sections. Add retry mechanism for concurrent download
>>> protection.
>>
>> What is type 0x5? How big is the firmware, and how long does it take?
>>
>>> After CBMCU firmware loads successfully, the driver continues
>>> to load corresponding BT firmware based on device ID through
>>> fallthrough to case 0x7922/0x7925.
>>
>> Please add the new log message to the commit message.
Thank you for adding those. Please also mention, where to find the new
firmware.
[…]
Kind regards,
Paul
PS: Also, Pauli’s question should be answered in the commit message
(internal/external name). (If questions show up during review, it’s a
good indicator to amend the commit message answering these questions.)
^ permalink raw reply
* Re: [Bug 221660] New: btmtk (MT7921K / RZ608): BR/EDR outgoing connection always fails with Page Timeout (0x04); scan/receive works, same device pairs fine on Windows
From: Paul Menzel @ 2026-06-17 6:57 UTC (permalink / raw)
To: Sean Wang, Sean Wang
Cc: Chris Lu (陸稚泓), linux-mediatek,
linux-bluetooth
In-Reply-To: <bug-221660-62941@https.bugzilla.kernel.org/>
[Cc: +Mediatek]
Am 17.06.26 um 00:39 schrieb bugzilla-daemon@kernel.org:
> https://bugzilla.kernel.org/show_bug.cgi?id=221660
>
> Bug ID: 221660
> Summary: btmtk (MT7921K / RZ608): BR/EDR outgoing connection
> always fails with Page Timeout (0x04); scan/receive
> works, same device pairs fine on Windows
> Product: Drivers
> Version: 2.5
> Kernel Version: 7.0.12-arch1-1
> Hardware: AMD
> OS: Linux
> Status: NEW
> Severity: normal
> Priority: P3
> Component: Bluetooth
> Assignee: linux-bluetooth@vger.kernel.org
> Reporter: bynxmusic@gmail.com
> Regression: No
>
> Created attachment 310333
> --> https://bugzilla.kernel.org/attachment.cgi?id=310333&action=edit
> btmon HCI trace (binary + decoded) of the Page Timeout + system info
>
> btmtk (MT7921K / RZ608): every BR/EDR outgoing connection fails with Page
> Timeout (0x04). Scan/receive works, and the same device pairs fine on Windows.
>
> HARDWARE
> WiFi+BT combo: MediaTek MT7921K (RZ608) Wi-Fi 6E, PCI 14c3:0608, driver mt7921e
> Bluetooth function: USB 0e8d:0608 (MediaTek Inc. Wireless_Device), btusb + btmtk
> Motherboard onboard radio, AMD desktop platform
>
> SOFTWARE
> Kernel: 7.0.12-arch1-1 (x86_64), Arch Linux (rolling)
> linux-firmware: 20260519-1 ; linux-firmware-mediatek: 20260519-1
> BlueZ: 5.86
> BT controller firmware: HW/SW Version 0x008a008a, Build Time 20260224111243
> BT firmware blob loads OK: mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin
>
> WHAT WORKS
> Controller initializes cleanly every boot ("hci0: Device setup in ~160000
> usecs", AOSP extensions v1.00). Inquiry/scan works: remote devices (a
> Skullcandy Crusher Evo headset and a Samsung TV) are reliably discovered with
> RSSI, so the RX path is fine.
>
> THE BUG
> Every outgoing connection (page) to any BR/EDR device times out. HCI Create
> Connection is issued and accepted (Command Status: Success), but roughly 7.7
> s
> later the controller returns Connect Complete with Status: Page Timeout (0x04).
> BlueZ reports org.bluez.Error.ConnectionAttemptFailed. The remote device never
> registers a connection. The same headset on the same PC pairs and works
> perfectly under Windows, so this is not dead hardware or a peripheral issue;
> it is the btmtk/MT7921K outgoing-connection path on Linux.
>
> KEY HCI TRACE (btmon), captured with the WiFi driver (mt7921e) UNLOADED, i.e.
> WiFi/BT coexistence ruled out:
>
> < HCI Command: Create Connection (0x01|0x0005) plen 13 #9 [hci0] 14.208614
> Address: 88:08:94:13:8F:94 (Skullcandy)
> Packet type: 0xcc18 (DM1/DH1/DM3/DH3 ...)
> > HCI Event: Command Status (0x0f) plen 4 #10 [hci0] 14.209664
> Create Connection (0x01|0x0005) ncmd 1
> Status: Success (0x00)
> > HCI Event: Connect Complete (0x03) plen 11 #11 [hci0] 21.899975
> Status: Page Timeout (0x04)
> Handle: 0
> Address: 88:08:94:13:8F:94 (Skullcandy)
> Link type: ACL (0x01)
>
> Also seen intermittently in dmesg during attempts:
> Bluetooth: hci0: ACL packet for unknown connection handle 3837
>
> STEPS TO REPRODUCE
> 1. Boot with MT7921K onboard Bluetooth.
> 2. Put any BR/EDR device (e.g. a freshly factory-reset BT headset) in pairing
> mode.
> 3. In bluetoothctl: scan on (device IS discovered), then pair <MAC>.
> 4. Pairing fails with org.bluez.Error.ConnectionAttemptFailed; btmon shows
> Connect Complete: Page Timeout (0x04).
>
> EXPECTED vs ACTUAL
> Expected: Create Connection succeeds and pairing/bonding proceeds (as on
> Windows).
> Actual: every Create Connection ends in Page Timeout; no outgoing connection
> ever completes.
>
> ALREADY RULED OUT
> - USB autosuspend: disabled via options btusb enable_autosuspend=0 (confirmed
> power/control=on). No change.
> - WiFi/BT coexistence: Page Timeout persists even with mt7921e fully unloaded
> (modprobe -r mt7921e); the trace above is from that state. Also tested with
> rfkill block wifi. No change.
> - LE vs BR/EDR bearer: tested with and without Experimental, and with
> ControllerMode = bredr. No change.
> - Stale/half state: reproduced after a fresh cold boot (controller not
> wedged).
> - Remote device: Crusher Evo factory-reset; nothing else paired to it
> (phone/TV BT off); works on Windows.
>
> ATTACHMENTS
> - bt-hci-trace.btsnoop: full binary btmon capture of one failed pairing.
> - bt-bugreport.txt: full system diagnostic bundle (versions, lspci/lsusb, dmesg).
^ permalink raw reply
* RE: Bluetooth: btmtksdio: teardown fixes
From: bluez.test.bot @ 2026-06-17 7:18 UTC (permalink / raw)
To: linux-bluetooth, senozhatsky
In-Reply-To: <20260617064543.574704-2-senozhatsky@chromium.org>
[-- Attachment #1: Type: text/plain, Size: 1751 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/project/bluetooth/list/?series=1112708
---Test result---
Test Summary:
CheckPatch PASS 1.09 seconds
VerifyFixes PASS 0.09 seconds
VerifySignedoff PASS 0.09 seconds
GitLint FAIL 0.47 seconds
SubjectPrefix PASS 0.16 seconds
BuildKernel PASS 25.03 seconds
CheckAllWarning PASS 27.24 seconds
CheckSparse PASS 25.75 seconds
BuildKernel32 PASS 23.81 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 526.47 seconds
IncrementalBuild PASS 25.43 seconds
Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v3,2/2] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope
1: T1 Title exceeds max length (81>80): "[v3,2/2] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope"
6: B3 Line contains hard tab characters (\t): "CPU0 CPU1"
7: B3 Line contains hard tab characters (\t): " close()/reset()"
8: B3 Line contains hard tab characters (\t): " sdio_claim_host()"
11: B3 Line contains hard tab characters (\t): " cancel_work_sync() // sleeps"
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
https://github.com/bluez/bluetooth-next/pull/324
---
Regards,
Linux Bluetooth
^ permalink raw reply
* RE: [v2] Bluetooth: btmtk: Add MT7928 support
From: bluez.test.bot @ 2026-06-17 7:19 UTC (permalink / raw)
To: linux-bluetooth, chris.lu
In-Reply-To: <20260617061737.1781971-1-chris.lu@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 1690 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/project/bluetooth/list/?series=1112696
---Test result---
Test Summary:
CheckPatch PASS 1.04 seconds
VerifyFixes PASS 0.09 seconds
VerifySignedoff PASS 0.09 seconds
GitLint FAIL 0.26 seconds
SubjectPrefix PASS 0.08 seconds
BuildKernel PASS 27.29 seconds
CheckAllWarning PASS 29.48 seconds
CheckSparse PASS 28.31 seconds
BuildKernel32 PASS 26.32 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 579.98 seconds
IncrementalBuild PASS 25.49 seconds
Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v2] Bluetooth: btmtk: Add MT7928 support
18: B1 Line exceeds max length (89>80): "[90.209995] usb 1-3: New USB device found, idVendor=0e8d, idProduct=7935, bcdDevice= 1.00"
23: B1 Line exceeds max length (88>80): "[90.223089] Bluetooth: hci1: CBMCU Version: 0x00000000, Build Time: 20260601T161751+0800"
25: B1 Line exceeds max length (82>80): "[90.685424] Bluetooth: hci1: HW/SW Version: 0x00000000, Build Time: 20260527000816"
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
https://github.com/bluez/bluetooth-next/pull/323
---
Regards,
Linux Bluetooth
^ permalink raw reply
* RE: [RFC] bluetooth: hci: Fix null-ptr-deref in hci_conn_timeout
From: bluez.test.bot @ 2026-06-17 7:28 UTC (permalink / raw)
To: linux-bluetooth, iam
In-Reply-To: <20260617035421.341457-2-iam@sung-woo.kim>
[-- Attachment #1: Type: text/plain, Size: 3953 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/project/bluetooth/list/?series=1112652
---Test result---
Test Summary:
CheckPatch FAIL 0.51 seconds
VerifyFixes PASS 0.07 seconds
VerifySignedoff PASS 0.06 seconds
GitLint FAIL 0.18 seconds
SubjectPrefix FAIL 0.05 seconds
BuildKernel PASS 26.51 seconds
CheckAllWarning PASS 29.50 seconds
CheckSparse PASS 27.67 seconds
BuildKernel32 PASS 25.72 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 574.33 seconds
TestRunner_l2cap-tester PASS 57.14 seconds
TestRunner_iso-tester PASS 76.29 seconds
TestRunner_bnep-tester PASS 18.68 seconds
TestRunner_mgmt-tester FAIL 205.98 seconds
TestRunner_rfcomm-tester PASS 25.72 seconds
TestRunner_sco-tester PASS 31.21 seconds
TestRunner_ioctl-tester PASS 25.32 seconds
TestRunner_mesh-tester FAIL 25.80 seconds
TestRunner_smp-tester PASS 22.85 seconds
TestRunner_userchan-tester PASS 19.58 seconds
TestRunner_6lowpan-tester PASS 23.13 seconds
IncrementalBuild PASS 24.93 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[RFC] bluetooth: hci: Fix null-ptr-deref in hci_conn_timeout
WARNING: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#119:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000007: 0000 [#1] SMP KASAN NOPTI
total: 0 errors, 1 warnings, 0 checks, 14 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14632510.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[RFC] bluetooth: hci: Fix null-ptr-deref in hci_conn_timeout
38: B1 Line exceeds max length (112>80): "Oops: general protection fault, probably for non-canonical address 0xdffffc0000000007: 0000 [#1] SMP KASAN NOPTI"
40: B1 Line exceeds max length (84>80): "CPU: 2 UID: 0 PID: 408 Comm: kworker/u17:4 Not tainted 7.1.0-dirty #96 PREEMPT(lazy)"
41: B1 Line exceeds max length (115>80): "Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014"
##############################
Test: SubjectPrefix - FAIL
Desc: Check subject contains "Bluetooth" prefix
Output:
"Bluetooth: " prefix is not specified in the subject
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.238 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.584 seconds
Mesh - Send cancel - 2 Timed out 1.980 seconds
https://github.com/bluez/bluetooth-next/pull/322
---
Regards,
Linux Bluetooth
^ permalink raw reply
* PATCH] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v3()
From: Neeraj Sanjay Kale @ 2026-06-17 8:21 UTC (permalink / raw)
To: Maoyi Xie, Amitkumar Karwar, Marcel Holtmann,
Luiz Augusto von Dentz
Cc: Ilpo Järvinen, linux-bluetooth@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <178162441367.2434858.9590661629618538235@maoyixie.com>
Hi Maoyi,
Thank you for the fix.
> During the v3 firmware download the controller sends a v3_data_req with a
> 32 bit offset and a 16 bit len. nxp_recv_fw_req_v3() checks only the lower
> bound of the offset and then sends firmware from that offset.
>
> nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
> serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
> nxpdev->fw_dnld_v3_offset, len);
>
> Nothing checks that fw_dnld_v3_offset + len stays within nxpdev->fw->size,
> so a controller that asks for an offset or length past the firmware image makes
> the driver read past the end of nxpdev->fw->data and send that memory
> back over UART.
>
> nxp_recv_fw_req_v1() already bounds the same write. Add the equivalent
> check to the v3 path, reject the request when it falls outside the firmware
> image, and zero len on the error path so the fw_v3_prev_sent bookkeeping at
> free_skb stays consistent.
>
> Fixes: 689ca16e5232 ("Bluetooth: NXP: Add protocol support for NXP
> Bluetooth chipsets")
> Suggested-by: Neeraj Kale <neeraj.sanjaykale@nxp.com>
> Cc: stable@vger.kernel.org
> Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
> ---
> This is the fix for the out of bounds read I reported on linux-bluetooth. Neeraj
> confirmed the bug and asked me to send it. The Suggested-by is for his
> suggestion to zero len on the reject path, which keeps the fw_v3_prev_sent
> bookkeeping at free_skb consistent.
>
> drivers/bluetooth/btnxpuart.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
> index e7036a48ce48..6a1cffe08d5f 100644
> --- a/drivers/bluetooth/btnxpuart.c
> +++ b/drivers/bluetooth/btnxpuart.c
> @@ -1267,6 +1267,12 @@ static int nxp_recv_fw_req_v3(struct hci_dev
> *hdev, struct sk_buff *skb)
> }
>
> nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
> + if (nxpdev->fw_dnld_v3_offset >= nxpdev->fw->size ||
> + len > nxpdev->fw->size - nxpdev->fw_dnld_v3_offset) {
> + bt_dev_err(hdev, "FW download out of bounds, ignoring request");
> + len = 0;
> + goto free_skb;
> + }
> serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
> nxpdev->fw_dnld_v3_offset, len);
>
> --
> 2.34.1
Reviewed-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Thanks,
Neeraj
^ permalink raw reply
* [PATCH v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v3()
From: Maoyi Xie @ 2026-06-17 8:36 UTC (permalink / raw)
To: Amitkumar Karwar, Neeraj Kale, Marcel Holtmann,
Luiz Augusto von Dentz
Cc: Ilpo Järvinen, linux-bluetooth, linux-kernel
During the v3 firmware download the controller sends a v3_data_req with a
32 bit offset and a 16 bit len. nxp_recv_fw_req_v3() checks only the lower
bound of the offset and then sends firmware from that offset.
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v3_offset, len);
Nothing checks that fw_dnld_v3_offset + len stays within nxpdev->fw->size,
so a controller that asks for an offset or length past the firmware image
makes the driver read past the end of nxpdev->fw->data and send that
memory back over UART.
nxp_recv_fw_req_v1() already bounds the same write. Add the equivalent
check to the v3 path, reject the request when it falls outside the firmware
image, and zero len on the error path so the fw_v3_prev_sent bookkeeping at
free_skb stays consistent.
Fixes: 689ca16e5232 ("Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets")
Suggested-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Reviewed-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
---
v2: rewrap the commit message under 75 columns and drop the hard tabs from
the quoted code so checkpatch and gitlint pass. No code change, so I
carried Neeraj's Reviewed-by from v1 (the diff is byte-identical).
The Suggested-by credits his suggestion to zero len on the reject path.
drivers/bluetooth/btnxpuart.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index e7036a48ce48..6a1cffe08d5f 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1267,6 +1267,12 @@ static int nxp_recv_fw_req_v3(struct hci_dev *hdev, struct sk_buff *skb)
}
nxpdev->fw_dnld_v3_offset = offset - nxpdev->fw_v3_offset_correction;
+ if (nxpdev->fw_dnld_v3_offset >= nxpdev->fw->size ||
+ len > nxpdev->fw->size - nxpdev->fw_dnld_v3_offset) {
+ bt_dev_err(hdev, "FW download out of bounds, ignoring request");
+ len = 0;
+ goto free_skb;
+ }
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v3_offset, len);
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox