[PATCH 1/2] thermal/drivers/qcom/tsens: Drop __init from init_common()

From: Christian Schmidbauer

Date: Wed Nov 04 2026 - 10:02:32 EST


Several tsens_ops instances store init_common() as their ->init
callback, which tsens_probe() calls through priv->ops->init().
init_common() is marked __init, but tsens_probe() is a normal platform
driver probe and can run after free_initmem().

This happens on IPQ8064 when CONFIG_IPQ_LCC_806X is disabled. In
qcom-ipq8064.dtsi the tsens node is a child of gcc, which uses a clock
from the LCC. Because no driver binds the LCC, fw_devlink defers the
probe of gcc until deferred_probe_timeout_work_func() runs.
deferred_probe_initcall() schedules that work to run
CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT seconds later, when kernel_init()
has already freed init memory. On an Aruba AP-325 the probe then
crashes:

Unable to handle kernel execution of memory at virtual address c0e1ffe0
Workqueue: events_unbound deferred_probe_work_func
PC is at init_common+0x0/0x540
LR is at tsens_probe+0x138/0x4b4

With CONFIG_QCOM_TSENS=m the driver has the same problem, because the
module loader frees __init code once the module's init function returns
and a later bind then calls into freed memory.

Removing __init from init_common() covers the ops that store it
directly, but the per-SoC init functions that wrap it are also marked
__init and need the same change.

Tested on an Aruba AP-325.

Fixes: 9066073c6c27 ("thermal: qcom: tsens: Add a skeletal TSENS drivers")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-opus-5
Signed-off-by: Christian Schmidbauer <opensource@xxxxxxxxxxx>
---
drivers/thermal/qcom/tsens.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 4d7013fc79d6..710c78aff8bc 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -929,7 +929,7 @@ static const struct regmap_config tsens_srot_config = {
.reg_stride = 4,
};

-int __init init_common(struct tsens_priv *priv)
+int init_common(struct tsens_priv *priv)
{
void __iomem *tm_base, *srot_base;
struct device *dev = priv->dev;
--
2.54.0