summaryrefslogtreecommitdiff
path: root/hifi/xaf/hifi-dpf/include/xf-msg.h
blob: 3448425b42811abbc5bea61706f7fb8ef4a396d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*******************************************************************************
* Copyright (C) 2018 Cadence Design Systems, Inc.
* 
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to use this Software with Cadence processor cores only and 
* not with any other processors and platforms, subject to
* the following conditions:
* 
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

******************************************************************************/

/*******************************************************************************
 * xf-msg.h
 *
 * Internal messages, and message queues.
 *
 *******************************************************************************/

#ifndef __XF_H
#error "xf-msg.h mustn't be included directly"
#endif

/*******************************************************************************
 * Types definitions
 ******************************************************************************/

/* ...forward declaration */
typedef struct xf_message   xf_message_t;

/* ...audio command/response message (internal to DSP processing framework) */
struct xf_message
{
    /* ...pointer to next item in the list */
    xf_message_t       *next;

    /* ...shmem session_id */
    u32                 id;

    /* ...operation code */
    u32                 opcode;

    /* ...length of attached message buffer */
    u32                 length;

    /* ...message buffer (translated virtual address) */
    void               *buffer;
#ifndef XAF_ENABLE_NON_HIKEY
    uint64_t           v_buffer;
#endif
};

/* ...cache-line aligned message buffer */
XF_ALIGNED_TYPEDEF(xf_message_t, __xf_message_t);

/* ...message pool definition */
typedef struct xf_msg_pool
{
    /* ...array of aligned messages */
    __xf_message_t     *p;

    /* ...pointer to first free item in the pool */
    __xf_message_t     *head;

    /* ...total size of the pool */
    u32                 n;

}   xf_msg_pool_t;

/* ...message accessor */
static inline xf_message_t * xf_msg_pool_item(xf_msg_pool_t *pool, u32 i)
{
    return (xf_message_t *) &pool->p[i];
}

/*******************************************************************************
 * Message queue data
 ******************************************************************************/

/* ...message queue (single-linked FIFO list) */
typedef struct  xf_msg_queue
{
    /* ...head of the queue */
    xf_message_t       *head;

    /* ...tail pointer */
    xf_message_t       *tail;

}   xf_msg_queue_t;

/*******************************************************************************
 * Message queue API
 ******************************************************************************/

/* ...initialize message queue */
static inline void  xf_msg_queue_init(xf_msg_queue_t *queue)
{
    queue->head = queue->tail = NULL;
}

/* ...push message in FIFO queue */
static inline int xf_msg_enqueue(xf_msg_queue_t *queue, xf_message_t *m)
{
    int     empty = (queue->head == NULL);

    /* ...set list terminating pointer */
    m->next = NULL;

    if (empty)
        queue->head = m;
    else
        queue->tail->next = m;

    /* ...advance tail pointer */
    queue->tail = m;

    /* ...return emptiness status */
    return empty;
}

#define xf_msg_enqueue(queue, m)                                        \
({                                                                      \
    BUG((m)->next != NULL, _x("message is active: %p"), (m));           \
    (xf_msg_enqueue)((queue), (m));                                     \
})

/* ...retrieve (pop) next message from FIFO queue */
static inline xf_message_t * xf_msg_dequeue(xf_msg_queue_t *queue)
{
    xf_message_t   *m = queue->head;

    /* ...check if there is anything in the queue and dequeue it */
    if (m != NULL)
    {
        /* ...advance head to the next entry in the queue */
        if ((queue->head = m->next) == NULL)
            queue->tail = NULL;

        /* ...debug - wipe out next pointer */
        m->next = NULL;
    }

    return m;
}

/* ...test if message queue is empty */
static inline int xf_msg_queue_empty(xf_msg_queue_t *queue)
{
    return (queue->head == NULL);
}

/* ...get message queue head pointer */
static inline xf_message_t * xf_msg_queue_head(xf_msg_queue_t *queue)
{
    return queue->head;
}

/* ...check if message belongs to a pool */
static inline int xf_msg_from_pool(xf_msg_pool_t *pool, xf_message_t *m)
{
    return (u32)((__xf_message_t*)m - pool->p) < pool->n;   
}

/*******************************************************************************
 * Global message pool API
 ******************************************************************************/

/* ...submit message execution on local DSP core */
extern void xf_msg_schedule(xf_message_t *m, u32 ts);

/* ...schedule message execution from ISR context */
extern void xf_msg_schedule_isr(xf_message_t *m);

/* ...submit message for execution on some DSP */
extern void xf_msg_submit(xf_message_t *m);

/* ...cancel local (scheduled on current core) message execution */
extern void xf_msg_cancel(xf_message_t *m);

/* ...complete message processing */
extern void xf_msg_complete(xf_message_t *m);

/* ...complete message from ISR context */
extern void xf_msg_complete_isr(xf_message_t *m);

/* ...allocate message pool on specific core */
extern int  xf_msg_pool_init(xf_msg_pool_t *pool, u32 n, u32 core);

/* ...allocate message from a pool (no concurrent access from other cores) */
extern xf_message_t * xf_msg_pool_get(xf_msg_pool_t *pool);

/* ...return message back to the pool (no concurrent access from other cores) */
extern void xf_msg_pool_put(xf_msg_pool_t *pool, xf_message_t *m);

/* ...destroy message pool */
extern void xf_msg_pool_destroy(xf_msg_pool_t *pool, u32 core);

/* ...indicate whether pool of free messages is empty */
extern int  xf_message_pool_empty(void);

/* ...initialize global pool of messages */
extern void xf_message_pool_init(void);

/*******************************************************************************
 * Auxiliary helpers
 ******************************************************************************/

/* ...send response message to caller */
static inline void xf_response(xf_message_t *m)
{
    xf_msg_complete(m);
}

/* ...send response message with output buffer */
static inline void xf_response_data(xf_message_t *m, u32 length)
{
    /* ...adjust message output buffer */
    m->length = length;

    /* ...return message to originator */
    xf_msg_complete(m);
}

/* ...send generic "ok" message (no data buffer) */
static inline void xf_response_ok(xf_message_t *m)
{
    /* ...adjust message output buffer */
    m->length = 0;

    /* ...return message to originator */
    xf_msg_complete(m);
}

/* ...send error-response message */
static inline void xf_response_err(xf_message_t *m)
{
    /* ...set generic error message */
    m->opcode = XF_UNREGISTER, m->length = 0;

    /* ...return message to originator */
    xf_msg_complete(m);
}