| From 0aec96f5897ac16ad9945f531b4bef9a2edd2ebd Mon Sep 17 00:00:00 2001 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Wed, 18 Dec 2019 20:26:06 +0100 |
| Subject: ALSA: ice1724: Fix sleep-in-atomic in Infrasonic Quartet support code |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| commit 0aec96f5897ac16ad9945f531b4bef9a2edd2ebd upstream. |
| |
| Jia-Ju Bai reported a possible sleep-in-atomic scenario in the ice1724 |
| driver with Infrasonic Quartet support code: namely, ice->set_rate |
| callback gets called inside ice->reg_lock spinlock, while the callback |
| in quartet.c holds ice->gpio_mutex. |
| |
| This patch fixes the invalid call: it simply moves the calls of |
| ice->set_rate and ice->set_mclk callbacks outside the spinlock. |
| |
| Reported-by: Jia-Ju Bai <baijiaju1990@gmail.com> |
| Cc: <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/5d43135e-73b9-a46a-2155-9e91d0dcdf83@gmail.com |
| Link: https://lore.kernel.org/r/20191218192606.12866-1-tiwai@suse.de |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| sound/pci/ice1712/ice1724.c | 9 ++++++--- |
| 1 file changed, 6 insertions(+), 3 deletions(-) |
| |
| --- a/sound/pci/ice1712/ice1724.c |
| +++ b/sound/pci/ice1712/ice1724.c |
| @@ -663,6 +663,7 @@ static int snd_vt1724_set_pro_rate(struc |
| unsigned long flags; |
| unsigned char mclk_change; |
| unsigned int i, old_rate; |
| + bool call_set_rate = false; |
| |
| if (rate > ice->hw_rates->list[ice->hw_rates->count - 1]) |
| return -EINVAL; |
| @@ -686,7 +687,7 @@ static int snd_vt1724_set_pro_rate(struc |
| * setting clock rate for internal clock mode */ |
| old_rate = ice->get_rate(ice); |
| if (force || (old_rate != rate)) |
| - ice->set_rate(ice, rate); |
| + call_set_rate = true; |
| else if (rate == ice->cur_rate) { |
| spin_unlock_irqrestore(&ice->reg_lock, flags); |
| return 0; |
| @@ -694,12 +695,14 @@ static int snd_vt1724_set_pro_rate(struc |
| } |
| |
| ice->cur_rate = rate; |
| + spin_unlock_irqrestore(&ice->reg_lock, flags); |
| + |
| + if (call_set_rate) |
| + ice->set_rate(ice, rate); |
| |
| /* setting master clock */ |
| mclk_change = ice->set_mclk(ice, rate); |
| |
| - spin_unlock_irqrestore(&ice->reg_lock, flags); |
| - |
| if (mclk_change && ice->gpio.i2s_mclk_changed) |
| ice->gpio.i2s_mclk_changed(ice); |
| if (ice->gpio.set_pro_rate) |