at v3.19-rc2 616 lines 15 kB view raw
1/* 2 * ALSA sequencer device management 3 * Copyright (c) 1999 by Takashi Iwai <tiwai@suse.de> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 * 20 *---------------------------------------------------------------- 21 * 22 * This device handler separates the card driver module from sequencer 23 * stuff (sequencer core, synth drivers, etc), so that user can avoid 24 * to spend unnecessary resources e.g. if he needs only listening to 25 * MP3s. 26 * 27 * The card (or lowlevel) driver creates a sequencer device entry 28 * via snd_seq_device_new(). This is an entry pointer to communicate 29 * with the sequencer device "driver", which is involved with the 30 * actual part to communicate with the sequencer core. 31 * Each sequencer device entry has an id string and the corresponding 32 * driver with the same id is loaded when required. For example, 33 * lowlevel codes to access emu8000 chip on sbawe card are included in 34 * emu8000-synth module. To activate this module, the hardware 35 * resources like i/o port are passed via snd_seq_device argument. 36 * 37 */ 38 39#include <linux/init.h> 40#include <linux/module.h> 41#include <sound/core.h> 42#include <sound/info.h> 43#include <sound/seq_device.h> 44#include <sound/seq_kernel.h> 45#include <sound/initval.h> 46#include <linux/kmod.h> 47#include <linux/slab.h> 48#include <linux/mutex.h> 49 50MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); 51MODULE_DESCRIPTION("ALSA sequencer device management"); 52MODULE_LICENSE("GPL"); 53 54/* driver state */ 55#define DRIVER_EMPTY 0 56#define DRIVER_LOADED (1<<0) 57#define DRIVER_REQUESTED (1<<1) 58#define DRIVER_LOCKED (1<<2) 59#define DRIVER_REQUESTING (1<<3) 60 61struct ops_list { 62 char id[ID_LEN]; /* driver id */ 63 int driver; /* driver state */ 64 int used; /* reference counter */ 65 int argsize; /* argument size */ 66 67 /* operators */ 68 struct snd_seq_dev_ops ops; 69 70 /* registered devices */ 71 struct list_head dev_list; /* list of devices */ 72 int num_devices; /* number of associated devices */ 73 int num_init_devices; /* number of initialized devices */ 74 struct mutex reg_mutex; 75 76 struct list_head list; /* next driver */ 77}; 78 79 80static LIST_HEAD(opslist); 81static int num_ops; 82static DEFINE_MUTEX(ops_mutex); 83#ifdef CONFIG_PROC_FS 84static struct snd_info_entry *info_entry; 85#endif 86 87/* 88 * prototypes 89 */ 90static int snd_seq_device_free(struct snd_seq_device *dev); 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 102/* 103 * show all drivers and their status 104 */ 105 106#ifdef CONFIG_PROC_FS 107static void snd_seq_device_info(struct snd_info_entry *entry, 108 struct snd_info_buffer *buffer) 109{ 110 struct ops_list *ops; 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} 123#endif 124 125/* 126 * load all registered drivers (called from seq_clientmgr.c) 127 */ 128 129#ifdef CONFIG_MODULES 130/* avoid auto-loading during module_init() */ 131static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */ 132void snd_seq_autoload_lock(void) 133{ 134 atomic_inc(&snd_seq_in_init); 135} 136 137void snd_seq_autoload_unlock(void) 138{ 139 atomic_dec(&snd_seq_in_init); 140} 141 142static void autoload_drivers(void) 143{ 144 /* avoid reentrance */ 145 if (atomic_inc_return(&snd_seq_in_init) == 1) { 146 struct ops_list *ops; 147 148 mutex_lock(&ops_mutex); 149 list_for_each_entry(ops, &opslist, list) { 150 if ((ops->driver & DRIVER_REQUESTING) && 151 !(ops->driver & DRIVER_REQUESTED)) { 152 ops->used++; 153 mutex_unlock(&ops_mutex); 154 ops->driver |= DRIVER_REQUESTED; 155 request_module("snd-%s", ops->id); 156 mutex_lock(&ops_mutex); 157 ops->used--; 158 } 159 } 160 mutex_unlock(&ops_mutex); 161 } 162 atomic_dec(&snd_seq_in_init); 163} 164 165static void call_autoload(struct work_struct *work) 166{ 167 autoload_drivers(); 168} 169 170static DECLARE_WORK(autoload_work, call_autoload); 171 172static void try_autoload(struct ops_list *ops) 173{ 174 if (!ops->driver) { 175 ops->driver |= DRIVER_REQUESTING; 176 schedule_work(&autoload_work); 177 } 178} 179 180static void queue_autoload_drivers(void) 181{ 182 struct ops_list *ops; 183 184 mutex_lock(&ops_mutex); 185 list_for_each_entry(ops, &opslist, list) 186 try_autoload(ops); 187 mutex_unlock(&ops_mutex); 188} 189 190void snd_seq_autoload_init(void) 191{ 192 atomic_dec(&snd_seq_in_init); 193#ifdef CONFIG_SND_SEQUENCER_MODULE 194 /* initial autoload only when snd-seq is a module */ 195 queue_autoload_drivers(); 196#endif 197} 198#else 199#define try_autoload(ops) /* NOP */ 200#endif 201 202void snd_seq_device_load_drivers(void) 203{ 204#ifdef CONFIG_MODULES 205 queue_autoload_drivers(); 206 flush_work(&autoload_work); 207#endif 208} 209 210/* 211 * register a sequencer device 212 * card = card info 213 * device = device number (if any) 214 * id = id of driver 215 * result = return pointer (NULL allowed if unnecessary) 216 */ 217int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, 218 struct snd_seq_device **result) 219{ 220 struct snd_seq_device *dev; 221 struct ops_list *ops; 222 int err; 223 static struct snd_device_ops dops = { 224 .dev_free = snd_seq_device_dev_free, 225 .dev_register = snd_seq_device_dev_register, 226 .dev_disconnect = snd_seq_device_dev_disconnect, 227 }; 228 229 if (result) 230 *result = NULL; 231 232 if (snd_BUG_ON(!id)) 233 return -EINVAL; 234 235 ops = find_driver(id, 1); 236 if (ops == NULL) 237 return -ENOMEM; 238 239 dev = kzalloc(sizeof(*dev)*2 + argsize, GFP_KERNEL); 240 if (dev == NULL) { 241 unlock_driver(ops); 242 return -ENOMEM; 243 } 244 245 /* set up device info */ 246 dev->card = card; 247 dev->device = device; 248 strlcpy(dev->id, id, sizeof(dev->id)); 249 dev->argsize = argsize; 250 dev->status = SNDRV_SEQ_DEVICE_FREE; 251 252 /* add this device to the list */ 253 mutex_lock(&ops->reg_mutex); 254 list_add_tail(&dev->list, &ops->dev_list); 255 ops->num_devices++; 256 mutex_unlock(&ops->reg_mutex); 257 258 if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) { 259 snd_seq_device_free(dev); 260 return err; 261 } 262 263 try_autoload(ops); 264 unlock_driver(ops); 265 266 if (result) 267 *result = dev; 268 269 return 0; 270} 271 272/* 273 * free the existing device 274 */ 275static int snd_seq_device_free(struct snd_seq_device *dev) 276{ 277 struct ops_list *ops; 278 279 if (snd_BUG_ON(!dev)) 280 return -EINVAL; 281 282 ops = find_driver(dev->id, 0); 283 if (ops == NULL) 284 return -ENXIO; 285 286 /* remove the device from the list */ 287 mutex_lock(&ops->reg_mutex); 288 list_del(&dev->list); 289 ops->num_devices--; 290 mutex_unlock(&ops->reg_mutex); 291 292 free_device(dev, ops); 293 if (dev->private_free) 294 dev->private_free(dev); 295 kfree(dev); 296 297 unlock_driver(ops); 298 299 return 0; 300} 301 302static int snd_seq_device_dev_free(struct snd_device *device) 303{ 304 struct snd_seq_device *dev = device->device_data; 305 return snd_seq_device_free(dev); 306} 307 308/* 309 * register the device 310 */ 311static int snd_seq_device_dev_register(struct snd_device *device) 312{ 313 struct snd_seq_device *dev = device->device_data; 314 struct ops_list *ops; 315 316 ops = find_driver(dev->id, 0); 317 if (ops == NULL) 318 return -ENOENT; 319 320 /* initialize this device if the corresponding driver was 321 * already loaded 322 */ 323 if (ops->driver & DRIVER_LOADED) 324 init_device(dev, ops); 325 326 unlock_driver(ops); 327 return 0; 328} 329 330/* 331 * disconnect the device 332 */ 333static int snd_seq_device_dev_disconnect(struct snd_device *device) 334{ 335 struct snd_seq_device *dev = device->device_data; 336 struct ops_list *ops; 337 338 ops = find_driver(dev->id, 0); 339 if (ops == NULL) 340 return -ENOENT; 341 342 free_device(dev, ops); 343 344 unlock_driver(ops); 345 return 0; 346} 347 348/* 349 * register device driver 350 * id = driver id 351 * entry = driver operators - duplicated to each instance 352 */ 353int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, 354 int argsize) 355{ 356 struct ops_list *ops; 357 struct snd_seq_device *dev; 358 359 if (id == NULL || entry == NULL || 360 entry->init_device == NULL || entry->free_device == NULL) 361 return -EINVAL; 362 363 ops = find_driver(id, 1); 364 if (ops == NULL) 365 return -ENOMEM; 366 if (ops->driver & DRIVER_LOADED) { 367 pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id); 368 unlock_driver(ops); 369 return -EBUSY; 370 } 371 372 mutex_lock(&ops->reg_mutex); 373 /* copy driver operators */ 374 ops->ops = *entry; 375 ops->driver |= DRIVER_LOADED; 376 ops->argsize = argsize; 377 378 /* initialize existing devices if necessary */ 379 list_for_each_entry(dev, &ops->dev_list, list) { 380 init_device(dev, ops); 381 } 382 mutex_unlock(&ops->reg_mutex); 383 384 unlock_driver(ops); 385 386 return 0; 387} 388 389 390/* 391 * create driver record 392 */ 393static struct ops_list * create_driver(char *id) 394{ 395 struct ops_list *ops; 396 397 ops = kzalloc(sizeof(*ops), GFP_KERNEL); 398 if (ops == NULL) 399 return ops; 400 401 /* set up driver entry */ 402 strlcpy(ops->id, id, sizeof(ops->id)); 403 mutex_init(&ops->reg_mutex); 404 /* 405 * The ->reg_mutex locking rules are per-driver, so we create 406 * separate per-driver lock classes: 407 */ 408 lockdep_set_class(&ops->reg_mutex, (struct lock_class_key *)id); 409 410 ops->driver = DRIVER_EMPTY; 411 INIT_LIST_HEAD(&ops->dev_list); 412 /* lock this instance */ 413 ops->used = 1; 414 415 /* register driver entry */ 416 mutex_lock(&ops_mutex); 417 list_add_tail(&ops->list, &opslist); 418 num_ops++; 419 mutex_unlock(&ops_mutex); 420 421 return ops; 422} 423 424 425/* 426 * unregister the specified driver 427 */ 428int snd_seq_device_unregister_driver(char *id) 429{ 430 struct ops_list *ops; 431 struct snd_seq_device *dev; 432 433 ops = find_driver(id, 0); 434 if (ops == NULL) 435 return -ENXIO; 436 if (! (ops->driver & DRIVER_LOADED) || 437 (ops->driver & DRIVER_LOCKED)) { 438 pr_err("ALSA: seq: driver_unregister: cannot unload driver '%s': status=%x\n", 439 id, ops->driver); 440 unlock_driver(ops); 441 return -EBUSY; 442 } 443 444 /* close and release all devices associated with this driver */ 445 mutex_lock(&ops->reg_mutex); 446 ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */ 447 list_for_each_entry(dev, &ops->dev_list, list) { 448 free_device(dev, ops); 449 } 450 451 ops->driver = 0; 452 if (ops->num_init_devices > 0) 453 pr_err("ALSA: seq: free_driver: init_devices > 0!! (%d)\n", 454 ops->num_init_devices); 455 mutex_unlock(&ops->reg_mutex); 456 457 unlock_driver(ops); 458 459 /* remove empty driver entries */ 460 remove_drivers(); 461 462 return 0; 463} 464 465 466/* 467 * remove empty driver entries 468 */ 469static void remove_drivers(void) 470{ 471 struct list_head *head; 472 473 mutex_lock(&ops_mutex); 474 head = opslist.next; 475 while (head != &opslist) { 476 struct ops_list *ops = list_entry(head, struct ops_list, list); 477 if (! (ops->driver & DRIVER_LOADED) && 478 ops->used == 0 && ops->num_devices == 0) { 479 head = head->next; 480 list_del(&ops->list); 481 kfree(ops); 482 num_ops--; 483 } else 484 head = head->next; 485 } 486 mutex_unlock(&ops_mutex); 487} 488 489/* 490 * initialize the device - call init_device operator 491 */ 492static int init_device(struct snd_seq_device *dev, struct ops_list *ops) 493{ 494 if (! (ops->driver & DRIVER_LOADED)) 495 return 0; /* driver is not loaded yet */ 496 if (dev->status != SNDRV_SEQ_DEVICE_FREE) 497 return 0; /* already initialized */ 498 if (ops->argsize != dev->argsize) { 499 pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n", 500 dev->name, ops->id, ops->argsize, dev->argsize); 501 return -EINVAL; 502 } 503 if (ops->ops.init_device(dev) >= 0) { 504 dev->status = SNDRV_SEQ_DEVICE_REGISTERED; 505 ops->num_init_devices++; 506 } else { 507 pr_err("ALSA: seq: init_device failed: %s: %s\n", 508 dev->name, dev->id); 509 } 510 511 return 0; 512} 513 514/* 515 * release the device - call free_device operator 516 */ 517static int free_device(struct snd_seq_device *dev, struct ops_list *ops) 518{ 519 int result; 520 521 if (! (ops->driver & DRIVER_LOADED)) 522 return 0; /* driver is not loaded yet */ 523 if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED) 524 return 0; /* not registered */ 525 if (ops->argsize != dev->argsize) { 526 pr_err("ALSA: seq: incompatible device '%s' for plug-in '%s' (%d %d)\n", 527 dev->name, ops->id, ops->argsize, dev->argsize); 528 return -EINVAL; 529 } 530 if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) { 531 dev->status = SNDRV_SEQ_DEVICE_FREE; 532 dev->driver_data = NULL; 533 ops->num_init_devices--; 534 } else { 535 pr_err("ALSA: seq: free_device failed: %s: %s\n", 536 dev->name, dev->id); 537 } 538 539 return 0; 540} 541 542/* 543 * find the matching driver with given id 544 */ 545static struct ops_list * find_driver(char *id, int create_if_empty) 546{ 547 struct ops_list *ops; 548 549 mutex_lock(&ops_mutex); 550 list_for_each_entry(ops, &opslist, list) { 551 if (strcmp(ops->id, id) == 0) { 552 ops->used++; 553 mutex_unlock(&ops_mutex); 554 return ops; 555 } 556 } 557 mutex_unlock(&ops_mutex); 558 if (create_if_empty) 559 return create_driver(id); 560 return NULL; 561} 562 563static void unlock_driver(struct ops_list *ops) 564{ 565 mutex_lock(&ops_mutex); 566 ops->used--; 567 mutex_unlock(&ops_mutex); 568} 569 570 571/* 572 * module part 573 */ 574 575static int __init alsa_seq_device_init(void) 576{ 577#ifdef CONFIG_PROC_FS 578 info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", 579 snd_seq_root); 580 if (info_entry == NULL) 581 return -ENOMEM; 582 info_entry->content = SNDRV_INFO_CONTENT_TEXT; 583 info_entry->c.text.read = snd_seq_device_info; 584 if (snd_info_register(info_entry) < 0) { 585 snd_info_free_entry(info_entry); 586 return -ENOMEM; 587 } 588#endif 589 return 0; 590} 591 592static void __exit alsa_seq_device_exit(void) 593{ 594#ifdef CONFIG_MODULES 595 cancel_work_sync(&autoload_work); 596#endif 597 remove_drivers(); 598#ifdef CONFIG_PROC_FS 599 snd_info_free_entry(info_entry); 600#endif 601 if (num_ops) 602 pr_err("ALSA: seq: drivers not released (%d)\n", num_ops); 603} 604 605module_init(alsa_seq_device_init) 606module_exit(alsa_seq_device_exit) 607 608EXPORT_SYMBOL(snd_seq_device_load_drivers); 609EXPORT_SYMBOL(snd_seq_device_new); 610EXPORT_SYMBOL(snd_seq_device_register_driver); 611EXPORT_SYMBOL(snd_seq_device_unregister_driver); 612#ifdef CONFIG_MODULES 613EXPORT_SYMBOL(snd_seq_autoload_init); 614EXPORT_SYMBOL(snd_seq_autoload_lock); 615EXPORT_SYMBOL(snd_seq_autoload_unlock); 616#endif