Skip to content

ipc4: notification: Add filtering feature#10552

Open
wjablon1 wants to merge 2 commits intothesofproject:mainfrom
wjablon1:notif_mask
Open

ipc4: notification: Add filtering feature#10552
wjablon1 wants to merge 2 commits intothesofproject:mainfrom
wjablon1:notif_mask

Conversation

@wjablon1
Copy link
Contributor

@wjablon1 wjablon1 commented Feb 17, 2026

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.

@wjablon1 wjablon1 changed the title Notif mask ipc4: notification: Add filtering feature Feb 17, 2026
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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

superfluous initialisation

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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

hd->xrun_notification_sent = true;
}
uint32_t ppl_id = dev->pipeline->pipeline_id;
bool notif_sent = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

if (!msg)
return false;

struct ipc4_resource_event_data_notification *notif = msg->tx_data;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this cannot be NULL

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about we only export send_resource_notif() and move all this component-specific functions to respective components and potentially make them static there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could make the argument const void *data and just initialise struct ipc4_notification_mask_info *mask_info = data; directly here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right. I just used a similar function as a template ;)

Copy link
Collaborator

@kv2019i kv2019i left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, no blockers.

Copy link
Member

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wjablon1 we may have a mix of kernel and user space clients sending IPC4 notifications, I assume this is being catered for here ?
LGTM.

@wjablon1
Copy link
Contributor Author

wjablon1 commented Feb 18, 2026

@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.

@wjablon1
Copy link
Contributor Author

Also, for this specific feature I found a TODO in the in the base_fw:

/* TODO: add more support */
case IPC4_DSP_RESOURCE_STATE:
case IPC4_NOTIFICATION_MASK:

(btw. I probably need to sort that out as well)

Comment on lines 37 to 40
memset(&notif->event_data, 0, sizeof(notif->event_data));
if (data && data_size)
memcpy_s(&notif->event_data, sizeof(notif->event_data), data, data_size);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines -291 to +299
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: A consistent interface would probably be better, either we return true when notification has been sent or we return nothing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

Comments