Re: [PATCH v4 3/3] firmware: qcom: scm: Fix tzmem state on probe retry
From: Mukesh Ojha
Date: Thu Aug 06 2026 - 07:12:37 EST
On Thu, Aug 06, 2026 at 11:27:39AM +0200, Marek Szyprowski wrote:
> On 24.07.2026 11:49, Mukesh Ojha wrote:
> > qcom_tzmem_enable() returns -EBUSY if called a second time, but this
> > causes probe retries to fail permanently if a later step in
> > qcom_scm_probe() defers after qcom_tzmem_enable() has already succeeded.
> >
> > Use DO_ONCE() to ensure qcom_tzmem_init() runs exactly once across all
> > calls in a thread-safe manner. qcom_tzmem_dev is set on every call since
> > probe retries use the same device pointer. The result of the first
> > initialisation is cached and returned to every subsequent caller.
> >
> > Fixes: 40289e35ca52 ("firmware: qcom: scm: enable the TZ mem allocator")
> > Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
> > Reviewed-by: Konrad Dybcio <konrad.dybcio@xxxxxxxxxxxxxxxx>
> > Signed-off-by: Mukesh Ojha <mukesh.ojha@xxxxxxxxxxxxxxxx>
> > ---
> > drivers/firmware/qcom/qcom_tzmem.c | 13 +++++++++----
> > 1 file changed, 9 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/firmware/qcom/qcom_tzmem.c b/drivers/firmware/qcom/qcom_tzmem.c
> > index 0635cbeacfc8..0fd9581275f1 100644
> > --- a/drivers/firmware/qcom/qcom_tzmem.c
> > +++ b/drivers/firmware/qcom/qcom_tzmem.c
> > @@ -15,6 +15,7 @@
> > #include <linux/kernel.h>
> > #include <linux/list.h>
> > #include <linux/mm.h>
> > +#include <linux/once.h>
> > #include <linux/radix-tree.h>
> > #include <linux/slab.h>
> > #include <linux/spinlock.h>
> > @@ -507,14 +508,18 @@ phys_addr_t qcom_tzmem_to_phys(void *vaddr)
> > }
> > EXPORT_SYMBOL_GPL(qcom_tzmem_to_phys);
> >
> > +static void qcom_tzmem_do_init(int *result)
> > +{
> > + *result = qcom_tzmem_init();
> > +}
> > +
> > int qcom_tzmem_enable(struct device *dev)
> > {
> > - if (qcom_tzmem_dev)
> > - return -EBUSY;
> > + static int result;
> >
> > qcom_tzmem_dev = dev;
> > -
> > - return qcom_tzmem_init();
> > + DO_ONCE(qcom_tzmem_do_init, &result);
> One should use DO_ONCE_SLEEPABLE() here, otherwise it triggers a warning during
> boot on some on my test systems. Here is a log captured with
> CONFIG_DEBUG_ATOMIC_SLEEP=y on recent linux-next releases, where this patch is
> applied as commit 9941fe8a04f3 ("firmware: qcom: scm: Fix tzmem state on probe
> retry"):
Thanks for reporting; I will spin a fix..and yes DO_ONCE_SLEEPABLE() is the right one.
>
> qcom_scm: convention: smc arm 64
> 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
> preempt_count: 1, expected: 0
> RCU nest depth: 0, expected: 0
> locks held by kworker/u16:2/49: 4, last CPU#3:
> #0: ffff000000032140 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0x6b4/0x840
> #1: ffff800080563d90 (deferred_probe_work){+.+.}-{0:0}, at: process_one_work+0x1fc/0x840
> #2: ffff00000036f938 (&dev->mutex){....}-{4:4}, at: __device_attach+0x3c/0x190
> #3: ffffa83e89fe4af0 (once_lock){....}-{3:3}, at: __do_once_start+0x2c/0x74
> irq event stamp: 80794
> hardirqs last enabled at (80793): [<ffffa83e87faa600>] _raw_spin_unlock_irqrestore+0x6c/0x70
> hardirqs last disabled at (80794): [<ffffa83e87fa9a6c>] _raw_spin_lock_irqsave+0x84/0x88
> softirqs last enabled at (80780): [<ffffa83e86ccc050>] handle_softirqs+0x5dc/0x5f4
> softirqs last disabled at (80755): [<ffffa83e86c10700>] __do_softirq+0x14/0x20
> CPU: 3 UID: 0 PID: 49 Comm: kworker/u16:2 Not tainted 7.2.0-rc6-next-20260805+ #13357 PREEMPT
> Hardware name: Arduino UnoQ (DT)
> Workqueue: events_unbound deferred_probe_work_func
> Call trace:
> show_stack+0x18/0x24 (C)
> dump_stack_lvl+0x8c/0xcc
> dump_stack+0x18/0x24
> __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
> platform_probe+0x5c/0x9c
> really_probe+0xbc/0x29c
> __driver_probe_device+0x16c/0x19c
> driver_probe_device+0xb8/0x118
> __device_attach_driver+0xb8/0x118
> bus_for_each_drv+0x88/0xe8
> __device_attach+0xa0/0x190
> device_initial_probe+0x50/0x54
> bus_probe_device+0x38/0xa8
> deferred_probe_work_func+0x8c/0xc8
> process_one_work+0x24c/0x840
> worker_thread+0x1bc/0x368
> kthread+0x134/0x140
> ret_from_fork+0x10/0x20
>
> =============================
> [ BUG: Invalid wait context ]
> 7.2.0-rc6-next-20260805+ #13357 Tainted: G W
> -----------------------------
> kworker/u16:2/49 is trying to lock:
> ffffa83e8a485e38 (qcom_scm_lock){....}-{4:4}, at: __scm_smc_do+0x70/0x488
> other info that might help us debug this:
> context-{5:5}
> locks held by kworker/u16:2/49: 4, last CPU#3:
> #0: ffff000000032140 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0x6b4/0x840
> #1: ffff800080563d90 (deferred_probe_work){+.+.}-{0:0}, at: process_one_work+0x1fc/0x840
> #2: ffff00000036f938 (&dev->mutex){....}-{4:4}, at: __device_attach+0x3c/0x190
> #3: ffffa83e89fe4af0 (once_lock){....}-{3:3}, at: __do_once_start+0x2c/0x74
> stack backtrace:
> CPU: 3 UID: 0 PID: 49 Comm: kworker/u16:2 Tainted: G W 7.2.0-rc6-next-20260805+ #13357 PREEMPT
> Tainted: [W]=WARN
> Hardware name: Arduino UnoQ (DT)
> Workqueue: events_unbound deferred_probe_work_func
> Call trace:
> show_stack+0x18/0x24 (C)
> dump_stack_lvl+0x8c/0xcc
> dump_stack+0x18/0x24
> __lock_acquire+0x928/0x1f90
> lock_acquire+0x2b8/0x3ec
> __mutex_lock+0xbc/0x860
> mutex_lock_nested+0x24/0x30
> __scm_smc_do+0x70/0x488
> __scm_smc_call+0xd4/0x444
> qcom_scm_call+0x64/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
> platform_probe+0x5c/0x9c
> really_probe+0xbc/0x29c
> __driver_probe_device+0x16c/0x19c
> driver_probe_device+0xb8/0x118
> __device_attach_driver+0xb8/0x118
> bus_for_each_drv+0x88/0xe8
> __device_attach+0xa0/0x190
> device_initial_probe+0x50/0x54
> bus_probe_device+0x38/0xa8
> deferred_probe_work_func+0x8c/0xc8
> process_one_work+0x24c/0x840
> worker_thread+0x1bc/0x368
> kthread+0x134/0x140
> ret_from_fork+0x10/0x20
> qcom_scm firmware:scm: qseecom: found qseecom with version 0x1402000
> qcom_scm firmware:scm: qseecom: untested machine, skipping
>
>
> > + return result;
> > }
> > EXPORT_SYMBOL_GPL(qcom_tzmem_enable);
> >
>
> Best regards
> --
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
>
--
-Mukesh Ojha