ASoC: SOF: utils: Add generic function to get the reply for a tx message

The code to get the reply for a tx is identical in all but one place:
imx8_get_reply(), imx8m_get_reply(), atom_get_reply(), bdw_get_reply().

hda_dsp_ipc_get_reply() have additional check in place for PROBES and
special handling of PM messages.

Add a generic implementation to the core which can be used as drop in
replacement.

The reply size check is changed to be able to handle cases when the reply
size is not know beforehand (this is the case for PROBES and
DEBUG_MEM_USAGE for example).

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Link: https://lore.kernel.org/r/20211116152137.52129-2-daniel.baluta@oss.nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Peter Ujfalusi 2021-11-16 17:21:34 +02:00 committed by Mark Brown
parent 7548a391c5
commit 8ae77801c8
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
2 changed files with 67 additions and 0 deletions

View file

@ -394,6 +394,67 @@ int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
}
EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
/* Generic helper function to retrieve the reply */
void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
{
struct snd_sof_ipc_msg *msg = sdev->msg;
struct sof_ipc_reply reply;
int ret = 0;
/*
* Sometimes, there is unexpected reply ipc arriving. The reply
* ipc belongs to none of the ipcs sent from driver.
* In this case, the driver must ignore the ipc.
*/
if (!msg) {
dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
return;
}
/* get the generic reply */
snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, &reply,
sizeof(reply));
if (reply.error < 0) {
memcpy(msg->reply_data, &reply, sizeof(reply));
ret = reply.error;
} else if (!reply.hdr.size) {
/* Reply should always be >= sizeof(struct sof_ipc_reply) */
if (msg->reply_size)
dev_err(sdev->dev,
"empty reply received, expected %zu bytes\n",
msg->reply_size);
else
dev_err(sdev->dev, "empty reply received\n");
ret = -EINVAL;
} else if (msg->reply_size > 0) {
if (reply.hdr.size == msg->reply_size) {
ret = 0;
} else if (reply.hdr.size < msg->reply_size) {
dev_dbg(sdev->dev,
"reply size (%u) is less than expected (%zu)\n",
reply.hdr.size, msg->reply_size);
msg->reply_size = reply.hdr.size;
ret = 0;
} else {
dev_err(sdev->dev,
"reply size (%u) exceeds the buffer size (%zu)\n",
reply.hdr.size, msg->reply_size);
ret = -EINVAL;
}
/* get the full message if reply.hdr.size <= msg->reply_size */
if (!ret)
snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset,
msg->reply_data, msg->reply_size);
}
msg->reply_error = ret;
}
EXPORT_SYMBOL(snd_sof_ipc_get_reply);
/* handle reply message from DSP */
void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
{

View file

@ -515,6 +515,7 @@ void snd_sof_fw_unload(struct snd_sof_dev *sdev);
*/
struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev);
void snd_sof_ipc_free(struct snd_sof_dev *sdev);
void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev);
void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id);
void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev);
int snd_sof_ipc_stream_pcm_params(struct snd_sof_dev *sdev,
@ -527,6 +528,11 @@ int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, u32 header,
void *msg_data, size_t msg_bytes,
void *reply_data, size_t reply_bytes);
int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev);
static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_id)
{
snd_sof_ipc_get_reply(sdev);
snd_sof_ipc_reply(sdev, msg_id);
}
/*
* Trace/debug