[1/2] ALSA: hda: hdmi - fix kernel oops caused by invalid PCM idx
diff mbox series

Message ID 20191129143756.23941-1-kai.vehmanen@linux.intel.com
State New
Headers show
Series
  • [1/2] ALSA: hda: hdmi - fix kernel oops caused by invalid PCM idx
Related show

Commit Message

Kai Vehmanen Nov. 29, 2019, 2:37 p.m. UTC
Add additional check in hdmi_find_pcm_slot() to not return
a pcm index that points to unallocated pcm. This could happen
if codec driver is set up in codec->mst_no_extra_pcms mode.
On some platforms, this leads to a kernel oops in snd_ctl_notify(),
called via update_eld().

BugLink: https://github.com/thesofproject/linux/issues/1536
Fixes: 5398e94fb753 ALSA: hda - Add DP-MST support for NVIDIA codecs
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
---
 sound/pci/hda/patch_hdmi.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

Comments

Takashi Iwai Nov. 29, 2019, 2:43 p.m. UTC | #1
On Fri, 29 Nov 2019 15:37:55 +0100,
Kai Vehmanen wrote:
> 
> Add additional check in hdmi_find_pcm_slot() to not return
> a pcm index that points to unallocated pcm. This could happen
> if codec driver is set up in codec->mst_no_extra_pcms mode.
> On some platforms, this leads to a kernel oops in snd_ctl_notify(),
> called via update_eld().
> 
> BugLink: https://github.com/thesofproject/linux/issues/1536
> Fixes: 5398e94fb753 ALSA: hda - Add DP-MST support for NVIDIA codecs
> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>

Applied, thanks.


Takashi
Nikhil Mahale Dec. 2, 2019, 4:44 a.m. UTC | #2
Oh sorry again for this regression, Kai.

Originally my patches were developed with slightly older code which doesn't have your commit 2a2edfbbfee4 (ALSA: hda/hdmi - implement mst_no_extra_pcms flag), when I merge them with tot I did not notice codec->mst_no_extra_pcms mode.

This patch looks good to me.

Thanks,
Nikhil Mahale

On 11/29/19 8:13 PM, Takashi Iwai wrote:
> On Fri, 29 Nov 2019 15:37:55 +0100,
> Kai Vehmanen wrote:
>>
>> Add additional check in hdmi_find_pcm_slot() to not return
>> a pcm index that points to unallocated pcm. This could happen
>> if codec driver is set up in codec->mst_no_extra_pcms mode.
>> On some platforms, this leads to a kernel oops in snd_ctl_notify(),
>> called via update_eld().
>>
>> BugLink: https://github.com/thesofproject/linux/issues/1536
>> Fixes: 5398e94fb753 ALSA: hda - Add DP-MST support for NVIDIA codecs
>> Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
> 
> Applied, thanks.
> 
> 
> Takashi
> 

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------

Patch
diff mbox series

diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 373ca99b7a2f..c3940c197122 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1335,24 +1335,24 @@  static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
 	int i;
 
 	/*
-	 * generic_hdmi_build_pcms() allocates (num_nids + dev_num - 1)
-	 * number of pcms.
+	 * generic_hdmi_build_pcms() may allocate extra PCMs on some
+	 * platforms (with maximum of 'num_nids + dev_num - 1')
 	 *
 	 * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n
 	 * if m==0. This guarantees that dynamic pcm assignments are compatible
-	 * with the legacy static per_pin-pmc assignment that existed in the
+	 * with the legacy static per_pin-pcm assignment that existed in the
 	 * days before DP-MST.
 	 *
 	 * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)).
 	 */
-	if (per_pin->dev_id == 0 &&
-	    !test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
-		return per_pin->pin_nid_idx;
-
-	if (per_pin->dev_id != 0 &&
-	    !(test_bit(spec->num_nids + (per_pin->dev_id - 1),
-		&spec->pcm_bitmap))) {
-		return spec->num_nids + (per_pin->dev_id - 1);
+
+	if (per_pin->dev_id == 0) {
+		if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
+			return per_pin->pin_nid_idx;
+	} else {
+		i = spec->num_nids + (per_pin->dev_id - 1);
+		if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap)))
+			return i;
 	}
 
 	/* have a second try; check the area over num_nids */