Skip to content

Commit

Permalink
ASoC: SOF: ipc: Read and pass the whole message to handlers for IPC e…
Browse files Browse the repository at this point in the history
…vents

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>
  • Loading branch information
ujfalusi authored and kv2019i committed Nov 23, 2021
1 parent af2db26 commit 9b704f0
Showing 1 changed file with 44 additions and 41 deletions.
85 changes: 44 additions & 41 deletions sound/soc/sof/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
#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.
Expand Down Expand Up @@ -461,44 +463,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 */
Expand All @@ -507,10 +495,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) {
Expand All @@ -535,20 +528,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);
Expand All @@ -557,19 +565,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);
Expand Down Expand Up @@ -651,11 +654,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:
Expand Down

0 comments on commit 9b704f0

Please sign in to comment.