summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-03-27 16:51:58 +0100
committerTakashi Iwai <tiwai@suse.de>2019-03-27 16:51:58 +0100
commit7bb4a8a2cc9382da720b46988bc976ebccaa49fd (patch)
tree6b24922b674ebce68bacc346cf52d378f9d2beda /sound/core
parent8748b850beccdbc87aa8776d63abd6b5628720c8 (diff)
downloadlwn-7bb4a8a2cc9382da720b46988bc976ebccaa49fd.tar.gz
lwn-7bb4a8a2cc9382da720b46988bc976ebccaa49fd.zip
ALSA: timer: Make sure to clear pending ack list
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>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/timer.c20
1 files changed, 18 insertions, 2 deletions
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);