Skip to content

Commit

Permalink
[ALSA] Improve the slots option handling
Browse files Browse the repository at this point in the history
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: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
tiwai committed May 28, 2008
1 parent f9423e7 commit a93bbaa
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 27 deletions.
4 changes: 4 additions & 0 deletions Documentation/sound/alsa/ALSA-Configuration.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
=======================================
Expand Down
67 changes: 40 additions & 27 deletions sound/core/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,24 @@ 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
/* return non-zero if the given index is reserved for the given
* 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
char *s1, *s2;
const char *s1, *s2;

if (!module || !module->name || !slots[idx])
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
* hyphens are handled as equivalent with underscore
*/
Expand All @@ -68,12 +75,12 @@ static int module_slot_mismatch(struct module *module, int idx)
if (c2 == '-')
c2 = '_';
if (c1 != c2)
return 1;
return !match;
if (!c1)
break;
}
#endif
return 0;
#endif /* MODULE */
return match;
}

#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
Expand Down Expand Up @@ -129,7 +136,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
struct module *module, int extra_size)
{
struct snd_card *card;
int err;
int err, idx2;

if (extra_size < 0)
extra_size = 0;
Expand All @@ -144,35 +151,41 @@ struct snd_card *snd_card_new(int idx, const char *xid,
err = 0;
mutex_lock(&snd_card_mutex);
if (idx < 0) {
int idx2;
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;
break;
if (module_slot_match(module, idx2)) {
idx = idx2;
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);
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
idx, snd_ecards_limit - 1, err);
goto __error;
}
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);
card->number = idx;
card->module = module;
Expand Down

0 comments on commit a93bbaa

Please sign in to comment.