From 30b35399ceb2398d05837863476dcb12f12f3a82 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Oct 2006 18:52:53 +0200 Subject: [PATCH] [ALSA] Various fixes for suspend/resume of ALSA PCI drivers - Check the return value of pci_enable_device() and request_irq() in the suspend. If any error occurs there, disable the device using snd_card_disconnect(). - Call pci_set_power_state() properly with pci_choose_state(). - Fix the order to call pci_set_power_state(). - Removed obsolete house-made PM codes in some drivers. Signed-off-by: Takashi Iwai Signed-off-by: Jaroslav Kysela --- sound/pci/ali5451/ali5451.c | 11 +++- sound/pci/als300.c | 11 ++-- sound/pci/als4000.c | 11 ++-- sound/pci/atiixp.c | 11 ++-- sound/pci/atiixp_modem.c | 11 ++-- sound/pci/azt3328.c | 11 ++-- sound/pci/cmipci.c | 11 ++-- sound/pci/cs4281.c | 9 +++- sound/pci/cs46xx/cs46xx_lib.c | 11 +++- sound/pci/cs5535audio/cs5535audio_pm.c | 11 +++- sound/pci/emu10k1/emu10k1.c | 13 +++-- sound/pci/ens1370.c | 12 +++-- sound/pci/es1938.c | 29 +++++++++-- sound/pci/es1968.c | 71 ++++---------------------- sound/pci/fm801.c | 11 ++-- sound/pci/hda/hda_intel.c | 33 ++++++++---- sound/pci/intel8x0.c | 23 +++++++-- sound/pci/intel8x0m.c | 23 +++++++-- sound/pci/maestro3.c | 13 +++-- sound/pci/nm256/nm256.c | 12 ++++- sound/pci/riptide/riptide.c | 11 ++-- sound/pci/trident/trident_main.c | 18 +++---- sound/pci/via82xx.c | 12 +++-- sound/pci/via82xx_modem.c | 12 +++-- sound/pci/vx222/vx222.c | 11 ++-- sound/pci/ymfpci/ymfpci_main.c | 9 +++- 26 files changed, 276 insertions(+), 145 deletions(-) diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 13a8cefa7749..a7edd56542d4 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -2032,8 +2032,10 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state) outl(0xffffffff, ALI_REG(chip, ALI_STOP)); spin_unlock_irq(&chip->reg_lock); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2048,8 +2050,15 @@ static int ali_resume(struct pci_dev *pci) if (! im) return 0; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "ali5451: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); spin_lock_irq(&chip->reg_lock); diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 9b16c299f0a9..95f70f3cc37e 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -768,9 +768,9 @@ static int snd_als300_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -779,9 +779,14 @@ static int snd_als300_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_als300 *chip = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "als300: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_als300_init(chip); diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 15fc3929b5f7..8fb55d3b454b 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -804,9 +804,9 @@ static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm); snd_sbmixer_suspend(chip); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -816,9 +816,14 @@ static int snd_als4000_resume(struct pci_dev *pci) struct snd_card_als4000 *acard = card->private_data; struct snd_sb *chip = acard->chip; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "als4000: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_als4000_configure(chip); diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 3e8fc5a0006a..e3e99f396711 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1442,9 +1442,9 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) snd_atiixp_aclink_down(chip); snd_atiixp_chip_stop(chip); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1454,9 +1454,14 @@ static int snd_atiixp_resume(struct pci_dev *pci) struct atiixp *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "atiixp: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_atiixp_aclink_reset(chip); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index c5dda1bf3d46..dc54f2c68ed7 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1128,9 +1128,9 @@ static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state) snd_atiixp_aclink_down(chip); snd_atiixp_chip_stop(chip); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1140,9 +1140,14 @@ static int snd_atiixp_resume(struct pci_dev *pci) struct atiixp_modem *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "atiixp-modem: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_atiixp_aclink_reset(chip); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 692f203d65d8..2414ee630756 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1903,9 +1903,9 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++) chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1916,9 +1916,14 @@ snd_azf3328_resume(struct pci_dev *pci) struct snd_azf3328 *chip = card->private_data; int reg; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "azt3328: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++) diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1f7e71083069..0093cd1f92db 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -3122,9 +3122,9 @@ static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) /* disable ints */ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -3134,9 +3134,14 @@ static int snd_cmipci_resume(struct pci_dev *pci) struct cmipci *cm = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cmipci: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* reset / initialize to a sane state */ diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index d54924e60bb1..0905fa88129d 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -2050,6 +2050,7 @@ static int cs4281_suspend(struct pci_dev *pci, pm_message_t state) pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2060,8 +2061,14 @@ static int cs4281_resume(struct pci_dev *pci) unsigned int i; u32 ulCLK; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cs4281: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1); diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 16d4ebf2a33f..2807b9756ef0 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -3687,8 +3687,10 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) /* disable CLKRUN */ chip->active_ctrl(chip, -chip->amplifier); chip->amplifier = amp_saved; /* restore the status */ + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -3698,9 +3700,16 @@ int snd_cs46xx_resume(struct pci_dev *pci) struct snd_cs46xx *chip = card->private_data; int amp_saved; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cs46xx: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); + amp_saved = chip->amplifier; chip->amplifier = 0; chip->active_ctrl(chip, 1); /* force to on */ diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index aad0e69db9c1..3e4d198a4502 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c @@ -73,9 +73,10 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) snd_ac97_suspend(cs5535au->ac97); /* save important regs, then disable aclink in hw */ snd_cs5535audio_stop_hardware(cs5535au); + pci_disable_device(pci); pci_save_state(pci); - + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -87,8 +88,14 @@ int snd_cs5535audio_resume(struct pci_dev *pci) int timeout; int i; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cs5535audio: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* set LNK_WRM_RST to reset AC link */ diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 493ec0816bb3..55caf341933a 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -226,9 +226,9 @@ static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) snd_emu10k1_done(emu); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -237,11 +237,16 @@ static int snd_emu10k1_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_emu10k1 *emu = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "emu10k1: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); - + snd_emu10k1_resume_init(emu); snd_emu10k1_efx_resume(emu); snd_ac97_resume(emu->ac97); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 8cb4fb2412db..d2a811f222c9 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -2072,9 +2072,10 @@ static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state) udelay(100); snd_ak4531_suspend(ensoniq->u.es1370.ak4531); #endif - pci_set_power_state(pci, PCI_D3hot); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2083,9 +2084,14 @@ static int snd_ensoniq_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct ensoniq *ensoniq = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR DRIVER_NAME ": pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_ensoniq_chip_init(ensoniq); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 2da988f78ba7..1a8d36df4b5d 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -1481,10 +1481,14 @@ static int es1938_suspend(struct pci_dev *pci, pm_message_t state) *d = snd_es1938_reg_read(chip, *s); outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */ - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1494,10 +1498,22 @@ static int es1938_resume(struct pci_dev *pci) struct es1938 *chip = card->private_data; unsigned char *s, *d; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); - request_irq(pci->irq, snd_es1938_interrupt, - IRQF_DISABLED|IRQF_SHARED, "ES1938", chip); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "es1938: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + + if (request_irq(pci->irq, snd_es1938_interrupt, + IRQF_DISABLED|IRQF_SHARED, "ES1938", chip)) { + printk(KERN_ERR "es1938: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; snd_es1938_chip_init(chip); @@ -1556,8 +1572,10 @@ static int snd_es1938_free(struct es1938 *chip) snd_es1938_free_gameport(chip); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + } pci_release_regions(chip->pci); pci_disable_device(chip->pci); kfree(chip); @@ -1602,6 +1620,7 @@ static int __devinit snd_es1938_create(struct snd_card *card, spin_lock_init(&chip->mixer_lock); chip->card = card; chip->pci = pci; + chip->irq = -1; if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) { kfree(chip); pci_disable_device(pci); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index b9d723c7e1db..092da53e1464 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -432,46 +432,6 @@ MODULE_PARM_DESC(joystick, "Enable joystick."); #define ESM_MODE_PLAY 0 #define ESM_MODE_CAPTURE 1 -/* acpi states */ -enum { - ACPI_D0=0, - ACPI_D1, - ACPI_D2, - ACPI_D3 -}; - -/* bits in the acpi masks */ -#define ACPI_12MHZ ( 1 << 15) -#define ACPI_24MHZ ( 1 << 14) -#define ACPI_978 ( 1 << 13) -#define ACPI_SPDIF ( 1 << 12) -#define ACPI_GLUE ( 1 << 11) -#define ACPI__10 ( 1 << 10) /* reserved */ -#define ACPI_PCIINT ( 1 << 9) -#define ACPI_HV ( 1 << 8) /* hardware volume */ -#define ACPI_GPIO ( 1 << 7) -#define ACPI_ASSP ( 1 << 6) -#define ACPI_SB ( 1 << 5) /* sb emul */ -#define ACPI_FM ( 1 << 4) /* fm emul */ -#define ACPI_RB ( 1 << 3) /* ringbus / aclink */ -#define ACPI_MIDI ( 1 << 2) -#define ACPI_GP ( 1 << 1) /* game port */ -#define ACPI_WP ( 1 << 0) /* wave processor */ - -#define ACPI_ALL (0xffff) -#define ACPI_SLEEP (~(ACPI_SPDIF|ACPI_ASSP|ACPI_SB|ACPI_FM| \ - ACPI_MIDI|ACPI_GP|ACPI_WP)) -#define ACPI_NONE (ACPI__10) - -/* these masks indicate which units we care about at - which states */ -static u16 acpi_state_mask[] = { - [ACPI_D0] = ACPI_ALL, - [ACPI_D1] = ACPI_SLEEP, - [ACPI_D2] = ACPI_SLEEP, - [ACPI_D3] = ACPI_NONE -}; - /* APU use in the driver */ enum snd_enum_apu_type { @@ -2159,21 +2119,6 @@ static void snd_es1968_reset(struct es1968 *chip) udelay(10); } -/* - * power management - */ -static void snd_es1968_set_acpi(struct es1968 *chip, int state) -{ - u16 active_mask = acpi_state_mask[state]; - - pci_set_power_state(chip->pci, state); - /* make sure the units we care about are on - XXX we might want to do this before state flipping? */ - pci_write_config_word(chip->pci, 0x54, ~ active_mask); - pci_write_config_word(chip->pci, 0x56, ~ active_mask); -} - - /* * initialize maestro chip */ @@ -2196,9 +2141,6 @@ static void snd_es1968_chip_init(struct es1968 *chip) * IRQs. */ - /* do config work at full power */ - snd_es1968_set_acpi(chip, ACPI_D0); - /* Config Reg A */ pci_read_config_word(pci, ESM_CONFIG_A, &w); @@ -2397,9 +2339,10 @@ static int es1968_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); snd_es1968_bob_stop(chip); - snd_es1968_set_acpi(chip, ACPI_D3); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2413,9 +2356,16 @@ static int es1968_resume(struct pci_dev *pci) return 0; /* restore all our config */ + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "es1968: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); + snd_es1968_chip_init(chip); /* need to restore the base pointers.. */ @@ -2514,7 +2464,6 @@ static int snd_es1968_free(struct es1968 *chip) if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); snd_es1968_free_gameport(chip); - snd_es1968_set_acpi(chip, ACPI_D3); chip->master_switch = NULL; chip->master_volume = NULL; pci_release_regions(chip->pci); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 3ec7d7ee04dd..77e3d5c18302 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1531,9 +1531,9 @@ static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state) chip->saved_regs[i] = inw(chip->port + saved_regs[i]); /* FIXME: tea575x suspend */ - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1543,9 +1543,14 @@ static int snd_fm801_resume(struct pci_dev *pci) struct fm801 *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "fm801: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_fm801_chip_init(chip, 1); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index feeed12920b4..7c96361b95e3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1379,12 +1379,16 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm[i]); snd_hda_suspend(chip->bus, state); azx_free_cmd_io(chip); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } if (!disable_msi) pci_disable_msi(chip->pci); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1393,15 +1397,25 @@ static int azx_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct azx *chip = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "hda-intel: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(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); + 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); + return -EIO; + } chip->irq = pci->irq; - pci_set_master(pci); azx_init_chip(chip); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); @@ -1431,15 +1445,14 @@ static int azx_free(struct azx *chip) /* disable position buffer */ azx_writel(chip, DPLBASE, 0); azx_writel(chip, DPUBASE, 0); - - synchronize_irq(chip->irq); } if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, (void*)chip); - if (!disable_msi) - pci_disable_msi(chip->pci); } + if (!disable_msi) + pci_disable_msi(chip->pci); if (chip->remap_addr) iounmap(chip->remap_addr); diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index f4319b8d4644..7f22dab07240 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2476,10 +2476,14 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) if (chip->device_type == DEVICE_INTEL_ICH4) chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2489,11 +2493,22 @@ static int intel8x0_resume(struct pci_dev *pci) struct intel8x0 *chip = card->private_data; int i; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "intel8x0: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); - request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, - card->shortname, chip); + if (request_irq(pci->irq, snd_intel8x0_interrupt, + IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) { + printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; synchronize_irq(chip->irq); snd_intel8x0_chip_init(chip, 0); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 6703f5cb5569..bd467c501123 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -1045,10 +1045,14 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) for (i = 0; i < chip->pcm_devs; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_ac97_suspend(chip->ac97); - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, chip); + chip->irq = -1; + } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1057,11 +1061,22 @@ static int intel8x0m_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct intel8x0m *chip = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "intel8x0m: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); - request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, - card->shortname, chip); + if (request_irq(pci->irq, snd_intel8x0_interrupt, + IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) { + printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " + "disabling device\n", pci->irq); + snd_card_disconnect(card); + return -EIO; + } chip->irq = pci->irq; snd_intel8x0_chip_init(chip, 0); snd_ac97_resume(chip->ac97); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 05605f474a72..8cab342bbaaf 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -2589,12 +2589,9 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) chip->suspend_mem[index++] = snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i); - /* power down apci registers */ - snd_m3_outw(chip, 0xffff, 0x54); - snd_m3_outw(chip, 0xffff, 0x56); - pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2607,8 +2604,14 @@ static int m3_resume(struct pci_dev *pci) if (chip->suspend_mem == NULL) return 0; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "maestor3: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); /* first lets just bring everything back. .*/ diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index b1bbdb9e3b7b..945d21bf187e 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1390,6 +1390,7 @@ static int nm256_suspend(struct pci_dev *pci, pm_message_t state) chip->coeffs_current = 0; pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1401,8 +1402,17 @@ static int nm256_resume(struct pci_dev *pci) /* Perform a full reset on the hardware */ chip->in_resume = 1; + + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "nm256: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); + snd_nm256_init_chip(chip); /* restore ac97 */ diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index ec4899147e1d..56e0c01123e7 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1178,9 +1178,9 @@ static int riptide_suspend(struct pci_dev *pci, pm_message_t state) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1189,9 +1189,14 @@ static int riptide_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_riptide *chip = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "riptide: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_riptide_initialize(chip); snd_ac97_resume(chip->ac97); diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 0d478871808d..1fbc4321122f 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c @@ -3966,15 +3966,9 @@ int snd_trident_suspend(struct pci_dev *pci, pm_message_t state) snd_ac97_suspend(trident->ac97); snd_ac97_suspend(trident->ac97_sec); - switch (trident->device) { - case TRIDENT_DEVICE_ID_DX: - case TRIDENT_DEVICE_ID_NX: - break; /* TODO */ - case TRIDENT_DEVICE_ID_SI7018: - break; - } pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -3983,9 +3977,15 @@ int snd_trident_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_trident *trident = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); - pci_set_master(pci); /* to be sure */ + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "trident: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); switch (trident->device) { case TRIDENT_DEVICE_ID_DX: diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index e6990e0bbf23..92b0736c0fdb 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -2185,9 +2185,9 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); } - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2197,9 +2197,15 @@ static int snd_via82xx_resume(struct pci_dev *pci) struct via82xx *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "via82xx: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); snd_via82xx_chip_init(chip); diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5ab1cf3d434b..feb27c966256 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -1032,9 +1032,10 @@ static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state) snd_via82xx_channel_reset(chip, &chip->devs[i]); synchronize_irq(chip->irq); snd_ac97_suspend(chip->ac97); - pci_set_power_state(pci, PCI_D3hot); + pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1044,9 +1045,14 @@ static int snd_via82xx_resume(struct pci_dev *pci) struct via82xx_modem *chip = card->private_data; int i; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "via82xx-modem: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_via82xx_chip_init(chip); diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index e7cd8acab59a..af49e8aabf55 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -266,9 +266,9 @@ static int snd_vx222_suspend(struct pci_dev *pci, pm_message_t state) int err; err = snd_vx_suspend(&vx->core, state); - pci_set_power_state(pci, PCI_D3hot); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return err; } @@ -277,9 +277,14 @@ static int snd_vx222_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct snd_vx222 *vx = card->private_data; - pci_restore_state(pci); - pci_enable_device(pci); pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "vx222: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); return snd_vx_resume(&vx->core); } diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index ebc6da89edf3..a40c1085fd20 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -2218,6 +2218,7 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state) snd_ymfpci_disable_dsp(chip); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -2227,8 +2228,14 @@ int snd_ymfpci_resume(struct pci_dev *pci) struct snd_ymfpci *chip = card->private_data; unsigned int i; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "ymfpci: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); snd_ymfpci_aclink_reset(pci); snd_ymfpci_codec_ready(chip, 0); -- 2.20.1