aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/rawmidi.h4
-rw-r--r--sound/core/rawmidi.c37
2 files changed, 14 insertions, 27 deletions
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 2480e7d10dcf..6b14359d9fed 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -27,6 +27,7 @@
27#include <linux/spinlock.h> 27#include <linux/spinlock.h>
28#include <linux/wait.h> 28#include <linux/wait.h>
29#include <linux/mutex.h> 29#include <linux/mutex.h>
30#include <linux/workqueue.h>
30 31
31#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) 32#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
32#include "seq_device.h" 33#include "seq_device.h"
@@ -63,6 +64,7 @@ struct snd_rawmidi_global_ops {
63}; 64};
64 65
65struct snd_rawmidi_runtime { 66struct snd_rawmidi_runtime {
67 struct snd_rawmidi_substream *substream;
66 unsigned int drain: 1, /* drain stage */ 68 unsigned int drain: 1, /* drain stage */
67 oss: 1; /* OSS compatible mode */ 69 oss: 1; /* OSS compatible mode */
68 /* midi stream buffer */ 70 /* midi stream buffer */
@@ -79,7 +81,7 @@ struct snd_rawmidi_runtime {
79 /* event handler (new bytes, input only) */ 81 /* event handler (new bytes, input only) */
80 void (*event)(struct snd_rawmidi_substream *substream); 82 void (*event)(struct snd_rawmidi_substream *substream);
81 /* defers calls to event [input] or ops->trigger [output] */ 83 /* defers calls to event [input] or ops->trigger [output] */
82 struct tasklet_struct tasklet; 84 struct work_struct event_work;
83 /* private data */ 85 /* private data */
84 void *private_data; 86 void *private_data;
85 void (*private_free)(struct snd_rawmidi_substream *substream); 87 void (*private_free)(struct snd_rawmidi_substream *substream);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index cbbed0db9e56..0757f542999d 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -92,16 +92,12 @@ static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substre
92 (!substream->append || runtime->avail >= count); 92 (!substream->append || runtime->avail >= count);
93} 93}
94 94
95static void snd_rawmidi_input_event_tasklet(unsigned long data) 95static void snd_rawmidi_input_event_work(struct work_struct *work)
96{ 96{
97 struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data; 97 struct snd_rawmidi_runtime *runtime =
98 substream->runtime->event(substream); 98 container_of(work, struct snd_rawmidi_runtime, event_work);
99} 99 if (runtime->event)
100 100 runtime->event(runtime->substream);
101static void snd_rawmidi_output_trigger_tasklet(unsigned long data)
102{
103 struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
104 substream->ops->trigger(substream, 1);
105} 101}
106 102
107static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream) 103static 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)
110 106
111 if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL) 107 if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
112 return -ENOMEM; 108 return -ENOMEM;
109 runtime->substream = substream;
113 spin_lock_init(&runtime->lock); 110 spin_lock_init(&runtime->lock);
114 init_waitqueue_head(&runtime->sleep); 111 init_waitqueue_head(&runtime->sleep);
115 if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT) 112 INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
116 tasklet_init(&runtime->tasklet,
117 snd_rawmidi_input_event_tasklet,
118 (unsigned long)substream);
119 else
120 tasklet_init(&runtime->tasklet,
121 snd_rawmidi_output_trigger_tasklet,
122 (unsigned long)substream);
123 runtime->event = NULL; 113 runtime->event = NULL;
124 runtime->buffer_size = PAGE_SIZE; 114 runtime->buffer_size = PAGE_SIZE;
125 runtime->avail_min = 1; 115 runtime->avail_min = 1;
@@ -150,12 +140,7 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs
150{ 140{
151 if (!substream->opened) 141 if (!substream->opened)
152 return; 142 return;
153 if (up) { 143 substream->ops->trigger(substream, up);
154 tasklet_schedule(&substream->runtime->tasklet);
155 } else {
156 tasklet_kill(&substream->runtime->tasklet);
157 substream->ops->trigger(substream, 0);
158 }
159} 144}
160 145
161static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) 146static 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
163 if (!substream->opened) 148 if (!substream->opened)
164 return; 149 return;
165 substream->ops->trigger(substream, up); 150 substream->ops->trigger(substream, up);
166 if (!up && substream->runtime->event) 151 if (!up)
167 tasklet_kill(&substream->runtime->tasklet); 152 cancel_work_sync(&substream->runtime->event_work);
168} 153}
169 154
170int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream) 155int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
@@ -926,7 +911,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
926 } 911 }
927 if (result > 0) { 912 if (result > 0) {
928 if (runtime->event) 913 if (runtime->event)
929 tasklet_schedule(&runtime->tasklet); 914 schedule_work(&runtime->event_work);
930 else if (snd_rawmidi_ready(substream)) 915 else if (snd_rawmidi_ready(substream))
931 wake_up(&runtime->sleep); 916 wake_up(&runtime->sleep);
932 } 917 }