diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c177192..0e292dc 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -337,6 +337,7 @@ struct azx { unsigned int initialized :1; unsigned int single_cmd :1; unsigned int polling_mode :1; + unsigned int msi :1; }; /* driver types */ @@ -397,6 +398,7 @@ static char *driver_short_names[] __devinitdata = { */ #define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0) +static int azx_acquire_irq(struct azx *chip, int do_disconnect); /* * Interface for HD codec @@ -536,6 +538,18 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) schedule_timeout_interruptible(1); } while (time_after_eq(timeout, jiffies)); + 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; + goto again; + } + if (!chip->polling_mode) { snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " "switching to polling mode...\n"); @@ -1364,6 +1378,20 @@ static int __devinit azx_init_stream(struct azx *chip) return 0; } +static int azx_acquire_irq(struct azx *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); + if (do_disconnect) + snd_card_disconnect(chip->card); + return -1; + } + chip->irq = chip->pci->irq; + return 0; +} + #ifdef CONFIG_PM /* @@ -1385,7 +1413,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) free_irq(chip->irq, chip); chip->irq = -1; } - if (!disable_msi) + if (chip->msi) pci_disable_msi(chip->pci); pci_disable_device(pci); pci_save_state(pci); @@ -1407,16 +1435,11 @@ static int azx_resume(struct pci_dev *pci) return -EIO; } pci_set_master(pci); - if (!disable_msi) - pci_enable_msi(pci); - if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, - "HDA Intel", chip)) { - printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " - "disabling device\n", pci->irq); - snd_card_disconnect(card); + if (chip->msi) + if (pci_enable_msi(pci) < 0) + chip->msi = 0; + if (azx_acquire_irq(chip, 1) < 0) return -EIO; - } - chip->irq = pci->irq; azx_init_chip(chip); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); @@ -1452,7 +1475,7 @@ static int azx_free(struct azx *chip) synchronize_irq(chip->irq); free_irq(chip->irq, (void*)chip); } - if (!disable_msi) + if (chip->msi) pci_disable_msi(chip->pci); if (chip->remap_addr) iounmap(chip->remap_addr); @@ -1508,6 +1531,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, 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; @@ -1537,16 +1561,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, 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, IRQF_DISABLED|IRQF_SHARED, - "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); |