1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 ******************************************************************************/
22
23 /*******************************************************************************
24 * xf-msg.h
25 *
26 * Internal messages, and message queues.
27 *
28 *******************************************************************************/
29
30 #ifndef __XF_H
31 #error "xf-msg.h mustn't be included directly"
32 #endif
33
34 /*******************************************************************************
35 * Types definitions
36 ******************************************************************************/
37
38 /* ...forward declaration */
39 typedef struct xf_message xf_message_t;
40
41 /* ...audio command/response message (internal to DSP processing framework) */
42 struct xf_message
43 {
44 /* ...pointer to next item in the list */
45 xf_message_t *next;
46
47 /* ...shmem session_id */
48 u32 id;
49
50 /* ...operation code */
51 u32 opcode;
52
53 /* ...length of attached message buffer */
54 u32 length;
55
56 /* ...message buffer (translated virtual address) */
57 void *buffer;
58 #ifndef XAF_ENABLE_NON_HIKEY
59 uint64_t v_buffer;
60 #endif
61 };
62
63 /* ...cache-line aligned message buffer */
64 XF_ALIGNED_TYPEDEF(xf_message_t, __xf_message_t);
65
66 /* ...message pool definition */
67 typedef struct xf_msg_pool
68 {
69 /* ...array of aligned messages */
70 __xf_message_t *p;
71
72 /* ...pointer to first free item in the pool */
73 __xf_message_t *head;
74
75 /* ...total size of the pool */
76 u32 n;
77
78 } xf_msg_pool_t;
79
80 /* ...message accessor */
xf_msg_pool_item(xf_msg_pool_t * pool,u32 i)81 static inline xf_message_t * xf_msg_pool_item(xf_msg_pool_t *pool, u32 i)
82 {
83 return (xf_message_t *) &pool->p[i];
84 }
85
86 /*******************************************************************************
87 * Message queue data
88 ******************************************************************************/
89
90 /* ...message queue (single-linked FIFO list) */
91 typedef struct xf_msg_queue
92 {
93 /* ...head of the queue */
94 xf_message_t *head;
95
96 /* ...tail pointer */
97 xf_message_t *tail;
98
99 } xf_msg_queue_t;
100
101 /*******************************************************************************
102 * Message queue API
103 ******************************************************************************/
104
105 /* ...initialize message queue */
xf_msg_queue_init(xf_msg_queue_t * queue)106 static inline void xf_msg_queue_init(xf_msg_queue_t *queue)
107 {
108 queue->head = queue->tail = NULL;
109 }
110
111 /* ...push message in FIFO queue */
xf_msg_enqueue(xf_msg_queue_t * queue,xf_message_t * m)112 static inline int xf_msg_enqueue(xf_msg_queue_t *queue, xf_message_t *m)
113 {
114 int empty = (queue->head == NULL);
115
116 /* ...set list terminating pointer */
117 m->next = NULL;
118
119 if (empty)
120 queue->head = m;
121 else
122 queue->tail->next = m;
123
124 /* ...advance tail pointer */
125 queue->tail = m;
126
127 /* ...return emptiness status */
128 return empty;
129 }
130
131 #define xf_msg_enqueue(queue, m) \
132 ({ \
133 BUG((m)->next != NULL, _x("message is active: %p"), (m)); \
134 (xf_msg_enqueue)((queue), (m)); \
135 })
136
137 /* ...retrieve (pop) next message from FIFO queue */
xf_msg_dequeue(xf_msg_queue_t * queue)138 static inline xf_message_t * xf_msg_dequeue(xf_msg_queue_t *queue)
139 {
140 xf_message_t *m = queue->head;
141
142 /* ...check if there is anything in the queue and dequeue it */
143 if (m != NULL)
144 {
145 /* ...advance head to the next entry in the queue */
146 if ((queue->head = m->next) == NULL)
147 queue->tail = NULL;
148
149 /* ...debug - wipe out next pointer */
150 m->next = NULL;
151 }
152
153 return m;
154 }
155
156 /* ...test if message queue is empty */
xf_msg_queue_empty(xf_msg_queue_t * queue)157 static inline int xf_msg_queue_empty(xf_msg_queue_t *queue)
158 {
159 return (queue->head == NULL);
160 }
161
162 /* ...get message queue head pointer */
xf_msg_queue_head(xf_msg_queue_t * queue)163 static inline xf_message_t * xf_msg_queue_head(xf_msg_queue_t *queue)
164 {
165 return queue->head;
166 }
167
168 /* ...check if message belongs to a pool */
xf_msg_from_pool(xf_msg_pool_t * pool,xf_message_t * m)169 static inline int xf_msg_from_pool(xf_msg_pool_t *pool, xf_message_t *m)
170 {
171 return (u32)((__xf_message_t*)m - pool->p) < pool->n;
172 }
173
174 /*******************************************************************************
175 * Global message pool API
176 ******************************************************************************/
177
178 /* ...submit message execution on local DSP core */
179 extern void xf_msg_schedule(xf_message_t *m, u32 ts);
180
181 /* ...schedule message execution from ISR context */
182 extern void xf_msg_schedule_isr(xf_message_t *m);
183
184 /* ...submit message for execution on some DSP */
185 extern void xf_msg_submit(xf_message_t *m);
186
187 /* ...cancel local (scheduled on current core) message execution */
188 extern void xf_msg_cancel(xf_message_t *m);
189
190 /* ...complete message processing */
191 extern void xf_msg_complete(xf_message_t *m);
192
193 /* ...complete message from ISR context */
194 extern void xf_msg_complete_isr(xf_message_t *m);
195
196 /* ...allocate message pool on specific core */
197 extern int xf_msg_pool_init(xf_msg_pool_t *pool, u32 n, u32 core);
198
199 /* ...allocate message from a pool (no concurrent access from other cores) */
200 extern xf_message_t * xf_msg_pool_get(xf_msg_pool_t *pool);
201
202 /* ...return message back to the pool (no concurrent access from other cores) */
203 extern void xf_msg_pool_put(xf_msg_pool_t *pool, xf_message_t *m);
204
205 /* ...destroy message pool */
206 extern void xf_msg_pool_destroy(xf_msg_pool_t *pool, u32 core);
207
208 /* ...indicate whether pool of free messages is empty */
209 extern int xf_message_pool_empty(void);
210
211 /* ...initialize global pool of messages */
212 extern void xf_message_pool_init(void);
213
214 /*******************************************************************************
215 * Auxiliary helpers
216 ******************************************************************************/
217
218 /* ...send response message to caller */
xf_response(xf_message_t * m)219 static inline void xf_response(xf_message_t *m)
220 {
221 xf_msg_complete(m);
222 }
223
224 /* ...send response message with output buffer */
xf_response_data(xf_message_t * m,u32 length)225 static inline void xf_response_data(xf_message_t *m, u32 length)
226 {
227 /* ...adjust message output buffer */
228 m->length = length;
229
230 /* ...return message to originator */
231 xf_msg_complete(m);
232 }
233
234 /* ...send generic "ok" message (no data buffer) */
xf_response_ok(xf_message_t * m)235 static inline void xf_response_ok(xf_message_t *m)
236 {
237 /* ...adjust message output buffer */
238 m->length = 0;
239
240 /* ...return message to originator */
241 xf_msg_complete(m);
242 }
243
244 /* ...send error-response message */
xf_response_err(xf_message_t * m)245 static inline void xf_response_err(xf_message_t *m)
246 {
247 /* ...set generic error message */
248 m->opcode = XF_UNREGISTER, m->length = 0;
249
250 /* ...return message to originator */
251 xf_msg_complete(m);
252 }
253