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 96c7d478ef "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>
This commit is contained in:
Takashi Iwai 2020-09-03 12:41:21 +02:00
parent 9ddb236f13
commit 68f86a905e
1 changed files with 5 additions and 7 deletions

View 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)