aboutsummaryrefslogtreecommitdiffstats
path: root/sound/sound_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/sound_core.c')
-rw-r--r--sound/sound_core.c109
1 files changed, 88 insertions, 21 deletions
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 12522e6913d..49c99818659 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -10,6 +10,8 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/device.h> 11#include <linux/device.h>
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/kdev_t.h>
14#include <linux/major.h>
13#include <sound/core.h> 15#include <sound/core.h>
14 16
15#ifdef CONFIG_SOUND_OSS_CORE 17#ifdef CONFIG_SOUND_OSS_CORE
@@ -27,8 +29,10 @@ MODULE_DESCRIPTION("Core sound module");
27MODULE_AUTHOR("Alan Cox"); 29MODULE_AUTHOR("Alan Cox");
28MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
29 31
30static char *sound_nodename(struct device *dev) 32static char *sound_devnode(struct device *dev, mode_t *mode)
31{ 33{
34 if (MAJOR(dev->devt) == SOUND_MAJOR)
35 return NULL;
32 return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev)); 36 return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
33} 37}
34 38
@@ -46,7 +50,7 @@ static int __init init_soundcore(void)
46 return PTR_ERR(sound_class); 50 return PTR_ERR(sound_class);
47 } 51 }
48 52
49 sound_class->nodename = sound_nodename; 53 sound_class->devnode = sound_devnode;
50 54
51 return 0; 55 return 0;
52} 56}
@@ -104,7 +108,6 @@ module_exit(cleanup_soundcore);
104#include <linux/types.h> 108#include <linux/types.h>
105#include <linux/kernel.h> 109#include <linux/kernel.h>
106#include <linux/sound.h> 110#include <linux/sound.h>
107#include <linux/major.h>
108#include <linux/kmod.h> 111#include <linux/kmod.h>
109 112
110#define SOUND_STEP 16 113#define SOUND_STEP 16
@@ -125,6 +128,46 @@ extern int msnd_pinnacle_init(void);
125#endif 128#endif
126 129
127/* 130/*
131 * By default, OSS sound_core claims full legacy minor range (0-255)
132 * of SOUND_MAJOR to trap open attempts to any sound minor and
133 * requests modules using custom sound-slot/service-* module aliases.
134 * The only benefit of doing this is allowing use of custom module
135 * aliases instead of the standard char-major-* ones. This behavior
136 * prevents alternative OSS implementation and is scheduled to be
137 * removed.
138 *
139 * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
140 * parameter are added to allow distros and developers to try and
141 * switch to alternative implementations without needing to rebuild
142 * the kernel in the meantime. If preclaim_oss is non-zero, the
143 * kernel will behave the same as before. All SOUND_MAJOR minors are
144 * preclaimed and the custom module aliases along with standard chrdev
145 * ones are emitted if a missing device is opened. If preclaim_oss is
146 * zero, sound_core only grabs what's actually in use and for missing
147 * devices only the standard chrdev aliases are requested.
148 *
149 * All these clutters are scheduled to be removed along with
150 * sound-slot/service-* module aliases. Please take a look at
151 * feature-removal-schedule.txt for details.
152 */
153#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
154static int preclaim_oss = 1;
155#else
156static int preclaim_oss = 0;
157#endif
158
159module_param(preclaim_oss, int, 0444);
160
161static int soundcore_open(struct inode *, struct file *);
162
163static const struct file_operations soundcore_fops =
164{
165 /* We must have an owner or the module locking fails */
166 .owner = THIS_MODULE,
167 .open = soundcore_open,
168};
169
170/*
128 * Low level list operator. Scan the ordered list, find a hole and 171 * Low level list operator. Scan the ordered list, find a hole and
129 * join into it. Called with the lock asserted 172 * join into it. Called with the lock asserted
130 */ 173 */
@@ -216,8 +259,9 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
216 259
217 if (!s) 260 if (!s)
218 return -ENOMEM; 261 return -ENOMEM;
219 262
220 spin_lock(&sound_loader_lock); 263 spin_lock(&sound_loader_lock);
264retry:
221 r = __sound_insert_unit(s, list, fops, index, low, top); 265 r = __sound_insert_unit(s, list, fops, index, low, top);
222 spin_unlock(&sound_loader_lock); 266 spin_unlock(&sound_loader_lock);
223 267
@@ -228,11 +272,31 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
228 else 272 else
229 sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); 273 sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
230 274
275 if (!preclaim_oss) {
276 /*
277 * Something else might have grabbed the minor. If
278 * first free slot is requested, rescan with @low set
279 * to the next unit; otherwise, -EBUSY.
280 */
281 r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
282 &soundcore_fops);
283 if (r < 0) {
284 spin_lock(&sound_loader_lock);
285 __sound_remove_unit(list, s->unit_minor);
286 if (index < 0) {
287 low = s->unit_minor + SOUND_STEP;
288 goto retry;
289 }
290 spin_unlock(&sound_loader_lock);
291 return -EBUSY;
292 }
293 }
294
231 device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), 295 device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
232 NULL, s->name+6); 296 NULL, s->name+6);
233 return r; 297 return s->unit_minor;
234 298
235 fail: 299fail:
236 kfree(s); 300 kfree(s);
237 return r; 301 return r;
238} 302}
@@ -251,6 +315,9 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
251 p = __sound_remove_unit(list, unit); 315 p = __sound_remove_unit(list, unit);
252 spin_unlock(&sound_loader_lock); 316 spin_unlock(&sound_loader_lock);
253 if (p) { 317 if (p) {
318 if (!preclaim_oss)
319 __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
320 p->name);
254 device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); 321 device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
255 kfree(p); 322 kfree(p);
256 } 323 }
@@ -488,19 +555,6 @@ void unregister_sound_dsp(int unit)
488 555
489EXPORT_SYMBOL(unregister_sound_dsp); 556EXPORT_SYMBOL(unregister_sound_dsp);
490 557
491/*
492 * Now our file operations
493 */
494
495static int soundcore_open(struct inode *, struct file *);
496
497static const struct file_operations soundcore_fops=
498{
499 /* We must have an owner or the module locking fails */
500 .owner = THIS_MODULE,
501 .open = soundcore_open,
502};
503
504static struct sound_unit *__look_for_unit(int chain, int unit) 558static struct sound_unit *__look_for_unit(int chain, int unit)
505{ 559{
506 struct sound_unit *s; 560 struct sound_unit *s;
@@ -536,8 +590,9 @@ static int soundcore_open(struct inode *inode, struct file *file)
536 s = __look_for_unit(chain, unit); 590 s = __look_for_unit(chain, unit);
537 if (s) 591 if (s)
538 new_fops = fops_get(s->unit_fops); 592 new_fops = fops_get(s->unit_fops);
539 if (!new_fops) { 593 if (preclaim_oss && !new_fops) {
540 spin_unlock(&sound_loader_lock); 594 spin_unlock(&sound_loader_lock);
595
541 /* 596 /*
542 * Please, don't change this order or code. 597 * Please, don't change this order or code.
543 * For ALSA slot means soundcard and OSS emulation code 598 * For ALSA slot means soundcard and OSS emulation code
@@ -547,6 +602,17 @@ static int soundcore_open(struct inode *inode, struct file *file)
547 */ 602 */
548 request_module("sound-slot-%i", unit>>4); 603 request_module("sound-slot-%i", unit>>4);
549 request_module("sound-service-%i-%i", unit>>4, chain); 604 request_module("sound-service-%i-%i", unit>>4, chain);
605
606 /*
607 * sound-slot/service-* module aliases are scheduled
608 * for removal in favor of the standard char-major-*
609 * module aliases. For the time being, generate both
610 * the legacy and standard module aliases to ease
611 * transition.
612 */
613 if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
614 request_module("char-major-%d", SOUND_MAJOR);
615
550 spin_lock(&sound_loader_lock); 616 spin_lock(&sound_loader_lock);
551 s = __look_for_unit(chain, unit); 617 s = __look_for_unit(chain, unit);
552 if (s) 618 if (s)
@@ -590,7 +656,8 @@ static void cleanup_oss_soundcore(void)
590 656
591static int __init init_oss_soundcore(void) 657static int __init init_oss_soundcore(void)
592{ 658{
593 if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) { 659 if (preclaim_oss &&
660 register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) {
594 printk(KERN_ERR "soundcore: sound device already in use.\n"); 661 printk(KERN_ERR "soundcore: sound device already in use.\n");
595 return -EBUSY; 662 return -EBUSY;
596 } 663 }