[alsa-devel] Device assignment and hotplug
Hi,
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 following:
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, too.
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.
thanks,
Takashi
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); 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; + } +#endif + return 0; +}
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 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;
On Wed, 05 Sep 2007 19:08:45 +0200 Takashi Iwai tiwai@suse.de wrote:
Hi,
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
I would rather try to contact udev guys how to solve this. This problem is not limited to sound cards. They have solution for hard drives already as it hit them first and could even lead to non-bootable system (sda swapped with sdb then e.g. /usr partition could not be mounted).
A general solution would be to use some kind of device locator (e.g. bus:device_id). For PCI devices the pci id could be used. For the USB devices, the device id reported by lsusb or something id string from the device (like for disks now - they can use disk number reported by disk).
Even, if the problem is solved for USB devices only, it will probably make life much easier as the PCI bus is probably always scanned in the same order.
The same may apply to graphics cards, modems, network cards, etc. A general solution (like bus:device_id) would solve it for the most if not all of them.
If it is not solvable by udev guys, then you can try doing it in alsa the way I mentioned so you can set in the config file which device id (USB serial number or bus:device_id) correspond to each sound device.
In your solution, it is a change of index to some kind of locator.
My two cents, Krzysztof
At Wed, 5 Sep 2007 20:41:00 +0200, Krzysztof Helt wrote:
On Wed, 05 Sep 2007 19:08:45 +0200 Takashi Iwai tiwai@suse.de wrote:
Hi,
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
I would rather try to contact udev guys how to solve this. This problem is not limited to sound cards. They have solution for hard drives already as it hit them first and could even lead to non-bootable system (sda swapped with sdb then e.g. /usr partition could not be mounted).
A general solution would be to use some kind of device locator (e.g. bus:device_id). For PCI devices the pci id could be used. For the USB devices, the device id reported by lsusb or something id string from the device (like for disks now - they can use disk number reported by disk).
Even, if the problem is solved for USB devices only, it will probably make life much easier as the PCI bus is probably always scanned in the same order.
The same may apply to graphics cards, modems, network cards, etc. A general solution (like bus:device_id) would solve it for the most if not all of them.
Well, I've talked about this with udev guys some times. Actually, the problem isn't about persistent device names. The problem does NOT exist if all apps do right -- namely, use ALSA API and open with the ID string instead of a number. But, the OSS apps don't handle persistent device names, and ALSA apps tend to access via the card number. These are the problems. (Also we have some code in alsa-lib assuming the number schemes, but it can be relatively easily fixed.)
So, we need either to fix all sound apps or to fix the order of devices in some way. Obviously, fixing all apps is not a solution right now (and we can't for binary-only ones).
One way to fix the device order is the index option, and another is more complex udev rules. The index option is the way to fix the order of devices at driver loading time while the latter, udev way, is to remap the existing devices to certain "traditional" device files. In either way, one would need a system-wide configuration: a module option or a udev rules file.
Note that these two don't conflict at all. The index option had been introduced far before udev was invented. That's why there is no complex remapping udev rules for the sound, so far. Thus, we can implement and improve both at the same time.
My suggestion here is just an improvement for the first one. We can introduce a remapping rule in udev at the same time. Eventually we'll be able to fix all in udev, then get rid of index stuff in future. But, udev remapping is still a longer way to go than my patch.
If it is not solvable by udev guys, then you can try doing it in alsa the way I mentioned so you can set in the config file which device id (USB serial number or bus:device_id) correspond to each sound device.
Yes, it's a possible solution, but it would need more codes, and above all, it would be more difficult to add entries manually. The beauty of this hack is its simpleness.
In your solution, it is a change of index to some kind of locator.
Yes, it's so. Merging scattered index options to a single location, so that you can manage easilly. Nothing more than that.
Takashi
participants (2)
-
Krzysztof Helt
-
Takashi Iwai