ALSA: hda - Check CORB overflow
Add an overflow check of CORB in HD-audio controller and codec drivers so that flood of sequential writes would work properly. In the controller side, add a check of CORB read-pointer to make returning -EAGAIN when it's full. Meanwhile in the codec side, when -EAGAIN error is received, it retries the write after flushing the pending verbs (calling get_response() essentially does it). Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
aa88a3553e
commit
3bcce5c0d9
2 changed files with 17 additions and 4 deletions
|
@ -222,8 +222,14 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
|
|||
again:
|
||||
snd_hda_power_up(codec);
|
||||
mutex_lock(&bus->cmd_mutex);
|
||||
trace_hda_send_cmd(codec, cmd);
|
||||
err = bus->ops.command(bus, cmd);
|
||||
for (;;) {
|
||||
trace_hda_send_cmd(codec, cmd);
|
||||
err = bus->ops.command(bus, cmd);
|
||||
if (err != -EAGAIN)
|
||||
break;
|
||||
/* process pending verbs */
|
||||
bus->ops.get_response(bus, codec->addr);
|
||||
}
|
||||
if (!err && res) {
|
||||
*res = bus->ops.get_response(bus, codec->addr);
|
||||
trace_hda_get_response(codec, *res);
|
||||
|
|
|
@ -797,7 +797,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
|
|||
{
|
||||
struct azx *chip = bus->private_data;
|
||||
unsigned int addr = azx_command_addr(val);
|
||||
unsigned int wp;
|
||||
unsigned int wp, rp;
|
||||
|
||||
spin_lock_irq(&chip->reg_lock);
|
||||
|
||||
|
@ -806,11 +806,18 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
|
|||
if (wp == 0xffff) {
|
||||
/* something wrong, controller likely turned to D3 */
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
wp++;
|
||||
wp %= ICH6_MAX_CORB_ENTRIES;
|
||||
|
||||
rp = azx_readw(chip, CORBRP);
|
||||
if (wp == rp) {
|
||||
/* oops, it's full */
|
||||
spin_unlock_irq(&chip->reg_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
chip->rirb.cmds[addr]++;
|
||||
chip->corb.buf[wp] = cpu_to_le32(val);
|
||||
azx_writel(chip, CORBWP, wp);
|
||||
|
|
Loading…
Reference in a new issue