diff options
| author | Mark Brown <broonie@kernel.org> | 2026-06-01 17:52:59 +0300 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-06-01 17:52:59 +0300 |
| commit | 3a129981440fbba4ce0219069fdf257fa2fbc2ab (patch) | |
| tree | 97bb48352b6c9501174d1573e0078a0cb92ea30e | |
| parent | debea6d6bce8abdb6f0dac6755936f48ababc7bb (diff) | |
| parent | eb7107264da8545ba7381a76818bae553e1fd1e4 (diff) | |
| download | linux-3a129981440fbba4ce0219069fdf257fa2fbc2ab.tar.xz | |
ASoC: codecs: pcm3168a: Fix and updates for power management
Cezary Rojewski <cezary.rojewski@intel.com> says:
Set of changes composed of one fix and two improvements.
The fix leads the series and addresses "unbalanced disables" coming from
the regulator core during S4 (hibernation) scenario.
The SLEEP_PM_OPS are unset for the driver. Hibernation (S4) causes no
resume (skipped thanks to smart_suspend=true) yet still performs the
suspend sequence unconditionally, see device_complete() in
drivers/base/power/main.c. In essence, we end up with double suspend
(double disable) and thus the warning. Exemplary stack:
unbalanced disables for regulator-dummy
WARNING: drivers/regulator/core.c:3244 at _regulator_disable+0x161/0x270, CPU#6: kworker/u64:2/120
(...)
Workqueue: pm pm_runtime_work
RIP: 0010:_regulator_disable+0x161/0x270
(...)
Call Trace:
<TASK>
regulator_bulk_disable+0xe4/0x220
? __pfx_regulator_bulk_disable+0x10/0x10
? pick_next_task_fair+0x36f/0x11f0
? __pfx_regmap_unlock_mutex+0x10/0x10
? regmap_unlock_mutex+0xe/0x20
pcm3168a_rt_suspend+0x57/0x90 [snd_soc_pcm3168a]
? __pfx_pcm3168a_rt_suspend+0x10/0x10 [snd_soc_pcm3168a]
__rpm_callback+0x69/0x200
? __pfx_pcm3168a_rt_suspend+0x10/0x10 [snd_soc_pcm3168a]
rpm_callback+0xbc/0xd0
rpm_suspend+0x225/0x960
? __pfx_rpm_suspend+0x10/0x10
? __kasan_check_write+0x14/0x20
? _raw_spin_lock_irq+0x8d/0xe0
? __pfx__raw_spin_lock_irq+0x10/0x10
? pwq_dec_nr_in_flight+0x63/0x4f0
pm_runtime_work+0xd0/0xf0
In regard to the improvements, both aim to drop redundant operations.
One targets pm_runtime_idle() - no need to fire it manually,
device-driver core will do that for us - while the second replaces
preprocessor directive with pm_runtime_status_suspended() check.
No !CONFIG_PM dependency equals better code coverege with default
kconfigs.
Link: https://patch.msgid.link/20260525201801.1336936-1-cezary.rojewski@intel.com
| -rw-r--r-- | sound/soc/codecs/pcm3168a.c | 22 |
1 files changed, 8 insertions, 14 deletions
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index c8617a488b11..4503f2f0724e 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -799,7 +799,6 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv)); ret = devm_snd_soc_register_component(dev, &pcm3168a_driver, @@ -822,15 +821,6 @@ err_clk: } EXPORT_SYMBOL_GPL(pcm3168a_probe); -static void pcm3168a_disable(struct device *dev) -{ - struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); - - regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), - pcm3168a->supplies); - clk_disable_unprepare(pcm3168a->scki); -} - void pcm3168a_remove(struct device *dev) { struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); @@ -842,10 +832,12 @@ void pcm3168a_remove(struct device *dev) * The asserted level of GPIO_ACTIVE_LOW is LOW. */ gpiod_set_value_cansleep(pcm3168a->gpio_rst, 1); + pm_runtime_disable(dev); -#ifndef CONFIG_PM - pcm3168a_disable(dev); -#endif + if (!pm_runtime_status_suspended(dev)) { + regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies); + clk_disable_unprepare(pcm3168a->scki); + } } EXPORT_SYMBOL_GPL(pcm3168a_remove); @@ -900,13 +892,15 @@ static int pcm3168a_rt_suspend(struct device *dev) regcache_cache_only(pcm3168a->regmap, true); - pcm3168a_disable(dev); + regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies); + clk_disable_unprepare(pcm3168a->scki); return 0; } EXPORT_GPL_DEV_PM_OPS(pcm3168a_pm_ops) = { RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; MODULE_DESCRIPTION("PCM3168A codec driver"); |
