diff options
author | Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> | 2021-09-28 13:35:16 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-09-28 15:16:26 +0300 |
commit | 6a0ba071b71c44bc905522b77e96afad464e8aac (patch) | |
tree | d2e121ed7e65d72c6846cce61be8700bdae3bee2 /sound/soc/sof/ipc.c | |
parent | b05cfb1215223a750cff5367b625f0ed285a36cf (diff) | |
download | linux-6a0ba071b71c44bc905522b77e96afad464e8aac.tar.xz |
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.c | 41 |
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); |