diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/Kconfig | 28 | ||||
-rw-r--r-- | sound/sound_core.c | 88 |
2 files changed, 98 insertions, 18 deletions
diff --git a/sound/Kconfig b/sound/Kconfig index 1eceb85287c5..439e15c8faa3 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -32,6 +32,34 @@ config SOUND_OSS_CORE | |||
32 | bool | 32 | bool |
33 | default n | 33 | default n |
34 | 34 | ||
35 | config SOUND_OSS_CORE_PRECLAIM | ||
36 | bool "Preclaim OSS device numbers" | ||
37 | depends on SOUND_OSS_CORE | ||
38 | default y | ||
39 | help | ||
40 | With this option enabled, the kernel will claim all OSS device | ||
41 | numbers if any OSS support (native or emulation) is enabled | ||
42 | whether the respective module is loaded or not and try to load the | ||
43 | appropriate module using sound-slot/service-* and char-major-* | ||
44 | module aliases when one of the device numbers is opened. With | ||
45 | this option disabled, kernel will only claim actually in-use | ||
46 | device numbers and opening a missing device will generate only the | ||
47 | standard char-major-* aliases. | ||
48 | |||
49 | The only visible difference is use of additional module aliases | ||
50 | and whether OSS sound devices appear multiple times in | ||
51 | /proc/devices. sound-slot/service-* module aliases are scheduled | ||
52 | to be removed (ie. PRECLAIM won't be available) and this option is | ||
53 | to make the transition easier. This option can be overridden | ||
54 | during boot using the kernel parameter soundcore.preclaim_oss. | ||
55 | |||
56 | Disabling this allows alternative OSS implementations. | ||
57 | |||
58 | Please read Documentation/feature-removal-schedule.txt for | ||
59 | details. | ||
60 | |||
61 | If unusre, say Y. | ||
62 | |||
35 | source "sound/oss/dmasound/Kconfig" | 63 | source "sound/oss/dmasound/Kconfig" |
36 | 64 | ||
37 | if !M68K | 65 | if !M68K |
diff --git a/sound/sound_core.c b/sound/sound_core.c index 786067c49b01..bb4b88e606bb 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c | |||
@@ -128,6 +128,46 @@ extern int msnd_pinnacle_init(void); | |||
128 | #endif | 128 | #endif |
129 | 129 | ||
130 | /* | 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 | /* | ||
131 | * 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 |
132 | * join into it. Called with the lock asserted | 172 | * join into it. Called with the lock asserted |
133 | */ | 173 | */ |
@@ -219,8 +259,9 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati | |||
219 | 259 | ||
220 | if (!s) | 260 | if (!s) |
221 | return -ENOMEM; | 261 | return -ENOMEM; |
222 | 262 | ||
223 | spin_lock(&sound_loader_lock); | 263 | spin_lock(&sound_loader_lock); |
264 | retry: | ||
224 | r = __sound_insert_unit(s, list, fops, index, low, top); | 265 | r = __sound_insert_unit(s, list, fops, index, low, top); |
225 | spin_unlock(&sound_loader_lock); | 266 | spin_unlock(&sound_loader_lock); |
226 | 267 | ||
@@ -231,11 +272,31 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati | |||
231 | else | 272 | else |
232 | sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); | 273 | sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); |
233 | 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 | |||
234 | device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), | 295 | device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), |
235 | NULL, s->name+6); | 296 | NULL, s->name+6); |
236 | return r; | 297 | return s->unit_minor; |
237 | 298 | ||
238 | fail: | 299 | fail: |
239 | kfree(s); | 300 | kfree(s); |
240 | return r; | 301 | return r; |
241 | } | 302 | } |
@@ -254,6 +315,9 @@ static void sound_remove_unit(struct sound_unit **list, int unit) | |||
254 | p = __sound_remove_unit(list, unit); | 315 | p = __sound_remove_unit(list, unit); |
255 | spin_unlock(&sound_loader_lock); | 316 | spin_unlock(&sound_loader_lock); |
256 | if (p) { | 317 | if (p) { |
318 | if (!preclaim_oss) | ||
319 | __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1, | ||
320 | p->name); | ||
257 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); | 321 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); |
258 | kfree(p); | 322 | kfree(p); |
259 | } | 323 | } |
@@ -491,19 +555,6 @@ void unregister_sound_dsp(int unit) | |||
491 | 555 | ||
492 | EXPORT_SYMBOL(unregister_sound_dsp); | 556 | EXPORT_SYMBOL(unregister_sound_dsp); |
493 | 557 | ||
494 | /* | ||
495 | * Now our file operations | ||
496 | */ | ||
497 | |||
498 | static int soundcore_open(struct inode *, struct file *); | ||
499 | |||
500 | static const struct file_operations soundcore_fops= | ||
501 | { | ||
502 | /* We must have an owner or the module locking fails */ | ||
503 | .owner = THIS_MODULE, | ||
504 | .open = soundcore_open, | ||
505 | }; | ||
506 | |||
507 | static struct sound_unit *__look_for_unit(int chain, int unit) | 558 | static struct sound_unit *__look_for_unit(int chain, int unit) |
508 | { | 559 | { |
509 | struct sound_unit *s; | 560 | struct sound_unit *s; |
@@ -539,7 +590,7 @@ static int soundcore_open(struct inode *inode, struct file *file) | |||
539 | s = __look_for_unit(chain, unit); | 590 | s = __look_for_unit(chain, unit); |
540 | if (s) | 591 | if (s) |
541 | new_fops = fops_get(s->unit_fops); | 592 | new_fops = fops_get(s->unit_fops); |
542 | if (!new_fops) { | 593 | if (preclaim_oss && !new_fops) { |
543 | spin_unlock(&sound_loader_lock); | 594 | spin_unlock(&sound_loader_lock); |
544 | 595 | ||
545 | /* | 596 | /* |
@@ -605,7 +656,8 @@ static void cleanup_oss_soundcore(void) | |||
605 | 656 | ||
606 | static int __init init_oss_soundcore(void) | 657 | static int __init init_oss_soundcore(void) |
607 | { | 658 | { |
608 | if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) { | 659 | if (preclaim_oss && |
660 | register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) { | ||
609 | printk(KERN_ERR "soundcore: sound device already in use.\n"); | 661 | printk(KERN_ERR "soundcore: sound device already in use.\n"); |
610 | return -EBUSY; | 662 | return -EBUSY; |
611 | } | 663 | } |