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.
Signed-off-by: Takashi Iwai tiwai@suse.de --- include/sound/timer.h | 8 ++++---- sound/core/hrtimer.c | 2 +- sound/core/timer.c | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/include/sound/timer.h b/include/sound/timer.h index 23e885d31525..760e132cc0cd 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -21,13 +21,13 @@ #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; diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index c61ba52a530a..e97ff8cccb64 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -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, diff --git a/sound/core/timer.c b/sound/core/timer.c index 6e27d87b18ed..4e74aa3d9e1f 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -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,