summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-03-27 16:42:51 +0100
committerTakashi Iwai <tiwai@suse.de>2019-03-27 16:42:51 +0100
commit8748b850beccdbc87aa8776d63abd6b5628720c8 (patch)
tree24c2656f0fa3df1d21817b82ef258a3176b60b8b /sound/core
parente42dd3ee3f9c6007c569386a8477a19d3e7503f9 (diff)
ALSA: timer: Unify timer callback process code
The timer core has two almost identical code for processing callbacks: once in snd_timer_interrupt() for fast callbacks and another in snd_timer_tasklet() for delayed callbacks. Let's unify them. In the new version, the resolution is read from ti->resolution at each call, and this must be fine; ti->resolution is set in the preparation step in snd_timer_interrupt(). Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/timer.c62
1 files changed, 26 insertions, 36 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 61a0cec6e1f6..fdcddfb756b4 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -720,29 +720,19 @@ static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_l
timer->sticks = ticks;
}
-/*
- * timer tasklet
- *
- */
-static void snd_timer_tasklet(unsigned long arg)
+/* call callbacks in timer ack list */
+static void snd_timer_process_callbacks(struct snd_timer *timer,
+ struct list_head *head)
{
- struct snd_timer *timer = (struct snd_timer *) arg;
struct snd_timer_instance *ti;
- struct list_head *p;
unsigned long resolution, ticks;
- unsigned long flags;
- if (timer->card && timer->card->shutdown)
- return;
-
- spin_lock_irqsave(&timer->lock, flags);
- /* now process all callbacks */
- while (!list_empty(&timer->sack_list_head)) {
- p = timer->sack_list_head.next; /* get first item */
- ti = list_entry(p, struct snd_timer_instance, ack_list);
+ while (!list_empty(head)) {
+ ti = list_first_entry(head, struct snd_timer_instance,
+ ack_list);
/* remove from ack_list and make empty */
- list_del_init(p);
+ list_del_init(&ti->ack_list);
ticks = ti->pticks;
ti->pticks = 0;
@@ -755,6 +745,22 @@ static void snd_timer_tasklet(unsigned long arg)
spin_lock(&timer->lock);
ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
}
+}
+
+/*
+ * timer tasklet
+ *
+ */
+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)
+ return;
+
+ spin_lock_irqsave(&timer->lock, flags);
+ snd_timer_process_callbacks(timer, &timer->sack_list_head);
spin_unlock_irqrestore(&timer->lock, flags);
}
@@ -767,8 +773,8 @@ static void snd_timer_tasklet(unsigned long arg)
void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
{
struct snd_timer_instance *ti, *ts, *tmp;
- unsigned long resolution, ticks;
- struct list_head *p, *ack_list_head;
+ unsigned long resolution;
+ struct list_head *ack_list_head;
unsigned long flags;
int use_tasklet = 0;
@@ -839,23 +845,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
}
/* now process all fast callbacks */
- while (!list_empty(&timer->ack_list_head)) {
- p = timer->ack_list_head.next; /* get first item */
- ti = list_entry(p, struct snd_timer_instance, ack_list);
-
- /* remove from ack_list and make empty */
- list_del_init(p);
-
- ticks = ti->pticks;
- ti->pticks = 0;
-
- ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
- spin_unlock(&timer->lock);
- if (ti->callback)
- ti->callback(ti, resolution, ticks);
- spin_lock(&timer->lock);
- ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
- }
+ snd_timer_process_callbacks(timer, &timer->ack_list_head);
/* do we have any slow callbacks? */
use_tasklet = !list_empty(&timer->sack_list_head);