ALSA: pcm: Add card sync_irq field
authorTakashi Iwai <tiwai@suse.de>
Sun, 17 Nov 2019 08:53:07 +0000 (09:53 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 20 Nov 2019 18:39:54 +0000 (19:39 +0100)
Many PCI and other drivers performs snd_pcm_period_elapsed() simply in
its interrupt handler, so the sync_stop operation is just to call
synchronize_irq().  Instead of putting this call multiple times,
introduce the common card->sync_irq field.  When this field is set,
PCM core performs synchronize_irq() for sync-stop operation.  Each
driver just needs to copy its local IRQ number to card->sync_irq, and
that's all we need.

Link: https://lore.kernel.org/r/20191117085308.23915-8-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/core.h
sound/core/init.c
sound/core/pcm_native.c

index ee238f100f73fbf41039ba44663539d4fea3a026..af3dce956c17959e7d1d7393ba91e00ce8712b87 100644 (file)
@@ -117,6 +117,7 @@ struct snd_card {
        struct device card_dev;         /* cardX object for sysfs */
        const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
        bool registered;                /* card_dev is registered? */
+       int sync_irq;                   /* assigned irq, used for PCM sync */
        wait_queue_head_t remove_sleep;
 
 #ifdef CONFIG_PM
index db99b7fad6ad8336ae12c8f72b3e10ff53779710..faa9f03c01ca99f0638fbd848bde9d4752b5f840 100644 (file)
@@ -215,6 +215,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        init_waitqueue_head(&card->power_sleep);
 #endif
        init_waitqueue_head(&card->remove_sleep);
+       card->sync_irq = -1;
 
        device_initialize(&card->card_dev);
        card->card_dev.parent = parent;
index 163d621ff238e3ffcf6e46a39595be3ccf5610b7..1fe581167b7b9aad19be6a06c3c5d98d3183cf45 100644 (file)
@@ -574,6 +574,8 @@ static void snd_pcm_sync_stop(struct snd_pcm_substream *substream)
                substream->runtime->stop_operating = false;
                if (substream->ops->sync_stop)
                        substream->ops->sync_stop(substream);
+               else if (substream->pcm->card->sync_irq > 0)
+                       synchronize_irq(substream->pcm->card->sync_irq);
        }
 }