diff mbox series

[2/4] ALSA: timer: Make sure to clear pending ack list

Message ID 20190327165217.4240-3-tiwai@suse.de (mailing list archive)
State New, archived
Headers show
Series ALSA: yet more timer cleanup and fixes | expand

Commit Message

Takashi Iwai March 27, 2019, 4:52 p.m. UTC
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 | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/sound/core/timer.c b/sound/core/timer.c
index fdcddfb756b4..107d8ebeeb2e 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -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);