thermal/drivers/samsung: acpm-tmu: Fixes and cleanups for GS101 TMU
Tudor Ambarus
maintainercover thermal/drivers/samsung: acpm-tmu: Fixes and cleanups for GS101 TMU
Hi,
The series is structured with fixes first (patches 1-10) followed by cleanups (patches 11-15), so the fixes can be picked up for the -rc phase if desired. Patches 11-12 are placed immediately after the fixes in case it is also preferred to take the driver and module renames before v7.4 is released.
Thanks,
ta
---
Tudor Ambarus (15):
thermal/drivers/samsung: Select REGMAP_MMIO for EXYNOS_ACPM_THERMAL thermal/drivers/samsung: Depend on PM for EXYNOS_ACPM_THERMAL thermal/drivers/samsung: acpm-tmu: Fix acpm_tmu_resume() error handling thermal/drivers/samsung: acpm-tmu: Disable IRQ across system suspend/resume thermal/drivers/samsung: acpm-tmu: Implement .change_mode() callback thermal/drivers/samsung: acpm-tmu: Rely on devres for probe error and remove teardown thermal/drivers/samsung: acpm-tmu: Return -ENODATA when sensor is disabled thermal/drivers/samsung: acpm-tmu: Annotate lockless sensor->enabled access thermal/drivers/samsung: acpm-tmu: Fix IRQ locking and error handling
MAINTAINERS: Use linux-pm mailing list for Samsung Exynos ACPM thermal driver thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu" thermal/drivers/samsung: Drop redundant composite object in Makefile thermal/drivers/samsung: acpm-tmu: Disable regmap locking for MMIO INTPEND reads thermal/drivers/samsung: acpm-tmu: Clean up probe error logging thermal/drivers/samsung: acpm-tmu: Simplify pm_runtime_resume_and_get() error checks
MAINTAINERS | 2 +- drivers/thermal/samsung/Kconfig | 2 + drivers/thermal/samsung/Makefile | 3 +- drivers/thermal/samsung/acpm-tmu.c | 232 +++++++++++++++---------------------- 4 files changed, 98 insertions(+), 141 deletions(-)
---
base-commit: 7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614
change-id: 20261014-acpm-tmu-fixes-8788d122bf1e
Best regards,
Signature · 1 line
Tudor Ambarus <[email protected]>
Tudor Ambarus
maintainerPATCH 1/15 thermal/drivers/samsung: Select REGMAP_MMIO for EXYNOS_ACPM_THERMAL
The Exynos ACPM TMU driver calls devm_regmap_init_mmio() in acpm_tmu_probe(), which requires CONFIG_REGMAP_MMIO.
When ARCH_EXYNOS is enabled, REGMAP_MMIO is selected transitively via EXYNOS_PMU. However, both the Samsung thermal menu and EXYNOS_ACPM_PROTOCOL allow COMPILE_TEST builds with ARCH_EXYNOS disabled (COMPILE_TEST && !ARCH_EXYNOS), where nothing in EXYNOS_ACPM_THERMAL's dependency chain selects REGMAP_MMIO, resulting in build failures when REGMAP_MMIO is not enabled by another driver.
Select REGMAP_MMIO under config EXYNOS_ACPM_THERMAL.
--- drivers/thermal/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/thermal/samsung/Kconfig +1 -0
@@ -16,6 +16,7 @@ config EXYNOS_ACPM_THERMAL depends on THERMAL_OF depends on HAS_IOMEM depends on EXYNOS_ACPM_PROTOCOL + select REGMAP_MMIO default ARCH_EXYNOS help Support for the Thermal Management Unit (TMU) on Samsung Exynos SoCs
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: Select REGMAP_MMIO for EXYNOS_ACPM_THERMAL
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: e7c21e12c48e95865c85bdf4431e595359d8abf4 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//e7c21e12c48e95865c85bdf4431e595359d8abf4 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:18 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: Select REGMAP_MMIO for EXYNOS_ACPM_THERMAL
The Exynos ACPM TMU driver calls devm_regmap_init_mmio() in acpm_tmu_probe(), which requires CONFIG_REGMAP_MMIO.
When ARCH_EXYNOS is enabled, REGMAP_MMIO is selected transitively via EXYNOS_PMU. However, both the Samsung thermal menu and EXYNOS_ACPM_PROTOCOL allow COMPILE_TEST builds with ARCH_EXYNOS disabled (COMPILE_TEST && !ARCH_EXYNOS), where nothing in EXYNOS_ACPM_THERMAL's dependency chain selects REGMAP_MMIO, resulting in build failures when REGMAP_MMIO is not enabled by another driver.
Select REGMAP_MMIO under config EXYNOS_ACPM_THERMAL.
--- drivers/thermal/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/thermal/samsung/Kconfig +1 -0
@@ -16,6 +16,7 @@ config EXYNOS_ACPM_THERMAL depends on THERMAL_OF depends on HAS_IOMEM depends on EXYNOS_ACPM_PROTOCOL + select REGMAP_MMIO default ARCH_EXYNOS help Support for the Thermal Management Unit (TMU) on Samsung Exynos SoCs
Tudor Ambarus
maintainerPATCH 2/15 thermal/drivers/samsung: Depend on PM for EXYNOS_ACPM_THERMAL
In reply to Tudor AmbarusThe Exynos ACPM TMU driver only prepares and enables its APB clock (priv->clk) from its runtime PM resume callback (acpm_tmu_runtime_resume()).
Neither ARM64 nor ARCH_EXYNOS selects CONFIG_PM. When CONFIG_PM is disabled, pm_runtime_resume_and_get() is a stub returning 0 without invoking acpm_tmu_runtime_resume(), leaving the APB clock gated when acpm_tmu_thread_fn() reads the memory-mapped INTPEND registers.
Add a PM dependency to EXYNOS_ACPM_THERMAL.
--- drivers/thermal/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/thermal/samsung/Kconfig +1 -0
@@ -15,6 +15,7 @@ config EXYNOS_ACPM_THERMAL tristate "Exynos ACPM thermal management unit driver" depends on THERMAL_OF depends on HAS_IOMEM + depends on PM depends on EXYNOS_ACPM_PROTOCOL select REGMAP_MMIO default ARCH_EXYNOS
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: Depend on PM for EXYNOS_ACPM_THERMAL
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 91bd8661501baae56980c0a3406774eacf4e645a Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//91bd8661501baae56980c0a3406774eacf4e645a Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:19 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: Depend on PM for EXYNOS_ACPM_THERMAL
The Exynos ACPM TMU driver only prepares and enables its APB clock (priv->clk) from its runtime PM resume callback (acpm_tmu_runtime_resume()).
Neither ARM64 nor ARCH_EXYNOS selects CONFIG_PM. When CONFIG_PM is disabled, pm_runtime_resume_and_get() is a stub returning 0 without invoking acpm_tmu_runtime_resume(), leaving the APB clock gated when acpm_tmu_thread_fn() reads the memory-mapped INTPEND registers.
Add a PM dependency to EXYNOS_ACPM_THERMAL.
--- drivers/thermal/samsung/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/thermal/samsung/Kconfig +1 -0
@@ -15,6 +15,7 @@ config EXYNOS_ACPM_THERMAL tristate "Exynos ACPM thermal management unit driver" depends on THERMAL_OF depends on HAS_IOMEM + depends on PM depends on EXYNOS_ACPM_PROTOCOL select REGMAP_MMIO default ARCH_EXYNOS
Tudor Ambarus
maintainerPATCH 3/15 thermal/drivers/samsung: acpm-tmu: Fix acpm_tmu_resume() error handling
In reply to Tudor AmbarusUnlike .suspend(), system resume cannot be aborted: device_resume() clears dev->power.is_suspended before invoking .resume(), and on error merely logs the failure and continues into normal system operation without re-enabling runtime PM on the driver's behalf.
acpm_tmu_resume() treats errors by rolling back into a suspended state, causing three problems:
1. acpm_tmu_suspend() disables runtime PM via pm_runtime_force_suspend(). If ops->resume() fails before pm_runtime_force_resume() runs, or if acpm_tmu_control() fails and the rollback path calls pm_runtime_force_suspend(), dev->power.disable_depth remains at 1 with the device runtime-suspended. Every subsequent pm_runtime_resume_and_get() then fails with -EACCES, breaking thermal zone operations and causing future system suspends to abort in acpm_tmu_suspend().
2. Calling ops->suspend() on error leaves the ACPM TMU firmware in the suspended state while Linux considers the device awake, so subsequent thermal zone operations run against suspended firmware and the next acpm_tmu_suspend() issues an unbalanced ops->suspend() call.
3. Rolling back sensors via acpm_tmu_control_rollback() when a single sensor fails to re-enable disables sensors that already resumed and skips remaining sensors, leaving active CPU clusters without thermal monitoring.
Mirror acpm_tmu_suspend() in reverse order by calling pm_runtime_force_resume() at the start of acpm_tmu_resume(), and drop the pm_runtime_force_suspend() and ops->suspend() error rollback paths. Re-enable sensors on a best-effort basis so any sensor that fails remains marked !sensor->enabled for the thermal core's post-resume update, and drop the now-unused rollback parameter from acpm_tmu_control().
--- drivers/thermal/samsung/acpm-tmu.c | 48 ++++++++++---------------------------- 1 file changed, 12 insertions(+), 36 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +12 -36
@@ -172,7 +172,7 @@ static void acpm_tmu_control_rollback(struct acpm_tmu_priv *priv, int start_idx) } } -static int acpm_tmu_control (struct acpm_tmu_priv *priv,bool on,bool rollback) +static int acpm_tmu_control (struct acpm_tmu_priv *priv,bool on) {struct device *dev = priv->dev;int i, ret, err =0 ;
@@ -191,16 +191,8 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on, bool rollback)mutex_lock (&sensor->lock); ret =acpm_tmu_op_tz_control (sensor, on);mutex_unlock (&sensor->lock); -if (ret) { -if (!err) - err = ret; - -/* On enable, stop on first error if rollback is requested */ -if (on && rollback) { -acpm_tmu_control_rollback (priv, i -1 ); -break ; - } - } +if (ret && !err) + err = ret; }pm_runtime_put_sync (dev);
@@ -539,7 +531,7 @@ static void acpm_tmu_remove(struct platform_device *pdev)* immediately, preventing clock leaks when the driver is removed. */ pm_runtime_dont_use_autosuspend (&pdev->dev); -acpm_tmu_control (priv, false, false); +acpm_tmu_control (priv, false); }static int acpm_tmu_suspend (struct device *dev)
@@ -549,7 +541,7 @@ static int acpm_tmu_suspend(struct device *dev)const struct acpm_tmu_ops *ops = &handle->ops->tmu;int ret, restore_ret; - ret =acpm_tmu_control (priv, false, false); + ret =acpm_tmu_control (priv, false);if (ret) goto err_restore_sensors;
@@ -571,7 +563,7 @@ static int acpm_tmu_suspend(struct device *dev) restore_ret); err_restore_sensors: - restore_ret =acpm_tmu_control (priv, true, false); + restore_ret =acpm_tmu_control (priv, true);if (restore_ret)dev_err (dev,"Failed to re-enable TMU after suspend failure: %d\n" , restore_ret);
@@ -584,34 +576,18 @@ static int acpm_tmu_resume(struct device *dev)struct acpm_tmu_priv *priv =dev_get_drvdata (dev);struct acpm_handle *handle = priv->handle;const struct acpm_tmu_ops *ops = &handle->ops->tmu; -int ret, restore_ret; - -/* APB clock not required for this specific msg */ - ret = ops->resume (handle, priv->mbox_chan_id); -if (ret) -return ret; +int ret; ret =pm_runtime_force_resume (dev);if (ret) - goto err_suspend_acpm; +return ret; - ret =acpm_tmu_control (priv, true, true); +/* APB clock not required for this specific msg */ + ret = ops->resume (handle, priv->mbox_chan_id);if (ret) - goto err_suspend_pm; - -return 0 ; +return ret; -err_suspend_pm: - restore_ret =pm_runtime_force_suspend (dev); -if (restore_ret) -dev_err (dev,"Failed to force suspend during resume rollback: %d\n" , - restore_ret); -err_suspend_acpm: - restore_ret = ops->suspend (handle, priv->mbox_chan_id); -if (restore_ret) -dev_err (dev,"Failed to suspend ACPM during resume rollback: %d\n" , - restore_ret); -return ret; +return acpm_tmu_control (priv, true); }static int acpm_tmu_runtime_suspend (struct device *dev)
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Fix acpm_tmu_resume() error handling
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 2cc5bc4c8be4c83211ddeb0fe38d46d7f239b85f Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//2cc5bc4c8be4c83211ddeb0fe38d46d7f239b85f Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:20 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: acpm-tmu: Fix acpm_tmu_resume() error handling
Unlike .suspend(), system resume cannot be aborted: device_resume() clears dev->power.is_suspended before invoking .resume(), and on error merely logs the failure and continues into normal system operation without re-enabling runtime PM on the driver's behalf.
acpm_tmu_resume() treats errors by rolling back into a suspended state, causing three problems:
1. acpm_tmu_suspend() disables runtime PM via pm_runtime_force_suspend(). If ops->resume() fails before pm_runtime_force_resume() runs, or if acpm_tmu_control() fails and the rollback path calls pm_runtime_force_suspend(), dev->power.disable_depth remains at 1 with the device runtime-suspended. Every subsequent pm_runtime_resume_and_get() then fails with -EACCES, breaking thermal zone operations and causing future system suspends to abort in acpm_tmu_suspend().
2. Calling ops->suspend() on error leaves the ACPM TMU firmware in the suspended state while Linux considers the device awake, so subsequent thermal zone operations run against suspended firmware and the next acpm_tmu_suspend() issues an unbalanced ops->suspend() call.
3. Rolling back sensors via acpm_tmu_control_rollback() when a single sensor fails to re-enable disables sensors that already resumed and skips remaining sensors, leaving active CPU clusters without thermal monitoring.
Mirror acpm_tmu_suspend() in reverse order by calling pm_runtime_force_resume() at the start of acpm_tmu_resume(), and drop the pm_runtime_force_suspend() and ops->suspend() error rollback paths. Re-enable sensors on a best-effort basis so any sensor that fails remains marked !sensor->enabled for the thermal core's post-resume update, and drop the now-unused rollback parameter from acpm_tmu_control().
--- drivers/thermal/samsung/acpm-tmu.c | 48 +++++++---------------------- 1 file changed, 12 insertions(+), 36 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +12 -36
@@ -172,7 +172,7 @@ static void acpm_tmu_control_rollback(struct acpm_tmu_priv *priv, int start_idx) } } -static int acpm_tmu_control (struct acpm_tmu_priv *priv,bool on,bool rollback) +static int acpm_tmu_control (struct acpm_tmu_priv *priv,bool on) {struct device *dev = priv->dev;int i, ret, err =0 ;
@@ -191,16 +191,8 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on, bool rollback)mutex_lock (&sensor->lock); ret =acpm_tmu_op_tz_control (sensor, on);mutex_unlock (&sensor->lock); -if (ret) { -if (!err) - err = ret; - -/* On enable, stop on first error if rollback is requested */ -if (on && rollback) { -acpm_tmu_control_rollback (priv, i -1 ); -break ; - } - } +if (ret && !err) + err = ret; }pm_runtime_put_sync (dev);
@@ -539,7 +531,7 @@ static void acpm_tmu_remove(struct platform_device *pdev)* immediately, preventing clock leaks when the driver is removed. */ pm_runtime_dont_use_autosuspend (&pdev->dev); -acpm_tmu_control (priv, false, false); +acpm_tmu_control (priv, false); }static int acpm_tmu_suspend (struct device *dev)
@@ -549,7 +541,7 @@ static int acpm_tmu_suspend(struct device *dev)const struct acpm_tmu_ops *ops = &handle->ops->tmu;int ret, restore_ret; - ret =acpm_tmu_control (priv, false, false); + ret =acpm_tmu_control (priv, false);if (ret) goto err_restore_sensors;
@@ -571,7 +563,7 @@ err_resume_acpm: restore_ret); err_restore_sensors: - restore_ret =acpm_tmu_control (priv, true, false); + restore_ret =acpm_tmu_control (priv, true);if (restore_ret)dev_err (dev,"Failed to re-enable TMU after suspend failure: %d\n" , restore_ret);
@@ -584,34 +576,18 @@ static int acpm_tmu_resume(struct device *dev)struct acpm_tmu_priv *priv =dev_get_drvdata (dev);struct acpm_handle *handle = priv->handle;const struct acpm_tmu_ops *ops = &handle->ops->tmu; -int ret, restore_ret; - -/* APB clock not required for this specific msg */ - ret = ops->resume (handle, priv->mbox_chan_id); -if (ret) -return ret; +int ret; ret =pm_runtime_force_resume (dev);if (ret) - goto err_suspend_acpm; +return ret; - ret =acpm_tmu_control (priv, true, true); +/* APB clock not required for this specific msg */ + ret = ops->resume (handle, priv->mbox_chan_id);if (ret) - goto err_suspend_pm; - -return 0 ; +return ret; -err_suspend_pm: - restore_ret =pm_runtime_force_suspend (dev); -if (restore_ret) -dev_err (dev,"Failed to force suspend during resume rollback: %d\n" , - restore_ret); -err_suspend_acpm: - restore_ret = ops->suspend (handle, priv->mbox_chan_id); -if (restore_ret) -dev_err (dev,"Failed to suspend ACPM during resume rollback: %d\n" , - restore_ret); -return ret; +return acpm_tmu_control (priv, true); }static int acpm_tmu_runtime_suspend (struct device *dev)
Tudor Ambarus
maintainerPATCH 4/15 thermal/drivers/samsung: acpm-tmu: Disable IRQ across system suspend/resume
In reply to Tudor AmbarusThe PM core masks device IRQs in dpm_suspend_noirq() and unmasks them in dpm_resume_noirq(), leaving the TMU interrupt enabled after acpm_tmu_suspend() and before acpm_tmu_resume() while runtime PM is disabled and PCLK is gated:
1. If acpm_tmu_thread_fn() runs in that window, pm_runtime_resume_and_get() fails with -EACCES and returns IRQ_NONE without clearing the level-high hardware interrupt, triggering an unhandled IRQF_ONESHOT interrupt storm when the line is unmasked.
2. If acpm_tmu_thread_fn() is already running when acpm_tmu_suspend() executes, pm_runtime_force_suspend() ignores usage_count and gates PCLK underneath MMIO INTPEND reads.
Call disable_irq() at the start of acpm_tmu_suspend() to mask and synchronize the interrupt before tearing down sensors and runtime PM, and re-enable it with enable_irq() on acpm_tmu_suspend() rollback and before returning from acpm_tmu_resume().
--- drivers/thermal/samsung/acpm-tmu.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +12 -3
@@ -541,6 +541,8 @@ static int acpm_tmu_suspend(struct device *dev)const struct acpm_tmu_ops *ops = &handle->ops->tmu;int ret, restore_ret; +disable_irq (priv->irq); + ret =acpm_tmu_control (priv, false);if (ret) goto err_restore_sensors;
@@ -568,6 +570,8 @@ static int acpm_tmu_suspend(struct device *dev)dev_err (dev,"Failed to re-enable TMU after suspend failure: %d\n" , restore_ret); +enable_irq (priv->irq); +return ret; }
@@ -580,14 +584,19 @@ static int acpm_tmu_resume(struct device *dev) ret =pm_runtime_force_resume (dev);if (ret) -return ret; + goto out_enable_irq;/* APB clock not required for this specific msg */ ret = ops->resume (handle, priv->mbox_chan_id);if (ret) -return ret; + goto out_enable_irq; + + ret =acpm_tmu_control (priv, true); -return acpm_tmu_control (priv, true); +out_enable_irq: +enable_irq (priv->irq); + +return ret; }static int acpm_tmu_runtime_suspend (struct device *dev)
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Disable IRQ across system suspend/resume
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: e0e2dbdc45f208c1d14cf891175378e93dde5098 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//e0e2dbdc45f208c1d14cf891175378e93dde5098 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:21 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: acpm-tmu: Disable IRQ across system suspend/resume
The PM core masks device IRQs in dpm_suspend_noirq() and unmasks them in dpm_resume_noirq(), leaving the TMU interrupt enabled after acpm_tmu_suspend() and before acpm_tmu_resume() while runtime PM is disabled and PCLK is gated:
1. If acpm_tmu_thread_fn() runs in that window, pm_runtime_resume_and_get() fails with -EACCES and returns IRQ_NONE without clearing the level-high hardware interrupt, triggering an unhandled IRQF_ONESHOT interrupt storm when the line is unmasked.
2. If acpm_tmu_thread_fn() is already running when acpm_tmu_suspend() executes, pm_runtime_force_suspend() ignores usage_count and gates PCLK underneath MMIO INTPEND reads.
Call disable_irq() at the start of acpm_tmu_suspend() to mask and synchronize the interrupt before tearing down sensors and runtime PM, and re-enable it with enable_irq() on acpm_tmu_suspend() rollback and before returning from acpm_tmu_resume().
--- drivers/thermal/samsung/acpm-tmu.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +12 -3
@@ -541,6 +541,8 @@ static int acpm_tmu_suspend(struct device *dev)const struct acpm_tmu_ops *ops = &handle->ops->tmu;int ret, restore_ret; +disable_irq (priv->irq); + ret =acpm_tmu_control (priv, false);if (ret) goto err_restore_sensors;
@@ -568,6 +570,8 @@ err_restore_sensors:dev_err (dev,"Failed to re-enable TMU after suspend failure: %d\n" , restore_ret); +enable_irq (priv->irq); +return ret; }
@@ -580,14 +584,19 @@ static int acpm_tmu_resume(struct device *dev) ret =pm_runtime_force_resume (dev);if (ret) -return ret; + goto out_enable_irq;/* APB clock not required for this specific msg */ ret = ops->resume (handle, priv->mbox_chan_id);if (ret) -return ret; + goto out_enable_irq; + + ret =acpm_tmu_control (priv, true); -return acpm_tmu_control (priv, true); +out_enable_irq: +enable_irq (priv->irq); + +return ret; }static int acpm_tmu_runtime_suspend (struct device *dev)
Tudor Ambarus
maintainerPATCH 5/15 thermal/drivers/samsung: acpm-tmu: Implement .change_mode() callback
In reply to Tudor AmbarusBecause acpm-tmu did not implement the .change_mode() callback and instead enabled the hardware sensor manually after registration, the hardware sensor state was out of sync with the thermal core:
1. Disabling a thermal zone (e.g. via /sys/class/thermal/thermal_zone*/mode or thermal_of_zone_unregister()) only set tz->mode to THERMAL_DEVICE_DISABLED and stopped software polling, while leaving sensor->enabled true and the ACPM TMU sensor active in hardware. Consequently, crossing a trip threshold still fired the hardware IRQ and ran acpm_tmu_thread_fn(), where thermal_zone_device_update() returned early without updating the trip window. Direct sysfs and hwmon temperature reads via thermal_zone_get_temp() also continued to resume the device and query ACPM over IPC on a disabled zone.
2. System suspend/resume paths in acpm_tmu_control() unconditionally toggled all registered sensors without checking the thermal zone mode or current hardware state. As a result, acpm_tmu_suspend() issued redundant disable IPC calls for already-disabled zones, acpm_tmu_resume() unconditionally re-enabled zones that had been disabled via sysfs prior to suspend, and suspend error recovery sent redundant enable IPC calls to sensors that had not yet been disabled.
3. devm_thermal_of_zone_register() enables the zone and triggers an initial thermal_zone_device_update() before returning. Because sensor->enabled was still false during registration, the initial acpm_tmu_get_temp() call failed with -EAGAIN and scheduled a retry, requiring a manual sensor enable and a second thermal_zone_device_update() call in acpm_tmu_probe().
Implement the .change_mode() callback to manage sensor hardware state transitions directly through the thermal core and record the requested zone mode in sensor->mode. Update acpm_tmu_control() to only toggle sensors whose zone mode is THERMAL_DEVICE_ENABLED and whose sensor->enabled state differs from the target state. Drop the redundant manual sensor enablement and thermal_zone_device_update() call from acpm_tmu_probe().
--- drivers/thermal/samsung/acpm-tmu.c | 59 ++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 19 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +40 -19
@@ -68,6 +68,7 @@ struct acpm_tmu_sensor {struct thermal_zone_device *tzd;struct acpm_tmu_priv *priv;struct mutex lock;/* protects sensor state */ +enum thermal_device_mode mode;bool enabled; };
@@ -188,9 +189,12 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on)if (!sensor->tzd)continue ; -mutex_lock (&sensor->lock); - ret =acpm_tmu_op_tz_control (sensor, on); -mutex_unlock (&sensor->lock); + scoped_guard(mutex, &sensor->lock) { + ret =0 ; +if (sensor->mode ==THERMAL_DEVICE_ENABLED && + sensor->enabled != on) + ret =acpm_tmu_op_tz_control (sensor, on); + }if (ret && !err) err = ret; }
@@ -313,7 +317,34 @@ static int acpm_tmu_set_trips(struct thermal_zone_device *tz, int low, int high)return ret; } +static int acpm_tmu_change_mode (struct thermal_zone_device *tz, +enum thermal_device_mode mode) +{ +struct acpm_tmu_sensor *sensor =thermal_zone_device_priv (tz); +struct acpm_tmu_priv *priv = sensor->priv; +struct device *dev = priv->dev; +bool enable = (mode ==THERMAL_DEVICE_ENABLED ); +int ret; + + ret =pm_runtime_resume_and_get (dev); +if (ret) +return ret; + + scoped_guard(mutex, &sensor->lock) { + ret =0 ; +if (sensor->enabled != enable) + ret =acpm_tmu_op_tz_control (sensor, enable); +if (!ret) + sensor->mode = mode; + } + +pm_runtime_put_autosuspend (dev); + +return ret; +} +static const struct thermal_zone_device_ops acpm_tmu_sensor_ops = { + .change_mode = acpm_tmu_change_mode, .get_temp = acpm_tmu_get_temp, .set_trips = acpm_tmu_set_trips, };
@@ -463,17 +494,17 @@ static int acpm_tmu_probe(struct platform_device *pdev)for (i =0 ; i < priv->num_sensors; i++) {struct acpm_tmu_sensor *sensor = &priv->sensors[i]; +struct thermal_zone_device *tzd;mutex_init (&sensor->lock); sensor->group = &data->sensor_groups[i]; sensor->priv = priv; - sensor->tzd =devm_thermal_of_zone_register (dev, i, sensor, - &acpm_tmu_sensor_ops); -if (IS_ERR (sensor->tzd)) { - ret =PTR_ERR (sensor->tzd); + tzd =devm_thermal_of_zone_register (dev, i, sensor, + &acpm_tmu_sensor_ops); +if (IS_ERR (tzd)) { + ret =PTR_ERR (tzd);if (ret == -ENODEV ) { - sensor->tzd =NULL ;dev_dbg (dev,"Sensor %d not used in DT, skipping\n" , i);continue ; }
@@ -481,17 +512,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) ret =dev_err_probe (dev, ret,"Failed to register sensor %d\n" , i); goto err_rollback; } - -mutex_lock (&sensor->lock); - ret =acpm_tmu_op_tz_control (sensor, true); -mutex_unlock (&sensor->lock); -if (ret) { - ret =dev_err_probe (dev, ret,"Failed to enable sensor %d\n" , i); - goto err_rollback; - } - -thermal_zone_device_update (sensor->tzd, -THERMAL_EVENT_UNSPECIFIED ); + sensor->tzd = tzd; ret =devm_thermal_add_hwmon_sysfs (dev, sensor->tzd);if (ret)
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Implement .change_mode() callback
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 09e928b13aaddbefc08aeca13b1a78bd8b0feb14 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//09e928b13aaddbefc08aeca13b1a78bd8b0feb14 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:22 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: acpm-tmu: Implement .change_mode() callback
Because acpm-tmu did not implement the .change_mode() callback and instead enabled the hardware sensor manually after registration, the hardware sensor state was out of sync with the thermal core:
1. Disabling a thermal zone (e.g. via /sys/class/thermal/thermal_zone*/mode or thermal_of_zone_unregister()) only set tz->mode to THERMAL_DEVICE_DISABLED and stopped software polling, while leaving sensor->enabled true and the ACPM TMU sensor active in hardware. Consequently, crossing a trip threshold still fired the hardware IRQ and ran acpm_tmu_thread_fn(), where thermal_zone_device_update() returned early without updating the trip window. Direct sysfs and hwmon temperature reads via thermal_zone_get_temp() also continued to resume the device and query ACPM over IPC on a disabled zone.
2. System suspend/resume paths in acpm_tmu_control() unconditionally toggled all registered sensors without checking the thermal zone mode or current hardware state. As a result, acpm_tmu_suspend() issued redundant disable IPC calls for already-disabled zones, acpm_tmu_resume() unconditionally re-enabled zones that had been disabled via sysfs prior to suspend, and suspend error recovery sent redundant enable IPC calls to sensors that had not yet been disabled.
3. devm_thermal_of_zone_register() enables the zone and triggers an initial thermal_zone_device_update() before returning. Because sensor->enabled was still false during registration, the initial acpm_tmu_get_temp() call failed with -EAGAIN and scheduled a retry, requiring a manual sensor enable and a second thermal_zone_device_update() call in acpm_tmu_probe().
Implement the .change_mode() callback to manage sensor hardware state transitions directly through the thermal core and record the requested zone mode in sensor->mode. Update acpm_tmu_control() to only toggle sensors whose zone mode is THERMAL_DEVICE_ENABLED and whose sensor->enabled state differs from the target state. Drop the redundant manual sensor enablement and thermal_zone_device_update() call from acpm_tmu_probe().
--- drivers/thermal/samsung/acpm-tmu.c | 59 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +40 -19
@@ -68,6 +68,7 @@ struct acpm_tmu_sensor {struct thermal_zone_device *tzd;struct acpm_tmu_priv *priv;struct mutex lock;/* protects sensor state */ +enum thermal_device_mode mode;bool enabled; };
@@ -188,9 +189,12 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on)if (!sensor->tzd)continue ; -mutex_lock (&sensor->lock); - ret =acpm_tmu_op_tz_control (sensor, on); -mutex_unlock (&sensor->lock); + scoped_guard(mutex, &sensor->lock) { + ret =0 ; +if (sensor->mode ==THERMAL_DEVICE_ENABLED && + sensor->enabled != on) + ret =acpm_tmu_op_tz_control (sensor, on); + }if (ret && !err) err = ret; }
@@ -313,7 +317,34 @@ static int acpm_tmu_set_trips(struct thermal_zone_device *tz, int low, int high)return ret; } +static int acpm_tmu_change_mode (struct thermal_zone_device *tz, +enum thermal_device_mode mode) +{ +struct acpm_tmu_sensor *sensor =thermal_zone_device_priv (tz); +struct acpm_tmu_priv *priv = sensor->priv; +struct device *dev = priv->dev; +bool enable = (mode ==THERMAL_DEVICE_ENABLED ); +int ret; + + ret =pm_runtime_resume_and_get (dev); +if (ret) +return ret; + + scoped_guard(mutex, &sensor->lock) { + ret =0 ; +if (sensor->enabled != enable) + ret =acpm_tmu_op_tz_control (sensor, enable); +if (!ret) + sensor->mode = mode; + } + +pm_runtime_put_autosuspend (dev); + +return ret; +} +static const struct thermal_zone_device_ops acpm_tmu_sensor_ops = { + .change_mode = acpm_tmu_change_mode, .get_temp = acpm_tmu_get_temp, .set_trips = acpm_tmu_set_trips, };
@@ -463,17 +494,17 @@ static int acpm_tmu_probe(struct platform_device *pdev)for (i =0 ; i < priv->num_sensors; i++) {struct acpm_tmu_sensor *sensor = &priv->sensors[i]; +struct thermal_zone_device *tzd;mutex_init (&sensor->lock); sensor->group = &data->sensor_groups[i]; sensor->priv = priv; - sensor->tzd =devm_thermal_of_zone_register (dev, i, sensor, - &acpm_tmu_sensor_ops); -if (IS_ERR (sensor->tzd)) { - ret =PTR_ERR (sensor->tzd); + tzd =devm_thermal_of_zone_register (dev, i, sensor, + &acpm_tmu_sensor_ops); +if (IS_ERR (tzd)) { + ret =PTR_ERR (tzd);if (ret == -ENODEV ) { - sensor->tzd =NULL ;dev_dbg (dev,"Sensor %d not used in DT, skipping\n" , i);continue ; }
@@ -481,17 +512,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) ret =dev_err_probe (dev, ret,"Failed to register sensor %d\n" , i); goto err_rollback; } - -mutex_lock (&sensor->lock); - ret =acpm_tmu_op_tz_control (sensor, true); -mutex_unlock (&sensor->lock); -if (ret) { - ret =dev_err_probe (dev, ret,"Failed to enable sensor %d\n" , i); - goto err_rollback; - } - -thermal_zone_device_update (sensor->tzd, -THERMAL_EVENT_UNSPECIFIED ); + sensor->tzd = tzd; ret =devm_thermal_add_hwmon_sysfs (dev, sensor->tzd);if (ret)
Tudor Ambarus
maintainerPATCH 6/15 thermal/drivers/samsung: acpm-tmu: Rely on devres for probe error and remove teardown
In reply to Tudor AmbarusDisabling sensors manually on acpm_tmu_probe() failure or in acpm_tmu_remove() happens before devres unregisters the thermal zones, leaving live zones backed by disabled hardware.
With .change_mode() implemented, devres tears down the IRQ, thermal zones, and runtime PM in reverse registration order:devm_thermal_of_zone_release() disables each sensor via thermal_zone_device_disable(), and devm_pm_runtime_enable() disables autosuspend and runtime PM.
Drop acpm_tmu_remove(), acpm_tmu_control_rollback(), and the manual teardown in acpm_tmu_probe(), and switch acpm_tmu_control() to pm_runtime_put_autosuspend() since pm_runtime_put_sync() was only needed by acpm_tmu_remove().
--- drivers/thermal/samsung/acpm-tmu.c | 56 ++++---------------------------------- 1 file changed, 5 insertions(+), 51 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +5 -51
@@ -153,26 +153,6 @@ static int acpm_tmu_op_tz_control(struct acpm_tmu_sensor *sensor, bool on)return 0 ; } -static void acpm_tmu_control_rollback (struct acpm_tmu_priv *priv,int start_idx) -{ -int i; - -for (i = start_idx; i >=0 ; i--) { -struct acpm_tmu_sensor *sensor = &priv->sensors[i]; -int ret; - -if (!sensor->tzd) -continue ; - -mutex_lock (&sensor->lock); - ret =acpm_tmu_op_tz_control (sensor, false); -mutex_unlock (&sensor->lock); -if (ret) -dev_err (priv->dev,"Rollback: Failed to disable sensor %d: %d\n" , - i, ret); - } -} -static int acpm_tmu_control (struct acpm_tmu_priv *priv,bool on) {struct device *dev = priv->dev;
@@ -199,7 +179,7 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on) err = ret; } -pm_runtime_put_sync (dev); +pm_runtime_put_autosuspend (dev);return err; }
@@ -489,7 +469,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) ret = acpm_handle->ops->tmu.init (acpm_handle, priv->mbox_chan_id);if (ret) { ret =dev_err_probe (dev, ret,"Failed to init TMU\n" ); - goto err_pm_put; + goto out_pm_put; }for (i =0 ; i < priv->num_sensors; i++) {
@@ -510,7 +490,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) } ret =dev_err_probe (dev, ret,"Failed to register sensor %d\n" , i); - goto err_rollback; + goto out_pm_put; } sensor->tzd = tzd;
@@ -522,39 +502,14 @@ static int acpm_tmu_probe(struct platform_device *pdev) ret =devm_request_threaded_irq (dev, priv->irq,NULL , acpm_tmu_thread_fn,IRQF_ONESHOT ,dev_name (dev), priv); -if (ret) { +if (ret) ret =dev_err_probe (dev, ret,"Failed to request irq\n" ); - goto err_rollback; - } +out_pm_put:pm_runtime_put_autosuspend (dev); - -return 0 ; - -err_rollback: -acpm_tmu_control_rollback (priv, i -1 ); -err_pm_put: -pm_runtime_dont_use_autosuspend (dev); -pm_runtime_put_sync (dev);return ret; } -static void acpm_tmu_remove (struct platform_device *pdev) -{ -struct acpm_tmu_priv *priv =platform_get_drvdata (pdev); - -/* Stop IRQ first to prevent race with thread_fn */ -disable_irq (priv->irq); - -/* -* Disable autosuspend to force the subsequent pm_runtime_put_sync() -* inside acpm_tmu_control() to synchronously suspend the device -* immediately, preventing clock leaks when the driver is removed. -*/ -pm_runtime_dont_use_autosuspend (&pdev->dev); -acpm_tmu_control (priv, false); -} -static int acpm_tmu_suspend (struct device *dev) {struct acpm_tmu_priv *priv =dev_get_drvdata (dev);
@@ -648,7 +603,6 @@ static struct platform_driver acpm_tmu_driver = { .of_match_table = acpm_tmu_match, }, .probe = acpm_tmu_probe, - .remove = acpm_tmu_remove, };module_platform_driver (acpm_tmu_driver);
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Rely on devres for probe error and remove teardown
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 3980362b31bf935b778dea1a8d90590ecef82e8d Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//3980362b31bf935b778dea1a8d90590ecef82e8d Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:23 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: acpm-tmu: Rely on devres for probe error and remove teardown
Disabling sensors manually on acpm_tmu_probe() failure or in acpm_tmu_remove() happens before devres unregisters the thermal zones, leaving live zones backed by disabled hardware.
With .change_mode() implemented, devres tears down the IRQ, thermal zones, and runtime PM in reverse registration order:devm_thermal_of_zone_release() disables each sensor via thermal_zone_device_disable(), and devm_pm_runtime_enable() disables autosuspend and runtime PM.
Drop acpm_tmu_remove(), acpm_tmu_control_rollback(), and the manual teardown in acpm_tmu_probe(), and switch acpm_tmu_control() to pm_runtime_put_autosuspend() since pm_runtime_put_sync() was only needed by acpm_tmu_remove().
--- drivers/thermal/samsung/acpm-tmu.c | 56 ++--------------------------- 1 file changed, 5 insertions(+), 51 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +5 -51
@@ -153,26 +153,6 @@ static int acpm_tmu_op_tz_control(struct acpm_tmu_sensor *sensor, bool on)return 0 ; } -static void acpm_tmu_control_rollback (struct acpm_tmu_priv *priv,int start_idx) -{ -int i; - -for (i = start_idx; i >=0 ; i--) { -struct acpm_tmu_sensor *sensor = &priv->sensors[i]; -int ret; - -if (!sensor->tzd) -continue ; - -mutex_lock (&sensor->lock); - ret =acpm_tmu_op_tz_control (sensor, false); -mutex_unlock (&sensor->lock); -if (ret) -dev_err (priv->dev,"Rollback: Failed to disable sensor %d: %d\n" , - i, ret); - } -} -static int acpm_tmu_control (struct acpm_tmu_priv *priv,bool on) {struct device *dev = priv->dev;
@@ -199,7 +179,7 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on) err = ret; } -pm_runtime_put_sync (dev); +pm_runtime_put_autosuspend (dev);return err; }
@@ -489,7 +469,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) ret = acpm_handle->ops->tmu.init (acpm_handle, priv->mbox_chan_id);if (ret) { ret =dev_err_probe (dev, ret,"Failed to init TMU\n" ); - goto err_pm_put; + goto out_pm_put; }for (i =0 ; i < priv->num_sensors; i++) {
@@ -510,7 +490,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) } ret =dev_err_probe (dev, ret,"Failed to register sensor %d\n" , i); - goto err_rollback; + goto out_pm_put; } sensor->tzd = tzd;
@@ -522,39 +502,14 @@ static int acpm_tmu_probe(struct platform_device *pdev) ret =devm_request_threaded_irq (dev, priv->irq,NULL , acpm_tmu_thread_fn,IRQF_ONESHOT ,dev_name (dev), priv); -if (ret) { +if (ret) ret =dev_err_probe (dev, ret,"Failed to request irq\n" ); - goto err_rollback; - } +out_pm_put:pm_runtime_put_autosuspend (dev); - -return 0 ; - -err_rollback: -acpm_tmu_control_rollback (priv, i -1 ); -err_pm_put: -pm_runtime_dont_use_autosuspend (dev); -pm_runtime_put_sync (dev);return ret; } -static void acpm_tmu_remove (struct platform_device *pdev) -{ -struct acpm_tmu_priv *priv =platform_get_drvdata (pdev); - -/* Stop IRQ first to prevent race with thread_fn */ -disable_irq (priv->irq); - -/* -* Disable autosuspend to force the subsequent pm_runtime_put_sync() -* inside acpm_tmu_control() to synchronously suspend the device -* immediately, preventing clock leaks when the driver is removed. -*/ -pm_runtime_dont_use_autosuspend (&pdev->dev); -acpm_tmu_control (priv, false); -} -static int acpm_tmu_suspend (struct device *dev) {struct acpm_tmu_priv *priv =dev_get_drvdata (dev);
@@ -648,7 +603,6 @@ static struct platform_driver acpm_tmu_driver = { .of_match_table = acpm_tmu_match, }, .probe = acpm_tmu_probe, - .remove = acpm_tmu_remove, };module_platform_driver (acpm_tmu_driver);
Tudor Ambarus
maintainerPATCH 7/15 thermal/drivers/samsung: acpm-tmu: Return -ENODATA when sensor is disabled
In reply to Tudor AmbarusIn the thermal core, returning -EAGAIN from .get_temp() instructs __thermal_zone_device_update() -> thermal_zone_recheck() to schedule a 250 ms (4 Hz) retry loop with no backoff. If re-enabling a sensor fails (for example on resume, or after an acpm_tmu_update_thresholds() failure when polling is active), sensor->enabled remains false while tz->mode is still THERMAL_DEVICE_ENABLED, causing an infinite 4 Hz retry loop instead of backing off and disabling the broken zone via thermal_zone_broken_disable(). In addition, hwmon's temp_input_show() forwards -EAGAIN directly to userspace rather than -ENODATA.
Return -ENODATA instead of -EAGAIN when !sensor->enabled in acpm_tmu_get_temp().
--- drivers/thermal/samsung/acpm-tmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +2 -2
@@ -200,7 +200,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp)* after PM resume. */ if (!sensor->enabled) -return -EAGAIN ; +return -ENODATA ; ret =pm_runtime_resume_and_get (dev);if (ret <0 )
@@ -208,7 +208,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp) scoped_guard(mutex, &sensor->lock) {if (!sensor->enabled) { - ret = -EAGAIN ; + ret = -ENODATA ; }else { ret = ops->read_temp (handle, priv->mbox_chan_id, sensor->group->id, &acpm_temp);
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Return -ENODATA when sensor is disabled
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: f04aff1cbba0080cd4af80134bbf4ac7452b2b8d Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//f04aff1cbba0080cd4af80134bbf4ac7452b2b8d Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:24 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: acpm-tmu: Return -ENODATA when sensor is disabled
In the thermal core, returning -EAGAIN from .get_temp() instructs __thermal_zone_device_update() -> thermal_zone_recheck() to schedule a 250 ms (4 Hz) retry loop with no backoff. If re-enabling a sensor fails (for example on resume, or after an acpm_tmu_update_thresholds() failure when polling is active), sensor->enabled remains false while tz->mode is still THERMAL_DEVICE_ENABLED, causing an infinite 4 Hz retry loop instead of backing off and disabling the broken zone via thermal_zone_broken_disable(). In addition, hwmon's temp_input_show() forwards -EAGAIN directly to userspace rather than -ENODATA.
Return -ENODATA instead of -EAGAIN when !sensor->enabled in acpm_tmu_get_temp().
--- drivers/thermal/samsung/acpm-tmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +2 -2
@@ -200,7 +200,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp)* after PM resume. */ if (!sensor->enabled) -return -EAGAIN ; +return -ENODATA ; ret =pm_runtime_resume_and_get (dev);if (ret <0 )
@@ -208,7 +208,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp) scoped_guard(mutex, &sensor->lock) {if (!sensor->enabled) { - ret = -EAGAIN ; + ret = -ENODATA ; }else { ret = ops->read_temp (handle, priv->mbox_chan_id, sensor->group->id, &acpm_temp);
Tudor Ambarus
maintainerPATCH 8/15 thermal/drivers/samsung: acpm-tmu: Annotate lockless sensor->enabled access
In reply to Tudor Ambarusacpm_tmu_get_temp() reads sensor->enabled outside sensor->lock as a fast path before resuming the device via runtime PM, while acpm_tmu_op_tz_control() updates sensor->enabled under sensor->lock. Because both accesses are plain C accesses, concurrent execution is a data race.
Pair READ_ONCE() on the lockless fast-path read with WRITE_ONCE() in acpm_tmu_op_tz_control() to prevent compiler misoptimizations and KCSAN data-race warnings.
--- drivers/thermal/samsung/acpm-tmu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +3 -2
@@ -7,6 +7,7 @@#include <linux/cleanup.h> #include <linux/clk.h> +#include <linux/compiler.h> #include <linux/device/devres.h> #include <linux/err.h> #include <linux/firmware/samsung/exynos-acpm-protocol.h>
@@ -148,7 +149,7 @@ static int acpm_tmu_op_tz_control(struct acpm_tmu_sensor *sensor, bool on)if (ret)return ret; - sensor->enabled = on; +WRITE_ONCE (sensor->enabled, on);return 0 ; }
@@ -199,7 +200,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp)* concurrent disabling is caught by the second check under the lock * after PM resume. */ -if (!sensor->enabled) +if (!READ_ONCE (sensor->enabled))return -ENODATA ; ret =pm_runtime_resume_and_get (dev);
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Annotate lockless sensor->enabled access
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 95580915961eca39d4f3159cb4a235f25ea301b5 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//95580915961eca39d4f3159cb4a235f25ea301b5 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:25 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:50 +01:00
thermal/drivers/samsung: acpm-tmu: Annotate lockless sensor->enabled access
acpm_tmu_get_temp() reads sensor->enabled outside sensor->lock as a fast path before resuming the device via runtime PM, while acpm_tmu_op_tz_control() updates sensor->enabled under sensor->lock. Because both accesses are plain C accesses, concurrent execution is a data race.
Pair READ_ONCE() on the lockless fast-path read with WRITE_ONCE() in acpm_tmu_op_tz_control() to prevent compiler misoptimizations and KCSAN data-race warnings.
--- drivers/thermal/samsung/acpm-tmu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +3 -2
@@ -7,6 +7,7 @@#include <linux/cleanup.h> #include <linux/clk.h> +#include <linux/compiler.h> #include <linux/device/devres.h> #include <linux/err.h> #include <linux/firmware/samsung/exynos-acpm-protocol.h>
@@ -148,7 +149,7 @@ static int acpm_tmu_op_tz_control(struct acpm_tmu_sensor *sensor, bool on)if (ret)return ret; - sensor->enabled = on; +WRITE_ONCE (sensor->enabled, on);return 0 ; }
@@ -199,7 +200,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp)* concurrent disabling is caught by the second check under the lock * after PM resume. */ -if (!sensor->enabled) +if (!READ_ONCE (sensor->enabled))return -ENODATA ; ret =pm_runtime_resume_and_get (dev);
Tudor Ambarus
maintainerPATCH 9/15 thermal/drivers/samsung: acpm-tmu: Fix IRQ locking and error handling
In reply to Tudor Ambarusacpm_tmu_has_pending_irq() acquires and releases sensor->lock around the INTPEND read, and acpm_tmu_thread_fn() re-acquires it to call ops->clear_tz_irq(), leaving a window where concurrent .set_trips() or .change_mode() calls can modify sensor state in between. Moreover, if ops->clear_tz_irq() fails, acpm_tmu_thread_fn() still sets handled = true and updates the thermal zone while INTPEND remains asserted; conversely, returning IRQ_NONE on a level-high IRQF_ONESHOT line re-triggers the interrupt up to 100,000 times before the spurious IRQ detector disables it, so unthrottled dev_err() calls flood the kernel log.
Replace acpm_tmu_has_pending_irq() with acpm_tmu_clear_pending_irq() so both the INTPEND check and ops->clear_tz_irq() run under a single guard(mutex)(&sensor->lock), only mark the IRQ handled and update the thermal zone when an interrupt was pending and cleared, and rate-limit the error messages on both IRQ_NONE failure paths in the threaded IRQ handler.
--- drivers/thermal/samsung/acpm-tmu.c | 42 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +20 -22
@@ -330,11 +330,12 @@ static const struct thermal_zone_device_ops acpm_tmu_sensor_ops = { .set_trips = acpm_tmu_set_trips, }; -static int acpm_tmu_has_pending_irq (struct acpm_tmu_sensor *sensor, -bool *pending_irq) +static bool acpm_tmu_clear_pending_irq (struct acpm_tmu_sensor *sensor) {struct acpm_tmu_priv *priv = sensor->priv; +const struct acpm_tmu_ops *ops = &priv->handle->ops->tmu;unsigned long mask = sensor->group->mask; +bool pending_irq = false;int i, ret;u32 val;
@@ -343,53 +344,50 @@ static int acpm_tmu_has_pending_irq(struct acpm_tmu_sensor *sensor,for_each_set_bit (i, &mask,EXYNOS_TMU_SENSORS_MAX_COUNT ) { ret =regmap_field_read (priv->regmap_fields[i], &val);if (ret) -return ret; +return false;if (val) { - *pending_irq = true; + pending_irq = true;break ; } } -return 0 ; +if (!pending_irq) +return false; + + ret = ops->clear_tz_irq (priv->handle, priv->mbox_chan_id, + sensor->group->id); +if (ret) { +dev_err_ratelimited (priv->dev, +"Sensor %u: failed to clear IRQ (%d)\n" , + sensor->group->id, ret); +return false; + } + +return true; }static irqreturn_t acpm_tmu_thread_fn (int irq,void *id) {struct acpm_tmu_priv *priv = id; -struct acpm_handle *handle = priv->handle; -const struct acpm_tmu_ops *ops = &handle->ops->tmu;struct device *dev = priv->dev;bool handled = false;int i, ret; ret =pm_runtime_resume_and_get (dev);if (ret) { -dev_err (dev,"Failed to resume: %d\n" , ret); +dev_err_ratelimited (dev,"Failed to resume: %d\n" , ret);return IRQ_NONE ; }for (i =0 ; i < priv->num_sensors; i++) {struct acpm_tmu_sensor *sensor = &priv->sensors[i]; -bool pending_irq = false; - -if (!sensor->tzd) -continue ; - ret =acpm_tmu_has_pending_irq (sensor, &pending_irq); -if (ret || !pending_irq) +if (!sensor->tzd || !acpm_tmu_clear_pending_irq (sensor))continue ; handled = true; - scoped_guard(mutex, &sensor->lock) { - ret = ops->clear_tz_irq (handle, priv->mbox_chan_id, - sensor->group->id); -if (ret) -dev_err (priv->dev,"Sensor %d: failed to clear IRQ (%d)\n" , - i, ret); - } -thermal_zone_device_update (sensor->tzd,THERMAL_EVENT_UNSPECIFIED ); }
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Fix IRQ locking and error handling
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 2237a6871722f9cafedf6820527a88430df26be2 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//2237a6871722f9cafedf6820527a88430df26be2 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:26 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
thermal/drivers/samsung: acpm-tmu: Fix IRQ locking and error handling
acpm_tmu_has_pending_irq() acquires and releases sensor->lock around the INTPEND read, and acpm_tmu_thread_fn() re-acquires it to call ops->clear_tz_irq(), leaving a window where concurrent .set_trips() or .change_mode() calls can modify sensor state in between. Moreover, if ops->clear_tz_irq() fails, acpm_tmu_thread_fn() still sets handled = true and updates the thermal zone while INTPEND remains asserted; conversely, returning IRQ_NONE on a level-high IRQF_ONESHOT line re-triggers the interrupt up to 100,000 times before the spurious IRQ detector disables it, so unthrottled dev_err() calls flood the kernel log.
Replace acpm_tmu_has_pending_irq() with acpm_tmu_clear_pending_irq() so both the INTPEND check and ops->clear_tz_irq() run under a single guard(mutex)(&sensor->lock), only mark the IRQ handled and update the thermal zone when an interrupt was pending and cleared, and rate-limit the error messages on both IRQ_NONE failure paths in the threaded IRQ handler.
--- drivers/thermal/samsung/acpm-tmu.c | 42 +++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +20 -22
@@ -330,11 +330,12 @@ static const struct thermal_zone_device_ops acpm_tmu_sensor_ops = { .set_trips = acpm_tmu_set_trips, }; -static int acpm_tmu_has_pending_irq (struct acpm_tmu_sensor *sensor, -bool *pending_irq) +static bool acpm_tmu_clear_pending_irq (struct acpm_tmu_sensor *sensor) {struct acpm_tmu_priv *priv = sensor->priv; +const struct acpm_tmu_ops *ops = &priv->handle->ops->tmu;unsigned long mask = sensor->group->mask; +bool pending_irq = false;int i, ret;u32 val;
@@ -343,53 +344,50 @@ static int acpm_tmu_has_pending_irq(struct acpm_tmu_sensor *sensor,for_each_set_bit (i, &mask,EXYNOS_TMU_SENSORS_MAX_COUNT ) { ret =regmap_field_read (priv->regmap_fields[i], &val);if (ret) -return ret; +return false;if (val) { - *pending_irq = true; + pending_irq = true;break ; } } -return 0 ; +if (!pending_irq) +return false; + + ret = ops->clear_tz_irq (priv->handle, priv->mbox_chan_id, + sensor->group->id); +if (ret) { +dev_err_ratelimited (priv->dev, +"Sensor %u: failed to clear IRQ (%d)\n" , + sensor->group->id, ret); +return false; + } + +return true; }static irqreturn_t acpm_tmu_thread_fn (int irq,void *id) {struct acpm_tmu_priv *priv = id; -struct acpm_handle *handle = priv->handle; -const struct acpm_tmu_ops *ops = &handle->ops->tmu;struct device *dev = priv->dev;bool handled = false;int i, ret; ret =pm_runtime_resume_and_get (dev);if (ret) { -dev_err (dev,"Failed to resume: %d\n" , ret); +dev_err_ratelimited (dev,"Failed to resume: %d\n" , ret);return IRQ_NONE ; }for (i =0 ; i < priv->num_sensors; i++) {struct acpm_tmu_sensor *sensor = &priv->sensors[i]; -bool pending_irq = false; - -if (!sensor->tzd) -continue ; - ret =acpm_tmu_has_pending_irq (sensor, &pending_irq); -if (ret || !pending_irq) +if (!sensor->tzd || !acpm_tmu_clear_pending_irq (sensor))continue ; handled = true; - scoped_guard(mutex, &sensor->lock) { - ret = ops->clear_tz_irq (handle, priv->mbox_chan_id, - sensor->group->id); -if (ret) -dev_err (priv->dev,"Sensor %d: failed to clear IRQ (%d)\n" , - i, ret); - } -thermal_zone_device_update (sensor->tzd,THERMAL_EVENT_UNSPECIFIED ); }
Tudor Ambarus
maintainerPATCH 10/15 MAINTAINERS: Use linux-pm mailing list for Samsung Exynos ACPM thermal driver
In reply to Tudor AmbarusList the power management and thermal subsystem mailing list ([email protected]) instead of the general [email protected] list under SAMSUNG EXYNOS ACPM THERMAL DRIVER.
--- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
MAINTAINERS +1 -1
@@ -24382,7 +24382,7 @@ F: include/linux/firmware/samsung/exynos-acpm-protocol.h SAMSUNG EXYNOS ACPM THERMAL DRIVER M: Tudor Ambarus <[email protected]> -L: [email protected] +L: [email protected] L: [email protected] S: Supported F: Documentation/devicetree/bindings/thermal/google,gs101-tmu-top.yaml
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] MAINTAINERS: Use linux-pm mailing list for Samsung Exynos ACPM thermal driver
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 9745df063ef8190d713f90ffd215f39838ad6e83 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//9745df063ef8190d713f90ffd215f39838ad6e83 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:27 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
MAINTAINERS: Use linux-pm mailing list for Samsung Exynos ACPM thermal driver
List the power management and thermal subsystem mailing list ([email protected]) instead of the general [email protected] list under SAMSUNG EXYNOS ACPM THERMAL DRIVER.
--- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
MAINTAINERS +1 -1
@@ -24899,7 +24899,7 @@ F: include/linux/firmware/samsung/exynos-acpm-protocol.h SAMSUNG EXYNOS ACPM THERMAL DRIVER M: Tudor Ambarus <[email protected]> -L: [email protected] +L: [email protected] L: [email protected] S: Supported F: Documentation/devicetree/bindings/thermal/google,gs101-tmu-top.yaml
Tudor Ambarus
maintainerPATCH 11/15 thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
In reply to Tudor AmbarusRename the platform driver from "gs-tmu" to "exynos-acpm-tmu" to reflect that the ACPM TMU architecture is shared across Samsung Exynos SoCs (such as GS101, AutoV920, and Exynos850) rather than being specific to GS101, matching "exynos-acpm-protocol" in drivers/firmware/samsung/.
--- drivers/thermal/samsung/acpm-tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/thermal/samsung/acpm-tmu.c +1 -1
@@ -597,7 +597,7 @@ static const struct dev_pm_ops acpm_tmu_pm_ops = {static struct platform_driver acpm_tmu_driver = { .driver = { - .name ="gs-tmu" , + .name ="exynos-acpm-tmu" , .pm =pm_ptr (&acpm_tmu_pm_ops), .of_match_table = acpm_tmu_match, },
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: ba446bdd27d4a2a6c0cb267f51a6ecc47cf19cf9 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//ba446bdd27d4a2a6c0cb267f51a6ecc47cf19cf9 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:28 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
Rename the platform driver from "gs-tmu" to "exynos-acpm-tmu" to reflect that the ACPM TMU architecture is shared across Samsung Exynos SoCs (such as GS101, AutoV920, and Exynos850) rather than being specific to GS101, matching "exynos-acpm-protocol" in drivers/firmware/samsung/.
--- drivers/thermal/samsung/acpm-tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/thermal/samsung/acpm-tmu.c +1 -1
@@ -597,7 +597,7 @@ static const struct dev_pm_ops acpm_tmu_pm_ops = {static struct platform_driver acpm_tmu_driver = { .driver = { - .name ="gs-tmu" , + .name ="exynos-acpm-tmu" , .pm =pm_ptr (&acpm_tmu_pm_ops), .of_match_table = acpm_tmu_match, },
Re: [thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
Quoted 10 lines · thermal-bot for Tudor Ambarus
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: ba446bdd27d4a2a6c0cb267f51a6ecc47cf19cf9 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//ba446bdd27d4a2a6c0cb267f51a6ecc47cf19cf9 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:28 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
Also, the fix for this problem was sent here earlier:
https://lore.kernel.org/linux-samsung-soc/[email protected]/
Why taking this one and ignoring the fix that was sent earlier -- this should be at least explained.
Quoted 6 lines
Rename the platform driver from "gs-tmu" to "exynos-acpm-tmu" to reflect that the ACPM TMU architecture is shared across Samsung Exynos SoCs (such as GS101, AutoV920, and Exynos850) rather than being specific to GS101, matching "exynos-acpm-protocol" in
drivers/firmware/samsung/.Suggested-by Alexey Klimov <[email protected]>
I don't recall suggesting this. Reporting -- yes, but not renaming to "exynos-acpm-tmu".
This was reported months ago and was never fixed in the updated series for acpm-tmu.c.
Quoted 12 lines
Signed-off-by Tudor Ambarus <[email protected]>Signed-off-by Daniel Lezcano <[email protected]>--- drivers/thermal/samsung/acpm-tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/thermal/samsung/acpm-tmu.c +0
-0
drivers/thermal/samsung/acpm-tmu.c static const struct dev_pm_ops acpm_tmu_pm_ops = { · line 600
Quoted 5 lines
drivers/thermal/samsung/acpm-tmu.c +1
-1@@ -597,7 +597,7 @@ static const struct dev_pm_ops acpm_tmu_pm_ops = {static struct platform_driver acpm_tmu_driver = { .driver = { - .name ="gs-tmu" , + .name ="exynos-acpm-tmu" ,
It is minor but it potentially clashes with exynos-acpm-tmu firmware file name. All other names in file acpm-tmu.c are "acpm-tmu".
Tudor Ambarus
maintainerRe: [thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
Quoted 10 lines · Alexey Klimov
Quoted 9 lines · thermal-bot for Tudor Ambarus
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: ba446bdd27d4a2a6c0cb267f51a6ecc47cf19cf9 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//ba446bdd27d4a2a6c0cb267f51a6ecc47cf19cf9 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:28 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
Quoted 7 lines
Quoted 1 line
thermal/drivers/samsung: acpm-tmu: Rename platform driver to "exynos-acpm-tmu"
Also, the fix for this problem was sent here earlier:
https://lore.kernel.org/linux-samsung-soc/[email protected]/Why taking this one and ignoring the fix that was sent earlier -- this should be at least explained.
I guess it slipped through the cracks, as it did for me.
Quoted 10 lines
Quoted 7 lines
Rename the platform driver from "gs-tmu" to "exynos-acpm-tmu" to reflect that the ACPM TMU architecture is shared across Samsung Exynos SoCs (such as GS101, AutoV920, and Exynos850) rather than being specific to GS101, matching "exynos-acpm-protocol" in
drivers/firmware/samsung/.Suggested-by Alexey Klimov <[email protected]>I don't recall suggesting this. Reporting -- yes, but not renaming to "exynos-acpm-tmu".
my apologies, it wasn't intended. If you have a strong opinion on the tag type, I guess Daniel can drop it.
Quoted 17 lines
This was reported months ago and was never fixed in the updated series for
acpm-tmu.c.Quoted 13 lines
Signed-off-by Tudor Ambarus <[email protected]>Signed-off-by Daniel Lezcano <[email protected]>--- drivers/thermal/samsung/acpm-tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/thermal/samsung/acpm-tmu.c +0
-0@@ -597,7 +597,7 @@ static const struct dev_pm_ops acpm_tmu_pm_ops = {
Quoted 6 lines
drivers/thermal/samsung/acpm-tmu.c static const struct dev_pm_ops acpm_tmu_pm_ops = { · line 600
Quoted 4 lines
drivers/thermal/samsung/acpm-tmu.c +1
-1static struct platform_driver acpm_tmu_driver = { .driver = { - .name ="gs-tmu" , + .name ="exynos-acpm-tmu" ,It is minor but it potentially clashes with exynos-acpm-tmu firmware
There's no driver name for the firmware tmu commands helpers but I see your point.
Quoted 1 line
file name. All other names in file
acpm-tmu.care "acpm-tmu".
I think "exynos-acpm-tmu" is fine, it aligns with "exynos-acpm-protocol" from drivers/firmware/samsung/exynos-acpm.c. I guess you may rename "acpm-clocks" (drivers/clk/samsung/clk-acpm.c) to "exynos-acpm-clocks", but I wouldn't bother too much. If you have a strong opinion on "acpm-tmu" send a patch on top please.
Cheers,
ta
Tudor Ambarus
maintainerPATCH 12/15 thermal/drivers/samsung: Drop redundant composite object in Makefile
In reply to Tudor AmbarusThe Exynos ACPM thermal driver consists of a single source file (acpm-tmu.c). Build acpm-tmu.o directly under CONFIG_EXYNOS_ACPM_THERMAL instead of wrapping it in a single-file exynos_acpm_thermal.o composite object.
--- drivers/thermal/samsung/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/thermal/samsung/Makefile +1 -2
@@ -4,5 +4,4 @@ # obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o exynos_thermal-y := exynos_tmu.o -obj-$(CONFIG_EXYNOS_ACPM_THERMAL) += exynos_acpm_thermal.o -exynos_acpm_thermal-y := acpm-tmu.o +obj-$(CONFIG_EXYNOS_ACPM_THERMAL) += acpm-tmu.o
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: Drop redundant composite object in Makefile
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 133c6b01f134b6f3da2961099ab2fffe6e9a5f3d Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//133c6b01f134b6f3da2961099ab2fffe6e9a5f3d Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:29 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
thermal/drivers/samsung: Drop redundant composite object in Makefile
The Exynos ACPM thermal driver consists of a single source file (acpm-tmu.c). Build acpm-tmu.o directly under CONFIG_EXYNOS_ACPM_THERMAL instead of wrapping it in a single-file exynos_acpm_thermal.o composite object.
--- drivers/thermal/samsung/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/thermal/samsung/Makefile +1 -2
@@ -4,5 +4,4 @@ # obj-$(CONFIG_EXYNOS_THERMAL) += exynos_thermal.o exynos_thermal-y := exynos_tmu.o -obj-$(CONFIG_EXYNOS_ACPM_THERMAL) += exynos_acpm_thermal.o -exynos_acpm_thermal-y := acpm-tmu.o +obj-$(CONFIG_EXYNOS_ACPM_THERMAL) += acpm-tmu.o
Tudor Ambarus
maintainerPATCH 13/15 thermal/drivers/samsung: acpm-tmu: Disable regmap locking for MMIO INTPEND reads
In reply to Tudor AmbarusThe regmap in acpm-tmu is only used for full-width 32-bit relaxed MMIO reads of the INTPEND registers, with no read-modify-write operations or regmap cache. Set .disable_locking = true in gs101_regmap_config to avoid unnecessary regmap lock overhead on every INTPEND register read.
--- drivers/thermal/samsung/acpm-tmu.c | 1 + 1 file changed, 1 insertion(+)
drivers/thermal/samsung/acpm-tmu.c +1 -0
@@ -127,6 +127,7 @@ static const struct regmap_config gs101_regmap_config = { .reg_stride = 4, .val_bits = 32, .use_relaxed_mmio = true, + .disable_locking = true, .max_register = GS101_REG_INTPEND(15), };
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Disable regmap locking for MMIO INTPEND reads
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 6eb64c42a31531de51b735a1709ac8b7c24bbb4e Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//6eb64c42a31531de51b735a1709ac8b7c24bbb4e Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:30 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
thermal/drivers/samsung: acpm-tmu: Disable regmap locking for MMIO INTPEND reads
The regmap in acpm-tmu is only used for full-width 32-bit relaxed MMIO reads of the INTPEND registers, with no read-modify-write operations or regmap cache. Set .disable_locking = true in gs101_regmap_config to avoid unnecessary regmap lock overhead on every INTPEND register read.
--- drivers/thermal/samsung/acpm-tmu.c | 1 + 1 file changed, 1 insertion(+)
drivers/thermal/samsung/acpm-tmu.c +1 -0
@@ -127,6 +127,7 @@ static const struct regmap_config gs101_regmap_config = { .reg_stride = 4, .val_bits = 32, .use_relaxed_mmio = true, + .disable_locking = true, .max_register = GS101_REG_INTPEND(15), };
Tudor Ambarus
maintainerPATCH 14/15 thermal/drivers/samsung: acpm-tmu: Clean up probe error logging
In reply to Tudor Ambarusplatform_get_irq(), devm_thermal_add_hwmon_sysfs(), and devm_request_threaded_irq() already log an error or warning message internally on failure, so drop the duplicate call-site messages in acpm_tmu_probe(). Also update the copy-pasted "Unable to map syscon registers" message on devm_regmap_field_bulk_alloc() failure to "Failed to allocate regmap fields".
--- drivers/thermal/samsung/acpm-tmu.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +3 -7
@@ -444,7 +444,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) data->reg_fields, REG_INTPEND_COUNT);if (ret)return dev_err_probe (dev, ret, -"Unable to map syscon registers\n" ); +"Failed to allocate regmap fields\n" ); priv->clk =devm_clk_get (dev,NULL );if (IS_ERR (priv->clk))
@@ -453,7 +453,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) priv->irq =platform_get_irq (pdev,0 );if (priv->irq <0 ) -return dev_err_probe (dev, priv->irq,"Failed to get irq\n" ); +return priv->irq;pm_runtime_set_autosuspend_delay (dev,100 );pm_runtime_use_autosuspend (dev);
@@ -494,16 +494,12 @@ static int acpm_tmu_probe(struct platform_device *pdev) } sensor->tzd = tzd; - ret =devm_thermal_add_hwmon_sysfs (dev, sensor->tzd); -if (ret) -dev_warn (dev,"Failed to add hwmon sysfs!\n" ); +devm_thermal_add_hwmon_sysfs (dev, sensor->tzd); } ret =devm_request_threaded_irq (dev, priv->irq,NULL , acpm_tmu_thread_fn,IRQF_ONESHOT ,dev_name (dev), priv); -if (ret) - ret =dev_err_probe (dev, ret,"Failed to request irq\n" ); out_pm_put:pm_runtime_put_autosuspend (dev);
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Clean up probe error logging
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: f316fea84421e3ca569d861ebc7e17632ac54cc2 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//f316fea84421e3ca569d861ebc7e17632ac54cc2 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:31 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
thermal/drivers/samsung: acpm-tmu: Clean up probe error logging
platform_get_irq(), devm_thermal_add_hwmon_sysfs(), and devm_request_threaded_irq() already log an error or warning message internally on failure, so drop the duplicate call-site messages in acpm_tmu_probe(). Also update the copy-pasted "Unable to map syscon registers" message on devm_regmap_field_bulk_alloc() failure to "Failed to allocate regmap fields".
--- drivers/thermal/samsung/acpm-tmu.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +3 -7
@@ -444,7 +444,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) data->reg_fields, REG_INTPEND_COUNT);if (ret)return dev_err_probe (dev, ret, -"Unable to map syscon registers\n" ); +"Failed to allocate regmap fields\n" ); priv->clk =devm_clk_get (dev,NULL );if (IS_ERR (priv->clk))
@@ -453,7 +453,7 @@ static int acpm_tmu_probe(struct platform_device *pdev) priv->irq =platform_get_irq (pdev,0 );if (priv->irq <0 ) -return dev_err_probe (dev, priv->irq,"Failed to get irq\n" ); +return priv->irq;pm_runtime_set_autosuspend_delay (dev,100 );pm_runtime_use_autosuspend (dev);
@@ -494,16 +494,12 @@ static int acpm_tmu_probe(struct platform_device *pdev) } sensor->tzd = tzd; - ret =devm_thermal_add_hwmon_sysfs (dev, sensor->tzd); -if (ret) -dev_warn (dev,"Failed to add hwmon sysfs!\n" ); +devm_thermal_add_hwmon_sysfs (dev, sensor->tzd); } ret =devm_request_threaded_irq (dev, priv->irq,NULL , acpm_tmu_thread_fn,IRQF_ONESHOT ,dev_name (dev), priv); -if (ret) - ret =dev_err_probe (dev, ret,"Failed to request irq\n" ); out_pm_put:pm_runtime_put_autosuspend (dev);
Tudor Ambarus
maintainerPATCH 15/15 thermal/drivers/samsung: acpm-tmu: Simplify pm_runtime_resume_and_get() error checks
In reply to Tudor AmbarusUnlike pm_runtime_get_sync(), pm_runtime_resume_and_get() returns 0 on success or a negative error code on failure. Check "if (ret)" consistently across all pm_runtime_resume_and_get() call sites in acpm-tmu.c.
--- drivers/thermal/samsung/acpm-tmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +3 -3
@@ -161,7 +161,7 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on)int i, ret, err =0 ; ret =pm_runtime_resume_and_get (dev); -if (ret <0 ) +if (ret)return ret;for (i =0 ; i < priv->num_sensors; i++) {
@@ -205,7 +205,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp)return -ENODATA ; ret =pm_runtime_resume_and_get (dev); -if (ret <0 ) +if (ret)return ret; scoped_guard(mutex, &sensor->lock) {
@@ -463,7 +463,7 @@ static int acpm_tmu_probe(struct platform_device *pdev)return dev_err_probe (dev, ret,"Failed to enable runtime PM\n" ); ret =pm_runtime_resume_and_get (dev); -if (ret <0 ) +if (ret)return dev_err_probe (dev, ret,"Failed to resume device\n" ); ret = acpm_handle->ops->tmu.init (acpm_handle, priv->mbox_chan_id);
Signature · 1 line
2.56.0.257.gf7497c7d27-goog
[thermal: thermal/linux-next] thermal/drivers/samsung: acpm-tmu: Simplify pm_runtime_resume_and_get() error checks
The following commit has been merged into the thermal/linux-next branch of thermal:
The following commit has been merged into the thermal/linux-next branch of thermal:
Commit-ID: 32cb06b34701827db0ff34244d84fc74e40ca350 Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git//32cb06b34701827db0ff34244d84fc74e40ca350 Author: Tudor Ambarus <[email protected]> AuthorDate: Mon, 26 Oct 2026 16:01:32 Committer: Daniel Lezcano <[email protected]> CommitterDate: Tue, 03 Nov 2026 19:51:51 +01:00
thermal/drivers/samsung: acpm-tmu: Simplify pm_runtime_resume_and_get() error checks
Unlike pm_runtime_get_sync(), pm_runtime_resume_and_get() returns 0 on success or a negative error code on failure. Check "if (ret)" consistently across all pm_runtime_resume_and_get() call sites in acpm-tmu.c.
--- drivers/thermal/samsung/acpm-tmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/thermal/samsung/acpm-tmu.c +3 -3
@@ -161,7 +161,7 @@ static int acpm_tmu_control(struct acpm_tmu_priv *priv, bool on)int i, ret, err =0 ; ret =pm_runtime_resume_and_get (dev); -if (ret <0 ) +if (ret)return ret;for (i =0 ; i < priv->num_sensors; i++) {
@@ -205,7 +205,7 @@ static int acpm_tmu_get_temp(struct thermal_zone_device *tz, int *temp)return -ENODATA ; ret =pm_runtime_resume_and_get (dev); -if (ret <0 ) +if (ret)return ret; scoped_guard(mutex, &sensor->lock) {
@@ -463,7 +463,7 @@ static int acpm_tmu_probe(struct platform_device *pdev)return dev_err_probe (dev, ret,"Failed to enable runtime PM\n" ); ret =pm_runtime_resume_and_get (dev); -if (ret <0 ) +if (ret)return dev_err_probe (dev, ret,"Failed to resume device\n" ); ret = acpm_handle->ops->tmu.init (acpm_handle, priv->mbox_chan_id);