[PATCH 1/2] Bluetooth: btmtksdio: wait while Wi-Fi downloads the shared patch
Ryan Brue
ryanbrue.dev at gmail.com
Mon Oct 26 12:02:13 PDT 2026
On MT7663 and MT7668 the Bluetooth and Wi-Fi SDIO functions share one
ROM patch, guarded by a semaphore in the firmware. The WMT semaphore
query answers 0 while the other function holds the semaphore and is
downloading the patch, 1 when the patch is ready, and 2 when it needs
downloading (MediaTek's own driver: PATCH_IS_DOWNLOAD_BY_OTHER,
PATCH_READY, PATCH_NEED_DOWNLOAD). btmtksdio treated 0 like 1, so when
it probed while mt7663s was downloading, it went on to enable the
Bluetooth function on a half-loaded patch. On an MT7663 module
(Amazon Fire TV Stick) that left the chip unresponsive until reset:
Bluetooth: hci0: Firmware already downloaded
Bluetooth: hci0: Execution of wmt command timed out
mt7663s mmc2:0001:1: Message 00000007 (seq 13) timeout
mt7663s mmc2:0001:1: Failed to start patch
Map 0 to BTMTK_WMT_PATCH_PROGRESS, and poll every 100 ms, for up to
5 s, while the other function is downloading, as MediaTek's driver
does.
Fixes: 9aebfd4a2200 ("Bluetooth: mediatek: add support for MediaTek MT7663S and MT7668S SDIO devices")
Signed-off-by: Ryan Brue <ryanbrue.dev at gmail.com>
---
drivers/bluetooth/btmtksdio.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index b9563df72983..bb311986271f 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -234,8 +234,16 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
switch (wmt_evt->whdr.op) {
case BTMTK_WMT_SEMAPHORE:
+ /*
+ * 0: the other function (Wi-Fi on MT7663/MT7668) holds the
+ * semaphore and is downloading the shared patch
+ * 1: the patch is ready
+ * 2: the patch needs downloading
+ */
if (wmt_evt->whdr.flag == 2)
status = BTMTK_WMT_PATCH_UNDONE;
+ else if (wmt_evt->whdr.flag == 0)
+ status = BTMTK_WMT_PATCH_PROGRESS;
else
status = BTMTK_WMT_PATCH_DONE;
break;
@@ -842,20 +850,35 @@ static int mt76xx_setup(struct hci_dev *hdev, const char *fwname)
struct btmtk_hci_wmt_params wmt_params;
struct btmtk_tci_sleep tci_sleep;
struct sk_buff *skb;
- int err, status;
+ int err, status, i;
u8 param = 0x1;
- /* Query whether the firmware is already download */
+ /*
+ * Query whether the firmware is already downloaded. While the Wi-Fi
+ * function downloads the shared patch, wait for it to finish.
+ */
wmt_params.op = BTMTK_WMT_SEMAPHORE;
wmt_params.flag = 1;
wmt_params.dlen = 0;
wmt_params.data = NULL;
wmt_params.status = &status;
- err = mtk_hci_wmt_sync(hdev, &wmt_params);
- if (err < 0) {
- bt_dev_err(hdev, "Failed to query firmware status (%d)", err);
- return err;
+ for (i = 0; i < 50; i++) {
+ err = mtk_hci_wmt_sync(hdev, &wmt_params);
+ if (err < 0) {
+ bt_dev_err(hdev, "Failed to query firmware status (%d)",
+ err);
+ return err;
+ }
+
+ if (status != BTMTK_WMT_PATCH_PROGRESS)
+ break;
+ msleep(100);
+ }
+
+ if (status == BTMTK_WMT_PATCH_PROGRESS) {
+ bt_dev_err(hdev, "Patch download by the other function did not finish");
+ return -EBUSY;
}
if (status == BTMTK_WMT_PATCH_DONE) {
--
2.55.0
More information about the Linux-mediatek
mailing list