| From b8d19dac2ea5f16fe08fe0055eb7fdd0e55d7ee6 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 7 Feb 2022 17:29:59 +0200 |
| Subject: ASoC: rt5668: do not block workqueue if card is unbound |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Kai Vehmanen <kai.vehmanen@linux.intel.com> |
| |
| [ Upstream commit a6d78661dc903d90a327892bbc34268f3a5f4b9c ] |
| |
| The current rt5668_jack_detect_handler() assumes the component |
| and card will always show up and implements an infinite usleep |
| loop waiting for them to show up. |
| |
| This does not hold true if a codec interrupt (or other |
| event) occurs when the card is unbound. The codec driver's |
| remove or shutdown functions cannot cancel the workqueue due |
| to the wait loop. As a result, code can either end up blocking |
| the workqueue, or hit a kernel oops when the card is freed. |
| |
| Fix the issue by rescheduling the jack detect handler in |
| case the card is not ready. In case card never shows up, |
| the shutdown/remove/suspend calls can now cancel the detect |
| task. |
| |
| Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> |
| Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> |
| Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> |
| Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> |
| Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> |
| Reviewed-by: Shuming Fan <shumingf@realtek.com> |
| Link: https://lore.kernel.org/r/20220207153000.3452802-2-kai.vehmanen@linux.intel.com |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/soc/codecs/rt5668.c | 12 +++++++----- |
| 1 file changed, 7 insertions(+), 5 deletions(-) |
| |
| diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c |
| index 5716cede99cb4..acc2b34ca334a 100644 |
| --- a/sound/soc/codecs/rt5668.c |
| +++ b/sound/soc/codecs/rt5668.c |
| @@ -1022,11 +1022,13 @@ static void rt5668_jack_detect_handler(struct work_struct *work) |
| container_of(work, struct rt5668_priv, jack_detect_work.work); |
| int val, btn_type; |
| |
| - while (!rt5668->component) |
| - usleep_range(10000, 15000); |
| - |
| - while (!rt5668->component->card->instantiated) |
| - usleep_range(10000, 15000); |
| + if (!rt5668->component || !rt5668->component->card || |
| + !rt5668->component->card->instantiated) { |
| + /* card not yet ready, try later */ |
| + mod_delayed_work(system_power_efficient_wq, |
| + &rt5668->jack_detect_work, msecs_to_jiffies(15)); |
| + return; |
| + } |
| |
| mutex_lock(&rt5668->calibrate_mutex); |
| |
| -- |
| 2.34.1 |
| |