ALSA: hda - Handle error from get_response bus ops directly
authorTakashi Iwai <tiwai@suse.de>
Wed, 25 Mar 2015 16:57:00 +0000 (17:57 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 14 Apr 2015 12:54:57 +0000 (14:54 +0200)
... 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>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_controller.c

index e70a7fb393dd5d441fef9c9316ee417c46d9606b..c13d5c3e1d03f468edd01592062cae0635706422 100644 (file)
@@ -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 = {
index 9075ac28dc4b03ad1f9e1235adbbd7f6775bd22f..fc4f76188a1db03b1aa1fe2abcb7bf467355021c 100644 (file)
@@ -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 */
index 26ce990592a04d102dde33ac41ad3a9edfc870a5..b4474e27631d6ef932421c1263fda1db0aff6be9 100644 (file)
@@ -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;