diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/init.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index ac0573416130..5c254d498ae0 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -46,17 +46,24 @@ static char *slots[SNDRV_CARDS]; | |||
46 | module_param_array(slots, charp, NULL, 0444); | 46 | module_param_array(slots, charp, NULL, 0444); |
47 | MODULE_PARM_DESC(slots, "Module names assigned to the slots."); | 47 | MODULE_PARM_DESC(slots, "Module names assigned to the slots."); |
48 | 48 | ||
49 | /* return non-zero if the given index is already reserved for another | 49 | /* return non-zero if the given index is reserved for the given |
50 | * module via slots option | 50 | * module via slots option |
51 | */ | 51 | */ |
52 | static int module_slot_mismatch(struct module *module, int idx) | 52 | static int module_slot_match(struct module *module, int idx) |
53 | { | 53 | { |
54 | int match = 1; | ||
54 | #ifdef MODULE | 55 | #ifdef MODULE |
55 | char *s1, *s2; | 56 | const char *s1, *s2; |
57 | |||
56 | if (!module || !module->name || !slots[idx]) | 58 | if (!module || !module->name || !slots[idx]) |
57 | return 0; | 59 | return 0; |
58 | s1 = slots[idx]; | 60 | |
59 | s2 = module->name; | 61 | s1 = module->name; |
62 | s2 = slots[idx]; | ||
63 | if (*s2 == '!') { | ||
64 | match = 0; /* negative match */ | ||
65 | s2++; | ||
66 | } | ||
60 | /* compare module name strings | 67 | /* compare module name strings |
61 | * hyphens are handled as equivalent with underscore | 68 | * hyphens are handled as equivalent with underscore |
62 | */ | 69 | */ |
@@ -68,12 +75,12 @@ static int module_slot_mismatch(struct module *module, int idx) | |||
68 | if (c2 == '-') | 75 | if (c2 == '-') |
69 | c2 = '_'; | 76 | c2 = '_'; |
70 | if (c1 != c2) | 77 | if (c1 != c2) |
71 | return 1; | 78 | return !match; |
72 | if (!c1) | 79 | if (!c1) |
73 | break; | 80 | break; |
74 | } | 81 | } |
75 | #endif | 82 | #endif /* MODULE */ |
76 | return 0; | 83 | return match; |
77 | } | 84 | } |
78 | 85 | ||
79 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 86 | #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 | struct module *module, int extra_size) | 136 | struct module *module, int extra_size) |
130 | { | 137 | { |
131 | struct snd_card *card; | 138 | struct snd_card *card; |
132 | int err; | 139 | int err, idx2; |
133 | 140 | ||
134 | if (extra_size < 0) | 141 | if (extra_size < 0) |
135 | extra_size = 0; | 142 | extra_size = 0; |
@@ -144,35 +151,41 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
144 | err = 0; | 151 | err = 0; |
145 | mutex_lock(&snd_card_mutex); | 152 | mutex_lock(&snd_card_mutex); |
146 | if (idx < 0) { | 153 | if (idx < 0) { |
147 | int idx2; | ||
148 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) | 154 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) |
149 | /* idx == -1 == 0xffff means: take any free slot */ | 155 | /* idx == -1 == 0xffff means: take any free slot */ |
150 | if (~snd_cards_lock & idx & 1<<idx2) { | 156 | if (~snd_cards_lock & idx & 1<<idx2) { |
151 | if (module_slot_mismatch(module, idx2)) | 157 | if (module_slot_match(module, idx2)) { |
152 | continue; | 158 | idx = idx2; |
153 | idx = idx2; | 159 | break; |
154 | if (idx >= snd_ecards_limit) | 160 | } |
155 | snd_ecards_limit = idx + 1; | 161 | } |
156 | break; | 162 | } |
163 | if (idx < 0) { | ||
164 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) | ||
165 | /* idx == -1 == 0xffff means: take any free slot */ | ||
166 | if (~snd_cards_lock & idx & 1<<idx2) { | ||
167 | if (!slots[idx2] || !*slots[idx2]) { | ||
168 | idx = idx2; | ||
169 | break; | ||
170 | } | ||
157 | } | 171 | } |
158 | } else { | ||
159 | if (idx < snd_ecards_limit) { | ||
160 | if (snd_cards_lock & (1 << idx)) | ||
161 | err = -EBUSY; /* invalid */ | ||
162 | } else { | ||
163 | if (idx < SNDRV_CARDS) | ||
164 | snd_ecards_limit = idx + 1; /* increase the limit */ | ||
165 | else | ||
166 | err = -ENODEV; | ||
167 | } | ||
168 | } | 172 | } |
169 | if (idx < 0 || err < 0) { | 173 | if (idx < 0) |
174 | err = -ENODEV; | ||
175 | else if (idx < snd_ecards_limit) { | ||
176 | if (snd_cards_lock & (1 << idx)) | ||
177 | err = -EBUSY; /* invalid */ | ||
178 | } else if (idx >= SNDRV_CARDS) | ||
179 | err = -ENODEV; | ||
180 | if (err < 0) { | ||
170 | mutex_unlock(&snd_card_mutex); | 181 | mutex_unlock(&snd_card_mutex); |
171 | snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n", | 182 | snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n", |
172 | idx, snd_ecards_limit - 1, err); | 183 | idx, snd_ecards_limit - 1, err); |
173 | goto __error; | 184 | goto __error; |
174 | } | 185 | } |
175 | snd_cards_lock |= 1 << idx; /* lock it */ | 186 | snd_cards_lock |= 1 << idx; /* lock it */ |
187 | if (idx >= snd_ecards_limit) | ||
188 | snd_ecards_limit = idx + 1; /* increase the limit */ | ||
176 | mutex_unlock(&snd_card_mutex); | 189 | mutex_unlock(&snd_card_mutex); |
177 | card->number = idx; | 190 | card->number = idx; |
178 | card->module = module; | 191 | card->module = module; |