summary refs log tree commit diff
path: root/sound/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-05-19 11:35:13 +0200
committerTakashi Iwai <tiwai@suse.de>2015-05-19 11:35:13 +0200
commit4214c5349c20005b7a83916801394eb7270896b2 (patch)
treefdb111598c33ce1601cead948ac12a4249b09295 /sound/hda
parent1882b0577b5b67e7b663be4e8126997423b6cb6f (diff)
downloadlinux-4214c5349c20005b7a83916801394eb7270896b2.tar.gz
ALSA: hda - Fix NULL dereference from CA0132 DSP loader
The CA0132 DSP loader leads to NULL deference since the recent
transition to HDA core code, as it unconditionally accesses
hdac_stream->substream->runtime.  For DSP loading, the substream
shouldn't be assigned.

This patch addresses the NULL dereference above in addition to assure
the substream is cleared while DSP loading.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=98151
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/hda')
-rw-r--r--sound/hda/hdac_stream.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index 52a894fe478f..4c15d0accc9e 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -139,9 +139,13 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_reset);
 int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
 {
 	struct hdac_bus *bus = azx_dev->bus;
-	struct snd_pcm_runtime *runtime = azx_dev->substream->runtime;
+	struct snd_pcm_runtime *runtime;
 	unsigned int val;
 
+	if (azx_dev->substream)
+		runtime = azx_dev->substream->runtime;
+	else
+		runtime = NULL;
 	/* make sure the run bit is zero for SD */
 	snd_hdac_stream_clear(azx_dev);
 	/* program the stream_tag */
@@ -189,14 +193,15 @@ int snd_hdac_stream_setup(struct hdac_stream *azx_dev)
 	 * we ignore it; currently set the threshold statically to
 	 * 64 frames
 	 */
-	if (runtime->period_size > 64)
+	if (runtime && runtime->period_size > 64)
 		azx_dev->delay_negative_threshold =
 			-frames_to_bytes(runtime, 64);
 	else
 		azx_dev->delay_negative_threshold = 0;
 
 	/* wallclk has 24Mhz clock source */
-	azx_dev->period_wallclk = (((runtime->period_size * 24000) /
+	if (runtime)
+		azx_dev->period_wallclk = (((runtime->period_size * 24000) /
 				    runtime->rate) * 1000);
 
 	return 0;
@@ -611,6 +616,7 @@ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format,
 	if (err < 0)
 		goto err_alloc;
 
+	azx_dev->substream = NULL;
 	azx_dev->bufsize = byte_size;
 	azx_dev->period_bytes = byte_size;
 	azx_dev->format_val = format;