diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-06 11:01:27 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-06 11:01:27 -0400 |
commit | 907bc6c7fc7071b00083fc11e510e47dd93df45d (patch) | |
tree | 0697a608561522c00da9e1814974a2eb051bb96d /sound/sound_core.c | |
parent | d2b247a8be57647d1745535acd58169fbcbe431a (diff) | |
parent | 2a0f5cb32772e9a9560209e241a80bfbbc31dbc3 (diff) |
Merge branch 'for-2.6.32' into for-2.6.33
Diffstat (limited to 'sound/sound_core.c')
-rw-r--r-- | sound/sound_core.c | 109 |
1 files changed, 88 insertions, 21 deletions
diff --git a/sound/sound_core.c b/sound/sound_core.c index 12522e6913d9..49c998186592 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"); | |||
27 | MODULE_AUTHOR("Alan Cox"); | 29 | MODULE_AUTHOR("Alan Cox"); |
28 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
29 | 31 | ||
30 | static char *sound_nodename(struct device *dev) | 32 | static 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 | ||
154 | static int preclaim_oss = 1; | ||
155 | #else | ||
156 | static int preclaim_oss = 0; | ||
157 | #endif | ||
158 | |||
159 | module_param(preclaim_oss, int, 0444); | ||
160 | |||
161 | static int soundcore_open(struct inode *, struct file *); | ||
162 | |||
163 | static 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); |
264 | retry: | ||
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: | 299 | fail: |
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 | ||
489 | EXPORT_SYMBOL(unregister_sound_dsp); | 556 | EXPORT_SYMBOL(unregister_sound_dsp); |
490 | 557 | ||
491 | /* | ||
492 | * Now our file operations | ||
493 | */ | ||
494 | |||
495 | static int soundcore_open(struct inode *, struct file *); | ||
496 | |||
497 | static 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 | |||
504 | static struct sound_unit *__look_for_unit(int chain, int unit) | 558 | static 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 | ||
591 | static int __init init_oss_soundcore(void) | 657 | static 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 | } |