diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-25 15:52:33 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-01-25 21:20:22 +0000 |
commit | b60fb519d7977e606621af85585c3677fc290ef8 (patch) | |
tree | c585e8f2e08717547a7d570ef84fbf2e8a6b874e /sound/arm | |
parent | 250c7a61c35a258e2422b3d55c61bfbad33326be (diff) | |
download | linux-b60fb519d7977e606621af85585c3677fc290ef8.tar.bz2 |
ALSA: AACI: fix multiple IRQ claiming
Claiming the IRQ each time a playback or capture interface is opened
is wasteful; the second copy of the registered handler is identical to
the first and just wastes resources. Track the number of opens and
only register the handler when necessary.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'sound/arm')
-rw-r--r-- | sound/arm/aaci.c | 24 | ||||
-rw-r--r-- | sound/arm/aaci.h | 2 |
2 files changed, 17 insertions, 9 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 24d3013c0231..65685afd8f77 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -370,7 +370,7 @@ static int __aaci_pcm_open(struct aaci *aaci, struct aaci_runtime *aacirun) { struct snd_pcm_runtime *runtime = substream->runtime; - int ret; + int ret = 0; aacirun->substream = substream; runtime->private_data = aacirun; @@ -391,14 +391,15 @@ static int __aaci_pcm_open(struct aaci *aaci, */ runtime->hw.fifo_size = aaci->fifosize * 2; - ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, - DRIVER_NAME, aaci); - if (ret) - goto out; - - return 0; + mutex_lock(&aaci->irq_lock); + if (!aaci->users++) { + ret = request_irq(aaci->dev->irq[0], aaci_irq, + IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci); + if (ret != 0) + aaci->users--; + } + mutex_unlock(&aaci->irq_lock); - out: return ret; } @@ -414,7 +415,11 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream) WARN_ON(aacirun->cr & CR_EN); aacirun->substream = NULL; - free_irq(aaci->dev->irq[0], aaci); + + mutex_lock(&aaci->irq_lock); + if (!--aaci->users) + free_irq(aaci->dev->irq[0], aaci); + mutex_unlock(&aaci->irq_lock); return 0; } @@ -943,6 +948,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) aaci = card->private_data; mutex_init(&aaci->ac97_sem); + mutex_init(&aaci->irq_lock); aaci->card = card; aaci->dev = dev; diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h index 6a4a2eebdda1..04c4568413f4 100644 --- a/sound/arm/aaci.h +++ b/sound/arm/aaci.h @@ -226,6 +226,8 @@ struct aaci { struct snd_card *card; void __iomem *base; unsigned int fifosize; + unsigned int users; + struct mutex irq_lock; /* AC'97 */ struct mutex ac97_sem; |