From 653fe90763e1160603fadd32a3e3524ce0aea328 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Wed, 30 Jan 2019 18:47:29 +0200 Subject: [PATCH 1/2] ASoC: SOF: ipc: enable large ipc messages Make SOF ipc to handle large IPC messages by chopping big messages to smaller parts. Signed-off-by: Jaska Uimonen --- include/sound/sof/header.h | 10 +++++- include/uapi/sound/sof/abi.h | 2 +- sound/soc/sof/ipc.c | 60 +++++++++++++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index ccb6a004b37b78..7150f6d2a49c62 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -48,7 +48,7 @@ #define SOF_IPC_FW_READY SOF_GLB_TYPE(0x7U) #define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U) #define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U) - +#define SOF_IPC_GLB_LARGE SOF_GLB_TYPE(0xBU) /* * DSP Command Message Types */ @@ -153,6 +153,14 @@ struct sof_ipc_compound_hdr { uint32_t count; /**< count of 0 means end of compound sequence */ } __packed; +struct sof_ipc_large_hdr { + struct sof_ipc_cmd_hdr hdr; + uint32_t cmd; + uint32_t count; + uint32_t id; + unsigned char data[]; +} __packed; + /** @}*/ #endif diff --git a/include/uapi/sound/sof/abi.h b/include/uapi/sound/sof/abi.h index cc0d3d2a47a74b..9d0ec469d36c70 100644 --- a/include/uapi/sound/sof/abi.h +++ b/include/uapi/sound/sof/abi.h @@ -26,7 +26,7 @@ /* SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 0 +#define SOF_ABI_MINOR 1 #define SOF_ABI_PATCH 0 /* SOF ABI version number. Format within 32bit word is MMmmmppp */ diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 2e6516eb400931..3368b34f3d9262 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -178,6 +178,8 @@ static void ipc_log_header(struct device *dev, u8 *text, u32 cmd) break; case SOF_IPC_GLB_TRACE_MSG: str = "GLB_TRACE_MSG"; break; + case SOF_IPC_GLB_LARGE: + str = "GLB_LARGE"; break; default: str = "unknown GLB command"; break; } @@ -241,10 +243,9 @@ static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg, return ret; } -/* send IPC message from host to DSP */ -int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, - void *msg_data, size_t msg_bytes, void *reply_data, - size_t reply_bytes) +static int sof_ipc_tx_msg(struct snd_sof_ipc *ipc, u32 header, + void *msg_data, size_t msg_bytes, void *reply_data, + size_t reply_bytes) { struct snd_sof_dev *sdev = ipc->sdev; struct snd_sof_ipc_msg *msg; @@ -279,6 +280,57 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, /* now wait for completion */ return tx_wait_done(ipc, msg, reply_data); } + +/* send IPC message from host to DSP */ +int sof_ipc_tx_message(struct snd_sof_ipc *ipc, u32 header, + void *msg_data, size_t msg_bytes, void *reply_data, + size_t reply_bytes) +{ + struct sof_ipc_large_hdr *hdr; + uint32_t num_msg = 0; + uint32_t offset = 0; + uint32_t send_bytes = 0; + int ret = -1; + int size; + int i; + + if (msg_bytes <= SOF_IPC_MSG_MAX_SIZE) + return sof_ipc_tx_msg(ipc, header, msg_data, msg_bytes, + reply_data, reply_bytes); + + /* if bigger than max size, chop to smaller pieces */ + dev_dbg(ipc->sdev->dev, "sending large ipc size %zu\n", msg_bytes); + size = SOF_IPC_MSG_MAX_SIZE - sizeof(struct sof_ipc_large_hdr); + num_msg = (msg_bytes + size - 1) / size; + + hdr = (struct sof_ipc_large_hdr *) + kzalloc(SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + hdr->hdr.cmd = SOF_IPC_GLB_LARGE; + hdr->cmd = header; + hdr->count = num_msg; + + for (i = 0; i < num_msg; i++) { + hdr->id = i; + send_bytes = msg_bytes > size ? size : msg_bytes; + memcpy(hdr->data, msg_data + offset, send_bytes); + hdr->hdr.size = send_bytes; + ret = sof_ipc_tx_msg(ipc, SOF_IPC_GLB_LARGE, hdr, send_bytes + + sizeof(struct sof_ipc_large_hdr), + reply_data, reply_bytes); + if (ret < 0) + break; + + offset += size; + msg_bytes -= send_bytes; + } + + kfree(hdr); + + return ret; +} EXPORT_SYMBOL(sof_ipc_tx_message); /* send next IPC message in list */ From 31abaa6cf4fd7bbe74a2605e3473da6beeb1f749 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Wed, 30 Jan 2019 18:48:05 +0200 Subject: [PATCH 2/2] ASoC: SOF: ipc: test big data with controls Currently SOF limits control bytes data to ipc max data size. Remove this limitation to test partial large ipc messages. Signed-off-by: Jaska Uimonen --- sound/soc/sof/topology.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 5438461c026742..08e4c9360d926e 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -300,11 +300,15 @@ static int sof_control_load_bytes(struct snd_soc_component *scomp, struct sof_ipc_ctrl_data *cdata; struct snd_soc_tplg_bytes_control *control = (struct snd_soc_tplg_bytes_control *)hdr; + /* const int max_size = SOF_IPC_MSG_MAX_SIZE - sizeof(const struct sof_ipc_ctrl_data); + */ + + const int max_size = SOF_IPC_MSG_MAX_SIZE * 10; /* init the get/put bytes data */ - scontrol->size = SOF_IPC_MSG_MAX_SIZE; + scontrol->size = max_size; scontrol->control_data = kzalloc(scontrol->size, GFP_KERNEL); cdata = scontrol->control_data; if (!scontrol->control_data)