aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-07-08 02:23:43 -0400
committerTakashi Iwai <tiwai@suse.de>2016-07-08 03:15:44 -0400
commita8ff48cb70835f48de5703052760312019afea55 (patch)
treea390e6a283029335160755394129bb9784719446 /sound/core
parentf388cdcdd160687c6650833f286b9c89c50960ff (diff)
ALSA: pcm: Free chmap at PCM free callback, too
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> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
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,
849} 849}
850EXPORT_SYMBOL(snd_pcm_new_internal); 850EXPORT_SYMBOL(snd_pcm_new_internal);
851 851
852static void free_chmap(struct snd_pcm_str *pstr)
853{
854 if (pstr->chmap_kctl) {
855 snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
856 pstr->chmap_kctl = NULL;
857 }
858}
859
852static void snd_pcm_free_stream(struct snd_pcm_str * pstr) 860static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
853{ 861{
854 struct snd_pcm_substream *substream, *substream_next; 862 struct snd_pcm_substream *substream, *substream_next;
@@ -871,6 +879,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
871 kfree(setup); 879 kfree(setup);
872 } 880 }
873#endif 881#endif
882 free_chmap(pstr);
874 if (pstr->substream_count) 883 if (pstr->substream_count)
875 put_device(&pstr->dev); 884 put_device(&pstr->dev);
876} 885}
@@ -1135,10 +1144,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1135 for (cidx = 0; cidx < 2; cidx++) { 1144 for (cidx = 0; cidx < 2; cidx++) {
1136 if (!pcm->internal) 1145 if (!pcm->internal)
1137 snd_unregister_device(&pcm->streams[cidx].dev); 1146 snd_unregister_device(&pcm->streams[cidx].dev);
1138 if (pcm->streams[cidx].chmap_kctl) { 1147 free_chmap(&pcm->streams[cidx]);
1139 snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
1140 pcm->streams[cidx].chmap_kctl = NULL;
1141 }
1142 } 1148 }
1143 mutex_unlock(&pcm->open_mutex); 1149 mutex_unlock(&pcm->open_mutex);
1144 mutex_unlock(&register_mutex); 1150 mutex_unlock(&register_mutex);