mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-24 07:50:02 -04:00
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
This commit is contained in:
@@ -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 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap)
|
||||
}
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user