ipc4: notification: Add filtering feature#10552
ipc4: notification: Add filtering feature#10552wjablon1 wants to merge 2 commits intothesofproject:mainfrom
Conversation
Moving memory allocation for IPC4 notifications to the notification module. With this change all the logic needed for sending IPC4 notifications is contained within the notification module. Currently all the notifications are allocated out of the same memory pool, so the selection of a memory pool is not part of the function interface of the notification module, but we can easily modify that behavior by adding a pool ID parameter. This change enables robust implementation of the notification filtering feature without exposing additional symbols to LLEXT modules. Signed-off-by: Wojciech Jablonski <wojciech.jablonski@intel.com>
Adding a handler for retrieving info about the IPC4 notification mask out of the LargeConfig. The notification mask is then used for filtering IPC4 notifications sent by the FW. This feature allows muting notifications of a given kind to enhance readability of logs during debugging. Also, this feature enhances reliability of certain tests run on FPGA-based setups where the FW notifications are too overwhelming for those setups. Signed-off-by: Wojciech Jablonski <wojciech.jablonski@intel.com>
| cd->xrun_notification_sent = true; | ||
| } | ||
| uint32_t node_id = cd->link_connector_node_id.dw; | ||
| bool notif_sent = false; |
| if (ret == -EPIPE && !dd->xrun_notification_sent) { | ||
| struct ipc_msg *notify = ipc_notification_pool_get(IPC4_RESOURCE_EVENT_SIZE); | ||
| uint32_t ppl_id = dev->pipeline->pipeline_id; | ||
| bool notif_sent = false; |
| hd->xrun_notification_sent = true; | ||
| } | ||
| uint32_t ppl_id = dev->pipeline->pipeline_id; | ||
| bool notif_sent = false; |
| if (!msg) | ||
| return false; | ||
|
|
||
| struct ipc4_resource_event_data_notification *notif = msg->tx_data; |
There was a problem hiding this comment.
I assume this cannot be NULL
There was a problem hiding this comment.
yes, the payload is allocated along with the msg as a single rzalloc operation.
| mixer_underrun_data.data_mixed = data_mixed; | ||
| mixer_underrun_data.expected_data_mixed = expected_data_mixed; | ||
|
|
||
| send_resource_notif(resource_id, SOF_IPC4_MIXER_UNDERRUN_DETECTED, SOF_IPC4_PIPELINE, |
There was a problem hiding this comment.
how about we only export send_resource_notif() and move all this component-specific functions to respective components and potentially make them static there?
There was a problem hiding this comment.
There are pros and cons. Function send_resource_notif takes numerous arguments. If we keep it static, we give the compile a chance to optimize them.
On the other hand, your idea would allow us to move the "if (cd->stream_direction)" condition into a single static function that determines the right arguments to send_resource_notif instead of having to choose the right function based on the condition.
Its a tough call and I didn't think about this. My focus was to allow efficient implantation of the notification mask without making the existing code too cumbersome.
There was a problem hiding this comment.
Also some middle ground approach is possible. For example we can merge send_gateway_underrun_notif_msg and send_gateway_overrun_notif_msg into a single function send_gateway_xrun_notif_msg but still keep it in the notification module.
This approach would eliminate the repetition of the following code in dai-zephyr.c and host-zephyr.c
if (dev->direction == SOF_IPC_STREAM_PLAYBACK)
notif_sent = send_copier_gateway_underrun_notif_msg(ppl_id);
else
notif_sent = send_copier_gateway_overrun_notif_msg(ppl_id);
|
|
||
| __cold static int basefw_notification_mask_info(const char *data) | ||
| { | ||
| struct ipc4_notification_mask_info *mask_info; |
There was a problem hiding this comment.
we could make the argument const void *data and just initialise struct ipc4_notification_mask_info *mask_info = data; directly here
There was a problem hiding this comment.
you are right. I just used a similar function as a template ;)
kv2019i
left a comment
There was a problem hiding this comment.
Looks good, no blockers.
|
@lgirdwood The goal is to enhance IPC4 compatibility to be able to re-use test scenarios for the SOF target (so yes, this is for a user-space test client). As I mention in the description, some test scenarios have the IPC notifications turned off due to reliability issues(poor performance on FPGA setups). Consequently, just because a single step is unsupported, the entire test scenario ends up with failure. The general goal is to turn our regression "green". We tend to disable selected tests for SOF target if an unsupported functionality it too heavy to implement and/or it is completely useless. But for lightweight and potentially useful features like this one, we typically lean towards adding a SOF implementation. |
|
Also, for this specific feature I found a TODO in the in the base_fw: (btw. I probably need to sort that out as well) |
| memset(¬if->event_data, 0, sizeof(notif->event_data)); | ||
| if (data && data_size) | ||
| memcpy_s(¬if->event_data, sizeof(notif->event_data), data, data_size); | ||
|
|
There was a problem hiding this comment.
Since you are using memcpy_s(), you should check the return value and avoid sending the IPC notification if the copy fails by returning false. This prevents sending potentially corrupted data.
| void process_data_error_notif_msg_init(struct ipc_msg *msg, uint32_t resource_id, | ||
| uint32_t error_code); | ||
| void send_process_data_error_notif_msg(uint32_t resource_id, uint32_t error_code); | ||
|
|
||
| void copier_gateway_underrun_notif_msg_init(struct ipc_msg *msg, uint32_t pipeline_id); | ||
| void copier_gateway_overrun_notif_msg_init(struct ipc_msg *msg, uint32_t pipeline_id); | ||
| void gateway_underrun_notif_msg_init(struct ipc_msg *msg, uint32_t resource_id); | ||
| void gateway_overrun_notif_msg_init(struct ipc_msg *msg, uint32_t resource_id); | ||
| bool send_copier_gateway_underrun_notif_msg(uint32_t pipeline_id); | ||
| bool send_copier_gateway_overrun_notif_msg(uint32_t pipeline_id); | ||
| bool send_gateway_underrun_notif_msg(uint32_t resource_id); | ||
| bool send_gateway_overrun_notif_msg(uint32_t resource_id); | ||
|
|
||
| void mixer_underrun_notif_msg_init(struct ipc_msg *msg, uint32_t resource_id, uint32_t eos_flag, | ||
| uint32_t data_mixed, uint32_t expected_data_mixed); | ||
| void send_mixer_underrun_notif_msg(uint32_t resource_id, uint32_t eos_flag, uint32_t data_mixed, | ||
| uint32_t expected_data_mixed); |
There was a problem hiding this comment.
nit: A consistent interface would probably be better, either we return true when notification has been sent or we return nothing.
Uh oh!
There was an error while loading. Please reload this page.