Home | History | Annotate | Download | only in proxy
      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 #define MODULE_TAG                      PROXY
     24 
     25 /*******************************************************************************
     26  * Includes
     27  ******************************************************************************/
     28 
     29 #include "xf.h"
     30 
     31 /*******************************************************************************
     32  * Tracing configuration
     33  ******************************************************************************/
     34 
     35 TRACE_TAG(INIT, 1);
     36 TRACE_TAG(CMD, 1);
     37 TRACE_TAG(EXEC, 1);
     38 TRACE_TAG(RSP, 1);
     39 TRACE_TAG(REG, 1);
     40 TRACE_TAG(MEM, 1);
     41 TRACE_TAG(GRAPH, 1);
     42 TRACE_TAG(BUFFER, 1);
     43 
     44 /*******************************************************************************
     45  * Internal functions definitions
     46  ******************************************************************************/
     47 
     48 /* ...execute proxy command synchronously */
     49 static inline int xf_proxy_cmd_exec(xf_proxy_t *proxy, xf_user_msg_t *msg)
     50 {
     51     xf_proxy_msg_t  m;
     52 
     53     /* ...send command to remote proxy */
     54     m.id = msg->id, m.opcode = msg->opcode, m.length = msg->length;
     55 
     56     /* ...translate address */
     57     XF_CHK_ERR((m.address = xf_proxy_b2a(proxy, msg->buffer)) != XF_PROXY_BADADDR, -EINVAL);
     58 
     59     /* ...pass command to remote proxy */
     60     XF_CHK_API(xf_ipc_send(&proxy->ipc, &m, msg->buffer));
     61 
     62     /* ...wait for response reception indication from proxy thread */
     63     XF_CHK_API(xf_proxy_response_get(proxy, &m));
     64 
     65     /* ...copy parameters */
     66     msg->id = m.id, msg->opcode = m.opcode, msg->length = m.length;
     67 
     68     /* ...translate address back to virtual space */
     69     XF_CHK_ERR((msg->buffer = xf_proxy_a2b(proxy, m.address)) != (void *)-1, -EBADFD);
     70 
     71     TRACE(EXEC, _b("proxy[%p]: command done: [%08x:%p:%u]"), proxy, msg->opcode, msg->buffer, msg->length);
     72 
     73     return 0;
     74 }
     75 
     76 #if 0
     77 /* ...pass command to remote DSP */
     78 static inline int xf_proxy_cmd(xf_proxy_t *proxy, xf_handle_t *handle, xf_user_msg_t *m)
     79 {
     80     xf_proxy_msg_t  msg;
     81 
     82     /* ...set session-id of the message */
     83     msg.id = __XF_MSG_ID(__XF_AP_CLIENT(proxy->core, handle->client), m->id);
     84     msg.opcode = m->opcode;
     85     msg.length = m->length;
     86 
     87     /* ...translate buffer pointer to shared address */
     88     XF_CHK_ERR((msg.address = xf_proxy_b2a(proxy, m->buffer)) != XF_PROXY_BADADDR, -EINVAL);
     89 
     90     /* ...submit command message to IPC layer */
     91     return XF_CHK_API(xf_ipc_send(&proxy->ipc, &msg, m->buffer));
     92 }
     93 #endif /* 0 */
     94 
     95 /* ...allocate local client-id number */
     96 static inline u32 xf_client_alloc(xf_proxy_t *proxy, xf_handle_t *handle)
     97 {
     98     u32     client;
     99 
    100     if ((client = proxy->cmap[0].next) != 0)
    101     {
    102         /* ...pop client from free clients list */
    103         proxy->cmap[0].next = proxy->cmap[client].next;
    104 
    105         /* ...put client handle into association map */
    106         handle->client = client, proxy->cmap[client].handle = handle;
    107     }
    108 
    109     return client;
    110 }
    111 
    112 /* ...recycle local client-id number */
    113 static inline void xf_client_free(xf_proxy_t *proxy, xf_handle_t *handle)
    114 {
    115     u32     client = handle->client;
    116 
    117     /* ...push client into head of the free clients list */
    118     proxy->cmap[client].next = proxy->cmap[0].next;
    119 
    120     /* ...adjust head of free clients */
    121     proxy->cmap[0].next = client;
    122 }
    123 
    124 /* ...lookup client basing on its local id */
    125 static inline xf_handle_t * xf_client_lookup(xf_proxy_t *proxy, u32 client)
    126 {
    127     /* ...client index must be in proper range */
    128     BUG(client >= XF_CFG_PROXY_MAX_CLIENTS, _x("Invalid client index: %u"), client);
    129 
    130     /* ...check if client index is small */
    131     if (proxy->cmap[client].next < XF_CFG_PROXY_MAX_CLIENTS)
    132         return NULL;
    133     else
    134         return proxy->cmap[client].handle;
    135 }
    136 
    137 /* ...create new client on remote core */
    138 static inline int xf_client_register(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core)
    139 {
    140     void           *b = xf_handle_aux(handle);
    141     xf_user_msg_t   msg;
    142 
    143     /* ...set session-id: source is local proxy, destination is remote proxy */
    144     msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_DSP_PROXY(core));
    145     msg.opcode = XF_REGISTER;
    146     msg.buffer = b;
    147     msg.length = strlen(id) + 1;
    148 
    149     /* ...copy component identifier */
    150     strncpy(b, id, xf_buffer_length(handle->aux));
    151 
    152     /* ...execute command synchronously */
    153     XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
    154 
    155     /* ...check operation is successfull */
    156     XF_CHK_ERR(msg.opcode == (u32) XF_REGISTER, -EFAULT);
    157 
    158     /* ...save received component global client-id */
    159     handle->id = XF_MSG_SRC(msg.id);
    160 
    161     TRACE(REG, _b("[%p]=[%s:%u:%u]"), handle, id, XF_PORT_CORE(handle->id), XF_PORT_CLIENT(handle->id));
    162 
    163     return 0;
    164 }
    165 
    166 /* ...unregister client from remote proxy */
    167 static inline int xf_client_unregister(xf_proxy_t *proxy, xf_handle_t *handle)
    168 {
    169     xf_user_msg_t   msg;
    170 
    171     /* ...make sure the client is consistent */
    172     BUG(proxy->cmap[handle->client].handle != handle, _x("Invalid handle: %p"), handle);
    173 
    174     /* ...set message parameters */
    175     msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), handle->id);
    176     msg.opcode = XF_UNREGISTER;
    177     msg.buffer = NULL;
    178     msg.length = 0;
    179 
    180     /* ...synchronously execute command on remote proxy */
    181     XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
    182 
    183     /* ...opcode must be XF_UNREGISTER - tbd */
    184     BUG(msg.opcode != XF_UNREGISTER, _x("Invalid opcode: %X"), msg.opcode);
    185 
    186     TRACE(REG, _b("%p[%u:%u] unregistered"), handle, XF_PORT_CORE(handle->id), XF_PORT_CLIENT(handle->id));
    187 
    188     return 0;
    189 }
    190 
    191 /* ...allocate shared buffer */
    192 static inline int xf_proxy_buffer_alloc(xf_proxy_t *proxy, u32 length, void **buffer)
    193 {
    194     u32             core = proxy->core;
    195     xf_user_msg_t   msg;
    196 
    197     /* ...prepare command parameters */
    198     msg.id = __XF_MSG_ID(__XF_AP_PROXY(core), __XF_DSP_PROXY(core));
    199     msg.opcode = XF_ALLOC;
    200     msg.length = length;
    201     msg.buffer = NULL;
    202 
    203     /* ...synchronously execute command on remote proxy */
    204     XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
    205 
    206     /* ...check if response is valid */
    207     XF_CHK_ERR(msg.opcode == XF_ALLOC, -EBADFD);
    208 
    209     /* ...check if allocation is successful */
    210     XF_CHK_ERR(msg.buffer != NULL, -ENOMEM);
    211 
    212     /* ...save output parameter */
    213     *buffer = msg.buffer;
    214 
    215     TRACE(MEM, _b("proxy-%u: allocated [%p:%u]"), core, *buffer, length);
    216 
    217     return 0;
    218 }
    219 
    220 /* ...free shared AP-DSP memory */
    221 static inline int xf_proxy_buffer_free(xf_proxy_t *proxy, void *buffer, u32 length)
    222 {
    223     u32             core = proxy->core;
    224     xf_user_msg_t   msg;
    225 
    226     /* ...prepare command parameters */
    227     msg.id = __XF_MSG_ID(__XF_AP_PROXY(core), __XF_DSP_PROXY(core));
    228     msg.opcode = XF_FREE;
    229     msg.length = length;
    230     msg.buffer = buffer;
    231 
    232     /* ...synchronously execute command on remote proxy */
    233     XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
    234 
    235     /* ...check if response is valid */
    236     XF_CHK_ERR(msg.opcode == XF_FREE, -EBADFD);
    237 
    238     TRACE(MEM, _b("proxy-%u: free [%p:%u]"), core, buffer, length);
    239 
    240     return 0;
    241 }
    242 
    243 /*******************************************************************************
    244  * Proxy interface asynchronous receiving thread
    245  ******************************************************************************/
    246 
    247 static void * xf_proxy_thread(void *arg)
    248 {
    249     xf_proxy_t     *proxy = arg;
    250     xf_handle_t    *client;
    251     int             r;
    252 
    253     /* ...start polling thread */
    254     while (1)
    255     {
    256         xf_proxy_msg_t  m;
    257         xf_user_msg_t   msg;
    258 
    259         /* ...wait for response from remote proxy (infinite timeout) */
    260         if ((r = xf_ipc_wait(&proxy->ipc, 0)) < 0)
    261             break;
    262 
    263         /* ...retrieve all responses received */
    264         while ((r = xf_ipc_recv(&proxy->ipc, &m, &msg.buffer)) == sizeof(m))
    265         {
    266             /* ...make sure we have proper core identifier of SHMEM interface */
    267             BUG(XF_MSG_DST_CORE(m.id) != proxy->core, _x("Invalid session-id: %X (core=%u)"), m.id, proxy->core);
    268 
    269             /* ...make sure translation is successful */
    270             BUG(msg.buffer == (void *)-1, _x("Invalid buffer address: %08x"), m.address);
    271 
    272             /* ...retrieve information fields */
    273             msg.id = XF_MSG_SRC(m.id), msg.opcode = m.opcode, msg.length = m.length;
    274 
    275             TRACE(RSP, _b("R[%08x]:(%08x,%u,%08x)"), m.id, m.opcode, m.length, m.address);
    276 
    277             /* ...lookup component basing on destination port specification */
    278             if (XF_AP_CLIENT(m.id) == 0)
    279             {
    280                 /* ...put proxy response to local IPC queue */
    281                 xf_proxy_response_put(proxy, &m);
    282             }
    283             else if ((client = xf_client_lookup(proxy, XF_AP_CLIENT(m.id))) != NULL)
    284             {
    285                 /* ...client is found; invoke its response callback (must be non-blocking) */
    286                 client->response(client, &msg);
    287             }
    288             else
    289             {
    290                 /* ...client has been disconnected already; drop message */
    291                 TRACE(RSP, _b("Client look-up failed - drop message"));
    292             }
    293         }
    294 
    295         /* ...if result code is negative; terminate thread operation */
    296         if (r < 0)
    297         {
    298             TRACE(ERROR, _x("abnormal proxy[%p] thread termination: %d"), proxy, r);
    299             break;
    300         }
    301     }
    302 
    303     TRACE(INIT, _b("IPC proxy[%p] thread terminated: %d"), proxy, r);
    304 
    305     return (void *)(intptr_t)r;
    306 }
    307 
    308 /*******************************************************************************
    309  * HiFi proxy API
    310  ******************************************************************************/
    311 
    312 /* ...open HiFi proxy */
    313 int xf_proxy_init(xf_proxy_t *proxy, u32 core, void *p_shmem)
    314 {
    315     u32             i;
    316     int             r;
    317 
    318     /* ...initialize proxy lock */
    319     __xf_lock_init(&proxy->lock);
    320 
    321     /* ...open proxy IPC interface */
    322     XF_CHK_API(xf_ipc_open(&proxy->ipc, core, p_shmem));
    323 
    324     /* ...save proxy core - hmm, too much core identifiers - tbd */
    325     proxy->core = core;
    326 
    327     /* ...line-up all clients into single-linked list */
    328     for (i = 0; i < XF_CFG_PROXY_MAX_CLIENTS - 1; i++)
    329     {
    330         proxy->cmap[i].next = i + 1;
    331     }
    332 
    333     /* ...tail of the list points back to head (list terminator) */
    334     proxy->cmap[i].next = 0;
    335 
    336     /* ...initialize thread attributes (joinable, with minimal stack) */
    337     if ((r = __xf_thread_create(&proxy->thread, xf_proxy_thread, proxy)) < 0)
    338     {
    339         TRACE(ERROR, _x("Failed to create polling thread: %d"), r);
    340         xf_ipc_close(&proxy->ipc, core);
    341         return r;
    342     }
    343 
    344     TRACE(INIT, _b("proxy-%u[%p] opened"), core, proxy);
    345 
    346     return 0;
    347 }
    348 
    349 /* ...close proxy handle */
    350 void xf_proxy_close(xf_proxy_t *proxy)
    351 {
    352     u32     core = proxy->core;
    353 
    354     /* ...terminate proxy thread */
    355     __xf_thread_destroy(&proxy->thread);
    356 
    357     /* ...close proxy IPC interface */
    358     xf_ipc_close(&proxy->ipc, core);
    359 
    360     TRACE(INIT, _b("proxy-%u[%p] closed"), core, proxy);
    361 }
    362 
    363 /*******************************************************************************
    364  * HiFi component API
    365  ******************************************************************************/
    366 
    367 /* ...open component handle */
    368 int xf_open(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core, xf_response_cb response)
    369 {
    370     int     r;
    371 
    372     /* ...retrieve auxiliary control buffer from proxy - need I */
    373     XF_CHK_ERR(handle->aux = xf_buffer_get(proxy->aux), -EBUSY);
    374 
    375     /* ...initialize IPC data */
    376     XF_CHK_API(xf_ipc_data_init(&handle->ipc));
    377 
    378     /* ...register client in interlocked fashion */
    379     xf_proxy_lock(proxy);
    380 
    381     /* ...allocate local client */
    382     if (xf_client_alloc(proxy, handle) == 0)
    383     {
    384         TRACE(ERROR, _x("client allocation failed"));
    385         r = -EBUSY;
    386     }
    387     else if ((r = xf_client_register(proxy, handle, id, core)) < 0)
    388     {
    389         TRACE(ERROR, _x("client registering failed"));
    390         xf_client_free(proxy, handle);
    391     }
    392 
    393     xf_proxy_unlock(proxy);
    394 
    395     /* ...if failed, release buffer handle */
    396     if (r < 0)
    397     {
    398         /* ...operation failed; return buffer back to proxy pool */
    399         xf_buffer_put(handle->aux), handle->aux = NULL;
    400     }
    401     else
    402     {
    403         /* ...operation completed successfully; assign handle data */
    404         handle->response = response;
    405         handle->proxy = proxy;
    406 
    407         TRACE(INIT, _b("component[%p]:(id=%s,core=%u) created"), handle, id, core);
    408     }
    409 
    410     return XF_CHK_API(r);
    411 }
    412 
    413 /* ...close component handle */
    414 void xf_close(xf_handle_t *handle)
    415 {
    416     xf_proxy_t *proxy = handle->proxy;
    417 
    418     /* ...do I need to take component lock here? guess no - tbd */
    419 
    420     /* ...buffers and stuff? - tbd */
    421 
    422     /* ...acquire global proxy lock */
    423     xf_proxy_lock(proxy);
    424 
    425     /* ...unregister component from remote DSP proxy (ignore result code) */
    426     (void) xf_client_unregister(proxy, handle);
    427 
    428     /* ...recycle client-id afterwards */
    429     xf_client_free(proxy, handle);
    430 
    431     /* ...release global proxy lock */
    432     xf_proxy_unlock(proxy);
    433 
    434     /* ...destroy IPC data */
    435     xf_ipc_data_destroy(&handle->ipc);
    436 
    437     /* ...clear handle data */
    438     xf_buffer_put(handle->aux), handle->aux = NULL;
    439 
    440     /* ...wipe out proxy pointer */
    441     handle->proxy = NULL;
    442 
    443     TRACE(INIT, _b("component[%p] destroyed"), handle);
    444 }
    445 
    446 /* ...port binding function */
    447 int xf_route(xf_handle_t *src, u32 src_port, xf_handle_t *dst, u32 dst_port, u32 num, u32 size, u32 align)
    448 {
    449     xf_proxy_t             *proxy = src->proxy;
    450     xf_buffer_t            *b;
    451     xf_route_port_msg_t    *m;
    452     xf_user_msg_t           msg;
    453 
    454     /* ...sanity checks - proxy pointers are same */
    455     XF_CHK_ERR(proxy == dst->proxy, -EINVAL);
    456 
    457     /* ...buffer data is sane */
    458     XF_CHK_ERR(num && size && xf_is_power_of_two(align), -EINVAL);
    459 
    460     /* ...get control buffer */
    461     XF_CHK_ERR(b = xf_buffer_get(proxy->aux), -EBUSY);
    462 
    463     /* ...get message buffer */
    464     m = xf_buffer_data(b);
    465 
    466     /* ...fill-in message parameters */
    467     //m->src = __XF_PORT_SPEC2(src->id, src_port);
    468     m->dst = __XF_PORT_SPEC2(dst->id, dst_port);
    469     m->alloc_number = num;
    470     m->alloc_size = size;
    471     m->alloc_align = align;
    472 
    473     /* ...set command parameters */
    474     msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_PORT_SPEC2(src->id, src_port));
    475     msg.opcode = XF_ROUTE;
    476     msg.length = sizeof(*m);
    477     msg.buffer = m;
    478 
    479     /* ...synchronously execute command on remote DSP */
    480     XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
    481 
    482     /* ...return buffer to proxy */
    483     xf_buffer_put(b);
    484 
    485     /* ...check result is successfull */
    486     XF_CHK_ERR(msg.opcode == (u32) XF_ROUTE, -ENOMEM);
    487 
    488     /* ...port binding completed */
    489     TRACE(GRAPH, _b("[%p]:%u bound to [%p]:%u"), src, src_port, dst, dst_port);
    490 
    491     return 0;
    492 }
    493 
    494 /* ...port unbinding function */
    495 int xf_unroute(xf_handle_t *src, u32 src_port)
    496 {
    497     xf_proxy_t             *proxy = src->proxy;
    498     xf_buffer_t            *b;
    499     xf_unroute_port_msg_t  *m;
    500     xf_user_msg_t           msg;
    501     int                     r;
    502 
    503     /* ...get control buffer */
    504     XF_CHK_ERR(b = xf_buffer_get(proxy->aux), -EBUSY);
    505 
    506     /* ...get message buffer */
    507     m = xf_buffer_data(b);
    508 
    509     /* ...fill-in message parameters */
    510     //m->src = __XF_PORT_SPEC2(src->id, src_port);
    511 
    512     /* ...set command parameters */
    513     msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_PORT_SPEC2(src->id, src_port));
    514     msg.opcode = XF_UNROUTE;
    515     msg.length = sizeof(*m);
    516     msg.buffer = m;
    517 
    518     /* ...synchronously execute command on remote DSP */
    519     if ((r = xf_proxy_cmd_exec(proxy, &msg)) != 0)
    520     {
    521         TRACE(ERROR, _x("Command failed: %d"), r);
    522         goto out;
    523     }
    524     else if (msg.opcode != (u32) XF_UNROUTE)
    525     {
    526         TRACE(ERROR, _x("Port unbinding failed"));
    527         r = -EBADFD;
    528         goto out;
    529     }
    530 
    531     /* ...port binding completed */
    532     TRACE(GRAPH, _b("[%p]:%u unbound"), src, src_port);
    533 
    534 out:
    535     /* ...return buffer to proxy */
    536     xf_buffer_put(b);
    537 
    538     return r;
    539 }
    540 
    541 /* ...send a command message to component */
    542 int xf_command(xf_handle_t *handle, u32 port, u32 opcode, void *buffer, u32 length)
    543 {
    544     xf_proxy_t     *proxy = handle->proxy;
    545     xf_proxy_msg_t  msg;
    546 
    547     /* ...fill-in message parameters */
    548     msg.id = __XF_MSG_ID(__XF_AP_CLIENT(proxy->core, handle->client), __XF_PORT_SPEC2(handle->id, port));
    549     msg.opcode = opcode;
    550     msg.length = length;
    551     XF_CHK_ERR((msg.address = xf_proxy_b2a(proxy, buffer)) != XF_PROXY_BADADDR, -EINVAL);
    552 
    553     TRACE(CMD, _b("[%p]:[%08x]:(%08x,%u,%p)"), handle, msg.id, opcode, length, buffer);
    554 
    555     /* ...pass command to IPC layer */
    556     return XF_CHK_API(xf_ipc_send(&proxy->ipc, &msg, buffer));
    557 }
    558 
    559 /*******************************************************************************
    560  * Buffer pool API
    561  ******************************************************************************/
    562 
    563 /* ...allocate buffer pool */
    564 int xf_pool_alloc(xf_proxy_t *proxy, u32 number, u32 length, xf_pool_type_t type, xf_pool_t **pool, s32 id,
    565                   xaf_mem_malloc_fxn_t xaf_malloc, xaf_mem_free_fxn_t xaf_free)
    566 {
    567     xf_pool_t      *p;
    568     xf_buffer_t    *b;
    569     void           *data;
    570     int             r;
    571 
    572     /* ...unused arg */
    573     (void) type;
    574 
    575     /* ...basic sanity checks; number of buffers is positive */
    576     XF_CHK_ERR(number > 0, -EINVAL);
    577 
    578     /* ...get properly aligned buffer length */
    579     length = (length + XF_PROXY_ALIGNMENT - 1) & ~(XF_PROXY_ALIGNMENT - 1);
    580 
    581     /* ...allocate data structure */
    582     p = xaf_malloc(offset_of(xf_pool_t, buffer) + number * sizeof(xf_buffer_t), id);
    583     XF_CHK_ERR(p, -ENOMEM);
    584 
    585     /* ...issue memory pool allocation request to remote DSP */
    586     xf_proxy_lock(proxy);
    587     r = xf_proxy_buffer_alloc(proxy, number * length, &p->p);
    588     xf_proxy_unlock(proxy);
    589 
    590     /* ...if operation is failed, do cleanup */
    591     if (r < 0)
    592     {
    593         TRACE(ERROR, _x("failed to allocate buffer: %d"), r);
    594         xaf_free(p, id);
    595         return r;
    596     }
    597     else
    598     {
    599         /* ...set pool parameters */
    600         p->number = number, p->length = length;
    601         p->proxy = proxy;
    602     }
    603 
    604     /* ...create individual buffers and link them into free list */
    605     for (p->free = b = &p->buffer[0], data = p->p; number > 0; number--, b++)
    606     {
    607         /* ...set address of the buffer (no length there) */
    608         b->address = data;
    609 
    610         /* ...file buffer into the free list */
    611         b->link.next = b + 1;
    612 
    613         /* ...advance data pointer in contiguous buffer */
    614         data = (unsigned char *) data + length;
    615     }
    616 
    617     /* ...terminate list of buffers (not too good - tbd) */
    618     b[-1].link.next = NULL;
    619 
    620     TRACE(BUFFER, _b("[%p]: pool[%p] created: %u * %u"), proxy, p, p->number, p->length);
    621 
    622     /* ...return buffer pointer */
    623     *pool = p;
    624 
    625     return 0;
    626 }
    627 
    628 /* ...buffer pool destruction */
    629 void xf_pool_free(xf_pool_t *pool, s32 id, xaf_mem_free_fxn_t xaf_free)
    630 {
    631     xf_proxy_t     *proxy = pool->proxy;
    632 
    633     /* ...check buffers are all freed - tbd */
    634 
    635     /* ...use global proxy lock for pool operations protection */
    636     xf_proxy_lock(proxy);
    637 
    638     /* ...release allocated buffer on remote DSP */
    639     xf_proxy_buffer_free(proxy, pool->p, pool->length * pool->number);
    640 
    641     /* ...release global proxy lock */
    642     xf_proxy_unlock(proxy);
    643 
    644     /* ...deallocate pool structure itself */
    645     xaf_free(pool, id);
    646 
    647     TRACE(BUFFER, _b("[%p]::pool[%p] destroyed"), proxy, pool);
    648 }
    649 
    650 /* ...get new buffer from a pool */
    651 xf_buffer_t * xf_buffer_get(xf_pool_t *pool)
    652 {
    653     xf_buffer_t    *b;
    654 
    655     /* ...use global proxy lock for pool operations protection */
    656     xf_proxy_lock(pool->proxy);
    657 
    658     /* ...take buffer from a head of the free list */
    659     if ((b = pool->free) != NULL)
    660     {
    661         /* ...advance free list head */
    662         pool->free = b->link.next, b->link.pool = pool;
    663 
    664         TRACE(BUFFER, _b("pool[%p]::get[%p]"), pool, b);
    665     }
    666 
    667     xf_proxy_unlock(pool->proxy);
    668 
    669     return b;
    670 }
    671 
    672 /* ...return buffer back to pool */
    673 void xf_buffer_put(xf_buffer_t *buffer)
    674 {
    675     xf_pool_t  *pool = buffer->link.pool;
    676 
    677     /* ...use global proxy lock for pool operations protection */
    678     xf_proxy_lock(pool->proxy);
    679 
    680     /* ...put buffer back to a pool */
    681     buffer->link.next = pool->free, pool->free = buffer;
    682 
    683     TRACE(BUFFER, _b("pool[%p]::put[%p]"), pool, buffer);
    684 
    685     xf_proxy_unlock(pool->proxy);
    686 }
    687