summaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-07-08 08:23:43 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-07-27 09:47:38 -0700
commit180cb74b64ec9ef6e5d637a2c1479e3dfb55a1d3 (patch)
tree51fe2ebc69fa6741a1a8e507377f541c5a95bf5b /sound/core
parent248bfcb1c7d5d59e0994be02bf25652d8c04d072 (diff)
ALSA: pcm: Free chmap at PCM free callback, too
commit a8ff48cb70835f48de5703052760312019afea55 upstream. The chmap ctls assigned to PCM streams are freed in the PCM disconnect callback. However, since the disconnect callback isn't called when the card gets freed before registering, the chmap ctls may still be left assigned. They are eventually freed together with other ctls, but it may cause an Oops at pcm_chmap_ctl_private_free(), as the function refers to the assigned PCM stream, while the PCM objects have been already freed beforehand. The fix is to free the chmap ctls also at PCM free callback, not only at PCM disconnect. Reported-by: Laxminath Kasam <b_lkasam@codeaurora.org> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/pcm.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 308c9ecf73db..8e980aa678d0 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -849,6 +849,14 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
}
EXPORT_SYMBOL(snd_pcm_new_internal);
+static void free_chmap(struct snd_pcm_str *pstr)
+{
+ if (pstr->chmap_kctl) {
+ snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
+ pstr->chmap_kctl = NULL;
+ }
+}
+
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
{
struct snd_pcm_substream *substream, *substream_next;
@@ -871,6 +879,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
kfree(setup);
}
#endif
+ free_chmap(pstr);
if (pstr->substream_count)
put_device(&pstr->dev);
}
@@ -1135,10 +1144,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
for (cidx = 0; cidx < 2; cidx++) {
if (!pcm->internal)
snd_unregister_device(&pcm->streams[cidx].dev);
- if (pcm->streams[cidx].chmap_kctl) {
- snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
- pcm->streams[cidx].chmap_kctl = NULL;
- }
+ free_chmap(&pcm->streams[cidx]);
}
mutex_unlock(&pcm->open_mutex);
mutex_unlock(&register_mutex);