OSDN Git Service

ASoC: SOF: ipc3: Implement the get_reply IPC ops
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Tue, 5 Apr 2022 17:26:59 +0000 (10:26 -0700)
committerMark Brown <broonie@kernel.org>
Mon, 11 Apr 2022 18:17:52 +0000 (19:17 +0100)
Add the implementation for the get_reply callback to copy the reply message
from mailbox to msg->reply_data buffer.

The implementation is equivalent to the currently used code in ipc.c

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20220405172708.122168-7-ranjani.sridharan@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc3.c

index 9aa263b..2ecd3bb 100644 (file)
@@ -217,6 +217,60 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
 }
 #endif
 
+static int sof_ipc3_get_reply(struct snd_sof_dev *sdev)
+{
+       struct snd_sof_ipc_msg *msg = sdev->msg;
+       struct sof_ipc_reply *reply;
+       int ret = 0;
+
+       /* get the generic reply */
+       reply = msg->reply_data;
+       snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, reply, sizeof(*reply));
+
+       if (reply->error < 0)
+               return reply->error;
+
+       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");
+
+               return -EINVAL;
+       }
+
+       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
+                * and the reply->hdr.size > sizeof(struct sof_ipc_reply)
+                */
+               if (!ret && msg->reply_size > sizeof(*reply))
+                       snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset,
+                                                msg->reply_data, msg->reply_size);
+       }
+
+       return ret;
+}
+
 /* wait for IPC message reply */
 static int ipc3_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data)
 {
@@ -453,4 +507,5 @@ const struct sof_ipc_ops ipc3_ops = {
 
        .tx_msg = sof_ipc3_tx_msg,
        .set_get_data = sof_ipc3_set_get_data,
+       .get_reply = sof_ipc3_get_reply,
 };