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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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) */ 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 */ 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