path: root/sound/drivers
diff options
authorTakashi Iwai <>2020-09-03 12:41:21 +0200
committerTakashi Iwai <>2020-09-09 18:32:37 +0200
commit68f86a905e2c1d7a6d5d0bcc57f4e44ae204c171 (patch)
treeea76de449bc5f6d84b6c8284d4deb6257237c59b /sound/drivers
parent9ddb236f13594b34a12dacf69a5adca7a1aef35e (diff)
ALSA: pcsp: Replace tasklet with work
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: Signed-off-by: Takashi Iwai <>
Diffstat (limited to 'sound/drivers')
1 files changed, 5 insertions, 7 deletions
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 4e79293d7f11..ed40d0f7432c 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -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)
- tasklet_kill(&pcsp_pcm_tasklet);
+ cancel_work_sync(&pcsp_pcm_work);
static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)