aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2015-01-25 08:34:29 -0500
committerTakashi Iwai <tiwai@suse.de>2015-01-26 07:53:13 -0500
commit0767e95bb96d7fdddcd590fb809e6975d93aebc5 (patch)
tree06c39d6e7a954c97c2812509dcab3800a955e95f
parent6715f728c8b080ab85db0f93f5d9fa6c7d9e906b (diff)
ALSA: seq-dummy: remove deadlock-causing events on close
When the last subscriber to a "Through" port has been removed, the subscribed destination ports might still be active, so it would be wrong to send "all sounds off" and "reset controller" events to them. The proper place for such a shutdown would be the closing of the actual MIDI port (and close_substream() in rawmidi.c already can do this). This also fixes a deadlock when dummy_unuse() tries to send events to its own port that is already locked because it is being freed. Reported-by: Peter Billam <peter@www.pjb.com.au> Cc: <stable@vger.kernel.org> Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/core/seq/seq_dummy.c31
1 files changed, 0 insertions, 31 deletions
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index ec667f158f19..5d905d90d504 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -82,36 +82,6 @@ struct snd_seq_dummy_port {
82static int my_client = -1; 82static int my_client = -1;
83 83
84/* 84/*
85 * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events
86 * to subscribers.
87 * Note: this callback is called only after all subscribers are removed.
88 */
89static int
90dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info)
91{
92 struct snd_seq_dummy_port *p;
93 int i;
94 struct snd_seq_event ev;
95
96 p = private_data;
97 memset(&ev, 0, sizeof(ev));
98 if (p->duplex)
99 ev.source.port = p->connect;
100 else
101 ev.source.port = p->port;
102 ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
103 ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
104 for (i = 0; i < 16; i++) {
105 ev.data.control.channel = i;
106 ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF;
107 snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
108 ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS;
109 snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
110 }
111 return 0;
112}
113
114/*
115 * event input callback - just redirect events to subscribers 85 * event input callback - just redirect events to subscribers
116 */ 86 */
117static int 87static int
@@ -175,7 +145,6 @@ create_port(int idx, int type)
175 | SNDRV_SEQ_PORT_TYPE_PORT; 145 | SNDRV_SEQ_PORT_TYPE_PORT;
176 memset(&pcb, 0, sizeof(pcb)); 146 memset(&pcb, 0, sizeof(pcb));
177 pcb.owner = THIS_MODULE; 147 pcb.owner = THIS_MODULE;
178 pcb.unuse = dummy_unuse;
179 pcb.event_input = dummy_input; 148 pcb.event_input = dummy_input;
180 pcb.private_free = dummy_free; 149 pcb.private_free = dummy_free;
181 pcb.private_data = rec; 150 pcb.private_data = rec;