Niranjan Yadla | 19336af | 2018-04-19 12:19:27 -0700 | [diff] [blame] | 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 | } |