[PATCH v4 3/3] ALSA: opl3: Shut down the timer after draining sequencer ports
From: Cen Zhang
Date: Sat Oct 24 2026 - 12:50:57 EST
The delayed-note timer is independent of the sequencer ports' use-locks
and runs code in snd-opl3-synth. Deleting the client drains the event
callbacks but does not cancel this timer. A direct fixed-duration NOTEON
without a subscription can arm it without any unuse callback to stop it.
A shutdown in only the native port's private_free callback is too early
to finish shared voice cleanup when the OSS port is enabled:
Sequencer client deletion In-flight OSS NOTEON
------------------------- -------------------
drain native port
clear native voice aliases
snd_opl3_oss_event_input()
refill shared voice array
drain OSS port
clear voice aliases again
free OSS channel set
client deletion returns
The per-port voice cleanup prevents the timer from dereferencing a freed
channel during that sequence, but a queued or running timer can still
outlive client deletion and the sequencer driver itself.
Shut the timer down synchronously after snd_seq_delete_kernel_client()
has drained both ports. No event can then start it again, and shutdown
waits for a callback already running and prevents callback self-rearming.
Do this outside voice_lock and sys_timer_lock, which the callback takes.
The probe initializes timer state before publishing ports on rebind.
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@xxxxxxxxx>
---
sound/drivers/opl3/opl3_seq.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index e03c88377bb6..1004a7df1b8c 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -259,6 +259,8 @@ static void snd_opl3_seq_remove(struct snd_seq_device *dev)
snd_seq_delete_kernel_client(opl3->seq_client);
opl3->seq_client = -1;
}
+ /* Stop the shared timer after all event callbacks have been drained. */
+ timer_shutdown_sync(&opl3->tlist);
}
static struct snd_seq_driver opl3_seq_driver = {
--
2.43.0