Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3] Bluetooth: btmtk: Add MT7928 support
From: Chris Lu @ 2026-06-17 23:51 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 (internal device ID is MT7935) which
requires additional firmware (CBMCU firmware) loading before
Bluetooth firmware.

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.

After CBMCU firmware loads successfully, the driver continues
to load corresponding BT firmware based on device ID through
fallthrough to case 0x7922/0x7925.

The firmware required for MT7928 will be scheduled for upload
to linux-firmware at a later stage.

MT7928 bringup kernel log:
[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.
v2->v3: Update commit message.
---
 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 *)&sectionmap->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

* RE: Bluetooth: simplify force_no_mitm_write() with kstrtobool_from_user()
From: bluez.test.bot @ 2026-06-17 18:17 UTC (permalink / raw)
  To: linux-bluetooth, dmantipov
In-Reply-To: <20260617153019.981515-1-dmantipov@yandex.ru>

[-- Attachment #1: Type: text/plain, Size: 2657 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=1113029

---Test result---

Test Summary:
CheckPatch                    PASS      0.59 seconds
VerifyFixes                   PASS      0.07 seconds
VerifySignedoff               PASS      0.07 seconds
GitLint                       PASS      0.20 seconds
SubjectPrefix                 PASS      0.06 seconds
BuildKernel                   PASS      26.57 seconds
CheckAllWarning               PASS      29.13 seconds
CheckSparse                   PASS      27.78 seconds
BuildKernel32                 PASS      25.66 seconds
CheckKernelLLVM               SKIP      0.00 seconds
TestRunnerSetup               PASS      572.07 seconds
TestRunner_l2cap-tester       FAIL      57.71 seconds
TestRunner_iso-tester         PASS      80.47 seconds
TestRunner_bnep-tester        PASS      18.93 seconds
TestRunner_mgmt-tester        FAIL      207.33 seconds
TestRunner_rfcomm-tester      PASS      25.14 seconds
TestRunner_sco-tester         PASS      32.73 seconds
TestRunner_ioctl-tester       PASS      26.21 seconds
TestRunner_mesh-tester        FAIL      25.95 seconds
TestRunner_smp-tester         PASS      23.16 seconds
TestRunner_userchan-tester    PASS      19.99 seconds
TestRunner_6lowpan-tester     PASS      22.39 seconds
IncrementalBuild              PASS      24.67 seconds

Details
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
Total: 96, Passed: 95 (99.0%), Failed: 1, Not Run: 0

Failed Test Cases
L2CAP BR/EDR Server - Set PHY 3M                     Failed       0.250 seconds
##############################
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.487 seconds
Mesh - Send cancel - 2                               Timed out    1.989 seconds


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

---
Regards,
Linux Bluetooth


^ permalink raw reply

* RE: Bluetooth: L2CAP: cancel pending_rx_work before taking conn->lock
From: bluez.test.bot @ 2026-06-17 18:04 UTC (permalink / raw)
  To: linux-bluetooth, runyu.xiao
In-Reply-To: <20260617153613.1139031-1-runyu.xiao@seu.edu.cn>

[-- Attachment #1: Type: text/plain, Size: 1355 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=1113030

---Test result---

Test Summary:
CheckPatch                    PASS      0.66 seconds
VerifyFixes                   PASS      0.46 seconds
VerifySignedoff               PASS      0.16 seconds
GitLint                       PASS      0.28 seconds
SubjectPrefix                 PASS      0.11 seconds
BuildKernel                   PASS      26.65 seconds
CheckAllWarning               PASS      29.50 seconds
CheckSparse                   PASS      27.53 seconds
BuildKernel32                 PASS      25.54 seconds
CheckKernelLLVM               SKIP      0.00 seconds
TestRunnerSetup               PASS      588.69 seconds
TestRunner_l2cap-tester       PENDING   57.76 seconds
IncrementalBuild              PASS      24.84 seconds

Details
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
##############################
Test: TestRunner_l2cap-tester - PENDING
Desc: Run l2cap-tester with test-runner
Output:



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

---
Regards,
Linux Bluetooth


^ permalink raw reply

* [PATCH] Bluetooth: L2CAP: cancel pending_rx_work before taking conn->lock
From: Runyu Xiao @ 2026-06-17 15:36 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz
  Cc: Jukka Taimisto, linux-bluetooth, linux-kernel, jianhao.xu,
	runyu.xiao, stable

l2cap_conn_del() takes conn->lock and then calls cancel_work_sync() for
pending_rx_work.  process_pending_rx() takes the same mutex, so teardown
can deadlock against the worker it is flushing.

This issue was found by our static analysis tool and then manually
reviewed against the current tree.

The grounded PoC kept the l2cap_conn_ready() -> queue_work(...,
&conn->pending_rx_work) submit path, the l2cap_conn_del() ->
cancel_work_sync(&conn->pending_rx_work) teardown path, and the
process_pending_rx() -> mutex_lock(&conn->lock) worker edge.  Lockdep
reported:

  WARNING: possible circular locking dependency detected
  process_pending_rx+0x21/0x2a [vuln_msv]
  l2cap_conn_del.constprop.0+0x3f/0x4e [vuln_msv]
  *** DEADLOCK ***

Cancel pending_rx_work before taking conn->lock, matching the existing
lock-before-drain ordering used for the two delayed works in the same
teardown path.  The pending_rx queue is still purged after the work has
been cancelled and conn->lock has been acquired.

Fixes: 7ab56c3a6ecc ("Bluetooth: Fix deadlock in l2cap_conn_del()")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
---
 net/bluetooth/l2cap_core.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 29e23f20dc43..0dad72716cca 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1774,19 +1774,13 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
 	disable_delayed_work_sync(&conn->info_timer);
 	disable_delayed_work_sync(&conn->id_addr_timer);
 
+	cancel_work_sync(&conn->pending_rx_work);
+
 	mutex_lock(&conn->lock);
 
 	kfree_skb(conn->rx_skb);
 
 	skb_queue_purge(&conn->pending_rx);
-
-	/* We can not call flush_work(&conn->pending_rx_work) here since we
-	 * might block if we are running on a worker from the same workqueue
-	 * pending_rx_work is waiting on.
-	 */
-	if (work_pending(&conn->pending_rx_work))
-		cancel_work_sync(&conn->pending_rx_work);
-
 	ida_destroy(&conn->tx_ida);
 
 	l2cap_unregister_all_users(conn);
-- 
2.34.1


^ permalink raw reply related

* [PATCH] Bluetooth: simplify force_no_mitm_write() with kstrtobool_from_user()
From: Dmitry Antipov @ 2026-06-17 15:30 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, Marcel Holtmann; +Cc: linux-bluetooth, Dmitry Antipov

Simplify 'force_no_mitm_write()' by using the convenient
'kstrtobool_from_user()'.

Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
---
 net/bluetooth/hci_debugfs.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
index 0635e4641db4..aadffaaff20e 100644
--- a/net/bluetooth/hci_debugfs.c
+++ b/net/bluetooth/hci_debugfs.c
@@ -1161,16 +1161,12 @@ static ssize_t force_no_mitm_write(struct file *file,
 				   size_t count, loff_t *ppos)
 {
 	struct hci_dev *hdev = file->private_data;
-	char buf[32];
-	size_t buf_size = min(count, (sizeof(buf) - 1));
 	bool enable;
+	int err;
 
-	if (copy_from_user(buf, user_buf, buf_size))
-		return -EFAULT;
-
-	buf[buf_size] = '\0';
-	if (kstrtobool(buf, &enable))
-		return -EINVAL;
+	err = kstrtobool_from_user(user_buf, count, &enable);
+	if (err)
+		return err;
 
 	if (enable == hci_dev_test_flag(hdev, HCI_FORCE_NO_MITM))
 		return -EALREADY;
-- 
2.54.0


^ permalink raw reply related

* [bluez/bluez]
From: BluezTestBot @ 2026-06-17 15:16 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1112111
  Home:   https://github.com/bluez/bluez

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [bluez/bluez]
From: BluezTestBot @ 2026-06-17 15:16 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1112321
  Home:   https://github.com/bluez/bluez

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [bluez/bluez] aa8d0a: shared/gatt: Fix gatt-db buffer overflow for clone...
From: Bhavani @ 2026-06-17 15:15 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/master
  Home:   https://github.com/bluez/bluez
  Commit: aa8d0a2b684176e2295588f58ea9c8c3fc86597c
      https://github.com/bluez/bluez/commit/aa8d0a2b684176e2295588f58ea9c8c3fc86597c
  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


  Commit: efa2a66a7964234039ab694e1a572a5c0937be0d
      https://github.com/bluez/bluez/commit/efa2a66a7964234039ab694e1a572a5c0937be0d
  Author: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
  Date:   2026-06-16 (Tue, 16 Jun 2026)

  Changed paths:
    M src/shared/rap.h

  Log Message:
  -----------
  shared: rap: Check role before sending CS Sec Enable cmd

Add the is_central parameter to verify whether
the local role is central before sending
the HCI CS Security Enable command.


  Commit: 20cc88874d5759f19f16ff649d46e5e2a660df8d
      https://github.com/bluez/bluez/commit/20cc88874d5759f19f16ff649d46e5e2a660df8d
  Author: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
  Date:   2026-06-16 (Tue, 16 Jun 2026)

  Changed paths:
    M profiles/ranging/rap.c
    M profiles/ranging/rap_hci.c

  Log Message:
  -----------
  profiles: ranging: Add CS Initiator cmd and evt handling

Introduce support for LE Channel Sounding (CS)
ranging procedures in the Initiator role by enabling
required HCI command sequencing and event handling.

Add handling of core HCI LE CS commands and events
This enables cs capability discovery, cs configuration
management and execution of CS ranging procedures
in the Initiator role.


  Commit: 629b788e11b5ba7a8b1554c5ed1b8a02f2f9f310
      https://github.com/bluez/bluez/commit/629b788e11b5ba7a8b1554c5ed1b8a02f2f9f310
  Author: Naga Bhavani Akella <naga.akella@oss.qualcomm.com>
  Date:   2026-06-16 (Tue, 16 Jun 2026)

  Changed paths:
    M src/shared/rap.h

  Log Message:
  -----------
  shared: rap: remove the old wrapper API

Replace API bt_rap_set_conn_handle with
bt_rap_set_conn_hndl which has extra parameter
to avoid compilation error for individual patches


Compare: https://github.com/bluez/bluez/compare/5297cf2b6af6...629b788e11b5

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* Re: [PATCH BlueZ] shared/gatt: Fix gatt-db buffer overflow for cloned db
From: patchwork-bot+bluetooth @ 2026-06-17 14:10 UTC (permalink / raw)
  To: =?utf-8?b?RnLDqWTDqXJpYyBEYW5pcyA8ZnJlZGVyaWMuZGFuaXNAY29sbGFib3JhLmNvbT4=?=
  Cc: linux-bluetooth
In-Reply-To: <20260616123029.301362-1-frederic.danis@collabora.com>

Hello:

This patch was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 16 Jun 2026 14:30:29 +0200 you wrote:
> 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)
> 
> [...]

Here is the summary with links:
  - [BlueZ] shared/gatt: Fix gatt-db buffer overflow for cloned db
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=aa8d0a2b6841

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH BlueZ v4 0/3]  Initial Channel Sounding Support for
From: patchwork-bot+bluetooth @ 2026-06-17 14:10 UTC (permalink / raw)
  To: Naga Bhavani Akella
  Cc: linux-bluetooth, luiz.dentz, quic_mohamull, quic_hbandi,
	quic_anubhavg
In-Reply-To: <20260616072245.3700010-1-naga.akella@oss.qualcomm.com>

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 16 Jun 2026 12:52:42 +0530 you wrote:
> This series adds initial LE Channel Sounding (CS) Initiator support by
> introducing the required HCI command flow and event handling for CS
> procedures.
> 
> The changes include
> 1. Adding an is_central parameter to validate that
> current local role is central before issuing
> HCI_LE_CS_Security_Enable command.
> 
> [...]

Here is the summary with links:
  - [BlueZ,v4,1/3] shared: rap: Check role before sending CS Sec Enable cmd
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=efa2a66a7964
  - [BlueZ,v4,2/3] profiles: ranging: Add CS Initiator cmd and evt handling
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=20cc88874d57
  - [BlueZ,v4,3/3] shared: rap: remove the old wrapper API
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=629b788e11b5

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH 7/7] arm64: dts: qcom: sm8350-hdk: describe WiFi/BT chip
From: Konrad Dybcio @ 2026-06-17 10:46 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas, Qiang Yu,
	Jeff Johnson, Liam Girdwood, Mark Brown, Krzysztof Kozlowski,
	Conor Dooley, Bartosz Golaszewski, Marcel Holtmann,
	Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
	Bjorn Andersson, Konrad Dybcio, linux-arm-msm, linux-pci,
	linux-kernel, linux-wireless, ath11k, devicetree,
	Bartosz Golaszewski, linux-bluetooth
In-Reply-To: <dz4qovpquxgynnzviqg6g23oa2o3trlkznremnmlqfnlj3b62x@oqgcuvalfcph>

On 6/11/26 9:44 PM, Dmitry Baryshkov wrote:
> On Thu, Jun 11, 2026 at 02:09:27PM +0200, Konrad Dybcio wrote:
>> On 6/1/26 11:46 AM, Dmitry Baryshkov wrote:
>>> The SM8350 HDK has onboard WiFi/BT chip, WCN6851. It is an earlier
>>> version of well-known WCN6855 WiFI/BT SoC. Describe the PMU, BT and WiFI
>>> parts of the device.
>>
>> [...]
>>
>>> +	wcn6855-pmu {
>>> +		compatible = "qcom,wcn6851-pmu", "qcom,wcn6855-pmu";
>>> +
>>> +		pinctrl-0 = <&bt_en>, <&wlan_en>, <&swctrl>;
>>> +		pinctrl-names = "default";
>>> +
>>> +		wlan-enable-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
>>> +		bt-enable-gpios = <&tlmm 65 GPIO_ACTIVE_HIGH>;
>>> +		swctrl-gpios = <&tlmm 153 GPIO_ACTIVE_HIGH>;
>>> +
>>> +		vddio-supply = <&vreg_s10b_1p8>;
>>> +		vddaon-supply = <&vreg_s11b_0p95>;
>>> +		vddpmu-supply = <&vreg_s11b_0p95>;
>>> +		vddpmumx-supply = <&vreg_s2e_0p85>;
>>> +		vddpmucx-supply = <&vreg_s11b_0p95>;
>>> +		vddrfa0p95-supply = <&vreg_s11b_0p95>;
>>> +		vddrfa1p3-supply = <&vreg_s12b_1p25>;
>>> +		vddrfa1p9-supply = <&vreg_s1c_1p86>;
>>> +		vddpcie1p3-supply = <&vreg_s12b_1p25>;
>>> +		vddpcie1p9-supply = <&vreg_s1c_1p86>;
>>
>> [...]
>>
>>> @@ -373,6 +437,13 @@ vreg_l7e_2p8: ldo7 {
>>>  			regulator-name = "vreg_l7e_2p8";
>>>  			regulator-min-microvolt = <2800000>;
>>>  			regulator-max-microvolt = <2800000>;
>>> +
>>> +			/*
>>> +			 * This is used by the RF front-end for which there is
>>> +			 * no way to represent it in DT (yet?).
>>> +			 */
>>> +			regulator-boot-on;
>>> +			regulator-always-on;
>>
>> msm-5.4 maps this to bt-vdd-asd-supply (asd being a keyboard smash,
>> perhaps?) - what is its actual use?
> 
> WiFI/BT RF front-end, a separate chip containing amplifiers, couplers,
> etc.
> 
> It is a separate chip (or a module), it is not powered on by the PMU,
> etc.

Ah, that thing.. yeah I don't really know. Although it'd be a shame to
keep it powered forever, so maybe one day someone will revisit this

Konrad

^ permalink raw reply

* Re: [PATCH RFC] bluetooth: hci: Fix null-ptr-deref in hci_conn_timeout
From: Sungwoo Kim @ 2026-06-17  9:23 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz
  Cc: Dave Tian, Luiz Augusto von Dentz, linux-bluetooth, linux-kernel
In-Reply-To: <20260617035421.341457-2-iam@sung-woo.kim>

On Tue, Jun 16, 2026 at 11:55 PM Sungwoo Kim <iam@sung-woo.kim> wrote:
>
> 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.

The Sashiko review[1] looks correct.
The race window is invalid because hci_conn_hash_flush() synchronously
disables all conn->disc_work, so hci_abort_conn() cannot execute
concurrently with hdev->sent_cmd being cleared.

[1] https://sashiko.dev/#/patchset/20260617035421.341457-2-iam%40sung-woo.kim

[snip]

^ permalink raw reply

* Re: [PATCH v1] Bluetooth: btmtk: Add MT7928 support
From: Paul Menzel @ 2026-06-17  8:49 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: <c983c544a39606e1468158a7b6fdc77b6ca5c8a2.camel@mediatek.com>

Dear Chris,


Thank you for your reply.

Am 17.06.26 um 10:34 schrieb Chris Lu (陸稚泓):

> On Wed, 2026-06-17 at 08:53 +0200, Paul Menzel wrote:
>>
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.

>> 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.
>>
>> […]
> 
> Since MT7928 hasn't been deployed in any commercially available
> products yet, MediaTek currently plans to send driver patch first and
> upload firmware part after done a series of internal test to make sure
> the quality.

Understood. Also something for the commit message. ;-)

I wonder, if this should only be put into Linus’ master branch, once the 
firmware is available.


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: [PATCH v1] Bluetooth: btmtk: Add MT7928 support
From: Chris Lu (陸稚泓) @ 2026-06-17  8:34 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: <4501985d-c8df-4121-89fd-0b4eb09273c6@molgen.mpg.de>

Hi Paul,

On Wed, 2026-06-17 at 08:53 +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 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.
> 
> […]

Since MT7928 hasn't been deployed in any commercially available
products yet, MediaTek currently plans to send driver patch first and
upload firmware part after done a series of internal test to make sure
the quality.

> 
> 
> 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.)


Chris Lu


^ 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

* 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

* 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

* 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: 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: [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: [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

* [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

* [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 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 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 *)&sectionmap->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


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