* [PATCH 00/11] ALSA: Kill tasklet usage
@ 2020-09-03 10:41 Takashi Iwai
2020-09-03 10:41 ` [PATCH 01/11] ALSA: pcsp: Replace tasklet with work Takashi Iwai
` (10 more replies)
0 siblings, 11 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
Hi,
here is a patch set to convert the tasklet usage in sound tree with
either the threaded irq or the dedicated work. It's applied after the
tasket API conversion series, found in topic/tasklet-convert branch of
sound git tree (which will be included in the next pull request for
5.9-rc4).
This contains only non-ASoC changes, the changes for ASoC will
follow at next.
Takashi
===
Takashi Iwai (11):
ALSA: pcsp: Replace tasklet with work
ALSA: timer: Replace tasklet with work
ALSA: usb-audio: Replace tasklet with work
ALSA: ua101: Replace tasklet with work
ALSA: aloop: Replace tasklet with work
ALSA: hdsp: Replace tasklet with work
ALSA: hdspm: Replace tasklet with work
ALSA: riptide: Replace tasklet with threaded irq
ALSA: asihpi: Replace tasklet with threaded irq
ALSA: firewire: Replace tasklet with work
ALSA: mixart: Correct comment wrt obsoleted tasklet usage
include/sound/timer.h | 8 +++---
sound/core/hrtimer.c | 2 +-
sound/core/timer.c | 20 +++++++-------
sound/drivers/aloop.c | 23 ++++++++--------
sound/drivers/pcsp/pcsp_lib.c | 12 ++++----
sound/firewire/amdtp-stream-trace.h | 2 +-
sound/firewire/amdtp-stream.c | 25 +++++++++--------
sound/firewire/amdtp-stream.h | 2 +-
sound/pci/asihpi/asihpi.c | 28 ++-----------------
sound/pci/asihpi/hpioctl.c | 16 +++++++++--
sound/pci/mixart/mixart.h | 2 +-
sound/pci/riptide/riptide.c | 20 ++++++++------
sound/pci/rme9652/hdsp.c | 55 ++++++++++++++++++-------------------
sound/pci/rme9652/hdspm.c | 13 ++++-----
sound/usb/midi.c | 13 +++++----
sound/usb/misc/ua101.c | 16 +++++------
16 files changed, 122 insertions(+), 135 deletions(-)
--
2.16.4
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/11] ALSA: pcsp: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 02/11] ALSA: timer: " Takashi Iwai
` (9 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
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.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/drivers/pcsp/pcsp_lib.c | 12 +++++-------
1 file 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)
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)
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 02/11] ALSA: timer: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
2020-09-03 10:41 ` [PATCH 01/11] ALSA: pcsp: Replace tasklet with work Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 03/11] ALSA: usb-audio: " Takashi Iwai
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
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,
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 03/11] ALSA: usb-audio: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
2020-09-03 10:41 ` [PATCH 01/11] ALSA: pcsp: Replace tasklet with work Takashi Iwai
2020-09-03 10:41 ` [PATCH 02/11] ALSA: timer: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 04/11] ALSA: ua101: " Takashi Iwai
` (7 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In USB-audio driver, a tasklet is
still used in MIDI interface code for handling the output byte
stream. It can be achieved gracefully with a work queued in the
high-prio system workqueue.
This patch replaces the tasklet usage in USB-audio driver with a
simple work.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/usb/midi.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index e8287a05e36b..c8213652470c 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -142,7 +142,7 @@ struct snd_usb_midi_out_endpoint {
unsigned int active_urbs;
unsigned int drain_urbs;
int max_transfer; /* size of urb buffer */
- struct tasklet_struct tasklet;
+ struct work_struct work;
unsigned int next_urb;
spinlock_t buffer_lock;
@@ -344,9 +344,10 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint *ep)
spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
-static void snd_usbmidi_out_tasklet(struct tasklet_struct *t)
+static void snd_usbmidi_out_work(struct work_struct *work)
{
- struct snd_usb_midi_out_endpoint *ep = from_tasklet(ep, t, tasklet);
+ struct snd_usb_midi_out_endpoint *ep =
+ container_of(work, struct snd_usb_midi_out_endpoint, work);
snd_usbmidi_do_output(ep);
}
@@ -1177,7 +1178,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
snd_rawmidi_proceed(substream);
return;
}
- tasklet_schedule(&port->ep->tasklet);
+ queue_work(system_highpri_wq, &port->ep->work);
}
}
@@ -1440,7 +1441,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
}
spin_lock_init(&ep->buffer_lock);
- tasklet_setup(&ep->tasklet, snd_usbmidi_out_tasklet);
+ INIT_WORK(&ep->work, snd_usbmidi_out_work);
init_waitqueue_head(&ep->drain_wait);
for (i = 0; i < 0x10; ++i)
@@ -1503,7 +1504,7 @@ void snd_usbmidi_disconnect(struct list_head *p)
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
if (ep->out)
- tasklet_kill(&ep->out->tasklet);
+ cancel_work_sync(&ep->out->work);
if (ep->out) {
for (j = 0; j < OUTPUT_URBS; ++j)
usb_kill_urb(ep->out->urbs[j].urb);
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 04/11] ALSA: ua101: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (2 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 03/11] ALSA: usb-audio: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 05/11] ALSA: aloop: " Takashi Iwai
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In UA101 driver, a tasklet is still
used for handling the output URBs. It can be achieved gracefully with
a work queued in the high-prio system workqueue, too.
This patch replaces the tasklet usage in UA101 driver with a simple
work.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/usb/misc/ua101.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 3b2dce1043f5..6b30155964ec 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -96,7 +96,7 @@ struct ua101 {
u8 rate_feedback[MAX_QUEUE_LENGTH];
struct list_head ready_playback_urbs;
- struct tasklet_struct playback_tasklet;
+ struct work_struct playback_work;
wait_queue_head_t alsa_capture_wait;
wait_queue_head_t rate_feedback_wait;
wait_queue_head_t alsa_playback_wait;
@@ -188,7 +188,7 @@ static void playback_urb_complete(struct urb *usb_urb)
spin_lock_irqsave(&ua->lock, flags);
list_add_tail(&urb->ready_list, &ua->ready_playback_urbs);
if (ua->rate_feedback_count > 0)
- tasklet_schedule(&ua->playback_tasklet);
+ queue_work(system_highpri_wq, &ua->playback_work);
ua->playback.substream->runtime->delay -=
urb->urb.iso_frame_desc[0].length /
ua->playback.frame_bytes;
@@ -247,9 +247,9 @@ static inline void add_with_wraparound(struct ua101 *ua,
*value -= ua->playback.queue_length;
}
-static void playback_tasklet(struct tasklet_struct *t)
+static void playback_work(struct work_struct *work)
{
- struct ua101 *ua = from_tasklet(ua, t, playback_tasklet);
+ struct ua101 *ua = container_of(work, struct ua101, playback_work);
unsigned long flags;
unsigned int frames;
struct ua101_urb *urb;
@@ -401,7 +401,7 @@ static void capture_urb_complete(struct urb *urb)
}
if (test_bit(USB_PLAYBACK_RUNNING, &ua->states) &&
!list_empty(&ua->ready_playback_urbs))
- tasklet_schedule(&ua->playback_tasklet);
+ queue_work(system_highpri_wq, &ua->playback_work);
}
spin_unlock_irqrestore(&ua->lock, flags);
@@ -532,7 +532,7 @@ static void stop_usb_playback(struct ua101 *ua)
kill_stream_urbs(&ua->playback);
- tasklet_kill(&ua->playback_tasklet);
+ cancel_work_sync(&ua->playback_work);
disable_iso_interface(ua, INTF_PLAYBACK);
}
@@ -550,7 +550,7 @@ static int start_usb_playback(struct ua101 *ua)
return 0;
kill_stream_urbs(&ua->playback);
- tasklet_kill(&ua->playback_tasklet);
+ cancel_work_sync(&ua->playback_work);
err = enable_iso_interface(ua, INTF_PLAYBACK);
if (err < 0)
@@ -1218,7 +1218,7 @@ static int ua101_probe(struct usb_interface *interface,
spin_lock_init(&ua->lock);
mutex_init(&ua->mutex);
INIT_LIST_HEAD(&ua->ready_playback_urbs);
- tasklet_setup(&ua->playback_tasklet, playback_tasklet);
+ INIT_WORK(&ua->playback_work, playback_work);
init_waitqueue_head(&ua->alsa_capture_wait);
init_waitqueue_head(&ua->rate_feedback_wait);
init_waitqueue_head(&ua->alsa_playback_wait);
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 05/11] ALSA: aloop: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (3 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 04/11] ALSA: ua101: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 06/11] ALSA: hdsp: " Takashi Iwai
` (5 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In aloop driver, a tasklet is still
used for offloading the timer event task. It can be achieved
gracefully with a work queued, too.
This patch replaces the tasklet usage in aloop driver with a simple
work.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/drivers/aloop.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 251eaf1152e2..c91356326699 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -110,7 +110,7 @@ struct loopback_cable {
struct {
int stream;
struct snd_timer_id id;
- struct tasklet_struct event_tasklet;
+ struct work_struct event_work;
struct snd_timer_instance *instance;
} snd_timer;
};
@@ -309,8 +309,8 @@ static int loopback_snd_timer_close_cable(struct loopback_pcm *dpcm)
*/
snd_timer_close(cable->snd_timer.instance);
- /* wait till drain tasklet has finished if requested */
- tasklet_kill(&cable->snd_timer.event_tasklet);
+ /* wait till drain work has finished if requested */
+ cancel_work_sync(&cable->snd_timer.event_work);
snd_timer_instance_free(cable->snd_timer.instance);
memset(&cable->snd_timer, 0, sizeof(cable->snd_timer));
@@ -794,11 +794,11 @@ static void loopback_snd_timer_function(struct snd_timer_instance *timeri,
resolution);
}
-static void loopback_snd_timer_tasklet(unsigned long arg)
+static void loopback_snd_timer_work(struct work_struct *work)
{
- struct snd_timer_instance *timeri = (struct snd_timer_instance *)arg;
- struct loopback_cable *cable = timeri->callback_data;
+ struct loopback_cable *cable;
+ cable = container_of(work, struct loopback_cable, snd_timer.event_work);
loopback_snd_timer_period_elapsed(cable, SNDRV_TIMER_EVENT_MSTOP, 0);
}
@@ -828,9 +828,9 @@ static void loopback_snd_timer_event(struct snd_timer_instance *timeri,
* state the streaming will be aborted by the usual timeout. It
* should not be aborted here because may be the timer sound
* card does only a recovery and the timer is back soon.
- * This tasklet triggers loopback_snd_timer_tasklet()
+ * This work triggers loopback_snd_timer_work()
*/
- tasklet_schedule(&cable->snd_timer.event_tasklet);
+ schedule_work(&cable->snd_timer.event_work);
}
}
@@ -1124,7 +1124,7 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm)
err = -ENOMEM;
goto exit;
}
- /* The callback has to be called from another tasklet. If
+ /* The callback has to be called from another work. If
* SNDRV_TIMER_IFLG_FAST is specified it will be called from the
* snd_pcm_period_elapsed() call of the selected sound card.
* snd_pcm_period_elapsed() helds snd_pcm_stream_lock_irqsave().
@@ -1137,9 +1137,8 @@ static int loopback_snd_timer_open(struct loopback_pcm *dpcm)
timeri->callback_data = (void *)cable;
timeri->ccallback = loopback_snd_timer_event;
- /* initialise a tasklet used for draining */
- tasklet_init(&cable->snd_timer.event_tasklet,
- loopback_snd_timer_tasklet, (unsigned long)timeri);
+ /* initialise a work used for draining */
+ INIT_WORK(&cable->snd_timer.event_work, loopback_snd_timer_work);
/* The mutex loopback->cable_lock is kept locked.
* Therefore snd_timer_open() cannot be called a second time
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 06/11] ALSA: hdsp: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (4 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 05/11] ALSA: aloop: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 07/11] ALSA: hdspm: " Takashi Iwai
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In HDSP driver, a tasklet is still
used for offloading the MIDI I/O handling (optional via mixer
switch). It can be achieved gracefully with a work queued, too.
This patch replaces the tasklet usage in HDSP driver with a simple
work. The conversion is fairly straightforward. The only significant
difference is that a superfluous tasklet_kill() call is removed from
snd_hdap_midi_input_trigger().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/rme9652/hdsp.c | 55 ++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 28 deletions(-)
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index dda56ecfd33b..cea53a878c36 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -447,8 +447,8 @@ struct hdsp {
struct snd_pcm_substream *capture_substream;
struct snd_pcm_substream *playback_substream;
struct hdsp_midi midi[2];
- struct tasklet_struct midi_tasklet;
- int use_midi_tasklet;
+ struct work_struct midi_work;
+ int use_midi_work;
int precise_ptr;
u32 control_register; /* cached value */
u32 control2_register; /* cached value */
@@ -1385,7 +1385,6 @@ static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream,
}
} else {
hdsp->control_register &= ~ie;
- tasklet_kill(&hdsp->midi_tasklet);
}
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -2542,37 +2541,37 @@ static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct sn
return change;
}
-#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
+#define HDSP_USE_MIDI_WORK(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
.name = xname, \
.index = xindex, \
- .info = snd_hdsp_info_use_midi_tasklet, \
- .get = snd_hdsp_get_use_midi_tasklet, \
- .put = snd_hdsp_put_use_midi_tasklet \
+ .info = snd_hdsp_info_use_midi_work, \
+ .get = snd_hdsp_get_use_midi_work, \
+ .put = snd_hdsp_put_use_midi_work \
}
-static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
+static int hdsp_set_use_midi_work(struct hdsp *hdsp, int use_work)
{
- if (use_tasklet)
- hdsp->use_midi_tasklet = 1;
+ if (use_work)
+ hdsp->use_midi_work = 1;
else
- hdsp->use_midi_tasklet = 0;
+ hdsp->use_midi_work = 0;
return 0;
}
-#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
+#define snd_hdsp_info_use_midi_work snd_ctl_boolean_mono_info
-static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hdsp_get_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdsp->lock);
- ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
+ ucontrol->value.integer.value[0] = hdsp->use_midi_work;
spin_unlock_irq(&hdsp->lock);
return 0;
}
-static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hdsp_put_use_midi_work(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
@@ -2582,8 +2581,8 @@ static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct s
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
spin_lock_irq(&hdsp->lock);
- change = (int)val != hdsp->use_midi_tasklet;
- hdsp_set_use_midi_tasklet(hdsp, val);
+ change = (int)val != hdsp->use_midi_work;
+ hdsp_set_use_midi_work(hdsp, val);
spin_unlock_irq(&hdsp->lock);
return change;
}
@@ -2950,7 +2949,7 @@ HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
HDSP_TOGGLE_SETTING("Line Out", HDSP_LineOut),
HDSP_PRECISE_POINTER("Precise Pointer", 0),
-HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
+HDSP_USE_MIDI_WORK("Use Midi Tasklet", 0),
};
@@ -3370,7 +3369,7 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
- snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
+ snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_work ? "on" : "off");
snd_iprintf(buffer, "\n");
@@ -3791,9 +3790,9 @@ static int snd_hdsp_set_defaults(struct hdsp *hdsp)
return 0;
}
-static void hdsp_midi_tasklet(struct tasklet_struct *t)
+static void hdsp_midi_work(struct work_struct *work)
{
- struct hdsp *hdsp = from_tasklet(hdsp, t, midi_tasklet);
+ struct hdsp *hdsp = container_of(work, struct hdsp, midi_work);
if (hdsp->midi[0].pending)
snd_hdsp_midi_input_read (&hdsp->midi[0]);
@@ -3838,7 +3837,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
}
if (midi0 && midi0status) {
- if (hdsp->use_midi_tasklet) {
+ if (hdsp->use_midi_work) {
/* we disable interrupts for this input until processing is done */
hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -3849,7 +3848,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
}
}
if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) {
- if (hdsp->use_midi_tasklet) {
+ if (hdsp->use_midi_work) {
/* we disable interrupts for this input until processing is done */
hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -3859,8 +3858,8 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
snd_hdsp_midi_input_read (&hdsp->midi[1]);
}
}
- if (hdsp->use_midi_tasklet && schedule)
- tasklet_schedule(&hdsp->midi_tasklet);
+ if (hdsp->use_midi_work && schedule)
+ queue_work(system_highpri_wq, &hdsp->midi_work);
return IRQ_HANDLED;
}
@@ -5182,7 +5181,7 @@ static int snd_hdsp_create(struct snd_card *card,
spin_lock_init(&hdsp->lock);
- tasklet_setup(&hdsp->midi_tasklet, hdsp_midi_tasklet);
+ INIT_WORK(&hdsp->midi_work, hdsp_midi_work);
pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
hdsp->firmware_rev &= 0xff;
@@ -5235,7 +5234,7 @@ static int snd_hdsp_create(struct snd_card *card,
hdsp->irq = pci->irq;
card->sync_irq = hdsp->irq;
hdsp->precise_ptr = 0;
- hdsp->use_midi_tasklet = 1;
+ hdsp->use_midi_work = 1;
hdsp->dds_value = 0;
if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
@@ -5305,7 +5304,7 @@ static int snd_hdsp_free(struct hdsp *hdsp)
{
if (hdsp->port) {
/* stop the audio, and cancel all interrupts */
- tasklet_kill(&hdsp->midi_tasklet);
+ cancel_work_sync(&hdsp->midi_work);
hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
}
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 07/11] ALSA: hdspm: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (5 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 06/11] ALSA: hdsp: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 08/11] ALSA: riptide: Replace tasklet with threaded irq Takashi Iwai
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In HDSP-MADI driver, a tasklet is
still used for offloading the MIDI I/O handling (optional via mixer
switch). It can be achieved gracefully with a work queued, too.
This patch replaces the tasklet usage in HDSP-MADI driver with a
simple work. The conversion is fairly straightforward. The only
significant difference is that the work initialization is moved to the
right place in snd_hdspm_create() and cancel_work_sync() is always
called in snd_hdspm_free() to assure killing the pending works.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/rme9652/hdspm.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 572350aaf18d..e532312a5e1c 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -997,7 +997,7 @@ struct hdspm {
u32 settings_register; /* cached value for AIO / RayDat (sync reference, master/slave) */
struct hdspm_midi midi[4];
- struct tasklet_struct midi_tasklet;
+ struct work_struct midi_work;
size_t period_bytes;
unsigned char ss_in_channels;
@@ -2169,9 +2169,9 @@ static int snd_hdspm_create_midi(struct snd_card *card,
}
-static void hdspm_midi_tasklet(struct tasklet_struct *t)
+static void hdspm_midi_work(struct work_struct *work)
{
- struct hdspm *hdspm = from_tasklet(hdspm, t, midi_tasklet);
+ struct hdspm *hdspm = container_of(work, struct hdspm, midi_work);
int i = 0;
while (i < hdspm->midiPorts) {
@@ -5449,7 +5449,7 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
}
if (schedule)
- tasklet_hi_schedule(&hdspm->midi_tasklet);
+ queue_work(system_highpri_wq, &hdspm->midi_work);
}
return IRQ_HANDLED;
@@ -6538,6 +6538,7 @@ static int snd_hdspm_create(struct snd_card *card,
hdspm->card = card;
spin_lock_init(&hdspm->lock);
+ INIT_WORK(&hdspm->midi_work, hdspm_midi_work);
pci_read_config_word(hdspm->pci,
PCI_CLASS_REVISION, &hdspm->firmware_rev);
@@ -6836,9 +6837,6 @@ static int snd_hdspm_create(struct snd_card *card,
}
- tasklet_setup(&hdspm->midi_tasklet, hdspm_midi_tasklet);
-
-
if (hdspm->io_type != MADIface) {
hdspm->serial = (hdspm_read(hdspm,
HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
@@ -6873,6 +6871,7 @@ static int snd_hdspm_free(struct hdspm * hdspm)
{
if (hdspm->port) {
+ cancel_work_sync(&hdspm->midi_work);
/* stop th audio, and cancel all interrupts */
hdspm->control_register &=
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 08/11] ALSA: riptide: Replace tasklet with threaded irq
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (6 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 07/11] ALSA: hdspm: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 09/11] ALSA: asihpi: " Takashi Iwai
` (2 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In Riptide driver, a tasklet is
still used for offloading the PCM IRQ handling. It can be achieved
gracefully with a threaded IRQ, too.
This patch replaces the tasklet usage in riptide driver with a
threaded IRQ.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/riptide/riptide.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 098c69b3b7aa..fcc2073c5025 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -445,7 +445,6 @@ struct snd_riptide {
union firmware_version firmware;
spinlock_t lock;
- struct tasklet_struct riptide_tq;
struct snd_info_entry *proc_entry;
unsigned long received_irqs;
@@ -1070,9 +1069,9 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval,
return 0;
}
-static void riptide_handleirq(struct tasklet_struct *t)
+static irqreturn_t riptide_handleirq(int irq, void *dev_id)
{
- struct snd_riptide *chip = from_tasklet(chip, t, riptide_tq);
+ struct snd_riptide *chip = dev_id;
struct cmdif *cif = chip->cif;
struct snd_pcm_substream *substream[PLAYBACK_SUBSTREAMS + 1];
struct snd_pcm_runtime *runtime;
@@ -1083,7 +1082,7 @@ static void riptide_handleirq(struct tasklet_struct *t)
unsigned int flag;
if (!cif)
- return;
+ return IRQ_HANDLED;
for (i = 0; i < PLAYBACK_SUBSTREAMS; i++)
substream[i] = chip->playback_substream[i];
@@ -1134,6 +1133,8 @@ static void riptide_handleirq(struct tasklet_struct *t)
}
}
}
+
+ return IRQ_HANDLED;
}
#ifdef CONFIG_PM_SLEEP
@@ -1699,13 +1700,14 @@ snd_riptide_interrupt(int irq, void *dev_id)
{
struct snd_riptide *chip = dev_id;
struct cmdif *cif = chip->cif;
+ irqreturn_t ret = IRQ_HANDLED;
if (cif) {
chip->received_irqs++;
if (IS_EOBIRQ(cif->hwport) || IS_EOSIRQ(cif->hwport) ||
IS_EOCIRQ(cif->hwport)) {
chip->handled_irqs++;
- tasklet_schedule(&chip->riptide_tq);
+ ret = IRQ_WAKE_THREAD;
}
if (chip->rmidi && IS_MPUIRQ(cif->hwport)) {
chip->handled_irqs++;
@@ -1714,7 +1716,7 @@ snd_riptide_interrupt(int irq, void *dev_id)
}
SET_AIACK(cif->hwport);
}
- return IRQ_HANDLED;
+ return ret;
}
static void
@@ -1843,7 +1845,6 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
chip->received_irqs = 0;
chip->handled_irqs = 0;
chip->cif = NULL;
- tasklet_setup(&chip->riptide_tq, riptide_handleirq);
if ((chip->res_port =
request_region(chip->port, 64, "RIPTIDE")) == NULL) {
@@ -1856,8 +1857,9 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
hwport = (struct riptideport *)chip->port;
UNSET_AIE(hwport);
- if (request_irq(pci->irq, snd_riptide_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, chip)) {
+ if (request_threaded_irq(pci->irq, snd_riptide_interrupt,
+ riptide_handleirq, IRQF_SHARED,
+ KBUILD_MODNAME, chip)) {
snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n",
pci->irq);
snd_riptide_free(chip);
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 09/11] ALSA: asihpi: Replace tasklet with threaded irq
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (7 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 08/11] ALSA: riptide: Replace tasklet with threaded irq Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 10/11] ALSA: firewire: Replace tasklet with work Takashi Iwai
2020-09-03 10:41 ` [PATCH 11/11] ALSA: mixart: Correct comment wrt obsoleted tasklet usage Takashi Iwai
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In ASIHPI driver, a tasklet is
still used for offloading the PCM IRQ handling. It can be achieved
gracefully with a threaded IRQ, too.
This patch replaces the tasklet usage in asihpi driver with a threaded
IRQ. It also simplified some call patterns.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/asihpi/asihpi.c | 28 +++-------------------------
sound/pci/asihpi/hpioctl.c | 16 +++++++++++++---
2 files changed, 16 insertions(+), 28 deletions(-)
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index 35e76480306e..46d8166ceaeb 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -117,7 +117,6 @@ struct snd_card_asihpi {
* snd_card_asihpi_timer_function().
*/
struct snd_card_asihpi_pcm *llmode_streampriv;
- struct tasklet_struct t;
void (*pcm_start)(struct snd_pcm_substream *substream);
void (*pcm_stop)(struct snd_pcm_substream *substream);
@@ -547,9 +546,7 @@ static void snd_card_asihpi_pcm_int_start(struct snd_pcm_substream *substream)
card = snd_pcm_substream_chip(substream);
WARN_ON(in_interrupt());
- tasklet_disable(&card->t);
card->llmode_streampriv = dpcm;
- tasklet_enable(&card->t);
hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE,
@@ -565,13 +562,7 @@ static void snd_card_asihpi_pcm_int_stop(struct snd_pcm_substream *substream)
hpi_handle_error(hpi_adapter_set_property(card->hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));
- if (in_interrupt())
- card->llmode_streampriv = NULL;
- else {
- tasklet_disable(&card->t);
- card->llmode_streampriv = NULL;
- tasklet_enable(&card->t);
- }
+ card->llmode_streampriv = NULL;
}
static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
@@ -921,10 +912,9 @@ static void snd_card_asihpi_timer_function(struct timer_list *t)
add_timer(&dpcm->timer);
}
-static void snd_card_asihpi_int_task(struct tasklet_struct *t)
+static void snd_card_asihpi_isr(struct hpi_adapter *a)
{
- struct snd_card_asihpi *asihpi = from_tasklet(asihpi, t, t);
- struct hpi_adapter *a = asihpi->hpi;
+ struct snd_card_asihpi *asihpi;
WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
@@ -933,15 +923,6 @@ static void snd_card_asihpi_int_task(struct tasklet_struct *t)
&asihpi->llmode_streampriv->timer);
}
-static void snd_card_asihpi_isr(struct hpi_adapter *a)
-{
- struct snd_card_asihpi *asihpi;
-
- WARN_ON(!a || !a->snd_card || !a->snd_card->private_data);
- asihpi = (struct snd_card_asihpi *)a->snd_card->private_data;
- tasklet_schedule(&asihpi->t);
-}
-
/***************************** PLAYBACK OPS ****************/
static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
substream)
@@ -2871,7 +2852,6 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
if (hpi->interrupt_mode) {
asihpi->pcm_start = snd_card_asihpi_pcm_int_start;
asihpi->pcm_stop = snd_card_asihpi_pcm_int_stop;
- tasklet_setup(&asihpi->t, snd_card_asihpi_int_task);
hpi->interrupt_callback = snd_card_asihpi_isr;
} else {
asihpi->pcm_start = snd_card_asihpi_pcm_timer_start;
@@ -2960,14 +2940,12 @@ static int snd_asihpi_probe(struct pci_dev *pci_dev,
static void snd_asihpi_remove(struct pci_dev *pci_dev)
{
struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
- struct snd_card_asihpi *asihpi = hpi->snd_card->private_data;
/* Stop interrupts */
if (hpi->interrupt_mode) {
hpi->interrupt_callback = NULL;
hpi_handle_error(hpi_adapter_set_property(hpi->adapter->index,
HPI_ADAPTER_PROPERTY_IRQ_RATE, 0, 0));
- tasklet_kill(&asihpi->t);
}
snd_card_free(hpi->snd_card);
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index 496dcde9715d..6cc2b6964bb5 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -329,11 +329,20 @@ static irqreturn_t asihpi_isr(int irq, void *dev_id)
asihpi_irq_count, a->adapter->type, a->adapter->index); */
if (a->interrupt_callback)
- a->interrupt_callback(a);
+ return IRQ_WAKE_THREAD;
return IRQ_HANDLED;
}
+static irqreturn_t asihpi_isr_thread(int irq, void *dev_id)
+{
+ struct hpi_adapter *a = dev_id;
+
+ if (a->interrupt_callback)
+ a->interrupt_callback(a);
+ return IRQ_HANDLED;
+}
+
int asihpi_adapter_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
@@ -478,8 +487,9 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev,
}
/* Note: request_irq calls asihpi_isr here */
- if (request_irq(pci_dev->irq, asihpi_isr, IRQF_SHARED,
- "asihpi", &adapters[adapter_index])) {
+ if (request_threaded_irq(pci_dev->irq, asihpi_isr,
+ asihpi_isr_thread, IRQF_SHARED,
+ "asihpi", &adapters[adapter_index])) {
dev_err(&pci_dev->dev, "request_irq(%d) failed\n",
pci_dev->irq);
goto err;
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 10/11] ALSA: firewire: Replace tasklet with work
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (8 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 09/11] ALSA: asihpi: " Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
2020-09-06 8:26 ` Takashi Sakamoto
2020-09-03 10:41 ` [PATCH 11/11] ALSA: mixart: Correct comment wrt obsoleted tasklet usage Takashi Iwai
10 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The tasklet is an old API that should be deprecated, usually can be
converted to another decent API. In FireWire driver, a tasklet is
still used for offloading the AMDTP PCM stream handling. It can be
achieved gracefully with a work queued, too.
This patch replaces the tasklet usage in firewire-lib driver with a
simple work. The conversion is fairly straightforward but for the
in_interrupt() checks that are replaced with the check using the
current_work().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/firewire/amdtp-stream-trace.h | 2 +-
sound/firewire/amdtp-stream.c | 25 +++++++++++++------------
sound/firewire/amdtp-stream.h | 2 +-
3 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h
index 26e7cb555d3c..5386d548cada 100644
--- a/sound/firewire/amdtp-stream-trace.h
+++ b/sound/firewire/amdtp-stream-trace.h
@@ -49,7 +49,7 @@ TRACE_EVENT(amdtp_packet,
__entry->data_blocks = data_blocks;
__entry->data_block_counter = data_block_counter,
__entry->packet_index = s->packet_index;
- __entry->irq = !!in_interrupt();
+ __entry->irq = (current_work() == &s->period_work);
__entry->index = index;
),
TP_printk(
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index ee1c428b1fd3..4e2f2bb7879f 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -64,7 +64,7 @@
#define IT_PKT_HEADER_SIZE_CIP 8 // For 2 CIP header.
#define IT_PKT_HEADER_SIZE_NO_CIP 0 // Nothing.
-static void pcm_period_tasklet(struct tasklet_struct *t);
+static void pcm_period_work(struct work_struct *work);
/**
* amdtp_stream_init - initialize an AMDTP stream structure
@@ -94,7 +94,7 @@ int amdtp_stream_init(struct amdtp_stream *s, struct fw_unit *unit,
s->flags = flags;
s->context = ERR_PTR(-1);
mutex_init(&s->mutex);
- tasklet_setup(&s->period_tasklet, pcm_period_tasklet);
+ INIT_WORK(&s->period_work, pcm_period_work);
s->packet_index = 0;
init_waitqueue_head(&s->callback_wait);
@@ -203,7 +203,7 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
// Linux driver for 1394 OHCI controller voluntarily flushes isoc
// context when total size of accumulated context header reaches
- // PAGE_SIZE. This kicks tasklet for the isoc context and brings
+ // PAGE_SIZE. This kicks work for the isoc context and brings
// callback in the middle of scheduled interrupts.
// Although AMDTP streams in the same domain use the same events per
// IRQ, use the largest size of context header between IT/IR contexts.
@@ -333,7 +333,7 @@ EXPORT_SYMBOL(amdtp_stream_get_max_payload);
*/
void amdtp_stream_pcm_prepare(struct amdtp_stream *s)
{
- tasklet_kill(&s->period_tasklet);
+ cancel_work_sync(&s->period_work);
s->pcm_buffer_pointer = 0;
s->pcm_period_pointer = 0;
}
@@ -437,13 +437,14 @@ static void update_pcm_pointers(struct amdtp_stream *s,
s->pcm_period_pointer += frames;
if (s->pcm_period_pointer >= pcm->runtime->period_size) {
s->pcm_period_pointer -= pcm->runtime->period_size;
- tasklet_hi_schedule(&s->period_tasklet);
+ queue_work(system_highpri_wq, &s->period_work);
}
}
-static void pcm_period_tasklet(struct tasklet_struct *t)
+static void pcm_period_work(struct work_struct *work)
{
- struct amdtp_stream *s = from_tasklet(s, t, period_tasklet);
+ struct amdtp_stream *s = container_of(work, struct amdtp_stream,
+ period_work);
struct snd_pcm_substream *pcm = READ_ONCE(s->pcm);
if (pcm)
@@ -794,7 +795,7 @@ static void generate_pkt_descs(struct amdtp_stream *s, struct pkt_desc *descs,
static inline void cancel_stream(struct amdtp_stream *s)
{
s->packet_index = -1;
- if (in_interrupt())
+ if (current_work() == &s->period_work)
amdtp_stream_pcm_abort(s);
WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
}
@@ -1184,7 +1185,7 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
if (irq_target && amdtp_stream_running(irq_target)) {
// This function is called in software IRQ context of
- // period_tasklet or process context.
+ // period_work or process context.
//
// When the software IRQ context was scheduled by software IRQ
// context of IT contexts, queued packets were already handled.
@@ -1195,9 +1196,9 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
// immediately to keep better granularity of PCM pointer.
//
// Later, the process context will sometimes schedules software
- // IRQ context of the period_tasklet. Then, no need to flush the
+ // IRQ context of the period_work. Then, no need to flush the
// queue by the same reason as described in the above
- if (!in_interrupt()) {
+ if (current_work() != &s->period_work) {
// Queued packet should be processed without any kernel
// preemption to keep latency against bus cycle.
preempt_disable();
@@ -1263,7 +1264,7 @@ static void amdtp_stream_stop(struct amdtp_stream *s)
return;
}
- tasklet_kill(&s->period_tasklet);
+ cancel_work_sync(&s->period_work);
fw_iso_context_stop(s->context);
fw_iso_context_destroy(s->context);
s->context = ERR_PTR(-1);
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index 703b710aaf7f..2ceb57d1d58e 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -163,7 +163,7 @@ struct amdtp_stream {
/* For a PCM substream processing. */
struct snd_pcm_substream *pcm;
- struct tasklet_struct period_tasklet;
+ struct work_struct period_work;
snd_pcm_uframes_t pcm_buffer_pointer;
unsigned int pcm_period_pointer;
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 11/11] ALSA: mixart: Correct comment wrt obsoleted tasklet usage
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
` (9 preceding siblings ...)
2020-09-03 10:41 ` [PATCH 10/11] ALSA: firewire: Replace tasklet with work Takashi Iwai
@ 2020-09-03 10:41 ` Takashi Iwai
10 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-03 10:41 UTC (permalink / raw)
To: alsa-devel; +Cc: Clemens Ladisch
The miXart driver has been already converted to use the threaded IRQ
instead of tasklet while there is a remaining comment still mentioning
a tasklet. Update the comment appropriately.
Fixes: 8d3a8b5cb57d ("ALSA: mixart: Use nonatomic PCM ops")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/pci/mixart/mixart.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 42111562e9bc..cbed6d9a9f2e 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -69,7 +69,7 @@ struct mixart_mgr {
u32 msg_fifo[MSG_FIFO_SIZE];
int msg_fifo_readptr;
int msg_fifo_writeptr;
- atomic_t msg_processed; /* number of messages to be processed in tasklet */
+ atomic_t msg_processed; /* number of messages to be processed in irq thread */
struct mutex lock; /* interrupt lock */
struct mutex msg_lock; /* mailbox lock */
--
2.16.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 10/11] ALSA: firewire: Replace tasklet with work
2020-09-03 10:41 ` [PATCH 10/11] ALSA: firewire: Replace tasklet with work Takashi Iwai
@ 2020-09-06 8:26 ` Takashi Sakamoto
2020-09-07 8:34 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Sakamoto @ 2020-09-06 8:26 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel, Clemens Ladisch
Hi,
On Thu, Sep 03, 2020 at 12:41:30PM +0200, Takashi Iwai wrote:
> The tasklet is an old API that should be deprecated, usually can be
> converted to another decent API. In FireWire driver, a tasklet is
> still used for offloading the AMDTP PCM stream handling. It can be
> achieved gracefully with a work queued, too.
>
> This patch replaces the tasklet usage in firewire-lib driver with a
> simple work. The conversion is fairly straightforward but for the
> in_interrupt() checks that are replaced with the check using the
> current_work().
>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> ---
> sound/firewire/amdtp-stream-trace.h | 2 +-
> sound/firewire/amdtp-stream.c | 25 +++++++++++++------------
> sound/firewire/amdtp-stream.h | 2 +-
> 3 files changed, 15 insertions(+), 14 deletions(-)
After testing this patch, I agree with the usage of
'(current_work() == &s->period_work)' as an alternative of 'in_interrupt()'.
However, the usage is not appropriate for tracepoints event in the case.
> diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h
> index 26e7cb555d3c..5386d548cada 100644
> --- a/sound/firewire/amdtp-stream-trace.h
> +++ b/sound/firewire/amdtp-stream-trace.h
> @@ -49,7 +49,7 @@ TRACE_EVENT(amdtp_packet,
> __entry->data_blocks = data_blocks;
> __entry->data_block_counter = data_block_counter,
> __entry->packet_index = s->packet_index;
> - __entry->irq = !!in_interrupt();
> + __entry->irq = (current_work() == &s->period_work);
> __entry->index = index;
> ),
> TP_printk(
The tracepoints event is probed in two contexts:
* softirq for isochronous context to process hardware events of 1394 OHCI.
* user task of ALSA PCM applications.
However, it's not probed in the workqueue task since the case is already
avoided carefully in below patch:
> @@ -1184,7 +1185,7 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
>
> if (irq_target && amdtp_stream_running(irq_target)) {
> // This function is called in software IRQ context of
> - // period_tasklet or process context.
> + // period_work or process context.
> //
> // When the software IRQ context was scheduled by software IRQ
> // context of IT contexts, queued packets were already handled.
> @@ -1195,9 +1196,9 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
> // immediately to keep better granularity of PCM pointer.
> //
> // Later, the process context will sometimes schedules software
> - // IRQ context of the period_tasklet. Then, no need to flush the
> + // IRQ context of the period_work. Then, no need to flush the
> // queue by the same reason as described in the above
> - if (!in_interrupt()) {
> + if (current_work() != &s->period_work) {
> // Queued packet should be processed without any kernel
> // preemption to keep latency against bus cycle.
> preempt_disable();
as long as testing, I can see no logs for the trancepoints event with the 'irq' field is 1.
I would like you to leave 'amdtp-stream-trace.h' as is by dropping the above change since
the irq field should record whether the context is softirq or user task.
Thanks
Takashi Sakamoto
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 10/11] ALSA: firewire: Replace tasklet with work
2020-09-06 8:26 ` Takashi Sakamoto
@ 2020-09-07 8:34 ` Takashi Iwai
0 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-09-07 8:34 UTC (permalink / raw)
To: Takashi Sakamoto; +Cc: alsa-devel, Clemens Ladisch
On Sun, 06 Sep 2020 10:26:28 +0200,
Takashi Sakamoto wrote:
>
> Hi,
>
> On Thu, Sep 03, 2020 at 12:41:30PM +0200, Takashi Iwai wrote:
> > The tasklet is an old API that should be deprecated, usually can be
> > converted to another decent API. In FireWire driver, a tasklet is
> > still used for offloading the AMDTP PCM stream handling. It can be
> > achieved gracefully with a work queued, too.
> >
> > This patch replaces the tasklet usage in firewire-lib driver with a
> > simple work. The conversion is fairly straightforward but for the
> > in_interrupt() checks that are replaced with the check using the
> > current_work().
> >
> > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > ---
> > sound/firewire/amdtp-stream-trace.h | 2 +-
> > sound/firewire/amdtp-stream.c | 25 +++++++++++++------------
> > sound/firewire/amdtp-stream.h | 2 +-
> > 3 files changed, 15 insertions(+), 14 deletions(-)
>
> After testing this patch, I agree with the usage of
> '(current_work() == &s->period_work)' as an alternative of 'in_interrupt()'.
>
> However, the usage is not appropriate for tracepoints event in the case.
>
> > diff --git a/sound/firewire/amdtp-stream-trace.h b/sound/firewire/amdtp-stream-trace.h
> > index 26e7cb555d3c..5386d548cada 100644
> > --- a/sound/firewire/amdtp-stream-trace.h
> > +++ b/sound/firewire/amdtp-stream-trace.h
> > @@ -49,7 +49,7 @@ TRACE_EVENT(amdtp_packet,
> > __entry->data_blocks = data_blocks;
> > __entry->data_block_counter = data_block_counter,
> > __entry->packet_index = s->packet_index;
> > - __entry->irq = !!in_interrupt();
> > + __entry->irq = (current_work() == &s->period_work);
> > __entry->index = index;
> > ),
> > TP_printk(
>
> The tracepoints event is probed in two contexts:
> * softirq for isochronous context to process hardware events of 1394 OHCI.
> * user task of ALSA PCM applications.
>
> However, it's not probed in the workqueue task since the case is already
> avoided carefully in below patch:
>
> > @@ -1184,7 +1185,7 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
> >
> > if (irq_target && amdtp_stream_running(irq_target)) {
> > // This function is called in software IRQ context of
> > - // period_tasklet or process context.
> > + // period_work or process context.
> > //
> > // When the software IRQ context was scheduled by software IRQ
> > // context of IT contexts, queued packets were already handled.
> > @@ -1195,9 +1196,9 @@ unsigned long amdtp_domain_stream_pcm_pointer(struct amdtp_domain *d,
> > // immediately to keep better granularity of PCM pointer.
> > //
> > // Later, the process context will sometimes schedules software
> > - // IRQ context of the period_tasklet. Then, no need to flush the
> > + // IRQ context of the period_work. Then, no need to flush the
> > // queue by the same reason as described in the above
> > - if (!in_interrupt()) {
> > + if (current_work() != &s->period_work) {
> > // Queued packet should be processed without any kernel
> > // preemption to keep latency against bus cycle.
> > preempt_disable();
>
> as long as testing, I can see no logs for the trancepoints event with the 'irq' field is 1.
> I would like you to leave 'amdtp-stream-trace.h' as is by dropping the above change since
> the irq field should record whether the context is softirq or user task.
OK, makes sense. Will fix in v2.
Thanks for reviewing!
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2020-09-07 8:35 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-09-03 10:41 [PATCH 00/11] ALSA: Kill tasklet usage Takashi Iwai
2020-09-03 10:41 ` [PATCH 01/11] ALSA: pcsp: Replace tasklet with work Takashi Iwai
2020-09-03 10:41 ` [PATCH 02/11] ALSA: timer: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 03/11] ALSA: usb-audio: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 04/11] ALSA: ua101: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 05/11] ALSA: aloop: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 06/11] ALSA: hdsp: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 07/11] ALSA: hdspm: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 08/11] ALSA: riptide: Replace tasklet with threaded irq Takashi Iwai
2020-09-03 10:41 ` [PATCH 09/11] ALSA: asihpi: " Takashi Iwai
2020-09-03 10:41 ` [PATCH 10/11] ALSA: firewire: Replace tasklet with work Takashi Iwai
2020-09-06 8:26 ` Takashi Sakamoto
2020-09-07 8:34 ` Takashi Iwai
2020-09-03 10:41 ` [PATCH 11/11] ALSA: mixart: Correct comment wrt obsoleted tasklet usage Takashi Iwai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.