mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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>
This commit is contained in:
parent
b05cfb1215
commit
6a0ba071b7
@ -369,11 +369,12 @@ static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imx8_ipc_msg_data(struct snd_sof_dev *sdev,
|
static int imx8_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz)
|
void *p, size_t sz)
|
||||||
{
|
{
|
||||||
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
|
static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||||
|
@ -232,11 +232,12 @@ static int imx8m_get_bar_index(struct snd_sof_dev *sdev, u32 type)
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imx8m_ipc_msg_data(struct snd_sof_dev *sdev,
|
static int imx8m_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz)
|
void *p, size_t sz)
|
||||||
{
|
{
|
||||||
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev,
|
static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||||
|
@ -253,9 +253,9 @@ int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
|
|||||||
return SRAM_WINDOW_OFFSET(id);
|
return SRAM_WINDOW_OFFSET(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz)
|
void *p, size_t sz)
|
||||||
{
|
{
|
||||||
if (!substream || !sdev->stream_box.size) {
|
if (!substream || !sdev->stream_box.size) {
|
||||||
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
||||||
@ -268,10 +268,13 @@ void hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
|||||||
hda_stream.hstream);
|
hda_stream.hstream);
|
||||||
|
|
||||||
/* The stream might already be closed */
|
/* The stream might already be closed */
|
||||||
if (hstream)
|
if (!hstream)
|
||||||
sof_mailbox_read(sdev, hda_stream->stream.posn_offset,
|
return -ESTRPIPE;
|
||||||
p, sz);
|
|
||||||
|
sof_mailbox_read(sdev, hda_stream->stream.posn_offset, p, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
|
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||||
|
@ -563,9 +563,9 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
|
|||||||
struct hdac_ext_stream *stream,
|
struct hdac_ext_stream *stream,
|
||||||
int enable, u32 size);
|
int enable, u32 size);
|
||||||
|
|
||||||
void hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz);
|
void *p, size_t sz);
|
||||||
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
|
int hda_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
const struct sof_ipc_pcm_params_reply *reply);
|
const struct sof_ipc_pcm_params_reply *reply);
|
||||||
|
@ -25,9 +25,9 @@ struct intel_stream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Mailbox-based Intel IPC implementation */
|
/* Mailbox-based Intel IPC implementation */
|
||||||
void intel_ipc_msg_data(struct snd_sof_dev *sdev,
|
int intel_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz)
|
void *p, size_t sz)
|
||||||
{
|
{
|
||||||
if (!substream || !sdev->stream_box.size) {
|
if (!substream || !sdev->stream_box.size) {
|
||||||
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
|
||||||
@ -35,9 +35,13 @@ void intel_ipc_msg_data(struct snd_sof_dev *sdev,
|
|||||||
struct intel_stream *stream = substream->runtime->private_data;
|
struct intel_stream *stream = substream->runtime->private_data;
|
||||||
|
|
||||||
/* The stream might already be closed */
|
/* The stream might already be closed */
|
||||||
if (stream)
|
if (!stream)
|
||||||
sof_mailbox_read(sdev, stream->posn_offset, p, sz);
|
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);
|
EXPORT_SYMBOL_NS(intel_ipc_msg_data, SND_SOC_SOF_INTEL_HIFI_EP_IPC);
|
||||||
|
|
||||||
|
@ -394,6 +394,7 @@ static void ipc_comp_notification(struct snd_sof_dev *sdev,
|
|||||||
{
|
{
|
||||||
u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
|
u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
|
||||||
struct sof_ipc_ctrl_data *cdata;
|
struct sof_ipc_ctrl_data *cdata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
case SOF_IPC_COMP_GET_VALUE:
|
case SOF_IPC_COMP_GET_VALUE:
|
||||||
@ -403,7 +404,12 @@ static void ipc_comp_notification(struct snd_sof_dev *sdev,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* read back full message */
|
/* 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;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(sdev->dev, "error: unhandled component message %#x\n", msg_type);
|
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);
|
snd_sof_control_notify(sdev, cdata);
|
||||||
|
|
||||||
|
err:
|
||||||
kfree(cdata);
|
kfree(cdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,10 +427,14 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
|
|||||||
{
|
{
|
||||||
struct sof_ipc_cmd_hdr hdr;
|
struct sof_ipc_cmd_hdr hdr;
|
||||||
u32 cmd, type;
|
u32 cmd, type;
|
||||||
int err = 0;
|
int err;
|
||||||
|
|
||||||
/* read back header */
|
/* 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);
|
ipc_log_header(sdev->dev, "ipc rx", hdr.cmd);
|
||||||
|
|
||||||
cmd = hdr.cmd & SOF_GLB_TYPE_MASK;
|
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)
|
static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type)
|
||||||
{
|
{
|
||||||
struct sof_ipc_dma_trace_posn posn;
|
struct sof_ipc_dma_trace_posn posn;
|
||||||
|
int ret;
|
||||||
|
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
case SOF_IPC_TRACE_DMA_POSITION:
|
case SOF_IPC_TRACE_DMA_POSITION:
|
||||||
/* read back full message */
|
/* read back full message */
|
||||||
snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn));
|
ret = snd_sof_ipc_msg_data(sdev, NULL, &posn, sizeof(posn));
|
||||||
snd_sof_trace_update_pos(sdev, &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;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type);
|
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 snd_sof_pcm_stream *stream;
|
||||||
struct sof_ipc_stream_posn posn;
|
struct sof_ipc_stream_posn posn;
|
||||||
struct snd_sof_pcm *spcm;
|
struct snd_sof_pcm *spcm;
|
||||||
int direction;
|
int direction, ret;
|
||||||
|
|
||||||
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
|
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
|
||||||
if (!spcm) {
|
if (!spcm) {
|
||||||
@ -511,7 +526,11 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream = &spcm->stream[direction];
|
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",
|
dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n",
|
||||||
posn.host_posn, posn.dai_posn, posn.wallclock);
|
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 snd_sof_pcm_stream *stream;
|
||||||
struct sof_ipc_stream_posn posn;
|
struct sof_ipc_stream_posn posn;
|
||||||
struct snd_sof_pcm *spcm;
|
struct snd_sof_pcm *spcm;
|
||||||
int direction;
|
int direction, ret;
|
||||||
|
|
||||||
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
|
spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
|
||||||
if (!spcm) {
|
if (!spcm) {
|
||||||
@ -540,7 +559,11 @@ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream = &spcm->stream[direction];
|
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",
|
dev_dbg(sdev->dev, "posn XRUN: host %llx comp %d size %d\n",
|
||||||
posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
|
posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
|
||||||
|
@ -422,11 +422,11 @@ static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* host DSP message data */
|
/* host DSP message data */
|
||||||
static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
|
static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz)
|
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 */
|
/* host configure DSP HW parameters */
|
||||||
|
@ -210,9 +210,9 @@ struct snd_sof_dsp_ops {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* host read DSP stream data */
|
/* host read DSP stream data */
|
||||||
void (*ipc_msg_data)(struct snd_sof_dev *sdev,
|
int (*ipc_msg_data)(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz); /* mandatory */
|
void *p, size_t sz); /* mandatory */
|
||||||
|
|
||||||
/* host configure DSP HW parameters */
|
/* host configure DSP HW parameters */
|
||||||
int (*ipc_pcm_params)(struct snd_sof_dev *sdev,
|
int (*ipc_pcm_params)(struct snd_sof_dev *sdev,
|
||||||
@ -567,9 +567,9 @@ int sof_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
|
|||||||
|
|
||||||
int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id);
|
int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id);
|
||||||
|
|
||||||
void intel_ipc_msg_data(struct snd_sof_dev *sdev,
|
int intel_ipc_msg_data(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
void *p, size_t sz);
|
void *p, size_t sz);
|
||||||
int intel_ipc_pcm_params(struct snd_sof_dev *sdev,
|
int intel_ipc_pcm_params(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
const struct sof_ipc_pcm_params_reply *reply);
|
const struct sof_ipc_pcm_params_reply *reply);
|
||||||
|
Loading…
Reference in New Issue
Block a user