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.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index af1f68f7e315..9b513a05765a 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -451,6 +451,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
451 unsigned long flags; 451 unsigned long flags;
452 452
453 spin_lock_irqsave(&slave_active_lock, flags); 453 spin_lock_irqsave(&slave_active_lock, flags);
454 if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
455 spin_unlock_irqrestore(&slave_active_lock, flags);
456 return -EBUSY;
457 }
454 timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; 458 timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
455 if (timeri->master && timeri->timer) { 459 if (timeri->master && timeri->timer) {
456 spin_lock(&timeri->timer->lock); 460 spin_lock(&timeri->timer->lock);
@@ -475,7 +479,8 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
475 return -EINVAL; 479 return -EINVAL;
476 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { 480 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
477 result = snd_timer_start_slave(timeri); 481 result = snd_timer_start_slave(timeri);
478 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); 482 if (result >= 0)
483 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
479 return result; 484 return result;
480 } 485 }
481 timer = timeri->timer; 486 timer = timeri->timer;
@@ -484,11 +489,18 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
484 if (timer->card && timer->card->shutdown) 489 if (timer->card && timer->card->shutdown)
485 return -ENODEV; 490 return -ENODEV;
486 spin_lock_irqsave(&timer->lock, flags); 491 spin_lock_irqsave(&timer->lock, flags);
492 if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
493 SNDRV_TIMER_IFLG_START)) {
494 result = -EBUSY;
495 goto unlock;
496 }
487 timeri->ticks = timeri->cticks = ticks; 497 timeri->ticks = timeri->cticks = ticks;
488 timeri->pticks = 0; 498 timeri->pticks = 0;
489 result = snd_timer_start1(timer, timeri, ticks); 499 result = snd_timer_start1(timer, timeri, ticks);
500 unlock:
490 spin_unlock_irqrestore(&timer->lock, flags); 501 spin_unlock_irqrestore(&timer->lock, flags);
491 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); 502 if (result >= 0)
503 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
492 return result; 504 return result;
493} 505}
494 506
@@ -502,6 +514,10 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
502 514
503 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { 515 if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
504 spin_lock_irqsave(&slave_active_lock, flags); 516 spin_lock_irqsave(&slave_active_lock, flags);
517 if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
518 spin_unlock_irqrestore(&slave_active_lock, flags);
519 return -EBUSY;
520 }
505 timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; 521 timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
506 list_del_init(&timeri->ack_list); 522 list_del_init(&timeri->ack_list);
507 list_del_init(&timeri->active_list); 523 list_del_init(&timeri->active_list);
@@ -512,6 +528,11 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
512 if (!timer) 528 if (!timer)
513 return -EINVAL; 529 return -EINVAL;
514 spin_lock_irqsave(&timer->lock, flags); 530 spin_lock_irqsave(&timer->lock, flags);
531 if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
532 SNDRV_TIMER_IFLG_START))) {
533 spin_unlock_irqrestore(&timer->lock, flags);
534 return -EBUSY;
535 }
515 list_del_init(&timeri->ack_list); 536 list_del_init(&timeri->ack_list);
516 list_del_init(&timeri->active_list); 537 list_del_init(&timeri->active_list);
517 if (timer->card && timer->card->shutdown) { 538 if (timer->card && timer->card->shutdown) {
@@ -581,10 +602,15 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
581 if (timer->card && timer->card->shutdown) 602 if (timer->card && timer->card->shutdown)
582 return -ENODEV; 603 return -ENODEV;
583 spin_lock_irqsave(&timer->lock, flags); 604 spin_lock_irqsave(&timer->lock, flags);
605 if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
606 result = -EBUSY;
607 goto unlock;
608 }
584 if (!timeri->cticks) 609 if (!timeri->cticks)
585 timeri->cticks = 1; 610 timeri->cticks = 1;
586 timeri->pticks = 0; 611 timeri->pticks = 0;
587 result = snd_timer_start1(timer, timeri, timer->sticks); 612 result = snd_timer_start1(timer, timeri, timer->sticks);
613 unlock:
588 spin_unlock_irqrestore(&timer->lock, flags); 614 spin_unlock_irqrestore(&timer->lock, flags);
589 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE); 615 snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
590 return result; 616 return result;
@@ -718,8 +744,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
718 ti->cticks = ti->ticks; 744 ti->cticks = ti->ticks;
719 } else { 745 } else {
720 ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; 746 ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
721 if (--timer->running) 747 --timer->running;
722 list_del_init(&ti->active_list); 748 list_del_init(&ti->active_list);
723 } 749 }
724 if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || 750 if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
725 (ti->flags & SNDRV_TIMER_IFLG_FAST)) 751 (ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -1032,11 +1058,21 @@ static int snd_timer_s_stop(struct snd_timer * timer)
1032 return 0; 1058 return 0;
1033} 1059}
1034 1060
1061static int snd_timer_s_close(struct snd_timer *timer)
1062{
1063 struct snd_timer_system_private *priv;
1064
1065 priv = (struct snd_timer_system_private *)timer->private_data;
1066 del_timer_sync(&priv->tlist);
1067 return 0;
1068}
1069
1035static struct snd_timer_hardware snd_timer_system = 1070static struct snd_timer_hardware snd_timer_system =
1036{ 1071{
1037 .flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET, 1072 .flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
1038 .resolution = 1000000000L / HZ, 1073 .resolution = 1000000000L / HZ,
1039 .ticks = 10000000L, 1074 .ticks = 10000000L,
1075 .close = snd_timer_s_close,
1040 .start = snd_timer_s_start, 1076 .start = snd_timer_s_start,
1041 .stop = snd_timer_s_stop 1077 .stop = snd_timer_s_stop
1042}; 1078};