summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/ipc.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>2021-09-28 13:35:16 +0300
committerMark Brown <broonie@kernel.org>2021-09-28 13:16:26 +0100
commit6a0ba071b71c44bc905522b77e96afad464e8aac (patch)
treed2e121ed7e65d72c6846cce61be8700bdae3bee2 /sound/soc/sof/ipc.c
parentb05cfb1215223a750cff5367b625f0ed285a36cf (diff)
downloadlinux-6a0ba071b71c44bc905522b77e96afad464e8aac.tar.bz2
ASoC: SOF: add error handling to snd_sof_ipc_msg_data()
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>
Diffstat (limited to 'sound/soc/sof/ipc.c')
-rw-r--r--sound/soc/sof/ipc.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 5d41924f37a6..152d36a6253d 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -394,6 +394,7 @@ static void ipc_comp_notification(struct snd_sof_dev *sdev,
{
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 snd_sof_dev *sdev,
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_dev *sdev,
snd_sof_control_notify(sdev, cdata);
+err:
kfree(cdata);
}
@@ -420,10 +427,14 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
{
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 snd_sof_dev *sdev, u32 msg_id)
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 snd_sof_dev *sdev, u32 msg_id)
}
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 *sdev, u32 msg_id)
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 *sdev, u32 msg_id)
}
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);