ASoC: SOF: ipc: Read and pass the whole message to handlers for IPC events
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Thu, 10 Feb 2022 15:05:19 +0000 (17:05 +0200)
committerMark Brown <broonie@kernel.org>
Thu, 10 Feb 2022 15:19:03 +0000 (15:19 +0000)
Change the parameter list for the firmware initiated message (IPC event)
handler functions to:
handler(struct snd_sof_dev *sdev, void *full_msg);

Allocate memory and read the whole message in snd_sof_ipc_msgs_rx() then
pass the pointer to the function handling the message.
Do this only if we actually have a function which is tasked to process the
given type.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20220210150525.30756-4-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc.c

index 16a0d7a..ee56d4f 100644 (file)
 #include "sof-audio.h"
 #include "ops.h"
 
-static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type);
-static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd);
+typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf);
+
+static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf);
+static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf);
 
 /*
  * IPC message Tx/Rx message handling.
@@ -477,44 +479,30 @@ void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
 }
 EXPORT_SYMBOL(snd_sof_ipc_reply);
 
-static void ipc_comp_notification(struct snd_sof_dev *sdev,
-                                 struct sof_ipc_cmd_hdr *hdr)
+static void ipc_comp_notification(struct snd_sof_dev *sdev, void *msg_buf)
 {
+       struct sof_ipc_cmd_hdr *hdr = msg_buf;
        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:
        case SOF_IPC_COMP_GET_DATA:
-               cdata = kmalloc(hdr->size, GFP_KERNEL);
-               if (!cdata)
-                       return;
-
-               /* read back full message */
-               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);
                return;
        }
 
-       snd_sof_control_notify(sdev, cdata);
-
-err:
-       kfree(cdata);
+       snd_sof_control_notify(sdev, msg_buf);
 }
 
 /* DSP firmware has sent host a message  */
 void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
 {
+       ipc_rx_callback rx_callback = NULL;
        struct sof_ipc_cmd_hdr hdr;
-       u32 cmd, type;
+       void *msg_buf;
+       u32 cmd;
        int err;
 
        /* read back header */
@@ -523,10 +511,15 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
                dev_warn(sdev->dev, "failed to read IPC header: %d\n", err);
                return;
        }
+
+       if (hdr.size < sizeof(hdr)) {
+               dev_err(sdev->dev, "The received message size is invalid\n");
+               return;
+       }
+
        ipc_log_header(sdev->dev, "ipc rx", hdr.cmd);
 
        cmd = hdr.cmd & SOF_GLB_TYPE_MASK;
-       type = hdr.cmd & SOF_CMD_TYPE_MASK;
 
        /* check message type */
        switch (cmd) {
@@ -551,20 +544,35 @@ void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
        case SOF_IPC_GLB_PM_MSG:
                break;
        case SOF_IPC_GLB_COMP_MSG:
-               ipc_comp_notification(sdev, &hdr);
+               rx_callback = ipc_comp_notification;
                break;
        case SOF_IPC_GLB_STREAM_MSG:
-               /* need to pass msg id into the function */
-               ipc_stream_message(sdev, hdr.cmd);
+               rx_callback = ipc_stream_message;
                break;
        case SOF_IPC_GLB_TRACE_MSG:
-               ipc_trace_message(sdev, type);
+               rx_callback = ipc_trace_message;
                break;
        default:
-               dev_err(sdev->dev, "error: unknown DSP message 0x%x\n", cmd);
+               dev_err(sdev->dev, "%s: Unknown DSP message: 0x%x\n", __func__, cmd);
                break;
        }
 
+       if (rx_callback) {
+               /* read the full message as we have rx handler for it */
+               msg_buf = kmalloc(hdr.size, GFP_KERNEL);
+               if (!msg_buf)
+                       return;
+
+               err = snd_sof_ipc_msg_data(sdev, NULL, msg_buf, hdr.size);
+               if (err < 0)
+                       dev_err(sdev->dev, "%s: Failed to read message: %d\n",
+                               __func__, err);
+               else
+                       rx_callback(sdev, msg_buf);
+
+               kfree(msg_buf);
+       }
+
        ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd);
 }
 EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);
@@ -573,19 +581,14 @@ EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);
  * IPC trace mechanism.
  */
 
-static void ipc_trace_message(struct snd_sof_dev *sdev, u32 msg_type)
+static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf)
 {
-       struct sof_ipc_dma_trace_posn posn;
-       int ret;
+       struct sof_ipc_cmd_hdr *hdr = msg_buf;
+       u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
 
        switch (msg_type) {
        case SOF_IPC_TRACE_DMA_POSITION:
-               /* read back full message */
-               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);
+               snd_sof_trace_update_pos(sdev, msg_buf);
                break;
        default:
                dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type);
@@ -667,11 +670,11 @@ static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
 }
 
 /* stream notifications from DSP FW */
-static void ipc_stream_message(struct snd_sof_dev *sdev, u32 msg_cmd)
+static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf)
 {
-       /* get msg cmd type and msd id */
-       u32 msg_type = msg_cmd & SOF_CMD_TYPE_MASK;
-       u32 msg_id = SOF_IPC_MESSAGE_ID(msg_cmd);
+       struct sof_ipc_cmd_hdr *hdr = msg_buf;
+       u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
+       u32 msg_id = SOF_IPC_MESSAGE_ID(hdr->cmd);
 
        switch (msg_type) {
        case SOF_IPC_STREAM_POSITION: