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