Skip to content

Commit

Permalink
ALSA: hda: Fix crash due to jack poll in suspend
Browse files Browse the repository at this point in the history
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 <mkumard@nvidia.com>
Fixes: b33115b ("ALSA: hda: Jack detection poll in suspend state")
Link: https://lore.kernel.org/r/20220811052704.2944-1-mkumard@nvidia.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Mohan Kumar authored and Takashi Iwai committed Aug 11, 2022
1 parent 74bba64 commit 636aa88
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2940,15 +2940,19 @@ static int hda_codec_runtime_suspend(struct device *dev)
if (!codec->card)
return 0;

if (!codec->bus->jackpoll_in_suspend)
cancel_delayed_work_sync(&codec->jackpoll_work);
cancel_delayed_work_sync(&codec->jackpoll_work);

state = hda_call_codec_suspend(codec);
if (codec->link_down_at_suspend ||
(codec_has_clkstop(codec) && codec_has_epss(codec) &&
(state & AC_PWRST_CLK_STOP_OK)))
snd_hdac_codec_link_down(&codec->core);
snd_hda_codec_display_power(codec, false);

if (codec->bus->jackpoll_in_suspend &&
(dev->power.power_state.event != PM_EVENT_SUSPEND))
schedule_delayed_work(&codec->jackpoll_work,
codec->jackpoll_interval);
return 0;
}

Expand All @@ -2972,6 +2976,9 @@ static int hda_codec_runtime_resume(struct device *dev)
#ifdef CONFIG_PM_SLEEP
static int hda_codec_pm_prepare(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);

cancel_delayed_work_sync(&codec->jackpoll_work);
dev->power.power_state = PMSG_SUSPEND;
return pm_runtime_suspended(dev);
}
Expand All @@ -2991,9 +2998,6 @@ static void hda_codec_pm_complete(struct device *dev)

static int hda_codec_pm_suspend(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);

cancel_delayed_work_sync(&codec->jackpoll_work);
dev->power.power_state = PMSG_SUSPEND;
return pm_runtime_force_suspend(dev);
}
Expand Down

0 comments on commit 636aa88

Please sign in to comment.