Browse Source

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>
Russell King 14 years ago
parent
commit
b60fb519d7
2 changed files with 17 additions and 9 deletions
  1. 15 9
      sound/arm/aaci.c
  2. 2 0
      sound/arm/aaci.h

+ 15 - 9
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;
 

+ 2 - 0
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;