X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=sound%2Fsound_core.c;h=dbca7c909a31ea305fe5fa543c6ca9c930fee794;hb=fa1f136e073ddc4e60497c51bc8918569314d38a;hp=68614c3ed5412f2209c16f94bc74d0785a0baa7c;hpb=d886e87cb82b0f6636476c1104bb84d7c8dc87d9;p=safe%2Fjmp%2Flinux-2.6 diff --git a/sound/sound_core.c b/sound/sound_core.c index 68614c3..dbca7c9 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -10,10 +10,13 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_SOUND_OSS_CORE static int __init init_oss_soundcore(void); -static void __exit cleanup_oss_soundcore(void); +static void cleanup_oss_soundcore(void); #else static inline int init_oss_soundcore(void) { return 0; } static inline void cleanup_oss_soundcore(void) { } @@ -26,6 +29,13 @@ MODULE_DESCRIPTION("Core sound module"); MODULE_AUTHOR("Alan Cox"); MODULE_LICENSE("GPL"); +static char *sound_devnode(struct device *dev, mode_t *mode) +{ + if (MAJOR(dev->devt) == SOUND_MAJOR) + return NULL; + return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev)); +} + static int __init init_soundcore(void) { int rc; @@ -40,6 +50,8 @@ static int __init init_soundcore(void) return PTR_ERR(sound_class); } + sound_class->devnode = sound_devnode; + return 0; } @@ -57,7 +69,7 @@ module_exit(cleanup_soundcore); /* * OSS sound core handling. Breaks out sound functions to submodules * - * Author: Alan Cox + * Author: Alan Cox * * Fixes: * @@ -96,7 +108,6 @@ module_exit(cleanup_soundcore); #include #include #include -#include #include #define SOUND_STEP 16 @@ -117,6 +128,46 @@ extern int msnd_pinnacle_init(void); #endif /* + * By default, OSS sound_core claims full legacy minor range (0-255) + * of SOUND_MAJOR to trap open attempts to any sound minor and + * requests modules using custom sound-slot/service-* module aliases. + * The only benefit of doing this is allowing use of custom module + * aliases instead of the standard char-major-* ones. This behavior + * prevents alternative OSS implementation and is scheduled to be + * removed. + * + * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel + * parameter are added to allow distros and developers to try and + * switch to alternative implementations without needing to rebuild + * the kernel in the meantime. If preclaim_oss is non-zero, the + * kernel will behave the same as before. All SOUND_MAJOR minors are + * preclaimed and the custom module aliases along with standard chrdev + * ones are emitted if a missing device is opened. If preclaim_oss is + * zero, sound_core only grabs what's actually in use and for missing + * devices only the standard chrdev aliases are requested. + * + * All these clutters are scheduled to be removed along with + * sound-slot/service-* module aliases. Please take a look at + * feature-removal-schedule.txt for details. + */ +#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM +static int preclaim_oss = 1; +#else +static int preclaim_oss = 0; +#endif + +module_param(preclaim_oss, int, 0444); + +static int soundcore_open(struct inode *, struct file *); + +static const struct file_operations soundcore_fops = +{ + /* We must have an owner or the module locking fails */ + .owner = THIS_MODULE, + .open = soundcore_open, +}; + +/* * Low level list operator. Scan the ordered list, find a hole and * join into it. Called with the lock asserted */ @@ -208,8 +259,9 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati if (!s) return -ENOMEM; - + spin_lock(&sound_loader_lock); +retry: r = __sound_insert_unit(s, list, fops, index, low, top); spin_unlock(&sound_loader_lock); @@ -220,12 +272,31 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati else sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); - device_create_drvdata(sound_class, dev, - MKDEV(SOUND_MAJOR, s->unit_minor), - NULL, s->name+6); - return r; + if (!preclaim_oss) { + /* + * Something else might have grabbed the minor. If + * first free slot is requested, rescan with @low set + * to the next unit; otherwise, -EBUSY. + */ + r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name, + &soundcore_fops); + if (r < 0) { + spin_lock(&sound_loader_lock); + __sound_remove_unit(list, s->unit_minor); + if (index < 0) { + low = s->unit_minor + SOUND_STEP; + goto retry; + } + spin_unlock(&sound_loader_lock); + return -EBUSY; + } + } - fail: + device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), + NULL, s->name+6); + return s->unit_minor; + +fail: kfree(s); return r; } @@ -244,6 +315,9 @@ static void sound_remove_unit(struct sound_unit **list, int unit) p = __sound_remove_unit(list, unit); spin_unlock(&sound_loader_lock); if (p) { + if (!preclaim_oss) + __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1, + p->name); device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); kfree(p); } @@ -279,7 +353,7 @@ static struct sound_unit *chains[SOUND_STEP]; * @dev: device pointer * * Allocate a special sound device by minor number from the sound - * subsystem. The allocated number is returned on succes. On failure + * subsystem. The allocated number is returned on success. On failure * a negative error code is returned. */ @@ -458,7 +532,7 @@ EXPORT_SYMBOL(unregister_sound_mixer); void unregister_sound_midi(int unit) { - return sound_remove_unit(&chains[2], unit); + sound_remove_unit(&chains[2], unit); } EXPORT_SYMBOL(unregister_sound_midi); @@ -475,25 +549,12 @@ EXPORT_SYMBOL(unregister_sound_midi); void unregister_sound_dsp(int unit) { - return sound_remove_unit(&chains[3], unit); + sound_remove_unit(&chains[3], unit); } EXPORT_SYMBOL(unregister_sound_dsp); -/* - * Now our file operations - */ - -static int soundcore_open(struct inode *, struct file *); - -static const struct file_operations soundcore_fops= -{ - /* We must have an owner or the module locking fails */ - .owner = THIS_MODULE, - .open = soundcore_open, -}; - static struct sound_unit *__look_for_unit(int chain, int unit) { struct sound_unit *s; @@ -508,7 +569,7 @@ static struct sound_unit *__look_for_unit(int chain, int unit) return NULL; } -int soundcore_open(struct inode *inode, struct file *file) +static int soundcore_open(struct inode *inode, struct file *file) { int chain; int unit = iminor(inode); @@ -529,8 +590,9 @@ int soundcore_open(struct inode *inode, struct file *file) s = __look_for_unit(chain, unit); if (s) new_fops = fops_get(s->unit_fops); - if (!new_fops) { + if (preclaim_oss && !new_fops) { spin_unlock(&sound_loader_lock); + /* * Please, don't change this order or code. * For ALSA slot means soundcard and OSS emulation code @@ -540,6 +602,17 @@ int soundcore_open(struct inode *inode, struct file *file) */ request_module("sound-slot-%i", unit>>4); request_module("sound-service-%i-%i", unit>>4, chain); + + /* + * sound-slot/service-* module aliases are scheduled + * for removal in favor of the standard char-major-* + * module aliases. For the time being, generate both + * the legacy and standard module aliases to ease + * transition. + */ + if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0) + request_module("char-major-%d", SOUND_MAJOR); + spin_lock(&sound_loader_lock); s = __look_for_unit(chain, unit); if (s) @@ -574,7 +647,7 @@ int soundcore_open(struct inode *inode, struct file *file) MODULE_ALIAS_CHARDEV_MAJOR(SOUND_MAJOR); -static void __exit cleanup_oss_soundcore(void) +static void cleanup_oss_soundcore(void) { /* We have nothing to really do here - we know the lists must be empty */ @@ -583,7 +656,8 @@ static void __exit cleanup_oss_soundcore(void) static int __init init_oss_soundcore(void) { - if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) { + if (preclaim_oss && + register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) { printk(KERN_ERR "soundcore: sound device already in use.\n"); return -EBUSY; }