Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: support module on-demand loading for seq and timer

If CONFIG_SND_DYNAMIC_MINORS is used, assign /dev/snd/seq and
/dev/snd/timer the usual static minors, and export specific
module aliases to generate udev module on-demand loading
instructions:

$ cat /lib/modules/2.6.33.4-smp/modules.devname
# Device nodes to trigger on-demand module loading.
microcode cpu/microcode c10:184
fuse fuse c10:229
ppp_generic ppp c108:0
tun net/tun c10:200
uinput uinput c10:223
dm_mod mapper/control c10:236
snd_timer snd/timer c116:33
snd_seq snd/seq c116:1

The last two lines instruct udev to create device nodes, even
when the modules are not loaded at that time.

As soon as userspace accesses any of these nodes, the in-kernel
module-loader will load the module, and the device can be used.

The header file minor calculation needed to be simplified to
make __stringify() (supports only two indirections) in
the MODULE_ALIAS macro work.

This is part of systemd's effort to get rid of unconditional
module load instructions and needless init scripts.

Cc: Lennart Poettering <lennart@poettering.net>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Kay Sievers and committed by
Takashi Iwai
03cfe6f5 109fef9e

+22 -7
+2 -2
include/sound/minors.h
··· 31 31 /* these minors can still be used for autoloading devices (/dev/aload*) */ 32 32 #define SNDRV_MINOR_CONTROL 0 /* 0 */ 33 33 #define SNDRV_MINOR_GLOBAL 1 /* 1 */ 34 - #define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32) 35 - #define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32) 34 + #define SNDRV_MINOR_SEQUENCER 1 /* SNDRV_MINOR_GLOBAL + 0 * 32 */ 35 + #define SNDRV_MINOR_TIMER 33 /* SNDRV_MINOR_GLOBAL + 1 * 32 */ 36 36 37 37 #ifndef CONFIG_SND_DYNAMIC_MINORS 38 38 /* 2 - 3 (reserved) */
+4
sound/core/seq/seq.c
··· 32 32 #include "seq_timer.h" 33 33 #include "seq_system.h" 34 34 #include "seq_info.h" 35 + #include <sound/minors.h> 35 36 #include <sound/seq_device.h> 36 37 37 38 #if defined(CONFIG_SND_SEQ_DUMMY_MODULE) ··· 73 72 MODULE_PARM_DESC(seq_default_timer_subdevice, "The default timer subdevice number."); 74 73 module_param(seq_default_timer_resolution, int, 0644); 75 74 MODULE_PARM_DESC(seq_default_timer_resolution, "The default timer resolution in Hz."); 75 + 76 + MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_SEQUENCER); 77 + MODULE_ALIAS("devname:snd/seq"); 76 78 77 79 /* 78 80 * INIT PART
+13 -5
sound/core/sound.c
··· 189 189 }; 190 190 191 191 #ifdef CONFIG_SND_DYNAMIC_MINORS 192 - static int snd_find_free_minor(void) 192 + static int snd_find_free_minor(int type) 193 193 { 194 194 int minor; 195 195 196 + /* static minors for module auto loading */ 197 + if (type == SNDRV_DEVICE_TYPE_SEQUENCER) 198 + return SNDRV_MINOR_SEQUENCER; 199 + if (type == SNDRV_DEVICE_TYPE_TIMER) 200 + return SNDRV_MINOR_TIMER; 201 + 196 202 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) { 197 - /* skip minors still used statically for autoloading devices */ 198 - if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL || 199 - minor == SNDRV_MINOR_SEQUENCER) 203 + /* skip static minors still used for module auto loading */ 204 + if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL) 205 + continue; 206 + if (minor == SNDRV_MINOR_SEQUENCER || 207 + minor == SNDRV_MINOR_TIMER) 200 208 continue; 201 209 if (!snd_minors[minor]) 202 210 return minor; ··· 278 270 preg->private_data = private_data; 279 271 mutex_lock(&sound_mutex); 280 272 #ifdef CONFIG_SND_DYNAMIC_MINORS 281 - minor = snd_find_free_minor(); 273 + minor = snd_find_free_minor(type); 282 274 #else 283 275 minor = snd_kernel_minor(type, card, dev); 284 276 if (minor >= 0 && snd_minors[minor])
+3
sound/core/timer.c
··· 52 52 module_param(timer_tstamp_monotonic, int, 0444); 53 53 MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for timestamps (default)."); 54 54 55 + MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER); 56 + MODULE_ALIAS("devname:snd/timer"); 57 + 55 58 struct snd_timer_user { 56 59 struct snd_timer_instance *timeri; 57 60 int tread; /* enhanced read with timestamps and events */