Re: [PATCH] firmware: qcom: tzmem: Use DO_ONCE_SLEEPABLE() in qcom_tzmem_enable()
Bartosz Golaszewski <[email protected]>
| Newsgroups | org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAMRc=MffWt7TrSXaQpd6Zo_BHOrDv2tMxBh9cmMvkqem3Q245w@mail.gmail.com> |
On Thu, 6 Aug 2026 13:27:09 +0200, Mukesh Ojha <[email protected]> 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 <[email protected]> > Closes: https://lore.kernel.org/lkml/[email protected]/ > Signed-off-by: Mukesh Ojha <[email protected]> > --- > 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 <[email protected]>