forked from luck/tmp_suning_uos_patched
ALSA: hda - Handle error from get_response bus ops directly
... and drop bus->rirb_error flag. This makes the code simpler. We treat -EAGAIN from get_response ops as a special meaning: it allows the caller to retry after bus reset. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
d6eb9e3ec7
commit
cad372f1be
@ -146,7 +146,7 @@ static int codec_exec_verb(struct hdac_device *dev, unsigned int cmd,
|
||||
bus->no_response_fallback = 0;
|
||||
mutex_unlock(&bus->core.cmd_mutex);
|
||||
snd_hda_power_down_pm(codec);
|
||||
if (!codec_in_pm(codec) && res && err < 0 && bus->rirb_error) {
|
||||
if (!codec_in_pm(codec) && res && err == -EAGAIN) {
|
||||
if (bus->response_reset) {
|
||||
codec_dbg(codec,
|
||||
"resetting BUS due to fatal communication error\n");
|
||||
@ -436,9 +436,8 @@ static unsigned int get_num_devices(struct hda_codec *codec, hda_nid_t nid)
|
||||
get_wcaps_type(wcaps) != AC_WID_PIN)
|
||||
return 0;
|
||||
|
||||
parm = snd_hda_param_read(codec, nid, AC_PAR_DEVLIST_LEN);
|
||||
if (parm == -1 && codec->bus->rirb_error)
|
||||
parm = 0;
|
||||
if (_snd_hdac_read_parm(&codec->core, nid, AC_PAR_DEVLIST_LEN, &parm))
|
||||
return 0; /* error */
|
||||
return parm & AC_DEV_LIST_LEN_MASK;
|
||||
}
|
||||
|
||||
@ -467,10 +466,9 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
|
||||
|
||||
devices = 0;
|
||||
while (devices < dev_len) {
|
||||
parm = snd_hda_codec_read(codec, nid, 0,
|
||||
AC_VERB_GET_DEVICE_LIST, devices);
|
||||
if (parm == -1 && codec->bus->rirb_error)
|
||||
break;
|
||||
if (snd_hdac_read(&codec->core, nid,
|
||||
AC_VERB_GET_DEVICE_LIST, devices, &parm))
|
||||
break; /* error */
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
dev_list[devices] = (u8)parm;
|
||||
@ -520,8 +518,7 @@ static int _hda_bus_get_response(struct hdac_bus *_bus, unsigned int addr,
|
||||
unsigned int *res)
|
||||
{
|
||||
struct hda_bus *bus = container_of(_bus, struct hda_bus, core);
|
||||
*res = bus->ops.get_response(bus, addr);
|
||||
return bus->rirb_error ? -EIO : 0;
|
||||
return bus->ops.get_response(bus, addr, res);
|
||||
}
|
||||
|
||||
static const struct hdac_bus_ops bus_ops = {
|
||||
|
@ -45,7 +45,7 @@ struct hda_bus_ops {
|
||||
/* send a single command */
|
||||
int (*command)(struct hda_bus *bus, unsigned int cmd);
|
||||
/* get a response from the last command */
|
||||
unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr);
|
||||
int (*get_response)(struct hda_bus *bus, unsigned int addr, unsigned int *res);
|
||||
/* free the private data */
|
||||
void (*private_free)(struct hda_bus *);
|
||||
/* attach a PCM stream */
|
||||
@ -92,7 +92,6 @@ struct hda_bus {
|
||||
unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
|
||||
/* status for codec/controller */
|
||||
unsigned int shutdown :1; /* being unloaded */
|
||||
unsigned int rirb_error:1; /* error in codec communication */
|
||||
unsigned int response_reset:1; /* controller was reset */
|
||||
unsigned int in_reset:1; /* during reset operation */
|
||||
unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
|
||||
|
@ -1156,8 +1156,8 @@ static void azx_update_rirb(struct azx *chip)
|
||||
}
|
||||
|
||||
/* receive a response */
|
||||
static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
||||
unsigned int addr)
|
||||
static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr,
|
||||
unsigned int *res)
|
||||
{
|
||||
struct azx *chip = bus->private_data;
|
||||
unsigned long timeout;
|
||||
@ -1175,11 +1175,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
||||
}
|
||||
if (!chip->rirb.cmds[addr]) {
|
||||
smp_rmb();
|
||||
bus->rirb_error = 0;
|
||||
|
||||
if (!do_poll)
|
||||
chip->poll_count = 0;
|
||||
return chip->rirb.res[addr]; /* the last value */
|
||||
if (res)
|
||||
*res = chip->rirb.res[addr]; /* the last value */
|
||||
return 0;
|
||||
}
|
||||
if (time_after(jiffies, timeout))
|
||||
break;
|
||||
@ -1192,7 +1193,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
||||
}
|
||||
|
||||
if (bus->no_response_fallback)
|
||||
return -1;
|
||||
return -EIO;
|
||||
|
||||
if (!chip->polling_mode && chip->poll_count < 2) {
|
||||
dev_dbg(chip->card->dev,
|
||||
@ -1217,10 +1218,8 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
||||
"No response from codec, disabling MSI: last cmd=0x%08x\n",
|
||||
chip->last_cmd[addr]);
|
||||
if (chip->ops->disable_msi_reset_irq(chip) &&
|
||||
chip->ops->disable_msi_reset_irq(chip) < 0) {
|
||||
bus->rirb_error = 1;
|
||||
return -1;
|
||||
}
|
||||
chip->ops->disable_msi_reset_irq(chip) < 0)
|
||||
return -EIO;
|
||||
goto again;
|
||||
}
|
||||
|
||||
@ -1229,16 +1228,15 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
||||
* phase, this is likely an access to a non-existing codec
|
||||
* slot. Better to return an error and reset the system.
|
||||
*/
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* a fatal communication error; need either to reset or to fallback
|
||||
* to the single_cmd mode
|
||||
*/
|
||||
bus->rirb_error = 1;
|
||||
if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) {
|
||||
bus->response_reset = 1;
|
||||
return -1; /* give a chance to retry */
|
||||
return -EAGAIN; /* give a chance to retry */
|
||||
}
|
||||
|
||||
dev_err(chip->card->dev,
|
||||
@ -1250,7 +1248,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
|
||||
azx_free_cmd_io(chip);
|
||||
/* disable unsolicited responses */
|
||||
azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL);
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1291,7 +1289,6 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
|
||||
unsigned int addr = azx_command_addr(val);
|
||||
int timeout = 50;
|
||||
|
||||
bus->rirb_error = 0;
|
||||
while (timeout--) {
|
||||
/* check ICB busy bit */
|
||||
if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
|
||||
@ -1313,11 +1310,14 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
|
||||
}
|
||||
|
||||
/* receive a response */
|
||||
static unsigned int azx_single_get_response(struct hda_bus *bus,
|
||||
unsigned int addr)
|
||||
static int azx_single_get_response(struct hda_bus *bus, unsigned int addr,
|
||||
unsigned int *res)
|
||||
{
|
||||
struct azx *chip = bus->private_data;
|
||||
return chip->rirb.res[addr];
|
||||
|
||||
if (res)
|
||||
*res = chip->rirb.res[addr];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1342,16 +1342,16 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
|
||||
}
|
||||
|
||||
/* get a response */
|
||||
static unsigned int azx_get_response(struct hda_bus *bus,
|
||||
unsigned int addr)
|
||||
static int azx_get_response(struct hda_bus *bus, unsigned int addr,
|
||||
unsigned int *res)
|
||||
{
|
||||
struct azx *chip = bus->private_data;
|
||||
if (chip->disabled)
|
||||
return 0;
|
||||
if (chip->single_cmd)
|
||||
return azx_single_get_response(bus, addr);
|
||||
return azx_single_get_response(bus, addr, res);
|
||||
else
|
||||
return azx_rirb_get_response(bus, addr);
|
||||
return azx_rirb_get_response(bus, addr, res);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
||||
@ -1762,15 +1762,16 @@ static int probe_codec(struct azx *chip, int addr)
|
||||
{
|
||||
unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
|
||||
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
|
||||
int err;
|
||||
unsigned int res;
|
||||
|
||||
mutex_lock(&chip->bus->core.cmd_mutex);
|
||||
chip->probing = 1;
|
||||
azx_send_cmd(chip->bus, cmd);
|
||||
res = azx_get_response(chip->bus, addr);
|
||||
err = azx_get_response(chip->bus, addr, &res);
|
||||
chip->probing = 0;
|
||||
mutex_unlock(&chip->bus->core.cmd_mutex);
|
||||
if (res == -1)
|
||||
if (err < 0 || res == -1)
|
||||
return -EIO;
|
||||
dev_dbg(chip->card->dev, "codec #%d probed OK\n", addr);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user