mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
ALSA: emux: Stop voices before freeing zones in all cases
The emux voice caches the soundfont zone pointer in vp->zone, which is referred to later, e.g. in snd_emux_send_effect(). For avoiding dangling pointers, the soundfont code calls the sample_reset callback to stop all voices before freeing zones. However, in a few cases (e.g. emu10k1's missing sample_reset or the call path via remove_info()), the sample reset isn't called properly, leaving the playing voices. Fix it by always registering the sample_reset callback, falling back to snd_emux_terminate_all() when the driver has no own ops, and by calling sample_reset in remove_info() before freeing the zones. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20261020101624.205638-2-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
34e3e04b8a
commit
8a5d87c2ba
|
|
@ -71,7 +71,12 @@ static int sf_sample_free(void *private_data, struct snd_sf_sample *sp,
|
|||
static void sf_sample_reset(void *private_data)
|
||||
{
|
||||
struct snd_emux *emu = private_data;
|
||||
emu->ops.sample_reset(emu);
|
||||
|
||||
/* stop all voices that might refer to zones and samples to be freed */
|
||||
if (emu->ops.sample_reset)
|
||||
emu->ops.sample_reset(emu);
|
||||
else
|
||||
snd_emux_terminate_all(emu);
|
||||
}
|
||||
|
||||
int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name)
|
||||
|
|
@ -95,8 +100,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch
|
|||
sf_cb.private_data = emu;
|
||||
sf_cb.sample_new = sf_sample_new;
|
||||
sf_cb.sample_free = sf_sample_free;
|
||||
if (emu->ops.sample_reset)
|
||||
sf_cb.sample_reset = sf_sample_reset;
|
||||
sf_cb.sample_reset = sf_sample_reset;
|
||||
emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);
|
||||
if (emu->sflist == NULL)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -443,6 +443,15 @@ remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
|
|||
struct snd_sf_zone *prev, *next, *p;
|
||||
int removed = 0;
|
||||
|
||||
/* stop voices before freeing the zones they might refer to */
|
||||
for (p = sf->zones; p; p = p->next) {
|
||||
if (!p->mapped && p->bank == bank && p->instr == instr) {
|
||||
if (sflist->callback.sample_reset)
|
||||
sflist->callback.sample_reset(sflist->callback.private_data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
for (p = sf->zones; p; p = next) {
|
||||
next = p->next;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user