[PATCH] firmware: qcom: tzmem: Use DO_ONCE_SLEEPABLE() in qcom_tzmem_enable()

Mukesh Ojha posted 1 patch 1 month, 3 weeks ago
drivers/firmware/qcom/qcom_tzmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] firmware: qcom: tzmem: Use DO_ONCE_SLEEPABLE() in qcom_tzmem_enable()
Posted by Mukesh Ojha 1 month, 3 weeks ago
qcom_tzmem_enable() is called from qcom_scm_probe() in a sleepable process
context. The helper it wraps, qcom_tzmem_init(), calls
qcom_scm_shm_bridge_enable() -> qcom_scm_call(), which invokes
might_sleep() and later acquires the qcom_scm_lock mutex via
__scm_smc_do().

DO_ONCE() takes the once_lock spinlock with IRQs disabled, so invoking
qcom_tzmem_init() from inside DO_ONCE() runs a sleepable call chain in
atomic context. CONFIG_DEBUG_ATOMIC_SLEEP=y catches this on boot:

  BUG: sleeping function called from invalid context at drivers/firmware/qcom/qcom_scm.c:334
  in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 49, name: kworker/u16:2
  ...
   __might_resched+0x148/0x24c
   __might_sleep+0x48/0x7c
   qcom_scm_call+0x30/0xc0
   __qcom_scm_is_call_available+0x98/0x100
   qcom_scm_shm_bridge_enable+0x60/0xbc
   qcom_tzmem_enable+0xf8/0x118
   qcom_scm_probe+0x2d0/0x680

  [ BUG: Invalid wait context ]
  ...
  kworker/u16:2/49 is trying to lock:
  ffffa83e8a485e38 (qcom_scm_lock){....}-{4:4}, at: __scm_smc_do+0x70/0x488

Switch to DO_ONCE_SLEEPABLE(), which guards the one-shot init with a
mutex-style path (__do_once_sleepable_start/done) that is safe to hold
across sleeping callees. All callers of qcom_tzmem_enable() are in
process context (driver probe), so this is safe.

Fixes: 9941fe8a04f3 ("firmware: qcom: scm: Fix tzmem state on probe retry")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/lkml/5ea74dd3-7471-4c7c-9242-c2005312b1ab@samsung.com/
Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
---
 drivers/firmware/qcom/qcom_tzmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/qcom/qcom_tzmem.c b/drivers/firmware/qcom/qcom_tzmem.c
index 0fd9581275f1..ebcdee3c5975 100644
--- a/drivers/firmware/qcom/qcom_tzmem.c
+++ b/drivers/firmware/qcom/qcom_tzmem.c
@@ -518,7 +518,7 @@ int qcom_tzmem_enable(struct device *dev)
 	static int result;
 
 	qcom_tzmem_dev = dev;
-	DO_ONCE(qcom_tzmem_do_init, &result);
+	DO_ONCE_SLEEPABLE(qcom_tzmem_do_init, &result);
 	return result;
 }
 EXPORT_SYMBOL_GPL(qcom_tzmem_enable);
-- 
2.53.0
Re: [PATCH] firmware: qcom: tzmem: Use DO_ONCE_SLEEPABLE() in qcom_tzmem_enable()
Posted by Bartosz Golaszewski 1 month, 3 weeks ago
On Thu, 6 Aug 2026 13:27:09 +0200, Mukesh Ojha
<mukesh.ojha@oss.qualcomm.com> said:
> qcom_tzmem_enable() is called from qcom_scm_probe() in a sleepable process
> context. The helper it wraps, qcom_tzmem_init(), calls
> qcom_scm_shm_bridge_enable() -> qcom_scm_call(), which invokes
> might_sleep() and later acquires the qcom_scm_lock mutex via
> __scm_smc_do().
>
> DO_ONCE() takes the once_lock spinlock with IRQs disabled, so invoking
> qcom_tzmem_init() from inside DO_ONCE() runs a sleepable call chain in
> atomic context. CONFIG_DEBUG_ATOMIC_SLEEP=y catches this on boot:
>
>   BUG: sleeping function called from invalid context at drivers/firmware/qcom/qcom_scm.c:334
>   in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 49, name: kworker/u16:2
>   ...
>    __might_resched+0x148/0x24c
>    __might_sleep+0x48/0x7c
>    qcom_scm_call+0x30/0xc0
>    __qcom_scm_is_call_available+0x98/0x100
>    qcom_scm_shm_bridge_enable+0x60/0xbc
>    qcom_tzmem_enable+0xf8/0x118
>    qcom_scm_probe+0x2d0/0x680
>
>   [ BUG: Invalid wait context ]
>   ...
>   kworker/u16:2/49 is trying to lock:
>   ffffa83e8a485e38 (qcom_scm_lock){....}-{4:4}, at: __scm_smc_do+0x70/0x488
>
> Switch to DO_ONCE_SLEEPABLE(), which guards the one-shot init with a
> mutex-style path (__do_once_sleepable_start/done) that is safe to hold
> across sleeping callees. All callers of qcom_tzmem_enable() are in
> process context (driver probe), so this is safe.
>
> Fixes: 9941fe8a04f3 ("firmware: qcom: scm: Fix tzmem state on probe retry")
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Closes: https://lore.kernel.org/lkml/5ea74dd3-7471-4c7c-9242-c2005312b1ab@samsung.com/
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> ---
>  drivers/firmware/qcom/qcom_tzmem.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/qcom/qcom_tzmem.c b/drivers/firmware/qcom/qcom_tzmem.c
> index 0fd9581275f1..ebcdee3c5975 100644
> --- a/drivers/firmware/qcom/qcom_tzmem.c
> +++ b/drivers/firmware/qcom/qcom_tzmem.c
> @@ -518,7 +518,7 @@ int qcom_tzmem_enable(struct device *dev)
>  	static int result;
>
>  	qcom_tzmem_dev = dev;
> -	DO_ONCE(qcom_tzmem_do_init, &result);
> +	DO_ONCE_SLEEPABLE(qcom_tzmem_do_init, &result);
>  	return result;
>  }
>  EXPORT_SYMBOL_GPL(qcom_tzmem_enable);
> --
> 2.53.0
>
>

Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>