소스 검색

ALSA: hda - Do not accept responses from non-existing codecs

While looking into some spurious responses, I found that the addr value was
treated a bit inconsistent: values 8..0xf will be treated as codec 0 and
values 0..7 will be treated as no error regardless of whether there is a codec
there, or not.

With this patch, all non-existing codecs will be treated equally.
In addition, printing rp and wp could help figuring out if the wp value is
reported wrongly from the controller or if something else is wrong.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
David Henningsson 11 년 전
부모
커밋
3d692451ea
1개의 변경된 파일9개의 추가작업 그리고 14개의 파일을 삭제
  1. 9 14
      sound/pci/hda/hda_intel.c

+ 9 - 14
sound/pci/hda/hda_intel.c

@@ -834,18 +834,6 @@ static unsigned int azx_command_addr(u32 cmd)
 	return addr;
 	return addr;
 }
 }
 
 
-static unsigned int azx_response_addr(u32 res)
-{
-	unsigned int addr = res & 0xf;
-
-	if (addr >= AZX_MAX_CODECS) {
-		snd_BUG();
-		addr = 0;
-	}
-
-	return addr;
-}
-
 /* send a command */
 /* send a command */
 static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 {
 {
@@ -907,8 +895,15 @@ static void azx_update_rirb(struct azx *chip)
 		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
 		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
 		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
 		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
 		res = le32_to_cpu(chip->rirb.buf[rp]);
 		res = le32_to_cpu(chip->rirb.buf[rp]);
-		addr = azx_response_addr(res_ex);
-		if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+		addr = res_ex & 0xf;
+		if ((addr >= AZX_MAX_CODECS) || !(chip->codec_mask & (1 << addr))) {
+			snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, rp = %d, wp = %d",
+				   pci_name(chip->pci),
+				   res, res_ex,
+				   chip->rirb.rp, wp);
+			snd_BUG();
+		}
+		else if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
 		else if (chip->rirb.cmds[addr]) {
 		else if (chip->rirb.cmds[addr]) {
 			chip->rirb.res[addr] = res;
 			chip->rirb.res[addr] = res;