Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cad372f1 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent d6eb9e3e
Loading
Loading
Loading
Loading
+7 −10
Original line number Diff line number Diff line
@@ -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 = {
+1 −2
Original line number Diff line number Diff line
@@ -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 */
+24 −23
Original line number Diff line number Diff line
@@ -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;