ALSA: timer: Replace tasklet with work
authorTakashi Iwai <tiwai@suse.de>
Thu, 3 Sep 2020 10:41:22 +0000 (12:41 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 9 Sep 2020 16:32:52 +0000 (18:32 +0200)
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API.  In ALSA core timer API, the
callbacks can be offlined to a tasklet when a flag is set in the timer
backend.  It can be achieved gracefully with a work queued in the
high-prio system workqueue.

This patch replaces the usage of tasklet in ALSA timer API with a
simple work.  Currently the tasklet feature is used only in the system
timer and hrtimer backends, so both are patched to use the new flag
name SNDRV_TIMER_HW_WORK, too.

Link: https://lore.kernel.org/r/20200903104131.21097-3-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/timer.h
sound/core/hrtimer.c
sound/core/timer.c

index 23e885d31525a2e1bfa76da4a166438d1afaaca0..760e132cc0cd24f336a4f4b21f287b0d993cb4fe 100644 (file)
 #define SNDRV_TIMER_HW_STOP    0x00000002      /* call stop before start */
 #define SNDRV_TIMER_HW_SLAVE   0x00000004      /* only slave timer (variable resolution) */
 #define SNDRV_TIMER_HW_FIRST   0x00000008      /* first tick can be incomplete */
-#define SNDRV_TIMER_HW_TASKLET 0x00000010      /* timer is called from tasklet */
+#define SNDRV_TIMER_HW_WORK    0x00000010      /* timer is called from work */
 
 #define SNDRV_TIMER_IFLG_SLAVE   0x00000001
 #define SNDRV_TIMER_IFLG_RUNNING  0x00000002
 #define SNDRV_TIMER_IFLG_START   0x00000004
 #define SNDRV_TIMER_IFLG_AUTO    0x00000008    /* auto restart */
-#define SNDRV_TIMER_IFLG_FAST    0x00000010    /* fast callback (do not use tasklet) */
+#define SNDRV_TIMER_IFLG_FAST    0x00000010    /* fast callback (do not use work) */
 #define SNDRV_TIMER_IFLG_CALLBACK 0x00000020   /* timer callback is active */
 #define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040  /* exclusive owner - no more instances */
 #define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080        /* write early event to the poll queue */
@@ -74,7 +74,7 @@ struct snd_timer {
        struct list_head active_list_head;
        struct list_head ack_list_head;
        struct list_head sack_list_head; /* slow ack list head */
-       struct tasklet_struct task_queue;
+       struct work_struct task_work;
        int max_instances;      /* upper limit of timer instances */
        int num_instances;      /* current number of timer instances */
 };
@@ -96,7 +96,7 @@ struct snd_timer_instance {
        unsigned long ticks;            /* auto-load ticks when expired */
        unsigned long cticks;           /* current ticks */
        unsigned long pticks;           /* accumulated ticks for callback */
-       unsigned long resolution;       /* current resolution for tasklet */
+       unsigned long resolution;       /* current resolution for work */
        unsigned long lost;             /* lost ticks */
        int slave_class;
        unsigned int slave_id;
index c61ba52a530aa95f9548af15031319997e646f8d..e97ff8cccb643359cae97162040f516a7b0c43b1 100644 (file)
@@ -114,7 +114,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
 }
 
 static const struct snd_timer_hardware hrtimer_hw __initconst = {
-       .flags =        SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_TASKLET,
+       .flags =        SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_WORK,
        .open =         snd_hrtimer_open,
        .close =        snd_hrtimer_close,
        .start =        snd_hrtimer_start,
index 227d8152d32559374bda4439e53a50fa5d8acea9..765ea66665a8c5e4b19f3763ef73f48a1ce35ba4 100644 (file)
@@ -813,12 +813,12 @@ static void snd_timer_clear_callbacks(struct snd_timer *timer,
 }
 
 /*
- * timer tasklet
+ * timer work
  *
  */
-static void snd_timer_tasklet(struct tasklet_struct *t)
+static void snd_timer_work(struct work_struct *work)
 {
-       struct snd_timer *timer = from_tasklet(timer, t, task_queue);
+       struct snd_timer *timer = container_of(work, struct snd_timer, task_work);
        unsigned long flags;
 
        if (timer->card && timer->card->shutdown) {
@@ -843,7 +843,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
        unsigned long resolution;
        struct list_head *ack_list_head;
        unsigned long flags;
-       int use_tasklet = 0;
+       bool use_work = false;
 
        if (timer == NULL)
                return;
@@ -884,7 +884,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
                        --timer->running;
                        list_del_init(&ti->active_list);
                }
-               if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
+               if ((timer->hw.flags & SNDRV_TIMER_HW_WORK) ||
                    (ti->flags & SNDRV_TIMER_IFLG_FAST))
                        ack_list_head = &timer->ack_list_head;
                else
@@ -919,11 +919,11 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
        snd_timer_process_callbacks(timer, &timer->ack_list_head);
 
        /* do we have any slow callbacks? */
-       use_tasklet = !list_empty(&timer->sack_list_head);
+       use_work = !list_empty(&timer->sack_list_head);
        spin_unlock_irqrestore(&timer->lock, flags);
 
-       if (use_tasklet)
-               tasklet_schedule(&timer->task_queue);
+       if (use_work)
+               queue_work(system_highpri_wq, &timer->task_work);
 }
 EXPORT_SYMBOL(snd_timer_interrupt);
 
@@ -967,7 +967,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
        INIT_LIST_HEAD(&timer->ack_list_head);
        INIT_LIST_HEAD(&timer->sack_list_head);
        spin_lock_init(&timer->lock);
-       tasklet_setup(&timer->task_queue, snd_timer_tasklet);
+       INIT_WORK(&timer->task_work, snd_timer_work);
        timer->max_instances = 1000; /* default limit per timer */
        if (card != NULL) {
                timer->module = card->module;
@@ -1200,7 +1200,7 @@ static int snd_timer_s_close(struct snd_timer *timer)
 
 static const struct snd_timer_hardware snd_timer_system =
 {
-       .flags =        SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
+       .flags =        SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_WORK,
        .resolution =   1000000000L / HZ,
        .ticks =        10000000L,
        .close =        snd_timer_s_close,