Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3c705aa authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: rawmidi - Use workq for event handling



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: default avatarTakashi Iwai <tiwai@suse.de>
parent 30bdee02
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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);
+11 −26
Original line number Diff line number Diff line
@@ -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);
	}