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>
This commit is contained in:
@ -370,7 +370,7 @@ static int __aaci_pcm_open(struct aaci *aaci,
|
|||||||
struct aaci_runtime *aacirun)
|
struct aaci_runtime *aacirun)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
aacirun->substream = substream;
|
aacirun->substream = substream;
|
||||||
runtime->private_data = aacirun;
|
runtime->private_data = aacirun;
|
||||||
@ -391,14 +391,15 @@ static int __aaci_pcm_open(struct aaci *aaci,
|
|||||||
*/
|
*/
|
||||||
runtime->hw.fifo_size = aaci->fifosize * 2;
|
runtime->hw.fifo_size = aaci->fifosize * 2;
|
||||||
|
|
||||||
ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED,
|
mutex_lock(&aaci->irq_lock);
|
||||||
DRIVER_NAME, aaci);
|
if (!aaci->users++) {
|
||||||
if (ret)
|
ret = request_irq(aaci->dev->irq[0], aaci_irq,
|
||||||
goto out;
|
IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci);
|
||||||
|
if (ret != 0)
|
||||||
|
aaci->users--;
|
||||||
|
}
|
||||||
|
mutex_unlock(&aaci->irq_lock);
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +415,11 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream)
|
|||||||
WARN_ON(aacirun->cr & CR_EN);
|
WARN_ON(aacirun->cr & CR_EN);
|
||||||
|
|
||||||
aacirun->substream = NULL;
|
aacirun->substream = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&aaci->irq_lock);
|
||||||
|
if (!--aaci->users)
|
||||||
free_irq(aaci->dev->irq[0], aaci);
|
free_irq(aaci->dev->irq[0], aaci);
|
||||||
|
mutex_unlock(&aaci->irq_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -943,6 +948,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
|
|||||||
|
|
||||||
aaci = card->private_data;
|
aaci = card->private_data;
|
||||||
mutex_init(&aaci->ac97_sem);
|
mutex_init(&aaci->ac97_sem);
|
||||||
|
mutex_init(&aaci->irq_lock);
|
||||||
aaci->card = card;
|
aaci->card = card;
|
||||||
aaci->dev = dev;
|
aaci->dev = dev;
|
||||||
|
|
||||||
|
|||||||
@ -226,6 +226,8 @@ struct aaci {
|
|||||||
struct snd_card *card;
|
struct snd_card *card;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
unsigned int fifosize;
|
unsigned int fifosize;
|
||||||
|
unsigned int users;
|
||||||
|
struct mutex irq_lock;
|
||||||
|
|
||||||
/* AC'97 */
|
/* AC'97 */
|
||||||
struct mutex ac97_sem;
|
struct mutex ac97_sem;
|
||||||
|
|||||||
Reference in New Issue
Block a user