Skip to content

Commit 753653a

Browse files
committed
ipc4: handler: make config and pipeline-state processing context-agnostic
Extract the per-message processing logic for module CONFIG_GET/SET and LARGE_CONFIG_GET/SET into standalone functions that return their results via output parameters instead of writing the global msg_reply directly, and give SET_PIPELINE_STATE external linkage. This is a pure refactor with no functional change. The new ipc4_process_module_config(), ipc4_process_large_config_get(), ipc4_process_large_config_set() and ipc4_set_pipeline_state() can be called from any execution context, which is needed to later dispatch these messages from a separate IPC user-space thread. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent ac8a08c commit 753653a

2 files changed

Lines changed: 246 additions & 4 deletions

File tree

src/include/ipc4/handler.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,36 @@ struct ipc4_message_request;
1616
*/
1717
int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, struct ipc_msg *reply);
1818

19+
/**
20+
* @brief Process MOD_CONFIG_GET or MOD_CONFIG_SET in any execution context.
21+
* @param[in] ipc4 IPC4 message request.
22+
* @param[in] set true for CONFIG_SET, false for CONFIG_GET.
23+
* @param[out] reply_ext Receives extension value for CONFIG_GET (may be NULL).
24+
* @return IPC4 status code (0 on success).
25+
*/
26+
int ipc4_process_module_config(struct ipc4_message_request *ipc4,
27+
bool set, uint32_t *reply_ext);
28+
29+
/**
30+
* @brief Process MOD_LARGE_CONFIG_GET in any execution context.
31+
* @param[in] ipc4 IPC4 message request.
32+
* @param[out] reply_ext Receives extension value for reply.
33+
* @param[out] reply_tx_size Receives TX data size for reply.
34+
* @param[out] reply_tx_data Receives TX data pointer for reply.
35+
* @return IPC4 status code (0 on success).
36+
*/
37+
int ipc4_process_large_config_get(struct ipc4_message_request *ipc4,
38+
uint32_t *reply_ext,
39+
uint32_t *reply_tx_size,
40+
void **reply_tx_data);
41+
42+
/**
43+
* @brief Process MOD_LARGE_CONFIG_SET in any execution context.
44+
* @param[in] ipc4 IPC4 message request.
45+
* @return IPC4 status code (0 on success).
46+
*/
47+
int ipc4_process_large_config_set(struct ipc4_message_request *ipc4);
48+
1949
/**
2050
* \brief Processes IPC4 userspace global message.
2151
* @param[in] ipc4 IPC4 message request.
@@ -24,6 +54,13 @@ int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, struct i
2454
*/
2555
int ipc4_user_process_glb_message(struct ipc4_message_request *ipc4, struct ipc_msg *reply);
2656

57+
/**
58+
* \brief Process SET_PIPELINE_STATE IPC4 message (prepare + trigger phases).
59+
* @param[in] ipc4 IPC4 message request.
60+
* @return 0 on success, IPC4 error code otherwise.
61+
*/
62+
int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4);
63+
2764
/**
2865
* \brief Increment the IPC compound message pre-start counter.
2966
* @param[in] msg_id IPC message ID.

src/ipc/ipc4/handler-user.c

Lines changed: 209 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,12 @@ __cold const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data_wrapper
424424
return ipc4_get_pipeline_data();
425425
}
426426

427-
/* Entry point for ipc4_pipeline_trigger(), therefore cannot be cold */
428-
static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4)
427+
/**
428+
* \brief Process SET_PIPELINE_STATE IPC4 message (prepare + trigger phases).
429+
* @param[in] ipc4 IPC4 message request.
430+
* @return 0 on success, IPC4 error code otherwise.
431+
*/
432+
int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4)
429433
{
430434
const struct ipc4_pipeline_set_state_data *ppl_data;
431435
struct ipc4_pipeline_set_state state;
@@ -809,7 +813,22 @@ __cold static int ipc4_unbind_module_instance(struct ipc4_message_request *ipc4)
809813
return ipc_comp_disconnect(ipc, (ipc_pipe_comp_connect *)&bu);
810814
}
811815

812-
static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4, bool set)
816+
/**
817+
* @brief Process MOD_CONFIG_GET or MOD_CONFIG_SET in any execution context.
818+
*
819+
* Looks up the target component by module_id:instance_id, verifies the
820+
* driver supports get_attribute/set_attribute, and dispatches the
821+
* operation. For GET, the retrieved value is written to @p reply_ext.
822+
*
823+
* Callable from both the IPC kernel task and the IPC user thread.
824+
*
825+
* @param ipc4 Pointer to the IPC4 message request (primary + extension)
826+
* @param set true for CONFIG_SET, false for CONFIG_GET
827+
* @param reply_ext Output: receives the extension value for CONFIG_GET (may be NULL for SET)
828+
* @return IPC4 status code (0 on success)
829+
*/
830+
__cold int ipc4_process_module_config(struct ipc4_message_request *ipc4,
831+
bool set, uint32_t *reply_ext)
813832
{
814833
struct ipc4_module_config *config = (struct ipc4_module_config *)ipc4;
815834
int (*function)(struct comp_dev *dev, uint32_t type, void *value);
@@ -859,8 +878,21 @@ static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4
859878
ret = IPC4_INVALID_CONFIG_PARAM_ID;
860879
}
861880

881+
if (!set && reply_ext)
882+
*reply_ext = config->extension.dat;
883+
884+
return ret;
885+
}
886+
887+
static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4, bool set)
888+
{
889+
uint32_t reply_ext;
890+
int ret;
891+
892+
ret = ipc4_process_module_config(ipc4, set, &reply_ext);
893+
862894
if (!set)
863-
msg_reply->extension = config->extension.dat;
895+
msg_reply->extension = reply_ext;
864896

865897
return ret;
866898
}
@@ -990,6 +1022,108 @@ __cold static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev,
9901022
return IPC4_SUCCESS;
9911023
}
9921024

1025+
__cold int ipc4_process_large_config_get(struct ipc4_message_request *ipc4,
1026+
uint32_t *reply_ext,
1027+
uint32_t *reply_tx_size,
1028+
void **reply_tx_data)
1029+
{
1030+
struct ipc4_module_large_config_reply reply;
1031+
struct ipc4_module_large_config config;
1032+
char *data = ipc_get()->comp_data;
1033+
const struct comp_driver *drv;
1034+
struct comp_dev *dev = NULL;
1035+
uint32_t data_offset;
1036+
1037+
assert_can_be_cold();
1038+
1039+
int ret = memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4));
1040+
1041+
if (ret < 0)
1042+
return IPC4_FAILURE;
1043+
1044+
tr_dbg(&ipc_tr, "%x : %x",
1045+
(uint32_t)config.primary.r.module_id, (uint32_t)config.primary.r.instance_id);
1046+
1047+
/* get component dev for non-basefw since there is no
1048+
* component dev for basefw
1049+
*/
1050+
if (config.primary.r.module_id) {
1051+
uint32_t comp_id;
1052+
1053+
comp_id = IPC4_COMP_ID(config.primary.r.module_id,
1054+
config.primary.r.instance_id);
1055+
dev = ipc4_get_comp_dev(comp_id);
1056+
if (!dev)
1057+
return IPC4_MOD_INVALID_ID;
1058+
1059+
drv = dev->drv;
1060+
1061+
/* Multicore disabled for userspace forwarding;
1062+
* non-userspace path retains ipc4_process_on_core()
1063+
*/
1064+
} else {
1065+
drv = ipc4_get_comp_drv(config.primary.r.module_id);
1066+
}
1067+
1068+
if (!drv)
1069+
return IPC4_MOD_INVALID_ID;
1070+
1071+
if (!drv->ops.get_large_config)
1072+
return IPC4_INVALID_REQUEST;
1073+
1074+
data_offset = config.extension.r.data_off_size;
1075+
1076+
/* check for vendor param first */
1077+
if (config.extension.r.large_param_id == VENDOR_CONFIG_PARAM) {
1078+
/* For now only vendor_config case uses payload from hostbox */
1079+
dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE,
1080+
config.extension.r.data_off_size);
1081+
ret = ipc4_get_vendor_config_module_instance(dev, drv,
1082+
config.extension.r.init_block,
1083+
config.extension.r.final_block,
1084+
&data_offset,
1085+
data,
1086+
(const char *)MAILBOX_HOSTBOX_BASE);
1087+
} else {
1088+
#if CONFIG_LIBRARY
1089+
data += sizeof(reply);
1090+
#endif
1091+
ipc4_prepare_for_kcontrol_get(dev, config.extension.r.large_param_id,
1092+
data, data_offset);
1093+
1094+
ret = drv->ops.get_large_config(dev, config.extension.r.large_param_id,
1095+
config.extension.r.init_block,
1096+
config.extension.r.final_block,
1097+
&data_offset, data);
1098+
}
1099+
1100+
/* set up ipc4 error code for reply data */
1101+
if (ret < 0)
1102+
ret = IPC4_MOD_INVALID_ID;
1103+
1104+
/* Copy host config and overwrite */
1105+
reply.extension.dat = config.extension.dat;
1106+
reply.extension.r.data_off_size = data_offset;
1107+
1108+
/* The last block, no more data */
1109+
if (!config.extension.r.final_block && data_offset < SOF_IPC_MSG_MAX_SIZE)
1110+
reply.extension.r.final_block = 1;
1111+
1112+
/* Indicate last block if error occurs */
1113+
if (ret)
1114+
reply.extension.r.final_block = 1;
1115+
1116+
/* no need to allocate memory for reply msg */
1117+
if (ret)
1118+
return ret;
1119+
1120+
/* Output via parameters instead of msg_reply */
1121+
*reply_ext = reply.extension.dat;
1122+
*reply_tx_size = data_offset;
1123+
*reply_tx_data = data;
1124+
return ret;
1125+
}
1126+
9931127
__cold static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ipc4)
9941128
{
9951129
struct ipc4_module_large_config_reply reply;
@@ -1182,6 +1316,77 @@ __cold static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev,
11821316
data_off_size, data);
11831317
}
11841318

1319+
__cold int ipc4_process_large_config_set(struct ipc4_message_request *ipc4)
1320+
{
1321+
struct ipc4_module_large_config config;
1322+
struct comp_dev *dev = NULL;
1323+
const struct comp_driver *drv;
1324+
1325+
assert_can_be_cold();
1326+
1327+
int ret = memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4));
1328+
1329+
if (ret < 0)
1330+
return IPC4_FAILURE;
1331+
1332+
dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE,
1333+
config.extension.r.data_off_size);
1334+
tr_dbg(&ipc_tr, "%x : %x",
1335+
(uint32_t)config.primary.r.module_id, (uint32_t)config.primary.r.instance_id);
1336+
1337+
if (config.primary.r.module_id) {
1338+
uint32_t comp_id;
1339+
1340+
comp_id = IPC4_COMP_ID(config.primary.r.module_id, config.primary.r.instance_id);
1341+
dev = ipc4_get_comp_dev(comp_id);
1342+
if (!dev)
1343+
return IPC4_MOD_INVALID_ID;
1344+
1345+
drv = dev->drv;
1346+
1347+
/* Multicore disabled for userspace forwarding;
1348+
* non-userspace path retains ipc4_process_on_core()
1349+
*/
1350+
} else {
1351+
drv = ipc4_get_comp_drv(config.primary.r.module_id);
1352+
}
1353+
1354+
if (!drv)
1355+
return IPC4_MOD_INVALID_ID;
1356+
1357+
if (!drv->ops.set_large_config)
1358+
return IPC4_INVALID_REQUEST;
1359+
1360+
/* check for vendor param first */
1361+
if (config.extension.r.large_param_id == VENDOR_CONFIG_PARAM) {
1362+
ret = ipc4_set_vendor_config_module_instance(dev, drv,
1363+
(uint32_t)config.primary.r.module_id,
1364+
(uint32_t)config.primary.r.instance_id,
1365+
config.extension.r.init_block,
1366+
config.extension.r.final_block,
1367+
config.extension.r.data_off_size,
1368+
(const char *)MAILBOX_HOSTBOX_BASE);
1369+
} else {
1370+
#if CONFIG_LIBRARY
1371+
struct ipc *ipc = ipc_get();
1372+
const char *data = (const char *)ipc->comp_data + sizeof(config);
1373+
#else
1374+
const char *data = (const char *)MAILBOX_HOSTBOX_BASE;
1375+
#endif
1376+
ret = drv->ops.set_large_config(dev, config.extension.r.large_param_id,
1377+
config.extension.r.init_block, config.extension.r.final_block,
1378+
config.extension.r.data_off_size, data);
1379+
if (ret < 0) {
1380+
ipc_cmd_err(&ipc_tr, "failed to set large_config_module_instance %x : %x",
1381+
(uint32_t)config.primary.r.module_id,
1382+
(uint32_t)config.primary.r.instance_id);
1383+
ret = IPC4_INVALID_RESOURCE_ID;
1384+
}
1385+
}
1386+
1387+
return ret;
1388+
}
1389+
11851390
__cold static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ipc4)
11861391
{
11871392
struct ipc4_module_large_config config;

0 commit comments

Comments
 (0)