Files
linux/include/sound/pcm_oss.h
T
Cen Zhang f0780cfa6a ALSA: oss: Keep emulation modules loaded until object teardown
OSS proc entries and notifier callbacks can remain in use without an
open OSS device file. Normal snd-pcm-oss removal can therefore delete
an existing PCM's OSS proc entry while late HDA codec binding repeats
snd_card_register() on the same live card:

  OSS PCM module unload                 Card registration
  ---------------------                 -----------------
  snd_info_free_entry(entry)
    proc_remove(entry->p)
    clear entry->p
                                        snd_info_card_register()
                                          republish linked entry
    unlink and free entry

The new proc node retains a pointer to freed storage. Mixer OSS removal
can likewise release an adapter while a card notification still uses it.

Hold a snd-pcm-oss module reference for each PCM registered with its
notifier and a snd-mixer-oss reference for each card adapter. Release
them at final unregister or FREE, after proc and adapter cleanup. Normal
module unload can no longer initiate removal while these objects exist.

Track PCM OSS registration with a separate bool registered. Unlike
oss.reg, this state also covers unmapped PCMs and remains set across
DISCONNECT until final unregister. BUILD-state and creation-error cleanup
must not drop a reference when registration never acquired one. The PCM
notifier's register_mutex serialization keeps the final put ahead of
notifier removal and module teardown until dispatch has finished.

For mixer OSS, serialize callback publication, dispatch and withdrawal
in the core so module exit waits for callbacks, including one dropping
the last reference, to return. Keep card enumeration in the OSS module,
with card references released after dispatch drops the mutex. Ignore
duplicate REGISTER notifications so a delayed registration cannot
replace an adapter retained across DISCONNECT and leak its module pin.

Partial HDA codec teardown can still remove an individual PCM while the
card remains registered; its object-lifetime handling is separate.

Fixes: 2471b6c80a ("ALSA: info: Register proc entries recursively, too")
Suggested-by: Takashi Iwai <tiwai@suse.de>
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-26d66390a25fec9fad6c-v6-5be251a3ac8832955a31-2@gmail.com
2026-10-19 10:08:47 +02:00

77 lines
2.0 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __SOUND_PCM_OSS_H
#define __SOUND_PCM_OSS_H
/*
* Digital Audio (PCM) - OSS compatibility abstract layer
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>
*/
struct snd_pcm_oss_setup {
char *task_name;
unsigned int disable:1,
direct:1,
block:1,
nonblock:1,
partialfrag:1,
nosilence:1,
buggyptr:1;
unsigned int periods;
unsigned int period_size;
struct snd_pcm_oss_setup *next;
};
struct snd_pcm_oss_runtime {
unsigned params: 1, /* format/parameter change */
prepare: 1, /* need to prepare the operation */
trigger: 1, /* trigger flag */
sync_trigger: 1; /* sync trigger flag */
int rate; /* requested rate */
int format; /* requested OSS format */
unsigned int channels; /* requested channels */
unsigned int fragshift;
unsigned int maxfrags;
unsigned int subdivision; /* requested subdivision */
size_t period_bytes; /* requested period size */
size_t period_frames; /* period frames for poll */
size_t period_ptr; /* actual write pointer to period */
unsigned int periods;
size_t buffer_bytes; /* requested buffer size */
size_t bytes; /* total # bytes processed */
size_t mmap_bytes;
char *buffer; /* vmallocated period */
size_t buffer_used; /* used length from period buffer */
struct mutex params_lock;
atomic_t rw_ref; /* concurrent read/write accesses */
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
struct snd_pcm_plugin *plugin_first;
struct snd_pcm_plugin *plugin_last;
#endif
unsigned int prev_hw_ptr_period;
};
struct snd_pcm_oss_file {
struct snd_pcm_substream *streams[2];
};
struct snd_pcm_oss_substream {
unsigned oss: 1; /* oss mode */
struct snd_pcm_oss_setup setup; /* active setup */
};
struct snd_pcm_oss_stream {
struct snd_pcm_oss_setup *setup_list; /* setup list */
struct mutex setup_mutex;
#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_entry;
#endif
};
struct snd_pcm_oss {
int reg;
unsigned int reg_mask;
bool registered;
};
#endif /* __SOUND_PCM_OSS_H */