1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2019 Intel Corporation. All rights reserved.
4 //
5 // Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com>
6 
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <sof/lib/alloc.h>
10 #include <sof/lib/notifier.h>
11 #include <sof/list.h>
12 #include <sof/common.h>
13 
14 struct callback_handle {
15 	void *receiver;
16 	const void *caller;
17 	void (*cb)(void *arg, enum notify_id, void *data);
18 	struct list_item list;
19 };
20 
21 static struct notify *_notify;
22 
arch_notify_get(void)23 struct notify **arch_notify_get(void)
24 {
25 	int i;
26 
27 	if (!_notify) {
28 		_notify = malloc(sizeof(*_notify));
29 
30 		for (i = 0; i < NOTIFIER_ID_COUNT; i++)
31 			list_init(&_notify->list[i]);
32 	}
33 
34 	return &_notify;
35 }
36 
notifier_event(const void * caller,enum notify_id type,uint32_t core_mask,void * data,uint32_t data_size)37 void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask,
38 		    void *data, uint32_t data_size)
39 {
40 	struct notify *notify = *arch_notify_get();
41 	struct list_item *wlist;
42 	struct list_item *tlist;
43 	struct callback_handle *handle;
44 
45 	list_for_item_safe(wlist, tlist, &notify->list[type]) {
46 		handle = container_of(wlist, struct callback_handle, list);
47 		if (!caller || !handle->caller || handle->caller == caller)
48 			handle->cb(handle->receiver, type, data);
49 	}
50 }
51 
notifier_register(void * receiver,void * caller,enum notify_id type,void (* cb)(void * arg,enum notify_id type,void * data),uint32_t flags)52 int notifier_register(void *receiver, void *caller, enum notify_id type,
53 	void (*cb)(void *arg, enum notify_id type, void *data), uint32_t flags)
54 {
55 	struct notify *notify = *arch_notify_get();
56 	struct callback_handle *handle;
57 
58 	if (type >= NOTIFIER_ID_COUNT)
59 		return -EINVAL;
60 
61 	handle = rzalloc(0, 0, 0, sizeof(struct callback_handle));
62 
63 	if (!handle)
64 		return -ENOMEM;
65 
66 	list_init(&handle->list);
67 	handle->receiver = receiver;
68 	handle->caller = caller;
69 	handle->cb = cb;
70 
71 	list_item_append(&handle->list, &notify->list[type]);
72 
73 	return 0;
74 }
75 
notifier_unregister(void * receiver,void * caller,enum notify_id type)76 void notifier_unregister(void *receiver, void *caller, enum notify_id type)
77 {
78 	struct notify *notify = *arch_notify_get();
79 	struct list_item *wlist;
80 	struct list_item *tlist;
81 	struct callback_handle *handle;
82 
83 	if (type >= NOTIFIER_ID_COUNT)
84 		return;
85 
86 	list_for_item_safe(wlist, tlist, &notify->list[type]) {
87 		handle = container_of(wlist, struct callback_handle, list);
88 		if ((!receiver || handle->receiver == receiver) &&
89 		    (!caller || handle->caller == caller)) {
90 			list_item_del(&handle->list);
91 			free(handle);
92 		}
93 	}
94 }
95 
notifier_unregister_all(void * receiver,void * caller)96 void notifier_unregister_all(void *receiver, void *caller)
97 {
98 	int i;
99 
100 	for (i = 0; i < NOTIFIER_ID_COUNT; i++)
101 		notifier_unregister(receiver, caller, i);
102 }
103