Commit 5f2cb361 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda: Unify get_response handling



Now most of the get_response handling became quite similar between
HDA-core and legacy drivers, and the only differences are:

- the handling of extra-long polling delay for some codecs
- the debug message for the stalled communication

and both are worth to share in the common code.

This patch unifies the code into snd_hdac_bus_get_response(), and use
this from the legacy get_response callback.  It results in a good
amount of code reduction in the end.

Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20191212191101.19517-3-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 89698ed5
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ struct hda_bus {
	DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);

	/* misc op flags */
	unsigned int needs_damn_long_delay :1;
	unsigned int allow_bus_reset:1;	/* allow bus reset at fatal error */
	/* status for codec/controller */
	unsigned int shutdown :1;	/* being unloaded */
+1 −0
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ struct hdac_bus {
	bool reverse_assign:1;		/* assign devices in reverse order */
	bool corbrp_self_clear:1;	/* CORBRP clears itself after reset */
	bool polling_mode:1;
	bool needs_damn_long_delay:1;

	int poll_count;

+10 −1
Original line number Diff line number Diff line
@@ -242,6 +242,7 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
	unsigned long timeout;
	unsigned long loopcounter;
	wait_queue_entry_t wait;
	bool warned = false;

	init_wait_entry(&wait, 0);
	timeout = jiffies + msecs_to_jiffies(1000);
@@ -264,9 +265,17 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
		spin_unlock_irq(&bus->reg_lock);
		if (time_after(jiffies, timeout))
			break;
#define LOOP_COUNT_MAX	3000
		if (!bus->polling_mode) {
			schedule_timeout(msecs_to_jiffies(2));
		} else if (loopcounter > 3000) {
		} else if (bus->needs_damn_long_delay ||
			   loopcounter > LOOP_COUNT_MAX) {
			if (loopcounter > LOOP_COUNT_MAX && !warned) {
				dev_dbg_ratelimited(bus->dev,
						    "too slow response, last cmd=%#08x\n",
						    bus->last_cmd[addr]);
				warned = true;
			}
			msleep(2); /* temporary workaround */
		} else {
			udelay(10);
+4 −45
Original line number Diff line number Diff line
@@ -784,53 +784,12 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
{
	struct azx *chip = bus_to_azx(bus);
	struct hda_bus *hbus = &chip->bus;
	unsigned long timeout;
	unsigned long loopcounter;
	wait_queue_entry_t wait;
	bool warned = false;
	int err;

	init_wait_entry(&wait, 0);
 again:
	timeout = jiffies + msecs_to_jiffies(1000);

	for (loopcounter = 0;; loopcounter++) {
		spin_lock_irq(&bus->reg_lock);
		if (!bus->polling_mode)
			prepare_to_wait(&bus->rirb_wq, &wait,
					TASK_UNINTERRUPTIBLE);
		if (bus->polling_mode)
			snd_hdac_bus_update_rirb(bus);
		if (!bus->rirb.cmds[addr]) {
			if (res)
				*res = bus->rirb.res[addr]; /* the last value */
			if (!bus->polling_mode)
				finish_wait(&bus->rirb_wq, &wait);
			spin_unlock_irq(&bus->reg_lock);
	err = snd_hdac_bus_get_response(bus, addr, res);
	if (!err)
		return 0;
		}
		spin_unlock_irq(&bus->reg_lock);
		if (time_after(jiffies, timeout))
			break;
#define LOOP_COUNT_MAX	3000
		if (!bus->polling_mode) {
			schedule_timeout(msecs_to_jiffies(2));
		} else if (hbus->needs_damn_long_delay ||
		    loopcounter > LOOP_COUNT_MAX) {
			if (loopcounter > LOOP_COUNT_MAX && !warned) {
				dev_dbg_ratelimited(chip->card->dev,
						    "too slow response, last cmd=%#08x\n",
						    bus->last_cmd[addr]);
				warned = true;
			}
			msleep(2); /* temporary workaround */
		} else {
			udelay(10);
			cond_resched();
		}
	}

	if (!bus->polling_mode)
		finish_wait(&bus->rirb_wq, &wait);

	if (hbus->no_response_fallback)
		return -EIO;
+1 −1
Original line number Diff line number Diff line
@@ -1809,7 +1809,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,

	if (chip->driver_type == AZX_DRIVER_NVIDIA) {
		dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
		chip->bus.needs_damn_long_delay = 1;
		chip->bus.core.needs_damn_long_delay = 1;
	}

	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
Loading