mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the ->init callbacks
@ 2026-11-04 14:57 Christian Schmidbauer
  2026-11-04 14:57 ` [PATCH 1/2] thermal/drivers/qcom/tsens: Drop __init from init_common() Christian Schmidbauer
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Christian Schmidbauer @ 2026-11-04 14:57 UTC (permalink / raw)
  To: Amit Kucheria, Thara Gopinath, Rafael J. Wysocki, Daniel Lezcano
  Cc: Zhang Rui, Lukasz Luba, Dmitry Baryshkov, Konrad Dybcio,
	AngeloGioacchino Del Regno, linux-pm, linux-arm-msm,
	linux-kernel, Christian Schmidbauer

Every function that tsens_probe() calls through priv->ops->init() is
marked __init, so a probe after free_initmem() jumps into freed memory.
On IPQ8064 with CONFIG_IPQ_LCC_806X disabled, fw_devlink defers the
probe of gcc and its tsens child until the deferred probe timeout,
which expires after init memory is freed.  On an Aruba AP-325 the probe
then crashes in init_common().  With CONFIG_QCOM_TSENS=m the driver has
the same problem once the module's init function has returned.

Patch 1 drops __init from init_common() in a one-line change that
applies to every stable tree.  Patch 2 drops it from the eight per-SoC
callbacks.

Patch 1 was tested on an Aruba AP-325 on a v7.2-rc7 based tree.

Not tested:
- Patch 2 on hardware.  None of msm8226, msm8909, msm8939, msm8952,
  msm8956, mdm9607, ipq5018, ipq5332 or ipq5424 was available, so patch
  2 is only compile-tested.
- CONFIG_QCOM_TSENS=m on hardware.

Christian Schmidbauer (2):
  thermal/drivers/qcom/tsens: Drop __init from init_common()
  thermal/drivers/qcom/tsens: Drop __init from the per-SoC ->init
    callbacks

 drivers/thermal/qcom/tsens-v0_1.c | 9 +++++----
 drivers/thermal/qcom/tsens-v1.c   | 7 ++++---
 drivers/thermal/qcom/tsens-v2.c   | 2 +-
 drivers/thermal/qcom/tsens.c      | 2 +-
 4 files changed, 11 insertions(+), 9 deletions(-)


base-commit: 2dc1f296b5754dd2441fc8b6613a362a47f6b98f
-- 
2.54.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] thermal/drivers/qcom/tsens: Drop __init from init_common()
  2026-11-04 14:57 [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the ->init callbacks Christian Schmidbauer
@ 2026-11-04 14:57 ` Christian Schmidbauer
  2026-11-04 14:57 ` [PATCH 2/2] thermal/drivers/qcom/tsens: Drop __init from the per-SoC ->init callbacks Christian Schmidbauer
  2026-11-04 15:33 ` [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the " Daniel Lezcano
  2 siblings, 0 replies; 4+ messages in thread
From: Christian Schmidbauer @ 2026-11-04 14:57 UTC (permalink / raw)
  To: Amit Kucheria, Thara Gopinath, Rafael J. Wysocki, Daniel Lezcano
  Cc: Zhang Rui, Lukasz Luba, Dmitry Baryshkov, Konrad Dybcio,
	AngeloGioacchino Del Regno, linux-pm, linux-arm-msm,
	linux-kernel, Christian Schmidbauer

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@vger.kernel.org
Assisted-by: Claude:claude-opus-5
Signed-off-by: Christian Schmidbauer <opensource@grische.xyz>
---
 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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] thermal/drivers/qcom/tsens: Drop __init from the per-SoC ->init callbacks
  2026-11-04 14:57 [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the ->init callbacks Christian Schmidbauer
  2026-11-04 14:57 ` [PATCH 1/2] thermal/drivers/qcom/tsens: Drop __init from init_common() Christian Schmidbauer
@ 2026-11-04 14:57 ` Christian Schmidbauer
  2026-11-04 15:33 ` [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the " Daniel Lezcano
  2 siblings, 0 replies; 4+ messages in thread
From: Christian Schmidbauer @ 2026-11-04 14:57 UTC (permalink / raw)
  To: Amit Kucheria, Thara Gopinath, Rafael J. Wysocki, Daniel Lezcano
  Cc: Zhang Rui, Lukasz Luba, Dmitry Baryshkov, Konrad Dybcio,
	AngeloGioacchino Del Regno, linux-pm, linux-arm-msm,
	linux-kernel, Christian Schmidbauer

init_8226(), init_8909(), init_8939(), init_8952(), init_8956(),
init_9607(), init_tsens_v1_no_rpm() and init_tsens_v2_no_rpm() are
marked __init, but tsens_probe() calls them through priv->ops->init()
and can run after free_initmem().  The call then jumps into memory that
is no longer mapped executable, and the kernel oopses.

The probe runs that late when fw_devlink defers it until the deferred
probe timeout.

Fixes: a7d3006be5ca ("thermal/drivers/tsens: Sort out msm8976 vs msm8956 data")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Christian Schmidbauer <opensource@grische.xyz>
---
 drivers/thermal/qcom/tsens-v0_1.c | 9 +++++----
 drivers/thermal/qcom/tsens-v1.c   | 7 ++++---
 drivers/thermal/qcom/tsens-v2.c   | 2 +-
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c
index 32d2d3e33287..a13897632b91 100644
--- a/drivers/thermal/qcom/tsens-v0_1.c
+++ b/drivers/thermal/qcom/tsens-v0_1.c
@@ -207,7 +207,7 @@ static int calibrate_8974(struct tsens_priv *priv)
 	return 0;
 }
 
-static int __init init_8226(struct tsens_priv *priv)
+static int init_8226(struct tsens_priv *priv)
 {
 	priv->sensor[0].slope = 2901;
 	priv->sensor[1].slope = 2846;
@@ -219,7 +219,7 @@ static int __init init_8226(struct tsens_priv *priv)
 	return init_common(priv);
 }
 
-static int __init init_8909(struct tsens_priv *priv)
+static int init_8909(struct tsens_priv *priv)
 {
 	int i;
 
@@ -240,7 +240,8 @@ static int __init init_8909(struct tsens_priv *priv)
 	return init_common(priv);
 }
 
-static int __init init_8939(struct tsens_priv *priv) {
+static int init_8939(struct tsens_priv *priv)
+{
 	priv->sensor[0].slope = 2911;
 	priv->sensor[1].slope = 2789;
 	priv->sensor[2].slope = 2906;
@@ -255,7 +256,7 @@ static int __init init_8939(struct tsens_priv *priv) {
 	return init_common(priv);
 }
 
-static int __init init_9607(struct tsens_priv *priv)
+static int init_9607(struct tsens_priv *priv)
 {
 	int i;
 
diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c
index 7bda8e6087c4..ed0064f4e1ae 100644
--- a/drivers/thermal/qcom/tsens-v1.c
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -145,7 +145,7 @@ static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
 	[TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
 };
 
-static int __init init_8952(struct tsens_priv *priv)
+static int init_8952(struct tsens_priv *priv)
 {
 	priv->sensor[0].p1_calib_offset = 2;
 	priv->sensor[0].p2_calib_offset = -1;
@@ -173,7 +173,8 @@ static int __init init_8952(struct tsens_priv *priv)
 	return init_common(priv);
 }
 
-static int __init init_8956(struct tsens_priv *priv) {
+static int init_8956(struct tsens_priv *priv)
+{
 	priv->sensor[0].slope = 3313;
 	priv->sensor[1].slope = 3275;
 	priv->sensor[2].slope = 3320;
@@ -189,7 +190,7 @@ static int __init init_8956(struct tsens_priv *priv) {
 	return init_common(priv);
 }
 
-static int __init init_tsens_v1_no_rpm(struct tsens_priv *priv)
+static int init_tsens_v1_no_rpm(struct tsens_priv *priv)
 {
 	int i, ret;
 	u32 mask = 0;
diff --git a/drivers/thermal/qcom/tsens-v2.c b/drivers/thermal/qcom/tsens-v2.c
index 843dd29fad2e..22284973bb61 100644
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -220,7 +220,7 @@ static int tsens_v2_calibration(struct tsens_priv *priv)
 	return 0;
 }
 
-static int __init init_tsens_v2_no_rpm(struct tsens_priv *priv)
+static int init_tsens_v2_no_rpm(struct tsens_priv *priv)
 {
 	struct device *dev = priv->dev;
 	int i, ret;
-- 
2.54.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the ->init callbacks
  2026-11-04 14:57 [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the ->init callbacks Christian Schmidbauer
  2026-11-04 14:57 ` [PATCH 1/2] thermal/drivers/qcom/tsens: Drop __init from init_common() Christian Schmidbauer
  2026-11-04 14:57 ` [PATCH 2/2] thermal/drivers/qcom/tsens: Drop __init from the per-SoC ->init callbacks Christian Schmidbauer
@ 2026-11-04 15:33 ` Daniel Lezcano
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Lezcano @ 2026-11-04 15:33 UTC (permalink / raw)
  To: Christian Schmidbauer, Amit Kucheria, Thara Gopinath,
	Rafael J. Wysocki, Daniel Lezcano
  Cc: Zhang Rui, Lukasz Luba, Dmitry Baryshkov, Konrad Dybcio,
	AngeloGioacchino Del Regno, linux-pm, linux-arm-msm,
	linux-kernel


Hi Christian,

I don't see the patches along with the cover letter


On 11/4/26 15:57, Christian Schmidbauer wrote:
> Every function that tsens_probe() calls through priv->ops->init() is
> marked __init, so a probe after free_initmem() jumps into freed memory.
> On IPQ8064 with CONFIG_IPQ_LCC_806X disabled, fw_devlink defers the
> probe of gcc and its tsens child until the deferred probe timeout,
> which expires after init memory is freed.  On an Aruba AP-325 the probe
> then crashes in init_common().  With CONFIG_QCOM_TSENS=m the driver has
> the same problem once the module's init function has returned.
> 
> Patch 1 drops __init from init_common() in a one-line change that
> applies to every stable tree.  Patch 2 drops it from the eight per-SoC
> callbacks.
> 
> Patch 1 was tested on an Aruba AP-325 on a v7.2-rc7 based tree.
> 
> Not tested:
> - Patch 2 on hardware.  None of msm8226, msm8909, msm8939, msm8952,
>    msm8956, mdm9607, ipq5018, ipq5332 or ipq5424 was available, so patch
>    2 is only compile-tested.
> - CONFIG_QCOM_TSENS=m on hardware.
> 
> Christian Schmidbauer (2):
>    thermal/drivers/qcom/tsens: Drop __init from init_common()
>    thermal/drivers/qcom/tsens: Drop __init from the per-SoC ->init
>      callbacks
> 
>   drivers/thermal/qcom/tsens-v0_1.c | 9 +++++----
>   drivers/thermal/qcom/tsens-v1.c   | 7 ++++---
>   drivers/thermal/qcom/tsens-v2.c   | 2 +-
>   drivers/thermal/qcom/tsens.c      | 2 +-
>   4 files changed, 11 insertions(+), 9 deletions(-)
> 
> 
> base-commit: 2dc1f296b5754dd2441fc8b6613a362a47f6b98f


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-11-04 15:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04 14:57 [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the ->init callbacks Christian Schmidbauer
2026-11-04 14:57 ` [PATCH 1/2] thermal/drivers/qcom/tsens: Drop __init from init_common() Christian Schmidbauer
2026-11-04 14:57 ` [PATCH 2/2] thermal/drivers/qcom/tsens: Drop __init from the per-SoC ->init callbacks Christian Schmidbauer
2026-11-04 15:33 ` [PATCH 0/2] thermal/drivers/qcom/tsens: Drop __init from the " Daniel Lezcano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®