ALSA: opl3: Shut down the timer after draining sequencer ports

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@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/pm-pmb-4552c4e605507d8d9b16-v9-70247b8436e10e26d324-3@gmail.com
This commit is contained in:
Cen Zhang 2026-10-25 00:49:51 +08:00 committed by Takashi Iwai
parent 02b1d5127f
commit 9194d8dd41

View File

@ -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 = {