[PATCH] [UBUNTU:sound/pci/hda/] Backport HDA fixes for MSI availability and polling mode for CORB/RIRB communication

crimsun at fungus.sh.nu crimsun at fungus.sh.nu
Tue Oct 24 17:01:43 UTC 2006


From f98c60447f590003abb3982c20f4054b5b07ff37 Mon Sep 17 00:00:00 2001
From: Daniel T. Chen <crimsun at garnish.localdomain>
Date: Tue, 24 Oct 2006 12:29:07 -0400
Subject: [PATCH] [UBUNTU:sound/pci/hda/] Backport HDA fixes for MSI availability and polling mode for CORB/RIRB communication

UpstreamStatus: Added in upstream alsa-kernel hg changesets:
		revision 57: 6e2ec3b30ff5 [http://hg-mirror.alsa-project.org/alsa-kernel?fd=71460c45addf;file=pci/hda/hda_intel.c;style=raw ]
		revision 44: ecaf8e5d9144 [http://hg-mirror.alsa-project.org/alsa-kernel?fd=2794c3d0b8fc;file=pci/hda/hda_intel.c;style=raw ]

These two commits from Takashi Iwai make the communication handling
more robust:

Check for MSI, and disable it automatically when it's not available.
This is necessary because MSI seems broken on some hardware, and
because the kernel doesn't know precisely, the sound driver needs to
disable MSI manually.

Also, switch to polling mode for CORB/RIRB communication if the
irq-driven mode doesn't work, and finally fall back to single_cmd
mode.

This commit is suitable for Dapper, Edgy, and Edgy+1 (but will
require typedef tweaks for the latter two).

Signed-off-by: Daniel T Chen <crimsun at ubuntu.com>
---
 sound/pci/hda/hda_intel.c |   69 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 8839c70..0f823aa 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -330,6 +330,8 @@ struct snd_azx {
 	int position_fix;
 	unsigned int initialized: 1;
 	unsigned int single_cmd: 1;
+	unsigned int polling_mode: 1;
+	unsigned int msi :1;
 };
 
 /* driver types */
@@ -388,6 +390,7 @@ #define get_azx_dev(substream) (azx_dev_
  */
 #define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
 
+static int azx_acquire_irq(azx_t *chip, int do_disconnect);
 
 /*
  * Interface for HD codec
@@ -514,8 +517,34 @@ static unsigned int azx_rirb_get_respons
 	azx_t *chip = codec->bus->private_data;
 	int timeout = 50;
 
-	while (chip->rirb.cmds) {
+	for (;;) {
+		if (chip->polling_mode) {
+			spin_lock_irq(&chip->reg_lock);
+			azx_update_rirb(chip);
+			spin_unlock_irq(&chip->reg_lock);
+		}
+		if (! chip->rirb.cmds)
+			break;
 		if (! --timeout) {
+			if (chip->msi) {
+				snd_printk(KERN_WARNING "hda_intel: No response from codec, "
+					"disabling MSI...\n");
+				free_irq(chip->irq, chip);
+				chip->irq = -1;
+				pci_disable_msi(chip->pci);
+				chip->msi = 0;
+				if (azx_acquire_irq(chip, 1) < 0)
+					return -1;
+				continue;
+			}
+			if (! chip->polling_mode) {
+				snd_printk(KERN_WARNING "hda_intel: "
+					   "azx_get_response timeout, "
+					   "switching to polling mode...\n");
+				chip->polling_mode = 1;
+				timeout = 50;
+				continue;
+			}
 			snd_printk(KERN_ERR
 					"hda_intel: azx_get_response timeout, "
 					"switching to single_cmd mode...\n");
@@ -1341,6 +1370,18 @@ static int __devinit azx_init_stream(azx
 	return 0;
 }
 
+static int azx_acquire_irq(azx_t *chip, int do_disconnect)
+{
+	if (request_irq(chip->pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
+			"HDA Intel", chip)) {
+		printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
+		       "disabling device\n", chip->pci->irq);
+		return -1;
+	}
+	chip->irq = chip->pci->irq;
+	return 0;
+}
+
 
 #ifdef CONFIG_PM
 /*
@@ -1359,7 +1400,7 @@ static int azx_suspend(struct pci_dev *p
 	azx_free_cmd_io(chip);
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	if (!disable_msi)
+	if (chip->msi)
 		pci_disable_msi(chip->pci);
 	pci_disable_device(pci);
 	pci_save_state(pci);
@@ -1373,13 +1414,12 @@ static int azx_resume(struct pci_dev *pc
 
 	pci_restore_state(pci);
 	pci_enable_device(pci);
-	if (!disable_msi)
-		pci_enable_msi(pci);
-	/* FIXME: need proper error handling */
-	request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
-		"HDA Intel", chip);
-	chip->irq = pci->irq;
 	pci_set_master(pci);
+	if (chip->msi)
+		if (pci_enable_msi(pci) < 0)
+			chip->msi = 0;
+	if (azx_acquire_irq(chip, 1) < 0)
+		return -EIO;
 	azx_init_chip(chip);
 	snd_hda_resume(chip->bus);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1415,7 +1455,7 @@ static int azx_free(azx_t *chip)
 
 	if (chip->irq >= 0) {
 		free_irq(chip->irq, (void*)chip);
-		if (!disable_msi)
+		if (chip->msi)
 			pci_disable_msi(chip->pci);
 	}
 	if (chip->remap_addr)
@@ -1472,6 +1512,7 @@ static int __devinit azx_create(snd_card
 	chip->pci = pci;
 	chip->irq = -1;
 	chip->driver_type = driver_type;
+	chip->msi = !disable_msi;
 
 	chip->position_fix = position_fix;
 	chip->single_cmd = single_cmd;
@@ -1500,16 +1541,14 @@ #endif
 		goto errout;
 	}
 
-	if (!disable_msi)
-		pci_enable_msi(pci);
+	if (chip->msi)
+		if (pci_enable_msi(pci) < 0)
+			chip->msi = 0;
 
-	if (request_irq(pci->irq, azx_interrupt, SA_INTERRUPT|SA_SHIRQ,
-			"HDA Intel", (void*)chip)) {
-		snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
+	if (azx_acquire_irq(chip, 0) < 0) {
 		err = -EBUSY;
 		goto errout;
 	}
-	chip->irq = pci->irq;
 
 	pci_set_master(pci);
 	synchronize_irq(chip->irq);
-- 
1.4.1

-- 
Daniel T. Chen            crimsun at ubuntu.com
GPG key:  0xC88ABDA3
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20061024/81df0965/attachment.pgp>


More information about the kernel-team mailing list