From 1e6f4fc06f6411adf98bbbe7fcd79442cd2b2a75 Mon Sep 17 00:00:00 2001 From: Ricard Wanderlof Date: Thu, 7 Sep 2017 15:31:38 +0200 Subject: ASoC: adau17x1: Workaround for noise bug in ADC The ADC in the ADAU1361 (and possibly other Analog Devices codecs) exhibits a cyclic variation in the noise floor (in our test setup between -87 and -93 dB), a new value being attained within this range whenever a new capture stream is started. The cycle repeats after about 10 or 11 restarts. The workaround recommended by the manufacturer is to toggle the ADOSR bit in the Converter Control 0 register each time a new capture stream is started. I have verified that the patch fixes this problem on the ADAU1361, and according to the manufacturer toggling the bit in question in this manner will at least have no detrimental effect on other chips served by this driver. Signed-off-by: Ricard Wanderlof Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/adau17x1.c | 24 +++++++++++++++++++++++- sound/soc/codecs/adau17x1.h | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 2c1bd2763864..6758f789b712 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -90,6 +90,27 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, return 0; } +static int adau17x1_adc_fixup(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct adau *adau = snd_soc_codec_get_drvdata(codec); + + /* + * If we are capturing, toggle the ADOSR bit in Converter Control 0 to + * avoid losing SNR (workaround from ADI). This must be done after + * the ADC(s) have been enabled. According to the data sheet, it is + * normally illegal to set this bit when the sampling rate is 96 kHz, + * but according to ADI it is acceptable for this workaround. + */ + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, + ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR); + regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0, + ADAU17X1_CONVERTER0_ADOSR, 0); + + return 0; +} + static const char * const adau17x1_mono_stereo_text[] = { "Stereo", "Mono Left Channel (L+R)", @@ -121,7 +142,8 @@ static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = { SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0, &adau17x1_dac_mode_mux), - SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0), + SND_SOC_DAPM_ADC_E("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0, + adau17x1_adc_fixup, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0), SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0), SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0), diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h index bf04b7efee40..db350035fad7 100644 --- a/sound/soc/codecs/adau17x1.h +++ b/sound/soc/codecs/adau17x1.h @@ -129,5 +129,7 @@ bool adau17x1_has_dsp(struct adau *adau); #define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7 +#define ADAU17X1_CONVERTER0_ADOSR BIT(3) + #endif -- cgit v1.2.3-59-g8ed1b From 659178f5d1bb5164480c35e5a749c4fe1dde5867 Mon Sep 17 00:00:00 2001 From: Hsin-Yu Chao Date: Wed, 13 Sep 2017 17:54:28 +0800 Subject: ASoC: rt5514-spi: check irq status to schedule data copy For wake on voice use case, we need to copy data from DSP buffer to PCM stream when system wakes up by voice. However the edge triggered IRQ could be missed when system wakes up, in that case the irq function will not be called. Fix that by checking the irq status bit and schedule data copy accordingly. Signed-off-by: Hsin-Yu Chao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5514-spi.c | 17 +++++++++++++++-- sound/soc/codecs/rt5514-spi.h | 3 +++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c index ed6e5373916c..12f2ecf3a4fe 100644 --- a/sound/soc/codecs/rt5514-spi.c +++ b/sound/soc/codecs/rt5514-spi.c @@ -145,9 +145,8 @@ done: mutex_unlock(&rt5514_dsp->dma_lock); } -static irqreturn_t rt5514_spi_irq(int irq, void *data) +static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp) { - struct rt5514_dsp *rt5514_dsp = data; u8 buf[8]; rt5514_dsp->get_size = 0; @@ -180,6 +179,13 @@ static irqreturn_t rt5514_spi_irq(int irq, void *data) if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit && rt5514_dsp->buf_rp && rt5514_dsp->buf_size) schedule_delayed_work(&rt5514_dsp->copy_work, 0); +} + +static irqreturn_t rt5514_spi_irq(int irq, void *data) +{ + struct rt5514_dsp *rt5514_dsp = data; + + rt5514_schedule_copy(rt5514_dsp); return IRQ_HANDLED; } @@ -199,12 +205,19 @@ static int rt5514_spi_hw_params(struct snd_pcm_substream *substream, struct rt5514_dsp *rt5514_dsp = snd_soc_platform_get_drvdata(rtd->platform); int ret; + u8 buf[8]; mutex_lock(&rt5514_dsp->dma_lock); ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, params_buffer_bytes(hw_params)); rt5514_dsp->substream = substream; rt5514_dsp->dma_offset = 0; + + /* Read IRQ status and schedule copy accordingly. */ + rt5514_spi_burst_read(RT5514_IRQ_CTRL, (u8 *)&buf, sizeof(buf)); + if (buf[0] & RT5514_IRQ_STATUS_BIT) + rt5514_schedule_copy(rt5514_dsp); + mutex_unlock(&rt5514_dsp->dma_lock); return ret; diff --git a/sound/soc/codecs/rt5514-spi.h b/sound/soc/codecs/rt5514-spi.h index a6434ee6ff03..c1a36647c119 100644 --- a/sound/soc/codecs/rt5514-spi.h +++ b/sound/soc/codecs/rt5514-spi.h @@ -20,6 +20,9 @@ #define RT5514_BUFFER_VOICE_BASE 0x18000200 #define RT5514_BUFFER_VOICE_LIMIT 0x18000204 #define RT5514_BUFFER_VOICE_WP 0x1800020c +#define RT5514_IRQ_CTRL 0x18002094 + +#define RT5514_IRQ_STATUS_BIT (0x1 << 5) /* SPI Command */ enum { -- cgit v1.2.3-59-g8ed1b From 6d5574ed5c8b1a1f31fcbdab5d26e15533c442ca Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2017 22:44:12 +0200 Subject: ASoC: topology: Fix a potential NULL pointer dereference in 'soc_tplg_dapm_widget_denum_create()' if 'se = kzalloc()' fails in the 'for' loop, we will branch to 'err'. But in this case, 'kc[i].private_value' will still be NULL. A NULL pointer dereference will then occur is the error handling path. In such a case, it is safe to just 'continue' in order to skip this entry and free the other ones. Fixes: 1a7dd6e2f192 ("ASoC: topology: Allow a widget to have multiple enum controls") Signed-off-by: Christophe JAILLET Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index dd471d2c0266..2499b54a57e8 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1378,6 +1378,9 @@ err_se: for (; i >= 0; i--) { /* free values and texts */ se = (struct soc_enum *)kc[i].private_value; + if (!se) + continue; + kfree(se->dobj.control.dvalues); for (j = 0; j < ec->items; j++) kfree(se->dobj.control.dtexts[j]); -- cgit v1.2.3-59-g8ed1b From f3ee9096fcaf55eae37dfb58603c4dbff6f0a7c9 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 14 Sep 2017 22:44:24 +0200 Subject: ASoC: topology: Fix a potential memory leak in 'soc_tplg_dapm_widget_denum_create()' If this sanity check fails, we must free the memory that has already been allocated. So we must go to 'err' as in the other error handling parth of this function. Fixes: 1a7dd6e2f192 ("ASoC: topology: Allow a widget to have multiple enum controls") Signed-off-by: Christophe JAILLET Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 2499b54a57e8..01a50413c66f 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1301,7 +1301,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( /* validate kcontrol */ if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) - return NULL; + goto err; se = kzalloc(sizeof(*se), GFP_KERNEL); if (se == NULL) -- cgit v1.2.3-59-g8ed1b From 37128514d708457fc060a2309aaa78b057a00043 Mon Sep 17 00:00:00 2001 From: Hsin-Yu Chao Date: Fri, 15 Sep 2017 12:32:00 +0800 Subject: ASoC: rt5514: Revert Hotword Model control This reverts commit eb33869c7206 ("ASoC: rt5514: Guard Hotword Model bytes loading") and commit d18420b0a0b8 ("ASoC: rt5514: expose Hotword Model control") It is discouraged to use SND_SOC_BYTES_TLV to load arbitrary bytes from userspace to driver. Removing the 'Hotword Model' control until we have a good way to verify the content of hotword model blobs. Signed-off-by: Hsin-Yu Chao Reviewed-by: Takashi Sakamoto Signed-off-by: Mark Brown --- sound/soc/codecs/rt5514.c | 63 ----------------------------------------------- sound/soc/codecs/rt5514.h | 3 --- 2 files changed, 66 deletions(-) diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 0945d212b8dc..d7956ababd11 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -338,39 +338,6 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, fw = NULL; } - if (rt5514->model_buf && rt5514->model_len) { -#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) - int ret; - - ret = rt5514_spi_burst_write(0x4ff80000, - rt5514->model_buf, - ((rt5514->model_len / 8) + 1) * 8); - if (ret) { - dev_err(codec->dev, - "Model load failed %d\n", ret); - return ret; - } -#else - dev_err(codec->dev, - "No SPI driver for loading firmware\n"); -#endif - } else { - request_firmware(&fw, RT5514_FIRMWARE3, - codec->dev); - if (fw) { -#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI) - rt5514_spi_burst_write(0x4ff80000, - fw->data, - ((fw->size/8)+1)*8); -#else - dev_err(codec->dev, - "No SPI driver to load fw\n"); -#endif - release_firmware(fw); - fw = NULL; - } - } - /* DSP run */ regmap_write(rt5514->i2c_regmap, 0x18002f00, 0x00055148); @@ -385,34 +352,6 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, return 0; } -static int rt5514_hotword_model_put(struct snd_kcontrol *kcontrol, - const unsigned int __user *bytes, unsigned int size) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); - struct snd_soc_codec *codec = rt5514->codec; - int ret = 0; - - if (rt5514->model_buf || rt5514->model_len < size) { - if (rt5514->model_buf) - devm_kfree(codec->dev, rt5514->model_buf); - rt5514->model_buf = devm_kmalloc(codec->dev, size, GFP_KERNEL); - if (!rt5514->model_buf) { - ret = -ENOMEM; - goto done; - } - } - - /* Skips the TLV header. */ - bytes += 2; - - if (copy_from_user(rt5514->model_buf, bytes, size)) - ret = -EFAULT; -done: - rt5514->model_len = (ret ? 0 : size); - return ret; -} - static const struct snd_kcontrol_new rt5514_snd_controls[] = { SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), @@ -424,8 +363,6 @@ static const struct snd_kcontrol_new rt5514_snd_controls[] = { adc_vol_tlv), SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0, rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put), - SND_SOC_BYTES_TLV("Hotword Model", 0x8504, - NULL, rt5514_hotword_model_put), }; /* ADC Mixer*/ diff --git a/sound/soc/codecs/rt5514.h b/sound/soc/codecs/rt5514.h index 803311cb7e2a..2dc40e6d8b3f 100644 --- a/sound/soc/codecs/rt5514.h +++ b/sound/soc/codecs/rt5514.h @@ -255,7 +255,6 @@ #define RT5514_FIRMWARE1 "rt5514_dsp_fw1.bin" #define RT5514_FIRMWARE2 "rt5514_dsp_fw2.bin" -#define RT5514_FIRMWARE3 "rt5514_dsp_fw3.bin" /* System Clock Source */ enum { @@ -282,8 +281,6 @@ struct rt5514_priv { int pll_in; int pll_out; int dsp_enabled; - u8 *model_buf; - unsigned int model_len; }; #endif /* __RT5514_H__ */ -- cgit v1.2.3-59-g8ed1b From a16cc6326d58b32f12f2e60d0b0ec2c8771469a5 Mon Sep 17 00:00:00 2001 From: "oder_chiou@realtek.com" Date: Mon, 25 Sep 2017 11:11:05 +0800 Subject: ASoC: rt5663: Change the dev getting function in rt5663_irq In the irq handler "rt5663_irq", while the codec is not initialized, rt5663->codec will be null, and it will cause the kernel panic in the debug print enabled. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown --- sound/soc/codecs/rt5663.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index ab9e0ebff5a7..e45b895d8279 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -1639,7 +1639,8 @@ static irqreturn_t rt5663_irq(int irq, void *data) { struct rt5663_priv *rt5663 = data; - dev_dbg(rt5663->codec->dev, "%s IRQ queue work\n", __func__); + dev_dbg(regmap_get_device(rt5663->regmap), "%s IRQ queue work\n", + __func__); queue_delayed_work(system_wq, &rt5663->jack_detect_work, msecs_to_jiffies(250)); -- cgit v1.2.3-59-g8ed1b From d1e84308ac8ad945a77f4fd7b08725d14181703b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 16 Oct 2017 19:15:13 +0800 Subject: ASoC: rt5659: register power bit of LOUT Amp There is a power bit for LOUT Amp. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 71216db15eab..999432e98a5a 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -2744,7 +2744,8 @@ static const struct snd_soc_dapm_widget rt5659_dapm_widgets[] = { SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5659_hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_PGA("LOUT Amp", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA_S("LOUT Amp", 1, RT5659_PWR_ANLG_1, RT5659_PWR_LM_BIT, + 0, NULL, 0), SND_SOC_DAPM_SUPPLY("Charge Pump", SND_SOC_NOPM, 0, 0, rt5659_charge_pump_event, SND_SOC_DAPM_PRE_PMU | -- cgit v1.2.3-59-g8ed1b From a6189d371d05863720e4381361f83ce5d376fad7 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 16 Oct 2017 19:15:14 +0800 Subject: ASoC: rt5659: connect LOUT Amp with Charge Pump "Charge Pump" is necessary for "LOUT Amp". Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 999432e98a5a..fa66b11df8d4 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3209,6 +3209,7 @@ static const struct snd_soc_dapm_route rt5659_dapm_routes[] = { { "LOUT R MIX", "OUTVOL R Switch", "OUTVOL R" }, { "LOUT Amp", NULL, "LOUT L MIX" }, { "LOUT Amp", NULL, "LOUT R MIX" }, + { "LOUT Amp", NULL, "Charge Pump" }, { "LOUT Amp", NULL, "SYS CLK DET" }, { "LOUT L Playback", "Switch", "LOUT Amp" }, { "LOUT R Playback", "Switch", "LOUT Amp" }, -- cgit v1.2.3-59-g8ed1b From ea968da7d45d4a1305e42107c5356fba0ab1ed3c Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 20 Oct 2017 15:46:55 +0800 Subject: ASoC: rt5616: fix 0x91 default value The default value of register 0x91 is 0x0c00 instead of 0x0000. Signed-off-by: Bard Liao Signed-off-by: Mark Brown --- sound/soc/codecs/rt5616.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index c94e94fe8297..0e5f54a9bc7e 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -98,7 +98,7 @@ static const struct reg_default rt5616_reg[] = { { 0x8e, 0x0004 }, { 0x8f, 0x1100 }, { 0x90, 0x0000 }, - { 0x91, 0x0000 }, + { 0x91, 0x0c00 }, { 0x92, 0x0000 }, { 0x93, 0x2000 }, { 0x94, 0x0200 }, -- cgit v1.2.3-59-g8ed1b From 79fb0518fec8c8b4ea7f1729f54f293724b3dbb0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 29 Oct 2017 11:02:04 +0100 Subject: ALSA: timer: Add missing mutex lock for compat ioctls The races among ioctl and other operations were protected by the commit af368027a49a ("ALSA: timer: Fix race among timer ioctls") and later fixes, but one code path was forgotten in the scenario: the 32bit compat ioctl. As syzkaller recently spotted, a very similar use-after-free may happen with the combination of compat ioctls. The fix is simply to apply the same ioctl_lock to the compat_ioctl callback, too. Fixes: af368027a49a ("ALSA: timer: Fix race among timer ioctls") Reference: http://lkml.kernel.org/r/089e082686ac9b482e055c832617@google.com Reported-by: syzbot Cc: Signed-off-by: Takashi Iwai --- sound/core/timer_compat.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 6a437eb66115..59127b6ef39e 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -133,7 +133,8 @@ enum { #endif /* CONFIG_X86_X32 */ }; -static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) { void __user *argp = compat_ptr(arg); @@ -153,7 +154,7 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns case SNDRV_TIMER_IOCTL_PAUSE: case SNDRV_TIMER_IOCTL_PAUSE_OLD: case SNDRV_TIMER_IOCTL_NEXT_DEVICE: - return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); + return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp); case SNDRV_TIMER_IOCTL_GPARAMS32: return snd_timer_user_gparams_compat(file, argp); case SNDRV_TIMER_IOCTL_INFO32: @@ -167,3 +168,15 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns } return -ENOIOCTLCMD; } + +static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct snd_timer_user *tu = file->private_data; + long ret; + + mutex_lock(&tu->ioctl_lock); + ret = __snd_timer_user_ioctl_compat(file, cmd, arg); + mutex_unlock(&tu->ioctl_lock); + return ret; +} -- cgit v1.2.3-59-g8ed1b From 1f20f9ff57ca23b9f5502fca85ce3977e8496cb1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 29 Oct 2017 11:10:43 +0100 Subject: ALSA: seq: Fix nested rwsem annotation for lockdep splat syzkaller reported the lockdep splat due to the possible deadlock of grp->list_mutex of each sequencer client object. Actually this is rather a false-positive report due to the missing nested lock annotations. The sequencer client may deliver the event directly to another client which takes another own lock. For addressing this issue, this patch replaces the simple down_read() with down_read_nested(). As a lock subclass, the already existing "hop" can be re-used, which indicates the depth of the call. Reference: http://lkml.kernel.org/r/089e082686ac9b482e055c832617@google.com Reported-by: syzbot Reported-by: Dmitry Vyukov Cc: Signed-off-by: Takashi Iwai --- sound/core/seq/seq_clientmgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 6c9cba2166d9..d10c780dfd54 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -663,7 +663,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client, if (atomic) read_lock(&grp->list_lock); else - down_read(&grp->list_mutex); + down_read_nested(&grp->list_mutex, hop); list_for_each_entry(subs, &grp->list_head, src_list) { /* both ports ready? */ if (atomic_read(&subs->ref_count) != 2) -- cgit v1.2.3-59-g8ed1b