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