Skip to content

Commit 636aa88

Browse files
mkumardtiwai
authored andcommitted
ALSA: hda: Fix crash due to jack poll in suspend
With jackpoll_in_suspend flag set, there is a possibility that jack poll worker thread will run even after system suspend was completed. Any register access after system pm callback flow will result in kernel crash as still jack poll worker thread tries to access registers. To fix the crash issue during system flow, cancel the jack poll worker thread during system pm prepare callback and cancel the worker thread at start of runtime suspend callback and re-schedule at last to avoid any unwarranted access of register by worker thread during suspend flow. Signed-off-by: Mohan Kumar <[email protected]> Fixes: b33115b ("ALSA: hda: Jack detection poll in suspend state") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 74bba64 commit 636aa88

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

sound/pci/hda/hda_codec.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,15 +2940,19 @@ static int hda_codec_runtime_suspend(struct device *dev)
29402940
if (!codec->card)
29412941
return 0;
29422942

2943-
if (!codec->bus->jackpoll_in_suspend)
2944-
cancel_delayed_work_sync(&codec->jackpoll_work);
2943+
cancel_delayed_work_sync(&codec->jackpoll_work);
29452944

29462945
state = hda_call_codec_suspend(codec);
29472946
if (codec->link_down_at_suspend ||
29482947
(codec_has_clkstop(codec) && codec_has_epss(codec) &&
29492948
(state & AC_PWRST_CLK_STOP_OK)))
29502949
snd_hdac_codec_link_down(&codec->core);
29512950
snd_hda_codec_display_power(codec, false);
2951+
2952+
if (codec->bus->jackpoll_in_suspend &&
2953+
(dev->power.power_state.event != PM_EVENT_SUSPEND))
2954+
schedule_delayed_work(&codec->jackpoll_work,
2955+
codec->jackpoll_interval);
29522956
return 0;
29532957
}
29542958

@@ -2972,6 +2976,9 @@ static int hda_codec_runtime_resume(struct device *dev)
29722976
#ifdef CONFIG_PM_SLEEP
29732977
static int hda_codec_pm_prepare(struct device *dev)
29742978
{
2979+
struct hda_codec *codec = dev_to_hda_codec(dev);
2980+
2981+
cancel_delayed_work_sync(&codec->jackpoll_work);
29752982
dev->power.power_state = PMSG_SUSPEND;
29762983
return pm_runtime_suspended(dev);
29772984
}
@@ -2991,9 +2998,6 @@ static void hda_codec_pm_complete(struct device *dev)
29912998

29922999
static int hda_codec_pm_suspend(struct device *dev)
29933000
{
2994-
struct hda_codec *codec = dev_to_hda_codec(dev);
2995-
2996-
cancel_delayed_work_sync(&codec->jackpoll_work);
29973001
dev->power.power_state = PMSG_SUSPEND;
29983002
return pm_runtime_force_suspend(dev);
29993003
}

0 commit comments

Comments
 (0)