Unverified Commit ab3a2189 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown
Browse files

ASoC: SOF: ipc: Read and pass the whole message to handlers for IPC events



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: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20220210150525.30756-4-peter.ujfalusi@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 5fdc1242
Loading
Loading
Loading
Loading
+44 −41
Original line number Diff line number Diff line
@@ -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.
@@ -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: