From 6a0ba071b71c44bc905522b77e96afad464e8aac Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Date: Tue, 28 Sep 2021 13:35:16 +0300
Subject: [PATCH] ASoC: SOF: add error handling to snd_sof_ipc_msg_data()
Git-commit: 6a0ba071b71c44bc905522b77e96afad464e8aac
Patch-mainline: v5.16-rc1
References: jsc#PED-850
If an invalid stream is passed to snd_sof_ipc_msg_data() it won't
fill the provided object with data. The caller has to be able to
recognise such cases to avoid handling invalid data. Make the
function return an error when failing.
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20210928103516.8066-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Acked-by: Takashi Iwai <tiwai@suse.de>
---
sound/soc/sof/imx/imx8.c | 7 +++---
sound/soc/sof/imx/imx8m.c | 7 +++---
sound/soc/sof/intel/hda-ipc.c | 15 ++++++++------
sound/soc/sof/intel/hda.h | 6 ++---
sound/soc/sof/intel/intel-ipc.c | 14 ++++++++-----
sound/soc/sof/ipc.c | 41 +++++++++++++++++++++++++++++++---------
sound/soc/sof/ops.h | 8 +++----
sound/soc/sof/sof-priv.h | 12 +++++------
8 files changed, 71 insertions(+), 39 deletions(-)
--- a/sound/soc/sof/imx/imx8.c
+++ b/sound/soc/sof/imx/imx8.c
@@ -376,11 +376,12 @@ static int imx8_get_bar_index(struct snd
}
}
-static void imx8_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz)
+static int imx8_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz)
{
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
+ return 0;
}
static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
--- a/sound/soc/sof/imx/imx8m.c
+++ b/sound/soc/sof/imx/imx8m.c
@@ -240,11 +240,12 @@ static int imx8m_get_bar_index(struct sn
}
}
-static void imx8m_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz)
+static int imx8m_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz)
{
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
+ return 0;
}
static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev,
--- a/sound/soc/sof/intel/hda-ipc.c
+++ b/sound/soc/sof/intel/hda-ipc.c
@@ -253,9 +253,9 @@ int hda_dsp_ipc_get_window_offset(struct
return SRAM_WINDOW_OFFSET(id);
}
-void hda_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz)
+int hda_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz)
{
if (!substream || !sdev->stream_box.size) {
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
@@ -268,10 +268,13 @@ void hda_ipc_msg_data(struct snd_sof_dev
hda_stream.hstream);
/* The stream might already be closed */
- if (hstream)
- sof_mailbox_read(sdev, hda_stream->stream.posn_offset,
- p, sz);
+ if (!hstream)
+ return -ESTRPIPE;
+
+ sof_mailbox_read(sdev, hda_stream->stream.posn_offset, p, sz);
}
+
+ return 0;
}
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -563,9 +563,9 @@ int hda_dsp_stream_spib_config(struct sn
struct hdac_ext_stream *stream,
int enable, u32 size);
-void hda_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz);
+int hda_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz);
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
const struct sof_ipc_pcm_params_reply *reply);
--- a/sound/soc/sof/intel/intel-ipc.c
+++ b/sound/soc/sof/intel/intel-ipc.c
@@ -25,9 +25,9 @@ struct intel_stream {
};
/* Mailbox-based Intel IPC implementation */
-void intel_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz)
+int intel_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz)
{
if (!substream || !sdev->stream_box.size) {
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
@@ -35,9 +35,13 @@ void intel_ipc_msg_data(struct snd_sof_d
struct intel_stream *stream = substream->runtime->private_data;
/* The stream might already be closed */
- if (stream)
- sof_mailbox_read(sdev, stream->posn_offset, p, sz);
+ if (!stream)
+ return -ESTRPIPE;
+
+ sof_mailbox_read(sdev, stream->posn_offset, p, sz);
}
+
+ return 0;
}
EXPORT_SYMBOL_NS(intel_ipc_msg_data, SND_SOC_SOF_INTEL_HIFI_EP_IPC);
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -394,6 +394,7 @@ static void ipc_comp_notification(struct
{
u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
struct sof_ipc_ctrl_data *cdata;
+ int ret;
switch (msg_type) {
case SOF_IPC_COMP_GET_VALUE:
@@ -403,7 +404,12 @@ static void ipc_comp_notification(struct
return;
/* read back full message */
- snd_sof_ipc_msg_data(sdev, NULL, cdata, hdr->size);
+ ret = snd_sof_ipc_msg_data(sdev, NULL, cdata, hdr->size);
+ if (ret < 0) {
+ dev_err(sdev->dev,
+ "error: failed to read component event: %d\n", ret);
+ goto err;
+ }
break;
default:
dev_err(sdev->dev, "error: unhandled component message %#x\n", msg_type);
@@ -412,6 +418,7 @@ static void ipc_comp_notification(struct
snd_sof_control_notify(sdev, cdata);
+err:
kfree(cdata);
}
@@ -420,10 +427,14 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_
{
struct sof_ipc_cmd_hdr hdr;
u32 cmd, type;
- int err = 0;
+ int err;
/* read back header */
- snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr));
+ err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr));
+ if (err < 0) {
+ dev_warn(sdev->dev, "failed to read IPC header: %d\n", err);
+ return;
+ }
ipc_log_header(sdev->dev, "ipc rx", hdr.cmd);
cmd = hdr.cmd & SOF_GLB_TYPE_MASK;
@@ -477,12 +488,16 @@ EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);
static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type)
{
struct sof_ipc_dma_trace_posn posn;
+ int ret;
switch (msg_type) {
case SOF_IPC_TRACE_DMA_POSITION:
/* read back full message */
- snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn));
- snd_sof_trace_update_pos(sdev, &posn);
+ ret = snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn));
+ if (ret < 0)
+ dev_warn(sdev->dev, "failed to read trace position: %d\n", ret);
+ else
+ snd_sof_trace_update_pos(sdev, &posn);
break;
default:
dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type);
@@ -500,7 +515,7 @@ static void ipc_period_elapsed(struct sn
struct snd_sof_pcm_stream *stream;
struct sof_ipc_stream_posn posn;
struct snd_sof_pcm *spcm;
- int direction;
+ int direction, ret;
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
if (!spcm) {
@@ -511,7 +526,11 @@ static void ipc_period_elapsed(struct sn
}
stream = &spcm->stream[direction];
- snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ if (ret < 0) {
+ dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
+ return;
+ }
dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n",
posn.host_posn, posn.dai_posn, posn.wallclock);
@@ -530,7 +549,7 @@ static void ipc_xrun(struct snd_sof_dev
struct snd_sof_pcm_stream *stream;
struct sof_ipc_stream_posn posn;
struct snd_sof_pcm *spcm;
- int direction;
+ int direction, ret;
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
if (!spcm) {
@@ -540,7 +559,11 @@ static void ipc_xrun(struct snd_sof_dev
}
stream = &spcm->stream[direction];
- snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+ if (ret < 0) {
+ dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret);
+ return;
+ }
dev_dbg(sdev->dev, "posn XRUN: host %llx comp %d size %d\n",
posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
--- a/sound/soc/sof/ops.h
+++ b/sound/soc/sof/ops.h
@@ -422,11 +422,11 @@ static inline int snd_sof_load_firmware(
}
/* host DSP message data */
-static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz)
+static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz)
{
- sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
+ return sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
}
/* host configure DSP HW parameters */
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -210,9 +210,9 @@ struct snd_sof_dsp_ops {
#endif
/* host read DSP stream data */
- void (*ipc_msg_data)(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz); /* mandatory */
+ int (*ipc_msg_data)(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz); /* mandatory */
/* host configure DSP HW parameters */
int (*ipc_pcm_params)(struct snd_sof_dev *sdev,
@@ -567,9 +567,9 @@ int sof_block_read(struct snd_sof_dev *s
int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id);
-void intel_ipc_msg_data(struct snd_sof_dev *sdev,
- struct snd_pcm_substream *substream,
- void *p, size_t sz);
+int intel_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz);
int intel_ipc_pcm_params(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream,
const struct sof_ipc_pcm_params_reply *reply);