Commit ebf029da38829ede6b53ac8a5ad45b149064ea16
1 parent
6b9a9b3296
Exists in
master
and in
20 other branches
[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>
Showing 9 changed files with 26 additions and 32 deletions Side-by-side Diff
sound/pci/ca0106/ca0106_main.c
... | ... | @@ -1114,6 +1114,8 @@ |
1114 | 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 | 1119 | // release the data |
1118 | 1120 | #if 1 |
1119 | 1121 | if (chip->buffer.area) |
... | ... | @@ -1123,9 +1125,6 @@ |
1123 | 1125 | // release the i/o port |
1124 | 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 | 1128 | pci_disable_device(chip->pci); |
1130 | 1129 | kfree(chip); |
1131 | 1130 | return 0; |
sound/pci/cs46xx/cs46xx_lib.c
... | ... | @@ -2772,6 +2772,9 @@ |
2772 | 2772 | if (chip->irq >= 0) |
2773 | 2773 | free_irq(chip->irq, chip); |
2774 | 2774 | |
2775 | + if (chip->active_ctrl) | |
2776 | + chip->active_ctrl(chip, -chip->amplifier); | |
2777 | + | |
2775 | 2778 | for (idx = 0; idx < 5; idx++) { |
2776 | 2779 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; |
2777 | 2780 | if (region->remap_addr) |
... | ... | @@ -2779,9 +2782,6 @@ |
2779 | 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 | 2785 | #ifdef CONFIG_SND_CS46XX_NEW_DSP |
2786 | 2786 | if (chip->dsp_spos_instance) { |
2787 | 2787 | cs46xx_dsp_spos_destroy(chip); |
sound/pci/echoaudio/echoaudio.c
... | ... | @@ -1852,14 +1852,15 @@ |
1852 | 1852 | static int snd_echo_free(struct echoaudio *chip) |
1853 | 1853 | { |
1854 | 1854 | DE_INIT(("Stop DSP...\n")); |
1855 | - if (chip->comm_page) { | |
1855 | + if (chip->comm_page) | |
1856 | 1856 | rest_in_peace(chip); |
1857 | - snd_dma_free_pages(&chip->commpage_dma_buf); | |
1858 | - } | |
1859 | 1857 | DE_INIT(("Stopped.\n")); |
1860 | 1858 | |
1861 | 1859 | if (chip->irq >= 0) |
1862 | 1860 | free_irq(chip->irq, chip); |
1861 | + | |
1862 | + if (chip->comm_page) | |
1863 | + snd_dma_free_pages(&chip->commpage_dma_buf); | |
1863 | 1864 | |
1864 | 1865 | if (chip->dsp_registers) |
1865 | 1866 | iounmap(chip->dsp_registers); |
sound/pci/emu10k1/emu10k1_main.c
... | ... | @@ -1249,11 +1249,6 @@ |
1249 | 1249 | if (emu->port) { /* avoid access to already used hardware */ |
1250 | 1250 | snd_emu10k1_fx8010_tram_setup(emu, 0); |
1251 | 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 | 1252 | snd_emu10k1_free_efx(emu); |
1258 | 1253 | } |
1259 | 1254 | if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { |
... | ... | @@ -1262,6 +1257,14 @@ |
1262 | 1257 | } |
1263 | 1258 | if (emu->emu1010.firmware_thread) |
1264 | 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 | 1268 | if (emu->memhdr) |
1266 | 1269 | snd_util_memhdr_free(emu->memhdr); |
1267 | 1270 | if (emu->silent_page.area) |
... | ... | @@ -1273,8 +1276,6 @@ |
1273 | 1276 | #ifdef CONFIG_PM |
1274 | 1277 | free_pm_buffer(emu); |
1275 | 1278 | #endif |
1276 | - if (emu->irq >= 0) | |
1277 | - free_irq(emu->irq, emu); | |
1278 | 1279 | if (emu->port) |
1279 | 1280 | pci_release_regions(emu->pci); |
1280 | 1281 | if (emu->card_capabilities->ca0151_chip) /* P16V */ |
sound/pci/emu10k1/emu10k1x.c
... | ... | @@ -754,12 +754,12 @@ |
754 | 754 | // disable audio |
755 | 755 | outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); |
756 | 756 | |
757 | - // release the i/o port | |
758 | - release_and_free_resource(chip->res_port); | |
759 | - | |
760 | - // release the irq | |
757 | + /* release the irq */ | |
761 | 758 | if (chip->irq >= 0) |
762 | 759 | free_irq(chip->irq, chip); |
760 | + | |
761 | + // release the i/o port | |
762 | + release_and_free_resource(chip->res_port); | |
763 | 763 | |
764 | 764 | // release the DMA |
765 | 765 | if (chip->dma_buffer.area) { |
sound/pci/intel8x0m.c
... | ... | @@ -985,18 +985,15 @@ |
985 | 985 | /* reset channels */ |
986 | 986 | for (i = 0; i < chip->bdbars_count; i++) |
987 | 987 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); |
988 | - /* --- */ | |
988 | + __hw_end: | |
989 | 989 | if (chip->irq >= 0) |
990 | - synchronize_irq(chip->irq); | |
991 | - __hw_end: | |
990 | + free_irq(chip->irq, chip); | |
992 | 991 | if (chip->bdbars.area) |
993 | 992 | snd_dma_free_pages(&chip->bdbars); |
994 | 993 | if (chip->addr) |
995 | 994 | pci_iounmap(chip->pci, chip->addr); |
996 | 995 | if (chip->bmaddr) |
997 | 996 | pci_iounmap(chip->pci, chip->bmaddr); |
998 | - if (chip->irq >= 0) | |
999 | - free_irq(chip->irq, chip); | |
1000 | 997 | pci_release_regions(chip->pci); |
1001 | 998 | pci_disable_device(chip->pci); |
1002 | 999 | kfree(chip); |
... | ... | @@ -1018,7 +1015,6 @@ |
1018 | 1015 | snd_pcm_suspend_all(chip->pcm[i]); |
1019 | 1016 | snd_ac97_suspend(chip->ac97); |
1020 | 1017 | if (chip->irq >= 0) { |
1021 | - synchronize_irq(chip->irq); | |
1022 | 1018 | free_irq(chip->irq, chip); |
1023 | 1019 | chip->irq = -1; |
1024 | 1020 | } |
sound/pci/korg1212/korg1212.c
sound/pci/nm256/nm256.c
... | ... | @@ -1439,7 +1439,7 @@ |
1439 | 1439 | snd_nm256_capture_stop(chip); |
1440 | 1440 | |
1441 | 1441 | if (chip->irq >= 0) |
1442 | - synchronize_irq(chip->irq); | |
1442 | + free_irq(chip->irq, chip); | |
1443 | 1443 | |
1444 | 1444 | if (chip->cport) |
1445 | 1445 | iounmap(chip->cport); |
... | ... | @@ -1447,8 +1447,6 @@ |
1447 | 1447 | iounmap(chip->buffer); |
1448 | 1448 | release_and_free_resource(chip->res_cport); |
1449 | 1449 | release_and_free_resource(chip->res_buffer); |
1450 | - if (chip->irq >= 0) | |
1451 | - free_irq(chip->irq, chip); | |
1452 | 1450 | |
1453 | 1451 | pci_disable_device(chip->pci); |
1454 | 1452 | kfree(chip->ac97_regs); |
sound/pci/trident/trident_main.c
... | ... | @@ -3676,6 +3676,8 @@ |
3676 | 3676 | else if (trident->device == TRIDENT_DEVICE_ID_SI7018) { |
3677 | 3677 | outl(0, TRID_REG(trident, SI_SERIAL_INTF_CTRL)); |
3678 | 3678 | } |
3679 | + if (trident->irq >= 0) | |
3680 | + free_irq(trident->irq, trident); | |
3679 | 3681 | if (trident->tlb.buffer.area) { |
3680 | 3682 | outl(0, TRID_REG(trident, NX_TLBC)); |
3681 | 3683 | if (trident->tlb.memhdr) |
... | ... | @@ -3685,8 +3687,6 @@ |
3685 | 3687 | vfree(trident->tlb.shadow_entries); |
3686 | 3688 | snd_dma_free_pages(&trident->tlb.buffer); |
3687 | 3689 | } |
3688 | - if (trident->irq >= 0) | |
3689 | - free_irq(trident->irq, trident); | |
3690 | 3690 | pci_release_regions(trident->pci); |
3691 | 3691 | pci_disable_device(trident->pci); |
3692 | 3692 | kfree(trident); |