Commit a93bbaa7 authored by Takashi Iwai's avatar Takashi Iwai

[ALSA] Improve the slots option handling

Fix and improve the slots option handling.  The sound core tries to
find the slot with the given module name first and assign if it's
still available.  If all pre-given slots are unavailable, then try
to find another free slot.

Also, when a module name begins with '!', it means the negative match:
the slot will be given for any modules but that one.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f9423e7a
...@@ -2271,6 +2271,10 @@ case above again, the first two slots are already reserved. If any ...@@ -2271,6 +2271,10 @@ case above again, the first two slots are already reserved. If any
other driver (e.g. snd-usb-audio) is loaded before snd-interwave or other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
snd-ens1371, it will be assigned to the third or later slot. snd-ens1371, it will be assigned to the third or later slot.
When a module name is given with '!', the slot will be given for any
modules but that name. For example, "slots=!snd-pcsp" will reserve
the first slot for any modules but snd-pcsp.
ALSA PCM devices to OSS devices mapping ALSA PCM devices to OSS devices mapping
======================================= =======================================
......
...@@ -46,17 +46,24 @@ static char *slots[SNDRV_CARDS]; ...@@ -46,17 +46,24 @@ static char *slots[SNDRV_CARDS];
module_param_array(slots, charp, NULL, 0444); module_param_array(slots, charp, NULL, 0444);
MODULE_PARM_DESC(slots, "Module names assigned to the slots."); MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
/* return non-zero if the given index is already reserved for another /* return non-zero if the given index is reserved for the given
* module via slots option * module via slots option
*/ */
static int module_slot_mismatch(struct module *module, int idx) static int module_slot_match(struct module *module, int idx)
{ {
int match = 1;
#ifdef MODULE #ifdef MODULE
char *s1, *s2; const char *s1, *s2;
if (!module || !module->name || !slots[idx]) if (!module || !module->name || !slots[idx])
return 0; return 0;
s1 = slots[idx];
s2 = module->name; s1 = module->name;
s2 = slots[idx];
if (*s2 == '!') {
match = 0; /* negative match */
s2++;
}
/* compare module name strings /* compare module name strings
* hyphens are handled as equivalent with underscore * hyphens are handled as equivalent with underscore
*/ */
...@@ -68,12 +75,12 @@ static int module_slot_mismatch(struct module *module, int idx) ...@@ -68,12 +75,12 @@ static int module_slot_mismatch(struct module *module, int idx)
if (c2 == '-') if (c2 == '-')
c2 = '_'; c2 = '_';
if (c1 != c2) if (c1 != c2)
return 1; return !match;
if (!c1) if (!c1)
break; break;
} }
#endif #endif /* MODULE */
return 0; return match;
} }
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
...@@ -129,7 +136,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, ...@@ -129,7 +136,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
struct module *module, int extra_size) struct module *module, int extra_size)
{ {
struct snd_card *card; struct snd_card *card;
int err; int err, idx2;
if (extra_size < 0) if (extra_size < 0)
extra_size = 0; extra_size = 0;
...@@ -144,35 +151,41 @@ struct snd_card *snd_card_new(int idx, const char *xid, ...@@ -144,35 +151,41 @@ struct snd_card *snd_card_new(int idx, const char *xid,
err = 0; err = 0;
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
if (idx < 0) { if (idx < 0) {
int idx2;
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
/* idx == -1 == 0xffff means: take any free slot */ /* idx == -1 == 0xffff means: take any free slot */
if (~snd_cards_lock & idx & 1<<idx2) { if (~snd_cards_lock & idx & 1<<idx2) {
if (module_slot_mismatch(module, idx2)) if (module_slot_match(module, idx2)) {
continue; idx = idx2;
idx = idx2; break;
if (idx >= snd_ecards_limit) }
snd_ecards_limit = idx + 1; }
break; }
if (idx < 0) {
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
/* idx == -1 == 0xffff means: take any free slot */
if (~snd_cards_lock & idx & 1<<idx2) {
if (!slots[idx2] || !*slots[idx2]) {
idx = idx2;
break;
}
} }
} else {
if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx))
err = -EBUSY; /* invalid */
} else {
if (idx < SNDRV_CARDS)
snd_ecards_limit = idx + 1; /* increase the limit */
else
err = -ENODEV;
}
} }
if (idx < 0 || err < 0) { if (idx < 0)
err = -ENODEV;
else if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx))
err = -EBUSY; /* invalid */
} else if (idx >= SNDRV_CARDS)
err = -ENODEV;
if (err < 0) {
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n", snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
idx, snd_ecards_limit - 1, err); idx, snd_ecards_limit - 1, err);
goto __error; goto __error;
} }
snd_cards_lock |= 1 << idx; /* lock it */ snd_cards_lock |= 1 << idx; /* lock it */
if (idx >= snd_ecards_limit)
snd_ecards_limit = idx + 1; /* increase the limit */
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
card->number = idx; card->number = idx;
card->module = module; card->module = module;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment