From 0d39e01ea2650f70a1ff02aec3193cbf6b8a0d7d Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Tue, 29 Jun 2021 05:34:07 +0000 Subject: [PATCH 1/2] notifier.h: document the API ... and rename some parameter names. Signed-off-by: Marc Herbert --- src/include/sof/lib/notifier.h | 40 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/include/sof/lib/notifier.h b/src/include/sof/lib/notifier.h index 6c00a89b48b4..2f10b2d97aee 100644 --- a/src/include/sof/lib/notifier.h +++ b/src/include/sof/lib/notifier.h @@ -58,15 +58,43 @@ struct notify_data { struct notify **arch_notify_get(void); -int notifier_register(void *receiver, void *caller, enum notify_id type, - void (*cb)(void *arg, enum notify_id type, void *data), +/** Register a callback to be run when event 'type' happens. + * + * The identifier for un-registration is the tuple (receiver_data, + * caller_id_filter, event_type), the callback argument is not part of + * it. + * + * caller_data argument from notifier_event() + * + * @param receiver_data private data passed to the callback. + * @param caller_id_filter optional, can be used to be notified only by + * some specific notifier_event() calls when not NULL. + * @param event_type list of callbacks to be added to + * @param callback callback function + * @param flags see NOTIFIER_FLAG_* above + */ +int notifier_register(void *receiver_data, void *caller_id_filter, enum notify_id event_type, + void (*callback)(void *receiver_data, enum notify_id event_type, + void *caller_data), uint32_t flags); -void notifier_unregister(void *receiver, void *caller, enum notify_id type); -void notifier_unregister_all(void *receiver, void *caller); + +/** Unregister all callbacks matching that arguments tuple. NULL acts + * as a wildcard. + */ +void notifier_unregister(void *receiver_data_filter, void *caller_id_filter, enum notify_id type); + +/** Unregister callbacks matching the arguments for every notify_id. + * A NULL parameter acts as a wildcard. + */ +void notifier_unregister_all(void *receiver_data_filter, void *caller_id_filter); void notifier_notify_remote(void); -void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask, - void *data, uint32_t data_size); + +/* data_size is required to manage cache coherency for notifications + * across cores. + */ +void notifier_event(const void *caller_id, enum notify_id event_type, uint32_t core_mask, + void *caller_data, uint32_t data_size); void init_system_notify(struct sof *sof); From ba6e2084392592411b10354135b5192c1001b291 Mon Sep 17 00:00:00 2001 From: Marc Herbert Date: Tue, 29 Jun 2021 09:01:16 +0000 Subject: [PATCH 2/2] zephyr: add notifier_register(ipc_send_queued_msg) in task_main_start() Fixes #4356 In XTOS SOF, ipc_send_queued_msg() is run by task_main_primary_core(), the initialization of which has a hard and circular dependency with the initialization of the EDF scheduler. This EDF scheduler is not part of Zephyr. Because of the circular dependency it does not seem possible (nor desirable?) to refactor this code and make it compatible with Zephyr. So schedule ipc_send_queued_msg() differently in Zephyr: using a notifier triggered by the periodic Low Latency scheduler. Signed-off-by: Marc Herbert --- zephyr/wrapper.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index f978f5d59b19..9ab76b66f1b0 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -406,6 +406,15 @@ unsigned int _xtos_ints_off(unsigned int mask) return 0; } +void ipc_send_queued_msg(void); + +static void ipc_send_queued_callback(void *private_data, enum notify_id event_type, + void *caller_data) +{ + if (!ipc_get()->pm_prepare_D3) + ipc_send_queued_msg(); +} + /* * Audio components. * @@ -528,6 +537,10 @@ int task_main_start(struct sof *sof) /* init pipeline position offsets */ pipeline_posn_init(sof); + (void)notifier_register(NULL, scheduler_get_data(SOF_SCHEDULE_LL_TIMER), + NOTIFIER_ID_LL_POST_RUN, + ipc_send_queued_callback, 0); + /* let host know DSP boot is complete */ ret = platform_boot_complete(0);