aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-03-24 02:36:09 -0400
committerTakashi Iwai <tiwai@suse.de>2009-04-21 05:10:44 -0400
commitb613291fb21a2d74eb8323d97fe9aa5d281b306c (patch)
tree142afbf9e2fa31b852c3fbfe1bb4dafd4977fb98 /sound/pci
parent92c7c8a7d6e03eb4c0a3c5888e35dbc45f24744c (diff)
ALSA: hda - Retry codec-verbs at errors
The current error-recovery scheme for the codec communication errors doesn't work always well. Especially falling back to the single-command mode causes the fatal problem on many systems. In this patch, the problematic verb is re-issued again after the error (even with polling mode) instead of the single-cmd mode. The single-cmd mode will be used only when specified via the command option explicitly, mainly just for testing. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_codec.c17
-rw-r--r--sound/pci/hda/hda_codec.h1
-rw-r--r--sound/pci/hda/hda_intel.c19
3 files changed, 24 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 3d8bf39e6d98..1736ccbebc72 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -174,14 +174,23 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
174 unsigned int verb, unsigned int parm) 174 unsigned int verb, unsigned int parm)
175{ 175{
176 struct hda_bus *bus = codec->bus; 176 struct hda_bus *bus = codec->bus;
177 unsigned int res; 177 unsigned int cmd, res;
178 int repeated = 0;
178 179
179 res = make_codec_cmd(codec, nid, direct, verb, parm); 180 cmd = make_codec_cmd(codec, nid, direct, verb, parm);
180 snd_hda_power_up(codec); 181 snd_hda_power_up(codec);
181 mutex_lock(&bus->cmd_mutex); 182 mutex_lock(&bus->cmd_mutex);
182 if (!bus->ops.command(bus, res)) 183 again:
184 if (!bus->ops.command(bus, cmd)) {
183 res = bus->ops.get_response(bus); 185 res = bus->ops.get_response(bus);
184 else 186 if (res == -1 && bus->rirb_error) {
187 if (repeated++ < 1) {
188 snd_printd(KERN_WARNING "hda_codec: "
189 "Trying verb 0x%08x again\n", cmd);
190 goto again;
191 }
192 }
193 } else
185 res = (unsigned int)-1; 194 res = (unsigned int)-1;
186 mutex_unlock(&bus->cmd_mutex); 195 mutex_unlock(&bus->cmd_mutex);
187 snd_hda_power_down(codec); 196 snd_hda_power_down(codec);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 2fdecf4b0eb6..cd8979c7670b 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -623,6 +623,7 @@ struct hda_bus {
623 /* misc op flags */ 623 /* misc op flags */
624 unsigned int needs_damn_long_delay :1; 624 unsigned int needs_damn_long_delay :1;
625 unsigned int shutdown :1; /* being unloaded */ 625 unsigned int shutdown :1; /* being unloaded */
626 unsigned int rirb_error:1; /* error in codec communication */
626}; 627};
627 628
628/* 629/*
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 30829ee920c3..803b72098ed3 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -604,6 +604,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
604 } 604 }
605 if (!chip->rirb.cmds) { 605 if (!chip->rirb.cmds) {
606 smp_rmb(); 606 smp_rmb();
607 bus->rirb_error = 0;
607 return chip->rirb.res; /* the last value */ 608 return chip->rirb.res; /* the last value */
608 } 609 }
609 if (time_after(jiffies, timeout)) 610 if (time_after(jiffies, timeout))
@@ -623,8 +624,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
623 chip->irq = -1; 624 chip->irq = -1;
624 pci_disable_msi(chip->pci); 625 pci_disable_msi(chip->pci);
625 chip->msi = 0; 626 chip->msi = 0;
626 if (azx_acquire_irq(chip, 1) < 0) 627 if (azx_acquire_irq(chip, 1) < 0) {
628 bus->rirb_error = 1;
627 return -1; 629 return -1;
630 }
628 goto again; 631 goto again;
629 } 632 }
630 633
@@ -644,14 +647,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
644 return -1; 647 return -1;
645 } 648 }
646 649
647 snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " 650 snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): "
648 "switching to single_cmd mode: last cmd=0x%08x\n", 651 "last cmd=0x%08x\n", chip->last_cmd);
649 chip->last_cmd); 652 spin_lock_irq(&chip->reg_lock);
650 chip->rirb.rp = azx_readb(chip, RIRBWP); 653 chip->rirb.cmds = 0; /* reset the index */
651 chip->rirb.cmds = 0; 654 bus->rirb_error = 1;
652 /* switch to single_cmd mode */ 655 spin_unlock_irq(&chip->reg_lock);
653 chip->single_cmd = 1;
654 azx_free_cmd_io(chip);
655 return -1; 656 return -1;
656} 657}
657 658