aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-02-12 04:51:59 -0500
committerTakashi Iwai <tiwai@suse.de>2015-02-12 05:35:11 -0500
commit7c37ae5c625aaa4836466cfaea829a3199dfc571 (patch)
tree14ea2a629eeb1b09154b41bf22617bf9d7f7fcd2
parent72496edcf85e048b4c5373d518e4f27938d9594e (diff)
ALSA: seq: Rewrite sequencer device binding with standard bus
We've used the old house-made code for binding the sequencer device and driver. This can be far better implemented with the standard bus nowadays. This patch refactors the whole sequencer binding code with the bus /sys/bus/snd_seq. The devices appear as id-card-device on this bus and are bound with the drivers corresponding to the given id like the former implementation. The module autoload is also kept like before. There is no change in API functions by this patch, and almost all transitions are kept inside seq_device.c. The proc file output will change slightly but kept compatible as much as possible. Further integration works will follow in later patches. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/seq_device.h3
-rw-r--r--sound/core/seq/seq_device.c541
2 files changed, 170 insertions, 374 deletions
diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index d52433563da2..ea256b825146 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -43,8 +43,11 @@ struct snd_seq_device {
43 void *private_data; /* private data for the caller */ 43 void *private_data; /* private data for the caller */
44 void (*private_free)(struct snd_seq_device *device); 44 void (*private_free)(struct snd_seq_device *device);
45 struct list_head list; /* link to next device */ 45 struct list_head list; /* link to next device */
46 struct device dev;
46}; 47};
47 48
49#define to_seq_dev(_dev) \
50 container_of(_dev, struct snd_seq_device, dev)
48 51
49/* driver operators 52/* driver operators
50 * init_device: 53 * init_device:
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 075a66c0cc6a..d3320ffe43c2 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -36,6 +36,7 @@
36 * 36 *
37 */ 37 */
38 38
39#include <linux/device.h>
39#include <linux/init.h> 40#include <linux/init.h>
40#include <linux/module.h> 41#include <linux/module.h>
41#include <sound/core.h> 42#include <sound/core.h>
@@ -51,77 +52,57 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
51MODULE_DESCRIPTION("ALSA sequencer device management"); 52MODULE_DESCRIPTION("ALSA sequencer device management");
52MODULE_LICENSE("GPL"); 53MODULE_LICENSE("GPL");
53 54
54/* driver state */ 55struct snd_seq_driver {
55#define DRIVER_EMPTY 0 56 struct device_driver driver;
56#define DRIVER_LOADED (1<<0) 57 char id[ID_LEN];
57#define DRIVER_REQUESTED (1<<1) 58 int argsize;
58#define DRIVER_LOCKED (1<<2) 59 struct snd_seq_dev_ops ops;
59#define DRIVER_REQUESTING (1<<3) 60};
60 61
61struct ops_list { 62#define to_seq_drv(_drv) \
62 char id[ID_LEN]; /* driver id */ 63 container_of(_drv, struct snd_seq_driver, driver)
63 int driver; /* driver state */
64 int used; /* reference counter */
65 int argsize; /* argument size */
66 64
67 /* operators */ 65/*
68 struct snd_seq_dev_ops ops; 66 * bus definition
67 */
68static int snd_seq_bus_match(struct device *dev, struct device_driver *drv)
69{
70 struct snd_seq_device *sdev = to_seq_dev(dev);
71 struct snd_seq_driver *sdrv = to_seq_drv(drv);
69 72
70 /* registered devices */ 73 return strcmp(sdrv->id, sdev->id) == 0 &&
71 struct list_head dev_list; /* list of devices */ 74 sdrv->argsize == sdev->argsize;
72 int num_devices; /* number of associated devices */ 75}
73 int num_init_devices; /* number of initialized devices */
74 struct mutex reg_mutex;
75 76
76 struct list_head list; /* next driver */ 77static struct bus_type snd_seq_bus_type = {
78 .name = "snd_seq",
79 .match = snd_seq_bus_match,
77}; 80};
78 81
79 82/*
80static LIST_HEAD(opslist); 83 * proc interface -- just for compatibility
81static int num_ops; 84 */
82static DEFINE_MUTEX(ops_mutex);
83#ifdef CONFIG_PROC_FS 85#ifdef CONFIG_PROC_FS
84static struct snd_info_entry *info_entry; 86static struct snd_info_entry *info_entry;
85#endif
86 87
87/* 88static int print_dev_info(struct device *dev, void *data)
88 * prototypes 89{
89 */ 90 struct snd_seq_device *sdev = to_seq_dev(dev);
90static int snd_seq_device_free(struct snd_seq_device *dev); 91 struct snd_info_buffer *buffer = data;
91static int snd_seq_device_dev_free(struct snd_device *device);
92static int snd_seq_device_dev_register(struct snd_device *device);
93static int snd_seq_device_dev_disconnect(struct snd_device *device);
94
95static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
96static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
97static struct ops_list *find_driver(char *id, int create_if_empty);
98static struct ops_list *create_driver(char *id);
99static void unlock_driver(struct ops_list *ops);
100static void remove_drivers(void);
101 92
102/* 93 snd_iprintf(buffer, "snd-%s,%s,%d\n", sdev->id,
103 * show all drivers and their status 94 dev->driver ? "loaded" : "empty",
104 */ 95 dev->driver ? 1 : 0);
96 return 0;
97}
105 98
106#ifdef CONFIG_PROC_FS
107static void snd_seq_device_info(struct snd_info_entry *entry, 99static void snd_seq_device_info(struct snd_info_entry *entry,
108 struct snd_info_buffer *buffer) 100 struct snd_info_buffer *buffer)
109{ 101{
110 struct ops_list *ops; 102 bus_for_each_dev(&snd_seq_bus_type, NULL, buffer, print_dev_info);
111
112 mutex_lock(&ops_mutex);
113 list_for_each_entry(ops, &opslist, list) {
114 snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
115 ops->id,
116 ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
117 ops->driver & DRIVER_REQUESTED ? ",requested" : "",
118 ops->driver & DRIVER_LOCKED ? ",locked" : "",
119 ops->num_devices);
120 }
121 mutex_unlock(&ops_mutex);
122} 103}
123#endif 104#endif
124 105
125/* 106/*
126 * load all registered drivers (called from seq_clientmgr.c) 107 * load all registered drivers (called from seq_clientmgr.c)
127 */ 108 */
@@ -141,52 +122,29 @@ void snd_seq_autoload_unlock(void)
141} 122}
142EXPORT_SYMBOL(snd_seq_autoload_unlock); 123EXPORT_SYMBOL(snd_seq_autoload_unlock);
143 124
144static void autoload_drivers(void) 125static int request_seq_drv(struct device *dev, void *data)
145{ 126{
146 /* avoid reentrance */ 127 struct snd_seq_device *sdev = to_seq_dev(dev);
147 if (atomic_inc_return(&snd_seq_in_init) == 1) {
148 struct ops_list *ops;
149
150 mutex_lock(&ops_mutex);
151 list_for_each_entry(ops, &opslist, list) {
152 if ((ops->driver & DRIVER_REQUESTING) &&
153 !(ops->driver & DRIVER_REQUESTED)) {
154 ops->used++;
155 mutex_unlock(&ops_mutex);
156 ops->driver |= DRIVER_REQUESTED;
157 request_module("snd-%s", ops->id);
158 mutex_lock(&ops_mutex);
159 ops->used--;
160 }
161 }
162 mutex_unlock(&ops_mutex);
163 }
164 atomic_dec(&snd_seq_in_init);
165}
166 128
167static void call_autoload(struct work_struct *work) 129 if (!dev->driver)
168{ 130 request_module("snd-%s", sdev->id);
169 autoload_drivers(); 131 return 0;
170} 132}
171 133
172static DECLARE_WORK(autoload_work, call_autoload); 134static void autoload_drivers(struct work_struct *work)
173
174static void try_autoload(struct ops_list *ops)
175{ 135{
176 if (!ops->driver) { 136 /* avoid reentrance */
177 ops->driver |= DRIVER_REQUESTING; 137 if (atomic_inc_return(&snd_seq_in_init) == 1)
178 schedule_work(&autoload_work); 138 bus_for_each_dev(&snd_seq_bus_type, NULL, NULL,
179 } 139 request_seq_drv);
140 atomic_dec(&snd_seq_in_init);
180} 141}
181 142
143static DECLARE_WORK(autoload_work, autoload_drivers);
144
182static void queue_autoload_drivers(void) 145static void queue_autoload_drivers(void)
183{ 146{
184 struct ops_list *ops; 147 schedule_work(&autoload_work);
185
186 mutex_lock(&ops_mutex);
187 list_for_each_entry(ops, &opslist, list)
188 try_autoload(ops);
189 mutex_unlock(&ops_mutex);
190} 148}
191 149
192void snd_seq_autoload_init(void) 150void snd_seq_autoload_init(void)
@@ -206,10 +164,51 @@ void snd_seq_device_load_drivers(void)
206} 164}
207EXPORT_SYMBOL(snd_seq_device_load_drivers); 165EXPORT_SYMBOL(snd_seq_device_load_drivers);
208#else 166#else
209#define try_autoload(ops) /* NOP */ 167#define queue_autoload_drivers() /* NOP */
210#endif 168#endif
211 169
212/* 170/*
171 * device management
172 */
173static int snd_seq_device_dev_free(struct snd_device *device)
174{
175 struct snd_seq_device *dev = device->device_data;
176
177 put_device(&dev->dev);
178 return 0;
179}
180
181static int snd_seq_device_dev_register(struct snd_device *device)
182{
183 struct snd_seq_device *dev = device->device_data;
184 int err;
185
186 err = device_add(&dev->dev);
187 if (err < 0)
188 return err;
189 if (!dev->dev.driver)
190 queue_autoload_drivers();
191 return 0;
192}
193
194static int snd_seq_device_dev_disconnect(struct snd_device *device)
195{
196 struct snd_seq_device *dev = device->device_data;
197
198 device_del(&dev->dev);
199 return 0;
200}
201
202static void snd_seq_dev_release(struct device *dev)
203{
204 struct snd_seq_device *sdev = to_seq_dev(dev);
205
206 if (sdev->private_free)
207 sdev->private_free(sdev);
208 kfree(sdev);
209}
210
211/*
213 * register a sequencer device 212 * register a sequencer device
214 * card = card info 213 * card = card info
215 * device = device number (if any) 214 * device = device number (if any)
@@ -220,7 +219,6 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
220 struct snd_seq_device **result) 219 struct snd_seq_device **result)
221{ 220{
222 struct snd_seq_device *dev; 221 struct snd_seq_device *dev;
223 struct ops_list *ops;
224 int err; 222 int err;
225 static struct snd_device_ops dops = { 223 static struct snd_device_ops dops = {
226 .dev_free = snd_seq_device_dev_free, 224 .dev_free = snd_seq_device_dev_free,
@@ -234,15 +232,9 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
234 if (snd_BUG_ON(!id)) 232 if (snd_BUG_ON(!id))
235 return -EINVAL; 233 return -EINVAL;
236 234
237 ops = find_driver(id, 1); 235 dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL);
238 if (ops == NULL) 236 if (!dev)
239 return -ENOMEM;
240
241 dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL);
242 if (dev == NULL) {
243 unlock_driver(ops);
244 return -ENOMEM; 237 return -ENOMEM;
245 }
246 238
247 /* set up device info */ 239 /* set up device info */
248 dev->card = card; 240 dev->card = card;
@@ -251,20 +243,19 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
251 dev->argsize = argsize; 243 dev->argsize = argsize;
252 dev->status = SNDRV_SEQ_DEVICE_FREE; 244 dev->status = SNDRV_SEQ_DEVICE_FREE;
253 245
254 /* add this device to the list */ 246 device_initialize(&dev->dev);
255 mutex_lock(&ops->reg_mutex); 247 dev->dev.parent = &card->card_dev;
256 list_add_tail(&dev->list, &ops->dev_list); 248 dev->dev.bus = &snd_seq_bus_type;
257 ops->num_devices++; 249 dev->dev.release = snd_seq_dev_release;
258 mutex_unlock(&ops->reg_mutex); 250 dev_set_name(&dev->dev, "%s-%d-%d", dev->id, card->number, device);
259 251
260 if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) { 252 /* add this device to the list */
261 snd_seq_device_free(dev); 253 err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops);
254 if (err < 0) {
255 put_device(&dev->dev);
262 return err; 256 return err;
263 } 257 }
264 258
265 try_autoload(ops);
266 unlock_driver(ops);
267
268 if (result) 259 if (result)
269 *result = dev; 260 *result = dev;
270 261
@@ -273,82 +264,33 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
273EXPORT_SYMBOL(snd_seq_device_new); 264EXPORT_SYMBOL(snd_seq_device_new);
274 265
275/* 266/*
276 * free the existing device 267 * driver binding - just pass to each driver callback
277 */
278static int snd_seq_device_free(struct snd_seq_device *dev)
279{
280 struct ops_list *ops;
281
282 if (snd_BUG_ON(!dev))
283 return -EINVAL;
284
285 ops = find_driver(dev->id, 0);
286 if (ops == NULL)
287 return -ENXIO;
288
289 /* remove the device from the list */
290 mutex_lock(&ops->reg_mutex);
291 list_del(&dev->list);
292 ops->num_devices--;
293 mutex_unlock(&ops->reg_mutex);
294
295 free_device(dev, ops);
296 if (dev->private_free)
297 dev->private_free(dev);
298 kfree(dev);
299
300 unlock_driver(ops);
301
302 return 0;
303}
304
305static int snd_seq_device_dev_free(struct snd_device *device)
306{
307 struct snd_seq_device *dev = device->device_data;
308 return snd_seq_device_free(dev);
309}
310
311/*
312 * register the device
313 */ 268 */
314static int snd_seq_device_dev_register(struct snd_device *device) 269static int snd_seq_drv_probe(struct device *dev)
315{ 270{
316 struct snd_seq_device *dev = device->device_data; 271 struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
317 struct ops_list *ops; 272 struct snd_seq_device *sdev = to_seq_dev(dev);
318 273 int err;
319 ops = find_driver(dev->id, 0);
320 if (ops == NULL)
321 return -ENOENT;
322
323 /* initialize this device if the corresponding driver was
324 * already loaded
325 */
326 if (ops->driver & DRIVER_LOADED)
327 init_device(dev, ops);
328 274
329 unlock_driver(ops); 275 err = sdrv->ops.init_device(sdev);
276 if (err < 0)
277 return err;
278 sdev->status = SNDRV_SEQ_DEVICE_REGISTERED;
330 return 0; 279 return 0;
331} 280}
332EXPORT_SYMBOL(snd_seq_device_register_driver);
333 281
334/* 282static int snd_seq_drv_remove(struct device *dev)
335 * disconnect the device
336 */
337static int snd_seq_device_dev_disconnect(struct snd_device *device)
338{ 283{
339 struct snd_seq_device *dev = device->device_data; 284 struct snd_seq_driver *sdrv = to_seq_drv(dev->driver);
340 struct ops_list *ops; 285 struct snd_seq_device *sdev = to_seq_dev(dev);
341 286 int err;
342 ops = find_driver(dev->id, 0);
343 if (ops == NULL)
344 return -ENOENT;
345
346 free_device(dev, ops);
347 287
348 unlock_driver(ops); 288 err = sdrv->ops.free_device(sdev);
289 if (err < 0)
290 return err;
291 sdev->status = SNDRV_SEQ_DEVICE_FREE;
349 return 0; 292 return 0;
350} 293}
351EXPORT_SYMBOL(snd_seq_device_unregister_driver);
352 294
353/* 295/*
354 * register device driver 296 * register device driver
@@ -358,226 +300,66 @@ EXPORT_SYMBOL(snd_seq_device_unregister_driver);
358int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, 300int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
359 int argsize) 301 int argsize)
360{ 302{
361 struct ops_list *ops; 303 struct snd_seq_driver *sdrv;
362 struct snd_seq_device *dev; 304 int err;
363 305
364 if (id == NULL || entry == NULL || 306 if (id == NULL || entry == NULL ||
365 entry->init_device == NULL || entry->free_device == NULL) 307 entry->init_device == NULL || entry->free_device == NULL)
366 return -EINVAL; 308 return -EINVAL;
367 309
368 ops = find_driver(id, 1); 310 sdrv = kzalloc(sizeof(*sdrv), GFP_KERNEL);
369 if (ops == NULL) 311 if (!sdrv)
370 return -ENOMEM; 312 return -ENOMEM;
371 if (ops->driver & DRIVER_LOADED) {
372 pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id);
373 unlock_driver(ops);
374 return -EBUSY;
375 }
376
377 mutex_lock(&ops->reg_mutex);
378 /* copy driver operators */
379 ops->ops = *entry;
380 ops->driver |= DRIVER_LOADED;
381 ops->argsize = argsize;
382 313
383 /* initialize existing devices if necessary */ 314 sdrv->driver.name = id;
384 list_for_each_entry(dev, &ops->dev_list, list) { 315 sdrv->driver.bus = &snd_seq_bus_type;
385 init_device(dev, ops); 316 sdrv->driver.probe = snd_seq_drv_probe;
386 } 317 sdrv->driver.remove = snd_seq_drv_remove;
387 mutex_unlock(&ops->reg_mutex); 318 strlcpy(sdrv->id, id, sizeof(sdrv->id));
388 319 sdrv->argsize = argsize;
389 unlock_driver(ops); 320 sdrv->ops = *entry;
390 321
391 return 0; 322 err = driver_register(&sdrv->driver);
323 if (err < 0)
324 kfree(sdrv);
325 return err;
392} 326}
327EXPORT_SYMBOL(snd_seq_device_register_driver);
393 328
394 329/* callback to find a specific driver; data is a pointer to the id string ptr.
395/* 330 * when the id matches, store the driver pointer in return and break the loop.
396 * create driver record
397 */ 331 */
398static struct ops_list * create_driver(char *id) 332static int find_drv(struct device_driver *drv, void *data)
399{ 333{
400 struct ops_list *ops; 334 struct snd_seq_driver *sdrv = to_seq_drv(drv);
401 335 void **ptr = (void **)data;
402 ops = kzalloc(sizeof(*ops), GFP_KERNEL);
403 if (ops == NULL)
404 return ops;
405
406 /* set up driver entry */
407 strlcpy(ops->id, id, sizeof(ops->id));
408 mutex_init(&ops->reg_mutex);
409 /*
410 * The ->reg_mutex locking rules are per-driver, so we create
411 * separate per-driver lock classes:
412 */
413 lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id);
414
415 ops->driver = DRIVER_EMPTY;
416 INIT_LIST_HEAD(&ops->dev_list);
417 /* lock this instance */
418 ops->used = 1;
419
420 /* register driver entry */
421 mutex_lock(&ops_mutex);
422 list_add_tail(&ops->list, &opslist);
423 num_ops++;
424 mutex_unlock(&ops_mutex);
425
426 return ops;
427}
428 336
337 if (strcmp(sdrv->id, *ptr))
338 return 0; /* id don't match, continue the loop */
339 *ptr = sdrv;
340 return 1; /* break the loop */
341}
429 342
430/* 343/*
431 * unregister the specified driver 344 * unregister the specified driver
432 */ 345 */
433int snd_seq_device_unregister_driver(char *id) 346int snd_seq_device_unregister_driver(char *id)
434{ 347{
435 struct ops_list *ops; 348 struct snd_seq_driver *sdrv = (struct snd_seq_driver *)id;
436 struct snd_seq_device *dev;
437 349
438 ops = find_driver(id, 0); 350 if (!bus_for_each_drv(&snd_seq_bus_type, NULL, &sdrv, find_drv))
439 if (ops == NULL)
440 return -ENXIO; 351 return -ENXIO;
441 if (! (ops->driver & DRIVER_LOADED) || 352 driver_unregister(&sdrv->driver);
442 (ops->driver & DRIVER_LOCKED)) { 353 kfree(sdrv);
443 pr_err("ALSA: seq: driver_unregister: cannot unload driver '%s': status=%x\n",
444 id, ops->driver);
445 unlock_driver(ops);
446 return -EBUSY;
447 }
448
449 /* close and release all devices associated with this driver */
450 mutex_lock(&ops->reg_mutex);
451 ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
452 list_for_each_entry(dev, &ops->dev_list, list) {
453 free_device(dev, ops);
454 }
455
456 ops->driver = 0;
457 if (ops->num_init_devices > 0)
458 pr_err("ALSA: seq: free_driver: init_devices > 0!! (%d)\n",
459 ops->num_init_devices);
460 mutex_unlock(&ops->reg_mutex);
461
462 unlock_driver(ops);
463
464 /* remove empty driver entries */
465 remove_drivers();
466
467 return 0; 354 return 0;
468} 355}
469 356EXPORT_SYMBOL(snd_seq_device_unregister_driver);
470
471/*
472 * remove empty driver entries
473 */
474static void remove_drivers(void)
475{
476 struct list_head *head;
477
478 mutex_lock(&ops_mutex);
479 head = opslist.next;
480 while (head != &opslist) {
481 struct ops_list *ops = list_entry(head, struct ops_list, list);
482 if (! (ops->driver & DRIVER_LOADED) &&
483 ops->used == 0 && ops->num_devices == 0) {
484 head = head->next;
485 list_del(&ops->list);
486 kfree(ops);
487 num_ops--;
488 } else
489 head = head->next;
490 }
491 mutex_unlock(&ops_mutex);
492}
493
494/*
495 * initialize the device - call init_device operator
496 */
497static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
498{
499 if (! (ops->driver & DRIVER_LOADED))
500 return 0; /* driver is not loaded yet */
501 if (dev->status != SNDRV_SEQ_DEVICE_FREE)
502 return 0; /* already initialized */
503 if (ops->argsize != dev->argsize) {
504 pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n",
505 dev->name, ops->id, ops->argsize, dev->argsize);
506 return -EINVAL;
507 }
508 if (ops->ops.init_device(dev) >= 0) {
509 dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
510 ops->num_init_devices++;
511 } else {
512 pr_err("ALSA: seq: init_device failed: %s: %s\n",
513 dev->name, dev->id);
514 }
515
516 return 0;
517}
518
519/*
520 * release the device - call free_device operator
521 */
522static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
523{
524 int result;
525
526 if (! (ops->driver & DRIVER_LOADED))
527 return 0; /* driver is not loaded yet */
528 if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
529 return 0; /* not registered */
530 if (ops->argsize != dev->argsize) {
531 pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n",
532 dev->name, ops->id, ops->argsize, dev->argsize);
533 return -EINVAL;
534 }
535 if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
536 dev->status = SNDRV_SEQ_DEVICE_FREE;
537 dev->driver_data = NULL;
538 ops->num_init_devices--;
539 } else {
540 pr_err("ALSA: seq: free_device failed: %s: %s\n",
541 dev->name, dev->id);
542 }
543
544 return 0;
545}
546
547/*
548 * find the matching driver with given id
549 */
550static struct ops_list * find_driver(char *id, int create_if_empty)
551{
552 struct ops_list *ops;
553
554 mutex_lock(&ops_mutex);
555 list_for_each_entry(ops, &opslist, list) {
556 if (strcmp(ops->id, id) == 0) {
557 ops->used++;
558 mutex_unlock(&ops_mutex);
559 return ops;
560 }
561 }
562 mutex_unlock(&ops_mutex);
563 if (create_if_empty)
564 return create_driver(id);
565 return NULL;
566}
567
568static void unlock_driver(struct ops_list *ops)
569{
570 mutex_lock(&ops_mutex);
571 ops->used--;
572 mutex_unlock(&ops_mutex);
573}
574
575 357
576/* 358/*
577 * module part 359 * module part
578 */ 360 */
579 361
580static int __init alsa_seq_device_init(void) 362static int __init seq_dev_proc_init(void)
581{ 363{
582#ifdef CONFIG_PROC_FS 364#ifdef CONFIG_PROC_FS
583 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", 365 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
@@ -594,17 +376,28 @@ static int __init alsa_seq_device_init(void)
594 return 0; 376 return 0;
595} 377}
596 378
379static int __init alsa_seq_device_init(void)
380{
381 int err;
382
383 err = bus_register(&snd_seq_bus_type);
384 if (err < 0)
385 return err;
386 err = seq_dev_proc_init();
387 if (err < 0)
388 bus_unregister(&snd_seq_bus_type);
389 return err;
390}
391
597static void __exit alsa_seq_device_exit(void) 392static void __exit alsa_seq_device_exit(void)
598{ 393{
599#ifdef CONFIG_MODULES 394#ifdef CONFIG_MODULES
600 cancel_work_sync(&autoload_work); 395 cancel_work_sync(&autoload_work);
601#endif 396#endif
602 remove_drivers();
603#ifdef CONFIG_PROC_FS 397#ifdef CONFIG_PROC_FS
604 snd_info_free_entry(info_entry); 398 snd_info_free_entry(info_entry);
605#endif 399#endif
606 if (num_ops) 400 bus_unregister(&snd_seq_bus_type);
607 pr_err("ALSA: seq: drivers not released (%d)\n", num_ops);
608} 401}
609 402
610module_init(alsa_seq_device_init) 403module_init(alsa_seq_device_init)