Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: gus: Fix repeated probes of snd_gus_create()

GUS card object may be repeatedly probed for the legacy ISA devices,
and the behavior doesn't fit with the devres resource management.

Revert partially back to the classical way for the snd_gus_card
object, so that the repeated calls of snd_gus_create() are allowed.

Fixes: 5b88da3c800f ("ALSA: gus: Allocate resources with device-managed APIs")
Reported-by: kernel test robot <oliver.sang@intel.com>
Link: https://lore.kernel.org/r/20210907093930.29009-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+31 -13
+31 -13
sound/isa/gus/gus_main.c
··· 87 87 88 88 static int snd_gus_free(struct snd_gus_card *gus) 89 89 { 90 - if (gus->gf1.res_port2) { 91 - snd_gf1_stop(gus); 92 - snd_gus_init_dma_irq(gus, 0); 90 + if (gus->gf1.res_port2 == NULL) 91 + goto __hw_end; 92 + snd_gf1_stop(gus); 93 + snd_gus_init_dma_irq(gus, 0); 94 + __hw_end: 95 + release_and_free_resource(gus->gf1.res_port1); 96 + release_and_free_resource(gus->gf1.res_port2); 97 + if (gus->gf1.irq >= 0) 98 + free_irq(gus->gf1.irq, (void *) gus); 99 + if (gus->gf1.dma1 >= 0) { 100 + disable_dma(gus->gf1.dma1); 101 + free_dma(gus->gf1.dma1); 93 102 } 103 + if (!gus->equal_dma && gus->gf1.dma2 >= 0) { 104 + disable_dma(gus->gf1.dma2); 105 + free_dma(gus->gf1.dma2); 106 + } 107 + kfree(gus); 94 108 return 0; 95 109 } 96 110 ··· 130 116 }; 131 117 132 118 *rgus = NULL; 133 - gus = devm_kzalloc(card->dev, sizeof(*gus), GFP_KERNEL); 119 + gus = kzalloc(sizeof(*gus), GFP_KERNEL); 134 120 if (gus == NULL) 135 121 return -ENOMEM; 136 122 spin_lock_init(&gus->reg_lock); ··· 156 142 gus->gf1.reg_timerctrl = GUSP(gus, TIMERCNTRL); 157 143 gus->gf1.reg_timerdata = GUSP(gus, TIMERDATA); 158 144 /* allocate resources */ 159 - gus->gf1.res_port1 = devm_request_region(card->dev, port, 16, 160 - "GUS GF1 (Adlib/SB)"); 145 + gus->gf1.res_port1 = request_region(port, 16, "GUS GF1 (Adlib/SB)"); 161 146 if (!gus->gf1.res_port1) { 162 147 snd_printk(KERN_ERR "gus: can't grab SB port 0x%lx\n", port); 148 + snd_gus_free(gus); 163 149 return -EBUSY; 164 150 } 165 - gus->gf1.res_port2 = devm_request_region(card->dev, port + 0x100, 12, 166 - "GUS GF1 (Synth)"); 151 + gus->gf1.res_port2 = request_region(port + 0x100, 12, "GUS GF1 (Synth)"); 167 152 if (!gus->gf1.res_port2) { 168 153 snd_printk(KERN_ERR "gus: can't grab synth port 0x%lx\n", port + 0x100); 154 + snd_gus_free(gus); 169 155 return -EBUSY; 170 156 } 171 - if (irq >= 0 && devm_request_irq(card->dev, irq, snd_gus_interrupt, 0, 172 - "GUS GF1", (void *) gus)) { 157 + if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) { 173 158 snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); 159 + snd_gus_free(gus); 174 160 return -EBUSY; 175 161 } 176 162 gus->gf1.irq = irq; 177 163 card->sync_irq = irq; 178 - if (snd_devm_request_dma(card->dev, dma1, "GUS - 1")) { 164 + if (request_dma(dma1, "GUS - 1")) { 179 165 snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1); 166 + snd_gus_free(gus); 180 167 return -EBUSY; 181 168 } 182 169 gus->gf1.dma1 = dma1; 183 170 if (dma2 >= 0 && dma1 != dma2) { 184 - if (snd_devm_request_dma(card->dev, dma2, "GUS - 2")) { 171 + if (request_dma(dma2, "GUS - 2")) { 185 172 snd_printk(KERN_ERR "gus: can't grab DMA2 %d\n", dma2); 173 + snd_gus_free(gus); 186 174 return -EBUSY; 187 175 } 188 176 gus->gf1.dma2 = dma2; ··· 209 193 gus->gf1.volume_ramp = 25; 210 194 gus->gf1.smooth_pan = 1; 211 195 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, gus, &ops); 212 - if (err < 0) 196 + if (err < 0) { 197 + snd_gus_free(gus); 213 198 return err; 199 + } 214 200 *rgus = gus; 215 201 return 0; 216 202 }