* [PATCH v2 0/3] Bluetooth: btmtksdio: teardown fixes
@ 2026-06-16 11:12 Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check Sergey Senozhatsky
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Sergey Senozhatsky @ 2026-06-16 11:12 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 is v2 of teardown fixes.
We noticed a number of cases when btmtk close/teardown would hung:
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
[..]
There are several issues with the teardown (close/reset) code
in the driver. First, the btmtksdio_txrx_work() potentially
can spin forever (infinite loop). Second, close/flush can
deadlock when run concurrently with btmtksdio_txrx_work().
v1 -> v2:
- added two more patches (deadlock fix, interrupts re-enabling
enhancement)
Sergey Senozhatsky (3):
Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check
Bluetooth: btmtksdio: test for bug IO errors in btmtksdio_txrx_work()
Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock
scope
drivers/bluetooth/btmtksdio.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check
2026-06-16 11:12 [PATCH v2 0/3] Bluetooth: btmtksdio: teardown fixes Sergey Senozhatsky
@ 2026-06-16 11:12 ` Sergey Senozhatsky
2026-06-16 15:30 ` Bluetooth: btmtksdio: teardown fixes bluez.test.bot
2026-06-16 11:12 ` [PATCH v2 2/3] Bluetooth: btmtksdio: test for bug IO errors in btmtksdio_txrx_work() Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 3/3] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope Sergey Senozhatsky
2 siblings, 1 reply; 5+ messages in thread
From: Sergey Senozhatsky @ 2026-06-16 11:12 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
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));
/* Enable interrupt */
if (bdev->func->irq_handler)
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/3] Bluetooth: btmtksdio: test for bug IO errors in btmtksdio_txrx_work()
2026-06-16 11:12 [PATCH v2 0/3] Bluetooth: btmtksdio: teardown fixes Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check Sergey Senozhatsky
@ 2026-06-16 11:12 ` Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 3/3] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope Sergey Senozhatsky
2 siblings, 0 replies; 5+ messages in thread
From: Sergey Senozhatsky @ 2026-06-16 11:12 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
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 [flat|nested] 5+ messages in thread
* [PATCH v2 3/3] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope
2026-06-16 11:12 [PATCH v2 0/3] Bluetooth: btmtksdio: teardown fixes Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 2/3] Bluetooth: btmtksdio: test for bug IO errors in btmtksdio_txrx_work() Sergey Senozhatsky
@ 2026-06-16 11:12 ` Sergey Senozhatsky
2 siblings, 0 replies; 5+ messages in thread
From: Sergey Senozhatsky @ 2026-06-16 11:12 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
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 [flat|nested] 5+ messages in thread
* RE: Bluetooth: btmtksdio: teardown fixes
2026-06-16 11:12 ` [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check Sergey Senozhatsky
@ 2026-06-16 15:30 ` bluez.test.bot
0 siblings, 0 replies; 5+ messages in thread
From: bluez.test.bot @ 2026-06-16 15:30 UTC (permalink / raw)
To: linux-bluetooth, senozhatsky
[-- Attachment #1: Type: text/plain, Size: 560 bytes --]
This is an automated email and please do not reply to this email.
Dear Submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.
----- Output -----
error: patch failed: drivers/bluetooth/btmtksdio.c:620
error: drivers/bluetooth/btmtksdio.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch
Please resolve the issue and submit the patches again.
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-16 15:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-16 11:12 [PATCH v2 0/3] Bluetooth: btmtksdio: teardown fixes Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 1/3] Bluetooth: btmtksdio: correct btmtksdio_txrx_work() loop timeout check Sergey Senozhatsky
2026-06-16 15:30 ` Bluetooth: btmtksdio: teardown fixes bluez.test.bot
2026-06-16 11:12 ` [PATCH v2 2/3] Bluetooth: btmtksdio: test for bug IO errors in btmtksdio_txrx_work() Sergey Senozhatsky
2026-06-16 11:12 ` [PATCH v2 3/3] Bluetooth: btmtksdio: call cancel_work_sync() outside of host lock scope Sergey Senozhatsky
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox