Merge branch 'topic/soundcore-preclaim' into for-linus

* topic/soundcore-preclaim:
  sound: make OSS device number claiming optional and schedule its removal
  sound: request char-major-* module aliases for missing OSS devices
  chrdev: implement __[un]register_chrdev()
This commit is contained in:
Takashi Iwai 2009-09-10 15:33:04 +02:00
commit 3827119e20
5 changed files with 176 additions and 34 deletions

View file

@ -32,6 +32,34 @@ config SOUND_OSS_CORE
bool
default n
config SOUND_OSS_CORE_PRECLAIM
bool "Preclaim OSS device numbers"
depends on SOUND_OSS_CORE
default y
help
With this option enabled, the kernel will claim all OSS device
numbers if any OSS support (native or emulation) is enabled
whether the respective module is loaded or not and try to load the
appropriate module using sound-slot/service-* and char-major-*
module aliases when one of the device numbers is opened. With
this option disabled, kernel will only claim actually in-use
device numbers and opening a missing device will generate only the
standard char-major-* aliases.
The only visible difference is use of additional module aliases
and whether OSS sound devices appear multiple times in
/proc/devices. sound-slot/service-* module aliases are scheduled
to be removed (ie. PRECLAIM won't be available) and this option is
to make the transition easier. This option can be overridden
during boot using the kernel parameter soundcore.preclaim_oss.
Disabling this allows alternative OSS implementations.
Please read Documentation/feature-removal-schedule.txt for
details.
If unusre, say Y.
source "sound/oss/dmasound/Kconfig"
if !M68K

View file

@ -127,6 +127,46 @@ extern int msnd_classic_init(void);
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
@ -219,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);
@ -231,11 +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);
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;
}
}
device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
NULL, s->name+6);
return r;
return s->unit_minor;
fail:
fail:
kfree(s);
return r;
}
@ -254,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);
}
@ -491,19 +555,6 @@ void unregister_sound_dsp(int 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;
@ -539,8 +590,9 @@ static 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
@ -550,6 +602,17 @@ static 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)
@ -593,7 +656,8 @@ static void 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;
}