diff options
author | Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> | 2021-06-14 13:08:13 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-06-21 13:00:44 +0100 |
commit | 18236370a098428d7639686daa36584d0d363c9e (patch) | |
tree | a89d56902ac8e5a4e8dab42355500ddf603e1bbd /sound/soc/codecs/rt711.c | |
parent | 60888ef827e354d7a3611288d86629e5f1824613 (diff) | |
download | linux-stable-18236370a098428d7639686daa36584d0d363c9e.tar.gz linux-stable-18236370a098428d7639686daa36584d0d363c9e.tar.bz2 linux-stable-18236370a098428d7639686daa36584d0d363c9e.zip |
ASoC: rt711-sdw: fix race condition on system suspend
In previous commits we cancelled deferred work, but there is still a
window of time where a new interrupt could result in new deferred work
executed after the link is disabled, leading to an IO error. While we
did not see this IO error on RT711-based platforms, the code pattern
is similar to the RT700 case where the IO error was noted, so the fix
is added for consistency.
This patch uses an 'disable_irq_lock' mutex to prevent new interrupts
from happening after the start of the system suspend. The choice of a
mutex v. a spinlock is mainly due to the time required to clear
interrupts, which requires a command to be transmitted by the
SoundWire host IP and acknowledged with an interrupt. The
'interrupt_callback' routine is also not meant to be called from an
interrupt context.
An additional 'disable_irq' flag prevents race conditions where the
status changes before the interrupts are disabled, but the workqueue
handling status changes is scheduled after the completion of the
system suspend. On resume the interrupts are re-enabled already by the
io_init routine so we only clear the flag.
BugLink: https://github.com/thesofproject/linux/issues/2943
Fixes: 501ef013390b ('ASoC: rt711: wait for the delayed work to finish when the system suspends')
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <bard.liao@intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20210614180815.153711-4-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/rt711.c')
-rw-r--r-- | sound/soc/codecs/rt711.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 9f5b2dc16c54..4dbfa7b8680e 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1166,6 +1166,8 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, rt711->sdw_regmap = sdw_regmap; rt711->regmap = regmap; + mutex_init(&rt711->disable_irq_lock); + /* * Mark hw_init to false * HW init will be performed when device reports present @@ -1190,6 +1192,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) { struct rt711_priv *rt711 = dev_get_drvdata(dev); + rt711->disable_irq = false; + if (rt711->hw_init) return 0; |