ALSA: timer: Make sure to clear pending ack list
authorTakashi Iwai <tiwai@suse.de>
Wed, 27 Mar 2019 15:51:58 +0000 (16:51 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 27 Mar 2019 15:51:58 +0000 (16:51 +0100)
When a card is under disconnection, we bail out immediately at each
timer interrupt or tasklet.  This might leave some items left in ack
list.  For a better integration of the upcoming change to check
ack_list emptiness, clear out the whole list upon the emergency exit
route.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/timer.c

index fdcddfb..107d8eb 100644 (file)
@@ -747,6 +747,18 @@ static void snd_timer_process_callbacks(struct snd_timer *timer,
        }
 }
 
+/* clear pending instances from ack list */
+static void snd_timer_clear_callbacks(struct snd_timer *timer,
+                                     struct list_head *head)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&timer->lock, flags);
+       while (!list_empty(head))
+               list_del_init(head->next);
+       spin_unlock_irqrestore(&timer->lock, flags);
+}
+
 /*
  * timer tasklet
  *
@@ -756,8 +768,10 @@ static void snd_timer_tasklet(unsigned long arg)
        struct snd_timer *timer = (struct snd_timer *) arg;
        unsigned long flags;
 
-       if (timer->card && timer->card->shutdown)
+       if (timer->card && timer->card->shutdown) {
+               snd_timer_clear_callbacks(timer, &timer->sack_list_head);
                return;
+       }
 
        spin_lock_irqsave(&timer->lock, flags);
        snd_timer_process_callbacks(timer, &timer->sack_list_head);
@@ -781,8 +795,10 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
        if (timer == NULL)
                return;
 
-       if (timer->card && timer->card->shutdown)
+       if (timer->card && timer->card->shutdown) {
+               snd_timer_clear_callbacks(timer, &timer->ack_list_head);
                return;
+       }
 
        spin_lock_irqsave(&timer->lock, flags);