[alsa-devel] Device assignment and hotplug

Takashi Iwai tiwai at suse.de
Wed Sep 5 19:08:45 CEST 2007


the recent Linux systems use the auto-probing at boot via udev, and
this often screws up the order of device loading, which results in the
inconsistent device appearance.  A typical case is that you have a PCI
onboard and a USB audio device.  Sometimes the USB appears as the
first device while sometimes (most times) PCI appears as the first.

So far, for fixing this order, we use index module option.  That is,
add the following to module config:

	options snd-onboard index=0
	options snd-usb-audio index=1

But this scheme has a problem.  It doesn't specify the order of other
possible devices.  For example, what if I plug a PCMCIA sound card and
reboot?  Since no index option is given for that, PCMCIA device may be
loaded at any unused slot.  If it's loaded before other devices, it
goes to slot 0.  Now, the onboard driver is loaded, and found that the
statically assigned slot 0 is already occupied.  Ouch, the driver
fails and the device gets unusable.

So, obviously, the problem of index option is that it's specific to
the driver, and it doesn't give the whole system-wide setting.  For
overcoming this, I'd like to propose the following new option to snd
module.  The "slots" option is used to pass the static assignment of
known drivers.  For example, in the case above, it'd be like the

	options snd slots=snd-onboard,snd-usb-audio

And you can omit all index options if you want.  When a new device is
loaded, then the first two slots are avoided, and it's loaded to the
third slot in the end.

The experimental patch is below.  As you see, the necessary change is
minimum, and it doesn't even conflict with the existing index option,

Any comments?  The module name "slots" is OK?

BTW, one missing feature is the support for built-in drivers.
But I don't think it's needed because the built-in drivers are always
loaded in prior to others, and thus you can give simply index options
for each.



diff -r 5debd8716290 core/init.c
--- a/core/init.c	Wed Sep 05 15:08:23 2007 +0200
+++ b/core/init.c	Wed Sep 05 19:00:08 2007 +0200
@@ -42,6 +42,40 @@ EXPORT_SYMBOL(snd_cards);
 static DEFINE_MUTEX(snd_card_mutex);
+static char *slots[SNDRV_CARDS];
+module_param_array(slots, charp, NULL, 0444);
+MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
+/* return non-zero if the given index is already reserved for another
+ * module via slots option
+ */
+static int module_slot_mismatch(struct module *module, int idx)
+#ifdef MODULE
+	char *s1, *s2;
+	if (!module || !module->name || !slots[idx])
+		return 0;
+	s1 = slots[idx];
+	s2 = module->name;
+	/* compare module name strings
+	 * hyphens are handled as equivalent with underscore
+	 */
+	for (;;) {
+		char c1 = *s1++;
+		char c2 = *s2++;
+		if (c1 == '-')
+			c1 = '_';
+		if (c2 == '-')
+			c2 = '_';
+		if (c1 != c2)
+			return 1;
+		if (!c1)
+			break;
+	}
+	return 0;
 int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
@@ -115,6 +149,8 @@ struct snd_card *snd_card_new(int idx, c
 		for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
 			/* idx == -1 == 0xffff means: take any free slot */
 			if (~snd_cards_lock & idx & 1<<idx2) {
+				if (module_slot_mismatch(module, idx2))
+					continue;
 				idx = idx2;
 				if (idx >= snd_ecards_limit)
 					snd_ecards_limit = idx + 1;

More information about the Alsa-devel mailing list