aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-07-16 06:17:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-25 17:07:24 -0400
commit409972c1c8678bb0c28eb0417054e2794dd59ec9 (patch)
tree8f7ce94129d2d04014ab538c67074b5c7fac8acf /sound
parent782e9cac197a38391820b425a4645e5bda7d121b (diff)
ALSA: seq-oss: Initialize MIDI clients asynchronously
commit 256ca9c3ad5013ff8a8f165e5a82fab437628c8e upstream. We've got bug reports that the module loading stuck on Debian system with 3.10 kernel. The debugging session revealed that the initial registration of OSS sequencer clients stuck at module loading time, which involves again with request_module() at the init phase. This is triggered only by special --install stuff Debian is using, but it's still not good to have such loops. As a workaround, call the registration part asynchronously. This is a better approach irrespective of the hang fix, in anyway. Reported-and-tested-by: Philipp Matthias Hahn <pmhahn@pmhahn.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/seq/oss/seq_oss_init.c16
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c2
2 files changed, 14 insertions, 4 deletions
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index e3cb46fef2c7..b3f39b5ed742 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -31,6 +31,7 @@
31#include <linux/export.h> 31#include <linux/export.h>
32#include <linux/moduleparam.h> 32#include <linux/moduleparam.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/workqueue.h>
34 35
35/* 36/*
36 * common variables 37 * common variables
@@ -60,6 +61,14 @@ static void free_devinfo(void *private);
60#define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec) 61#define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec)
61 62
62 63
64/* call snd_seq_oss_midi_lookup_ports() asynchronously */
65static void async_call_lookup_ports(struct work_struct *work)
66{
67 snd_seq_oss_midi_lookup_ports(system_client);
68}
69
70static DECLARE_WORK(async_lookup_work, async_call_lookup_ports);
71
63/* 72/*
64 * create sequencer client for OSS sequencer 73 * create sequencer client for OSS sequencer
65 */ 74 */
@@ -85,9 +94,6 @@ snd_seq_oss_create_client(void)
85 system_client = rc; 94 system_client = rc;
86 debug_printk(("new client = %d\n", rc)); 95 debug_printk(("new client = %d\n", rc));
87 96
88 /* look up midi devices */
89 snd_seq_oss_midi_lookup_ports(system_client);
90
91 /* create annoucement receiver port */ 97 /* create annoucement receiver port */
92 memset(port, 0, sizeof(*port)); 98 memset(port, 0, sizeof(*port));
93 strcpy(port->name, "Receiver"); 99 strcpy(port->name, "Receiver");
@@ -115,6 +121,9 @@ snd_seq_oss_create_client(void)
115 } 121 }
116 rc = 0; 122 rc = 0;
117 123
124 /* look up midi devices */
125 schedule_work(&async_lookup_work);
126
118 __error: 127 __error:
119 kfree(port); 128 kfree(port);
120 return rc; 129 return rc;
@@ -160,6 +169,7 @@ receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic
160int 169int
161snd_seq_oss_delete_client(void) 170snd_seq_oss_delete_client(void)
162{ 171{
172 cancel_work_sync(&async_lookup_work);
163 if (system_client >= 0) 173 if (system_client >= 0)
164 snd_seq_delete_kernel_client(system_client); 174 snd_seq_delete_kernel_client(system_client);
165 175
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 677dc84590c7..862d84893ee8 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -72,7 +72,7 @@ static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev,
72 * look up the existing ports 72 * look up the existing ports
73 * this looks a very exhausting job. 73 * this looks a very exhausting job.
74 */ 74 */
75int __init 75int
76snd_seq_oss_midi_lookup_ports(int client) 76snd_seq_oss_midi_lookup_ports(int client)
77{ 77{
78 struct snd_seq_client_info *clinfo; 78 struct snd_seq_client_info *clinfo;