aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r--sound/core/timer.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 6cdd04a45962..15e82a656d96 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -180,7 +180,7 @@ static void snd_timer_request(struct snd_timer_id *tid)
180 * 180 *
181 * call this with register_mutex down. 181 * call this with register_mutex down.
182 */ 182 */
183static void snd_timer_check_slave(struct snd_timer_instance *slave) 183static int snd_timer_check_slave(struct snd_timer_instance *slave)
184{ 184{
185 struct snd_timer *timer; 185 struct snd_timer *timer;
186 struct snd_timer_instance *master; 186 struct snd_timer_instance *master;
@@ -190,16 +190,21 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
190 list_for_each_entry(master, &timer->open_list_head, open_list) { 190 list_for_each_entry(master, &timer->open_list_head, open_list) {
191 if (slave->slave_class == master->slave_class && 191 if (slave->slave_class == master->slave_class &&
192 slave->slave_id == master->slave_id) { 192 slave->slave_id == master->slave_id) {
193 if (master->timer->num_instances >=
194 master->timer->max_instances)
195 return -EBUSY;
193 list_move_tail(&slave->open_list, 196 list_move_tail(&slave->open_list,
194 &master->slave_list_head); 197 &master->slave_list_head);
198 master->timer->num_instances++;
195 spin_lock_irq(&slave_active_lock); 199 spin_lock_irq(&slave_active_lock);
196 slave->master = master; 200 slave->master = master;
197 slave->timer = master->timer; 201 slave->timer = master->timer;
198 spin_unlock_irq(&slave_active_lock); 202 spin_unlock_irq(&slave_active_lock);
199 return; 203 return 0;
200 } 204 }
201 } 205 }
202 } 206 }
207 return 0;
203} 208}
204 209
205/* 210/*
@@ -208,7 +213,7 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
208 * 213 *
209 * call this with register_mutex down. 214 * call this with register_mutex down.
210 */ 215 */
211static void snd_timer_check_master(struct snd_timer_instance *master) 216static int snd_timer_check_master(struct snd_timer_instance *master)
212{ 217{
213 struct snd_timer_instance *slave, *tmp; 218 struct snd_timer_instance *slave, *tmp;
214 219
@@ -216,7 +221,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
216 list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) { 221 list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
217 if (slave->slave_class == master->slave_class && 222 if (slave->slave_class == master->slave_class &&
218 slave->slave_id == master->slave_id) { 223 slave->slave_id == master->slave_id) {
224 if (master->timer->num_instances >=
225 master->timer->max_instances)
226 return -EBUSY;
219 list_move_tail(&slave->open_list, &master->slave_list_head); 227 list_move_tail(&slave->open_list, &master->slave_list_head);
228 master->timer->num_instances++;
220 spin_lock_irq(&slave_active_lock); 229 spin_lock_irq(&slave_active_lock);
221 spin_lock(&master->timer->lock); 230 spin_lock(&master->timer->lock);
222 slave->master = master; 231 slave->master = master;
@@ -228,8 +237,11 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
228 spin_unlock_irq(&slave_active_lock); 237 spin_unlock_irq(&slave_active_lock);
229 } 238 }
230 } 239 }
240 return 0;
231} 241}
232 242
243static int snd_timer_close_locked(struct snd_timer_instance *timeri);
244
233/* 245/*
234 * open a timer instance 246 * open a timer instance
235 * when opening a master, the slave id must be here given. 247 * when opening a master, the slave id must be here given.
@@ -240,6 +252,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
240{ 252{
241 struct snd_timer *timer; 253 struct snd_timer *timer;
242 struct snd_timer_instance *timeri = NULL; 254 struct snd_timer_instance *timeri = NULL;
255 int err;
243 256
244 if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { 257 if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
245 /* open a slave instance */ 258 /* open a slave instance */
@@ -259,10 +272,14 @@ int snd_timer_open(struct snd_timer_instance **ti,
259 timeri->slave_id = tid->device; 272 timeri->slave_id = tid->device;
260 timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; 273 timeri->flags |= SNDRV_TIMER_IFLG_SLAVE;
261 list_add_tail(&timeri->open_list, &snd_timer_slave_list); 274 list_add_tail(&timeri->open_list, &snd_timer_slave_list);
262 snd_timer_check_slave(timeri); 275 err = snd_timer_check_slave(timeri);
276 if (err < 0) {
277 snd_timer_close_locked(timeri);
278 timeri = NULL;
279 }
263 mutex_unlock(&register_mutex); 280 mutex_unlock(&register_mutex);
264 *ti = timeri; 281 *ti = timeri;
265 return 0; 282 return err;
266 } 283 }
267 284
268 /* open a master instance */ 285 /* open a master instance */
@@ -288,6 +305,10 @@ int snd_timer_open(struct snd_timer_instance **ti,
288 return -EBUSY; 305 return -EBUSY;
289 } 306 }
290 } 307 }
308 if (timer->num_instances >= timer->max_instances) {
309 mutex_unlock(&register_mutex);
310 return -EBUSY;
311 }
291 timeri = snd_timer_instance_new(owner, timer); 312 timeri = snd_timer_instance_new(owner, timer);
292 if (!timeri) { 313 if (!timeri) {
293 mutex_unlock(&register_mutex); 314 mutex_unlock(&register_mutex);
@@ -314,25 +335,27 @@ int snd_timer_open(struct snd_timer_instance **ti,
314 } 335 }
315 336
316 list_add_tail(&timeri->open_list, &timer->open_list_head); 337 list_add_tail(&timeri->open_list, &timer->open_list_head);
317 snd_timer_check_master(timeri); 338 timer->num_instances++;
339 err = snd_timer_check_master(timeri);
340 if (err < 0) {
341 snd_timer_close_locked(timeri);
342 timeri = NULL;
343 }
318 mutex_unlock(&register_mutex); 344 mutex_unlock(&register_mutex);
319 *ti = timeri; 345 *ti = timeri;
320 return 0; 346 return err;
321} 347}
322EXPORT_SYMBOL(snd_timer_open); 348EXPORT_SYMBOL(snd_timer_open);
323 349
324/* 350/*
325 * close a timer instance 351 * close a timer instance
352 * call this with register_mutex down.
326 */ 353 */
327int snd_timer_close(struct snd_timer_instance *timeri) 354static int snd_timer_close_locked(struct snd_timer_instance *timeri)
328{ 355{
329 struct snd_timer *timer = NULL; 356 struct snd_timer *timer = NULL;
330 struct snd_timer_instance *slave, *tmp; 357 struct snd_timer_instance *slave, *tmp;
331 358
332 if (snd_BUG_ON(!timeri))
333 return -ENXIO;
334
335 mutex_lock(&register_mutex);
336 list_del(&timeri->open_list); 359 list_del(&timeri->open_list);
337 360
338 /* force to stop the timer */ 361 /* force to stop the timer */
@@ -340,6 +363,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
340 363
341 timer = timeri->timer; 364 timer = timeri->timer;
342 if (timer) { 365 if (timer) {
366 timer->num_instances--;
343 /* wait, until the active callback is finished */ 367 /* wait, until the active callback is finished */
344 spin_lock_irq(&timer->lock); 368 spin_lock_irq(&timer->lock);
345 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { 369 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
@@ -355,6 +379,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
355 list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, 379 list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
356 open_list) { 380 open_list) {
357 list_move_tail(&slave->open_list, &snd_timer_slave_list); 381 list_move_tail(&slave->open_list, &snd_timer_slave_list);
382 timer->num_instances--;
358 slave->master = NULL; 383 slave->master = NULL;
359 slave->timer = NULL; 384 slave->timer = NULL;
360 list_del_init(&slave->ack_list); 385 list_del_init(&slave->ack_list);
@@ -382,9 +407,24 @@ int snd_timer_close(struct snd_timer_instance *timeri)
382 module_put(timer->module); 407 module_put(timer->module);
383 } 408 }
384 409
385 mutex_unlock(&register_mutex);
386 return 0; 410 return 0;
387} 411}
412
413/*
414 * close a timer instance
415 */
416int snd_timer_close(struct snd_timer_instance *timeri)
417{
418 int err;
419
420 if (snd_BUG_ON(!timeri))
421 return -ENXIO;
422
423 mutex_lock(&register_mutex);
424 err = snd_timer_close_locked(timeri);
425 mutex_unlock(&register_mutex);
426 return err;
427}
388EXPORT_SYMBOL(snd_timer_close); 428EXPORT_SYMBOL(snd_timer_close);
389 429
390unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) 430unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
@@ -856,6 +896,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
856 spin_lock_init(&timer->lock); 896 spin_lock_init(&timer->lock);
857 tasklet_init(&timer->task_queue, snd_timer_tasklet, 897 tasklet_init(&timer->task_queue, snd_timer_tasklet,
858 (unsigned long)timer); 898 (unsigned long)timer);
899 timer->max_instances = 1000; /* default limit per timer */
859 if (card != NULL) { 900 if (card != NULL) {
860 timer->module = card->module; 901 timer->module = card->module;
861 err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); 902 err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);