ALSA: timer: Fix race between stop and interrupt
[pandora-kernel.git] / sound / core / timer.c
index 39bf01d..9198fe2 100644 (file)
@@ -414,7 +414,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
        spin_lock_irqsave(&timer->lock, flags);
        list_for_each_entry(ts, &ti->slave_active_head, active_list)
                if (ts->ccallback)
-                       ts->ccallback(ti, event + 100, &tstamp, resolution);
+                       ts->ccallback(ts, event + 100, &tstamp, resolution);
        spin_unlock_irqrestore(&timer->lock, flags);
 }
 
@@ -510,9 +510,13 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
                                spin_unlock_irqrestore(&slave_active_lock, flags);
                                return -EBUSY;
                        }
+                       if (timeri->timer)
+                               spin_lock(&timeri->timer->lock);
                        timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
                        list_del_init(&timeri->ack_list);
                        list_del_init(&timeri->active_list);
+                       if (timeri->timer)
+                               spin_unlock(&timeri->timer->lock);
                        spin_unlock_irqrestore(&slave_active_lock, flags);
                }
                goto __end;
@@ -727,8 +731,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
                        ti->cticks = ti->ticks;
                } else {
                        ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
-                       if (--timer->running)
-                               list_del_init(&ti->active_list);
+                       --timer->running;
+                       list_del_init(&ti->active_list);
                }
                if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
                    (ti->flags & SNDRV_TIMER_IFLG_FAST))