Commit ebf029da38829ede6b53ac8a5ad45b149064ea16

Authored by Takashi Iwai
1 parent 6b9a9b3296

[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
... ... @@ -2102,7 +2102,6 @@
2102 2102 snd_korg1212_TurnOffIdleMonitor(korg1212);
2103 2103  
2104 2104 if (korg1212->irq >= 0) {
2105   - synchronize_irq(korg1212->irq);
2106 2105 snd_korg1212_DisableCardInterrupts(korg1212);
2107 2106 free_irq(korg1212->irq, korg1212);
2108 2107 korg1212->irq = -1;
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);