ALSA: pcsp: Replace tasklet with work
authorTakashi Iwai <tiwai@suse.de>
Thu, 3 Sep 2020 10:41:21 +0000 (12:41 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 9 Sep 2020 16:32:37 +0000 (18:32 +0200)
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API.  This patch replaces the usage of
tasklet in pcsp driver with a simple work.  In pcsp driver, a global
tasklet is used for offloading the period-elapse handling in the
hrtimer callback (introduced in commit 96c7d478efad "ALSA: pcsp - Fix
locking messes in snd-pcsp").  It can be achieved gracefully with a
work queued in the high-prio system workqueue.

This also changes tasklet_kill() with cancel_work_sync() in the
sync_stop callback, which is anyway better to assure canceling the
pending tasks.

Link: https://lore.kernel.org/r/20200903104131.21097-2-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/drivers/pcsp/pcsp_lib.c

index 4e79293..ed40d0f 100644 (file)
@@ -23,10 +23,10 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
 #define DMIX_WANTS_S16 1
 
 /*
- * Call snd_pcm_period_elapsed in a tasklet
+ * Call snd_pcm_period_elapsed in a work
  * This avoids spinlock messes and long-running irq contexts
  */
-static void pcsp_call_pcm_elapsed(unsigned long priv)
+static void pcsp_call_pcm_elapsed(struct work_struct *work)
 {
        if (atomic_read(&pcsp_chip.timer_active)) {
                struct snd_pcm_substream *substream;
@@ -36,7 +36,7 @@ static void pcsp_call_pcm_elapsed(unsigned long priv)
        }
 }
 
-static DECLARE_TASKLET_OLD(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed);
+static DECLARE_WORK(pcsp_pcm_work, pcsp_call_pcm_elapsed);
 
 /* write the port and returns the next expire time in ns;
  * called at the trigger-start and in hrtimer callback
@@ -119,11 +119,9 @@ static void pcsp_pointer_update(struct snd_pcsp *chip)
        if (periods_elapsed) {
                chip->period_ptr += periods_elapsed * period_bytes;
                chip->period_ptr %= buffer_bytes;
+               queue_work(system_highpri_wq, &pcsp_pcm_work);
        }
        spin_unlock_irqrestore(&chip->substream_lock, flags);
-
-       if (periods_elapsed)
-               tasklet_schedule(&pcsp_pcm_tasklet);
 }
 
 enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
@@ -196,7 +194,7 @@ void pcsp_sync_stop(struct snd_pcsp *chip)
        pcsp_stop_playing(chip);
        local_irq_enable();
        hrtimer_cancel(&chip->timer);
-       tasklet_kill(&pcsp_pcm_tasklet);
+       cancel_work_sync(&pcsp_pcm_work);
 }
 
 static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)