blob: 3448425b42811abbc5bea61706f7fb8ef4a396d4 [file] [log] [blame]
/*******************************************************************************
* 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);
}