aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/skylake/skl-sst-ipc.c
diff options
context:
space:
mode:
authorCezary Rojewski <cezary.rojewski@intel.com>2019-08-08 20:15:49 +0200
committerMark Brown <broonie@kernel.org>2019-08-08 21:22:33 +0100
commit36004c42c761a6d95b867a4fbb9a955034e53351 (patch)
treef07efe44fdec98551940c8eeb7672ba56c25cf07 /sound/soc/intel/skylake/skl-sst-ipc.c
parentASoC: Intel: Skylake: Limit large_config_get to single frame (diff)
downloadlinux-dev-36004c42c761a6d95b867a4fbb9a955034e53351.tar.xz
linux-dev-36004c42c761a6d95b867a4fbb9a955034e53351.zip
ASoC: Intel: Skylake: large_config_get overhaul
LARGE_CONFIG_GET is mainly used to retrieve requested module parameters but it may also carry TX payload with them. Update its implementation to account for both TX and RX data. First reply.header carries total payload size within data_off_sizefield. Make use of reply.header to realloc returned buffer with correct size. Failure of IPC request is permissive - error-payload may be returned, an informative data why GET for given param failed - and thus function should not collapse before entire processing is finished. Caller is responsible for checking returned payload and bytes parameters. Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://lore.kernel.org/r/20190808181549.12521-3-cezary.rojewski@intel.com Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/intel/skylake/skl-sst-ipc.c')
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c
index 196c80dadb1f..667cdddc289f 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.c
+++ b/sound/soc/intel/skylake/skl-sst-ipc.c
@@ -969,12 +969,18 @@ int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
- struct skl_ipc_large_config_msg *msg, u32 *param)
+ struct skl_ipc_large_config_msg *msg,
+ u32 **payload, size_t *bytes)
{
struct skl_ipc_header header = {0};
- struct sst_ipc_message request = {0}, reply = {0};
+ struct sst_ipc_message request, reply = {0};
+ unsigned int *buf;
int ret;
+ reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL);
+ if (!reply.data)
+ return -ENOMEM;
+
header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
@@ -986,13 +992,22 @@ int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
header.extension |= IPC_FINAL_BLOCK(1);
header.extension |= IPC_INITIAL_BLOCK(1);
- request.header = *(u64 *)(&header);
- reply.data = param;
- reply.size = msg->param_data_size;
+ request.header = *(u64 *)&header;
+ request.data = *payload;
+ request.size = *bytes;
+ reply.size = SKL_ADSP_W1_SZ;
+
ret = sst_ipc_tx_message_wait(ipc, request, &reply);
if (ret < 0)
dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret);
+ reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK;
+ buf = krealloc(reply.data, reply.size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ *payload = buf;
+ *bytes = reply.size;
+
return ret;
}
EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);