ALSA: rawmidi - Use workq for event handling
authorTakashi Iwai <tiwai@suse.de>
Tue, 14 Jun 2011 12:37:06 +0000 (14:37 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 14 Jun 2011 12:37:06 +0000 (14:37 +0200)
Kill tasklet usage in rawmidi core code.  Use workq for the event callback
instead of tasklet (which is used only in core/seq/seq_midi.c).

Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/rawmidi.h
sound/core/rawmidi.c

index 2480e7d10dcf9f04c7f1cb8f8ef4fd82414df369..6b14359d9fed92c0872a6f9a88b5280ca9e1a4b4 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
 #include "seq_device.h"
@@ -63,6 +64,7 @@ struct snd_rawmidi_global_ops {
 };
 
 struct snd_rawmidi_runtime {
+       struct snd_rawmidi_substream *substream;
        unsigned int drain: 1,  /* drain stage */
                     oss: 1;    /* OSS compatible mode */
        /* midi stream buffer */
@@ -79,7 +81,7 @@ struct snd_rawmidi_runtime {
        /* event handler (new bytes, input only) */
        void (*event)(struct snd_rawmidi_substream *substream);
        /* defers calls to event [input] or ops->trigger [output] */
-       struct tasklet_struct tasklet;
+       struct work_struct event_work;
        /* private data */
        void *private_data;
        void (*private_free)(struct snd_rawmidi_substream *substream);
index cbbed0db9e560315ae0559c7e5e97786387a5371..0757f542999df6623ad600fe395415eaea908ad7 100644 (file)
@@ -92,16 +92,12 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre
               (!substream->append || runtime->avail >= count);
 }
 
-static void snd_rawmidi_input_event_tasklet(unsigned long data)
+static void snd_rawmidi_input_event_work(struct work_struct *work)
 {
-       struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
-       substream->runtime->event(substream);
-}
-
-static void snd_rawmidi_output_trigger_tasklet(unsigned long data)
-{
-       struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
-       substream->ops->trigger(substream, 1);
+       struct snd_rawmidi_runtime *runtime =
+               container_of(work, struct snd_rawmidi_runtime, event_work);
+       if (runtime->event)
+               runtime->event(runtime->substream);
 }
 
 static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
@@ -110,16 +106,10 @@ static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
 
        if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
                return -ENOMEM;
+       runtime->substream = substream;
        spin_lock_init(&runtime->lock);
        init_waitqueue_head(&runtime->sleep);
-       if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
-               tasklet_init(&runtime->tasklet,
-                            snd_rawmidi_input_event_tasklet,
-                            (unsigned long)substream);
-       else
-               tasklet_init(&runtime->tasklet,
-                            snd_rawmidi_output_trigger_tasklet,
-                            (unsigned long)substream);
+       INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
        runtime->event = NULL;
        runtime->buffer_size = PAGE_SIZE;
        runtime->avail_min = 1;
@@ -150,12 +140,7 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs
 {
        if (!substream->opened)
                return;
-       if (up) {
-               tasklet_schedule(&substream->runtime->tasklet);
-       } else {
-               tasklet_kill(&substream->runtime->tasklet);
-               substream->ops->trigger(substream, 0);
-       }
+       substream->ops->trigger(substream, up);
 }
 
 static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -163,8 +148,8 @@ static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, i
        if (!substream->opened)
                return;
        substream->ops->trigger(substream, up);
-       if (!up && substream->runtime->event)
-               tasklet_kill(&substream->runtime->tasklet);
+       if (!up)
+               cancel_work_sync(&substream->runtime->event_work);
 }
 
 int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
@@ -926,7 +911,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
        }
        if (result > 0) {
                if (runtime->event)
-                       tasklet_schedule(&runtime->tasklet);
+                       schedule_work(&runtime->event_work);
                else if (snd_rawmidi_ready(substream))
                        wake_up(&runtime->sleep);
        }