summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof
diff options
context:
space:
mode:
authorKeyon Jie <yang.jie@linux.intel.com>2019-06-12 12:23:41 -0500
committerMark Brown <broonie@kernel.org>2019-06-17 13:44:50 +0100
commit7fd572e7d317fa51049d623badb8b2874bfd0119 (patch)
tree1bf4759fdf3345c0e519ea77cc14d8f8661ccbc7 /sound/soc/sof
parent6297a0dc4c14a62bea5a9137ceef280cb7a80665 (diff)
downloadlinux-7fd572e7d317fa51049d623badb8b2874bfd0119.tar.gz
linux-7fd572e7d317fa51049d623badb8b2874bfd0119.tar.bz2
linux-7fd572e7d317fa51049d623badb8b2874bfd0119.zip
ASoC: SOF: Intel: hda-stream: fix a deadlock with bus->reg_lock
We should use irq disabled mode when read/write hda registers from thread context, as we need to hold the same bus->reg_lock in interrupt context hda_dsp_stream_interrupt(), otherwise, when we are holding the lock in hda_dsp_stream_hw_free() and the interrupt arrives, we will get deadlock in the interrupt handler. Error logs like this: [ 5.603606] CPU0 [ 5.603606] ---- [ 5.603607] lock(&(&bus->reg_lock)->rlock); [ 5.603608] <Interrupt> [ 5.603609] lock(&(&bus->reg_lock)->rlock); [ 5.603610] *** DEADLOCK *** [ 5.603611] 2 locks held by pulseaudio/2329: [ 5.603612] #0: 000000005fcf26c6 (&card->mutex/1){+.+.}, at: dpcm_fe_dai_hw_free+0x2b/0x110 [snd_soc_core] [ 5.603619] #1: 00000000ef369faf (&rtd->pcm_mutex){+.+.}, at: soc_pcm_hw_free+0x2e/0x1c0 [snd_soc_core] The fix is simple, let's switch to use spin_lock/unlock_irq(). Reported-by: Xun Zhang <xun2.zhang@intel.com> Signed-off-by: Keyon Jie <yang.jie@linux.intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof')
-rw-r--r--sound/soc/sof/intel/hda-stream.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index d44318040948..23cff5aca007 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -448,12 +448,12 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
struct hdac_bus *bus = sof_to_bus(sdev);
u32 mask = 0x1 << stream->index;
- spin_lock(&bus->reg_lock);
+ spin_lock_irq(&bus->reg_lock);
/* couple host and link DMA if link DMA channel is idle */
if (!link_dev->link_locked)
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR,
SOF_HDA_REG_PP_PPCTL, mask, 0);
- spin_unlock(&bus->reg_lock);
+ spin_unlock_irq(&bus->reg_lock);
return 0;
}