diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-04-22 11:28:11 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:41 -0400 |
commit | ebf029da38829ede6b53ac8a5ad45b149064ea16 (patch) | |
tree | aebf6bddd245a874577fc321978b3f7137e8ac39 /sound | |
parent | 6b9a9b329640b7e8143df7b2782884ea758650f7 (diff) |
[ALSA] Fix possible races at free_irq in PCI drivers
The irq handler of PCI drivers must be released before releasing other
resources since the handler for a shared irq can be still called and
may access the freed resource again.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/ca0106/ca0106_main.c | 5 | ||||
-rw-r--r-- | sound/pci/cs46xx/cs46xx_lib.c | 6 | ||||
-rw-r--r-- | sound/pci/echoaudio/echoaudio.c | 7 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1_main.c | 15 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1x.c | 8 | ||||
-rw-r--r-- | sound/pci/intel8x0m.c | 8 | ||||
-rw-r--r-- | sound/pci/korg1212/korg1212.c | 1 | ||||
-rw-r--r-- | sound/pci/nm256/nm256.c | 4 | ||||
-rw-r--r-- | sound/pci/trident/trident_main.c | 4 |
9 files changed, 26 insertions, 32 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 3818249fcc81..ecbe79b67e43 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1114,6 +1114,8 @@ static int snd_ca0106_free(struct snd_ca0106 *chip) | |||
1114 | * So we can fix: snd-malloc: Memory leak? pages not freed = 8 | 1114 | * So we can fix: snd-malloc: Memory leak? pages not freed = 8 |
1115 | */ | 1115 | */ |
1116 | } | 1116 | } |
1117 | if (chip->irq >= 0) | ||
1118 | free_irq(chip->irq, chip); | ||
1117 | // release the data | 1119 | // release the data |
1118 | #if 1 | 1120 | #if 1 |
1119 | if (chip->buffer.area) | 1121 | if (chip->buffer.area) |
@@ -1123,9 +1125,6 @@ static int snd_ca0106_free(struct snd_ca0106 *chip) | |||
1123 | // release the i/o port | 1125 | // release the i/o port |
1124 | release_and_free_resource(chip->res_port); | 1126 | release_and_free_resource(chip->res_port); |
1125 | 1127 | ||
1126 | // release the irq | ||
1127 | if (chip->irq >= 0) | ||
1128 | free_irq(chip->irq, chip); | ||
1129 | pci_disable_device(chip->pci); | 1128 | pci_disable_device(chip->pci); |
1130 | kfree(chip); | 1129 | kfree(chip); |
1131 | return 0; | 1130 | return 0; |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 87ddffcd9d89..e214e567dec8 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -2772,6 +2772,9 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
2772 | if (chip->irq >= 0) | 2772 | if (chip->irq >= 0) |
2773 | free_irq(chip->irq, chip); | 2773 | free_irq(chip->irq, chip); |
2774 | 2774 | ||
2775 | if (chip->active_ctrl) | ||
2776 | chip->active_ctrl(chip, -chip->amplifier); | ||
2777 | |||
2775 | for (idx = 0; idx < 5; idx++) { | 2778 | for (idx = 0; idx < 5; idx++) { |
2776 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; | 2779 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; |
2777 | if (region->remap_addr) | 2780 | if (region->remap_addr) |
@@ -2779,9 +2782,6 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
2779 | release_and_free_resource(region->resource); | 2782 | release_and_free_resource(region->resource); |
2780 | } | 2783 | } |
2781 | 2784 | ||
2782 | if (chip->active_ctrl) | ||
2783 | chip->active_ctrl(chip, -chip->amplifier); | ||
2784 | |||
2785 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | 2785 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
2786 | if (chip->dsp_spos_instance) { | 2786 | if (chip->dsp_spos_instance) { |
2787 | cs46xx_dsp_spos_destroy(chip); | 2787 | cs46xx_dsp_spos_destroy(chip); |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 90ec090792ba..e16dc92e82fb 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
@@ -1852,15 +1852,16 @@ static irqreturn_t snd_echo_interrupt(int irq, void *dev_id) | |||
1852 | static int snd_echo_free(struct echoaudio *chip) | 1852 | static int snd_echo_free(struct echoaudio *chip) |
1853 | { | 1853 | { |
1854 | DE_INIT(("Stop DSP...\n")); | 1854 | DE_INIT(("Stop DSP...\n")); |
1855 | if (chip->comm_page) { | 1855 | if (chip->comm_page) |
1856 | rest_in_peace(chip); | 1856 | rest_in_peace(chip); |
1857 | snd_dma_free_pages(&chip->commpage_dma_buf); | ||
1858 | } | ||
1859 | DE_INIT(("Stopped.\n")); | 1857 | DE_INIT(("Stopped.\n")); |
1860 | 1858 | ||
1861 | if (chip->irq >= 0) | 1859 | if (chip->irq >= 0) |
1862 | free_irq(chip->irq, chip); | 1860 | free_irq(chip->irq, chip); |
1863 | 1861 | ||
1862 | if (chip->comm_page) | ||
1863 | snd_dma_free_pages(&chip->commpage_dma_buf); | ||
1864 | |||
1864 | if (chip->dsp_registers) | 1865 | if (chip->dsp_registers) |
1865 | iounmap(chip->dsp_registers); | 1866 | iounmap(chip->dsp_registers); |
1866 | 1867 | ||
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 9a9b977d3cf1..abde5b901884 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -1249,11 +1249,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1249 | if (emu->port) { /* avoid access to already used hardware */ | 1249 | if (emu->port) { /* avoid access to already used hardware */ |
1250 | snd_emu10k1_fx8010_tram_setup(emu, 0); | 1250 | snd_emu10k1_fx8010_tram_setup(emu, 0); |
1251 | snd_emu10k1_done(emu); | 1251 | snd_emu10k1_done(emu); |
1252 | /* remove reserved page */ | ||
1253 | if (emu->reserved_page) { | ||
1254 | snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page); | ||
1255 | emu->reserved_page = NULL; | ||
1256 | } | ||
1257 | snd_emu10k1_free_efx(emu); | 1252 | snd_emu10k1_free_efx(emu); |
1258 | } | 1253 | } |
1259 | if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { | 1254 | if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { |
@@ -1262,6 +1257,14 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1262 | } | 1257 | } |
1263 | if (emu->emu1010.firmware_thread) | 1258 | if (emu->emu1010.firmware_thread) |
1264 | kthread_stop(emu->emu1010.firmware_thread); | 1259 | kthread_stop(emu->emu1010.firmware_thread); |
1260 | if (emu->irq >= 0) | ||
1261 | free_irq(emu->irq, emu); | ||
1262 | /* remove reserved page */ | ||
1263 | if (emu->reserved_page) { | ||
1264 | snd_emu10k1_synth_free(emu, | ||
1265 | (struct snd_util_memblk *)emu->reserved_page); | ||
1266 | emu->reserved_page = NULL; | ||
1267 | } | ||
1265 | if (emu->memhdr) | 1268 | if (emu->memhdr) |
1266 | snd_util_memhdr_free(emu->memhdr); | 1269 | snd_util_memhdr_free(emu->memhdr); |
1267 | if (emu->silent_page.area) | 1270 | if (emu->silent_page.area) |
@@ -1273,8 +1276,6 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1273 | #ifdef CONFIG_PM | 1276 | #ifdef CONFIG_PM |
1274 | free_pm_buffer(emu); | 1277 | free_pm_buffer(emu); |
1275 | #endif | 1278 | #endif |
1276 | if (emu->irq >= 0) | ||
1277 | free_irq(emu->irq, emu); | ||
1278 | if (emu->port) | 1279 | if (emu->port) |
1279 | pci_release_regions(emu->pci); | 1280 | pci_release_regions(emu->pci); |
1280 | if (emu->card_capabilities->ca0151_chip) /* P16V */ | 1281 | if (emu->card_capabilities->ca0151_chip) /* P16V */ |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 341f34e19f3c..491a4a50f869 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -754,13 +754,13 @@ static int snd_emu10k1x_free(struct emu10k1x *chip) | |||
754 | // disable audio | 754 | // disable audio |
755 | outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); | 755 | outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); |
756 | 756 | ||
757 | // release the i/o port | 757 | /* release the irq */ |
758 | release_and_free_resource(chip->res_port); | ||
759 | |||
760 | // release the irq | ||
761 | if (chip->irq >= 0) | 758 | if (chip->irq >= 0) |
762 | free_irq(chip->irq, chip); | 759 | free_irq(chip->irq, chip); |
763 | 760 | ||
761 | // release the i/o port | ||
762 | release_and_free_resource(chip->res_port); | ||
763 | |||
764 | // release the DMA | 764 | // release the DMA |
765 | if (chip->dma_buffer.area) { | 765 | if (chip->dma_buffer.area) { |
766 | snd_dma_free_pages(&chip->dma_buffer); | 766 | snd_dma_free_pages(&chip->dma_buffer); |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 15db810d5893..faf674e671ac 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -985,18 +985,15 @@ static int snd_intel8x0_free(struct intel8x0m *chip) | |||
985 | /* reset channels */ | 985 | /* reset channels */ |
986 | for (i = 0; i < chip->bdbars_count; i++) | 986 | for (i = 0; i < chip->bdbars_count; i++) |
987 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); | 987 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); |
988 | /* --- */ | 988 | __hw_end: |
989 | if (chip->irq >= 0) | 989 | if (chip->irq >= 0) |
990 | synchronize_irq(chip->irq); | 990 | free_irq(chip->irq, chip); |
991 | __hw_end: | ||
992 | if (chip->bdbars.area) | 991 | if (chip->bdbars.area) |
993 | snd_dma_free_pages(&chip->bdbars); | 992 | snd_dma_free_pages(&chip->bdbars); |
994 | if (chip->addr) | 993 | if (chip->addr) |
995 | pci_iounmap(chip->pci, chip->addr); | 994 | pci_iounmap(chip->pci, chip->addr); |
996 | if (chip->bmaddr) | 995 | if (chip->bmaddr) |
997 | pci_iounmap(chip->pci, chip->bmaddr); | 996 | pci_iounmap(chip->pci, chip->bmaddr); |
998 | if (chip->irq >= 0) | ||
999 | free_irq(chip->irq, chip); | ||
1000 | pci_release_regions(chip->pci); | 997 | pci_release_regions(chip->pci); |
1001 | pci_disable_device(chip->pci); | 998 | pci_disable_device(chip->pci); |
1002 | kfree(chip); | 999 | kfree(chip); |
@@ -1018,7 +1015,6 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) | |||
1018 | snd_pcm_suspend_all(chip->pcm[i]); | 1015 | snd_pcm_suspend_all(chip->pcm[i]); |
1019 | snd_ac97_suspend(chip->ac97); | 1016 | snd_ac97_suspend(chip->ac97); |
1020 | if (chip->irq >= 0) { | 1017 | if (chip->irq >= 0) { |
1021 | synchronize_irq(chip->irq); | ||
1022 | free_irq(chip->irq, chip); | 1018 | free_irq(chip->irq, chip); |
1023 | chip->irq = -1; | 1019 | chip->irq = -1; |
1024 | } | 1020 | } |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 10c713d9ac49..f4c85b52bde3 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2102,7 +2102,6 @@ snd_korg1212_free(struct snd_korg1212 *korg1212) | |||
2102 | snd_korg1212_TurnOffIdleMonitor(korg1212); | 2102 | snd_korg1212_TurnOffIdleMonitor(korg1212); |
2103 | 2103 | ||
2104 | if (korg1212->irq >= 0) { | 2104 | if (korg1212->irq >= 0) { |
2105 | synchronize_irq(korg1212->irq); | ||
2106 | snd_korg1212_DisableCardInterrupts(korg1212); | 2105 | snd_korg1212_DisableCardInterrupts(korg1212); |
2107 | free_irq(korg1212->irq, korg1212); | 2106 | free_irq(korg1212->irq, korg1212); |
2108 | korg1212->irq = -1; | 2107 | korg1212->irq = -1; |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 7ac654e381da..7efb838d18a6 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -1439,7 +1439,7 @@ static int snd_nm256_free(struct nm256 *chip) | |||
1439 | snd_nm256_capture_stop(chip); | 1439 | snd_nm256_capture_stop(chip); |
1440 | 1440 | ||
1441 | if (chip->irq >= 0) | 1441 | if (chip->irq >= 0) |
1442 | synchronize_irq(chip->irq); | 1442 | free_irq(chip->irq, chip); |
1443 | 1443 | ||
1444 | if (chip->cport) | 1444 | if (chip->cport) |
1445 | iounmap(chip->cport); | 1445 | iounmap(chip->cport); |
@@ -1447,8 +1447,6 @@ static int snd_nm256_free(struct nm256 *chip) | |||
1447 | iounmap(chip->buffer); | 1447 | iounmap(chip->buffer); |
1448 | release_and_free_resource(chip->res_cport); | 1448 | release_and_free_resource(chip->res_cport); |
1449 | release_and_free_resource(chip->res_buffer); | 1449 | release_and_free_resource(chip->res_buffer); |
1450 | if (chip->irq >= 0) | ||
1451 | free_irq(chip->irq, chip); | ||
1452 | 1450 | ||
1453 | pci_disable_device(chip->pci); | 1451 | pci_disable_device(chip->pci); |
1454 | kfree(chip->ac97_regs); | 1452 | kfree(chip->ac97_regs); |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 71138ff9b310..bbcee2c09ae4 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -3676,6 +3676,8 @@ static int snd_trident_free(struct snd_trident *trident) | |||
3676 | else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { | 3676 | else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { |
3677 | outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); | 3677 | outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); |
3678 | } | 3678 | } |
3679 | if (trident->irq >= 0) | ||
3680 | free_irq(trident->irq, trident); | ||
3679 | if (trident->tlb.buffer.area) { | 3681 | if (trident->tlb.buffer.area) { |
3680 | outl(0, TRID_REG(trident, NX_TLBC)); | 3682 | outl(0, TRID_REG(trident, NX_TLBC)); |
3681 | if (trident->tlb.memhdr) | 3683 | if (trident->tlb.memhdr) |
@@ -3685,8 +3687,6 @@ static int snd_trident_free(struct snd_trident *trident) | |||
3685 | vfree(trident->tlb.shadow_entries); | 3687 | vfree(trident->tlb.shadow_entries); |
3686 | snd_dma_free_pages(&trident->tlb.buffer); | 3688 | snd_dma_free_pages(&trident->tlb.buffer); |
3687 | } | 3689 | } |
3688 | if (trident->irq >= 0) | ||
3689 | free_irq(trident->irq, trident); | ||
3690 | pci_release_regions(trident->pci); | 3690 | pci_release_regions(trident->pci); |
3691 | pci_disable_device(trident->pci); | 3691 | pci_disable_device(trident->pci); |
3692 | kfree(trident); | 3692 | kfree(trident); |