aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-01-25 15:52:33 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-01-25 21:20:22 +0000
commitb60fb519d7977e606621af85585c3677fc290ef8 (patch)
treec585e8f2e08717547a7d570ef84fbf2e8a6b874e
parent250c7a61c35a258e2422b3d55c61bfbad33326be (diff)
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>
-rw-r--r--sound/arm/aaci.c24
-rw-r--r--sound/arm/aaci.h2
2 files changed, 17 insertions, 9 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 24d3013c023..65685afd8f7 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 6a4a2eebdda..04c4568413f 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;