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 */
xf_proxy_cmd_exec(xf_proxy_t * proxy,xf_user_msg_t * msg)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 */
xf_client_alloc(xf_proxy_t * proxy,xf_handle_t * handle)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 */
xf_client_free(xf_proxy_t * proxy,xf_handle_t * handle)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 */
xf_client_lookup(xf_proxy_t * proxy,u32 client)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 */
xf_client_register(xf_proxy_t * proxy,xf_handle_t * handle,xf_id_t id,u32 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 */
xf_client_unregister(xf_proxy_t * proxy,xf_handle_t * handle)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 */
xf_proxy_buffer_alloc(xf_proxy_t * proxy,u32 length,void ** 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 */
xf_proxy_buffer_free(xf_proxy_t * proxy,void * buffer,u32 length)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 
xf_proxy_thread(void * arg)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 */
xf_proxy_init(xf_proxy_t * proxy,u32 core,void * p_shmem)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 */
xf_proxy_close(xf_proxy_t * proxy)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 */
xf_open(xf_proxy_t * proxy,xf_handle_t * handle,xf_id_t id,u32 core,xf_response_cb response)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 */
xf_close(xf_handle_t * 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 */
xf_route(xf_handle_t * src,u32 src_port,xf_handle_t * dst,u32 dst_port,u32 num,u32 size,u32 align)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 */
xf_unroute(xf_handle_t * src,u32 src_port)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 */
xf_command(xf_handle_t * handle,u32 port,u32 opcode,void * buffer,u32 length)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 */
xf_pool_alloc(xf_proxy_t * proxy,u32 number,u32 length,xf_pool_type_t type,xf_pool_t ** pool,s32 id,xaf_mem_malloc_fxn_t xaf_malloc,xaf_mem_free_fxn_t xaf_free)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 */
xf_pool_free(xf_pool_t * pool,s32 id,xaf_mem_free_fxn_t xaf_free)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 */
xf_buffer_get(xf_pool_t * 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 */
xf_buffer_put(xf_buffer_t * buffer)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