]> granicus.if.org Git - esp-idf/blob - components/bt/bluedroid/gki/gki_buffer.c
component/bt: A2DP code original in example project moved to component/bt directory;
[esp-idf] / components / bt / bluedroid / gki / gki_buffer.c
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18
19 #include "bt_trace.h"
20 #include "allocator.h"
21 #include "gki_int.h"
22
23 #define ALIGN_POOL(pl_size)  ( (((pl_size) + 3) / sizeof(UINT32)) * sizeof(UINT32))
24 #define BUFFER_HDR_SIZE     (sizeof(BUFFER_HDR_T))                  /* Offset past header */
25 #define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */
26 #define MAGIC_NO            0xDDBADDBA
27
28 #define BUF_STATUS_FREE     0
29 #define BUF_STATUS_UNLINKED 1
30 #define BUF_STATUS_QUEUED   2
31
32 /*******************************************************************************
33 **
34 ** Function         gki_init_free_queue
35 **
36 ** Description      Internal function called at startup to initialize a free
37 **                  queue. It is called once for each free queue.
38 **
39 ** Returns          void
40 **
41 *******************************************************************************/
42 static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
43 {
44     UINT16           i;
45     UINT16           act_size;
46     BUFFER_HDR_T    *hdr;
47     BUFFER_HDR_T    *hdr1 = NULL;
48     UINT32          *magic;
49     INT32            tempsize = size;
50     tGKI_COM_CB     *p_cb = &gki_cb.com;
51
52     /* Ensure an even number of longwords */
53     tempsize = (INT32)ALIGN_POOL(size);
54     act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
55
56     /* Remember pool start and end addresses */
57     if (p_mem) {
58         p_cb->pool_start[id] = (UINT8 *)p_mem;
59         p_cb->pool_end[id]   = (UINT8 *)p_mem + (act_size * total);
60     }
61
62     p_cb->pool_size[id]  = act_size;
63
64     p_cb->freeq[id].size      = (UINT16) tempsize;
65     p_cb->freeq[id].total     = total;
66     p_cb->freeq[id].cur_cnt   = 0;
67     p_cb->freeq[id].max_cnt   = 0;
68
69     /* Initialize  index table */
70     if (p_mem) {
71         hdr = (BUFFER_HDR_T *)p_mem;
72         p_cb->freeq[id]._p_first = hdr;
73         for (i = 0; i < total; i++) {
74             hdr->q_id    = id;
75             hdr->status  = BUF_STATUS_FREE;
76             magic        = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
77             *magic       = MAGIC_NO;
78             hdr1         = hdr;
79             hdr          = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
80             hdr1->p_next = hdr;
81         }
82         hdr1->p_next = NULL;
83         p_cb->freeq[id]._p_last = hdr1;
84     }
85 }
86
87 void gki_buffer_cleanup(void)
88 {
89     UINT8   i;
90     tGKI_COM_CB *p_cb = &gki_cb.com;
91
92     for (i = 0; i < GKI_NUM_FIXED_BUF_POOLS; i++) {
93         if ( 0 < p_cb->freeq[i].max_cnt ) {
94             osi_free(p_cb->pool_start[i]);
95
96             p_cb->freeq[i].cur_cnt   = 0;
97             p_cb->freeq[i].max_cnt   = 0;
98             p_cb->freeq[i]._p_first   = NULL;
99             p_cb->freeq[i]._p_last    = NULL;
100
101             p_cb->pool_start[i] = NULL;
102             p_cb->pool_end[i]   = NULL;
103             p_cb->pool_size[i]  = 0;
104         }
105     }
106 }
107
108 /*******************************************************************************
109 **
110 ** Function         gki_buffer_init
111 **
112 ** Description      Called once internally by GKI at startup to initialize all
113 **                  buffers and free buffer pools.
114 **
115 ** Returns          void
116 **
117 *******************************************************************************/
118 void gki_buffer_init(void)
119 {
120     static const struct {
121         uint16_t size;
122         uint16_t count;
123     } buffer_info[GKI_NUM_FIXED_BUF_POOLS] = {
124         { GKI_BUF0_SIZE, GKI_BUF0_MAX },
125         { GKI_BUF1_SIZE, GKI_BUF1_MAX },
126         { GKI_BUF2_SIZE, GKI_BUF2_MAX },
127         { GKI_BUF3_SIZE, GKI_BUF3_MAX },
128         { GKI_BUF4_SIZE, GKI_BUF4_MAX },
129         { GKI_BUF5_SIZE, GKI_BUF5_MAX },
130         { GKI_BUF6_SIZE, GKI_BUF6_MAX },
131         { GKI_BUF7_SIZE, GKI_BUF7_MAX },
132         { GKI_BUF8_SIZE, GKI_BUF8_MAX },
133         { GKI_BUF9_SIZE, GKI_BUF9_MAX },
134     };
135
136     tGKI_COM_CB *p_cb = &gki_cb.com;
137
138     for (int i = 0; i < GKI_NUM_TOTAL_BUF_POOLS; i++) {
139         p_cb->pool_start[i] = NULL;
140         p_cb->pool_end[i]   = NULL;
141         p_cb->pool_size[i]  = 0;
142
143         p_cb->freeq[i]._p_first = 0;
144         p_cb->freeq[i]._p_last  = 0;
145         p_cb->freeq[i].size    = 0;
146         p_cb->freeq[i].total   = 0;
147         p_cb->freeq[i].cur_cnt = 0;
148         p_cb->freeq[i].max_cnt = 0;
149     }
150
151     /* Use default from target.h */
152     p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
153
154     for (int i = 0; i < GKI_NUM_FIXED_BUF_POOLS; ++i) {
155         gki_init_free_queue(i, buffer_info[i].size, buffer_info[i].count, NULL);
156     }
157 }
158
159 /*******************************************************************************
160 **
161 ** Function         GKI_init_q
162 **
163 ** Description      Called by an application to initialize a buffer queue.
164 **
165 ** Returns          void
166 **
167 *******************************************************************************/
168 void GKI_init_q (BUFFER_Q *p_q)
169 {
170     p_q->_p_first = p_q->_p_last = NULL;
171     p_q->_count = 0;
172 }
173
174 /*******************************************************************************
175 **
176 ** Function         GKI_getbuf
177 **
178 ** Description      Called by an application to get a free buffer which
179 **                  is of size greater or equal to the requested size.
180 **
181 **                  Note: This routine only takes buffers from public pools.
182 **                        It will not use any buffers from pools
183 **                        marked GKI_RESTRICTED_POOL.
184 **
185 ** Parameters       size - (input) number of bytes needed.
186 **
187 ** Returns          A pointer to the buffer, or NULL if none available
188 **
189 *******************************************************************************/
190 void *GKI_getbuf (UINT16 size)
191 {
192     BUFFER_HDR_T *header = osi_malloc(size + BUFFER_HDR_SIZE);
193     assert(header != NULL);
194     if (header != NULL) {
195         header->status  = BUF_STATUS_UNLINKED;
196         header->p_next  = NULL;
197         header->Type    = 0;
198         header->size = size;
199
200         return header + 1;
201     } else {
202         return NULL;
203     }
204 }
205
206
207 /*******************************************************************************
208 **
209 ** Function         GKI_getpoolbuf
210 **
211 ** Description      Called by an application to get a free buffer from
212 **                  a specific buffer pool.
213 **
214 **                  Note: If there are no more buffers available from the pool,
215 **                        the public buffers are searched for an available buffer.
216 **
217 ** Parameters       pool_id - (input) pool ID to get a buffer out of.
218 **
219 ** Returns          A pointer to the buffer, or NULL if none available
220 **
221 *******************************************************************************/
222 void *GKI_getpoolbuf (UINT8 pool_id)
223 {
224     return GKI_getbuf(gki_cb.com.pool_size[pool_id]);
225 }
226
227 /*******************************************************************************
228 **
229 ** Function         GKI_freebuf
230 **
231 ** Description      Called by an application to return a buffer to the free pool.
232 **
233 ** Parameters       p_buf - (input) address of the beginning of a buffer.
234 **
235 ** Returns          void
236 **
237 *******************************************************************************/
238 void GKI_freebuf (void *p_buf)
239 {
240     osi_free((BUFFER_HDR_T *)p_buf - 1);
241 }
242
243
244 /*******************************************************************************
245 **
246 ** Function         GKI_get_buf_size
247 **
248 ** Description      Called by an application to get the size of a buffer.
249 **
250 ** Parameters       p_buf - (input) address of the beginning of a buffer.
251 **
252 ** Returns          the size of the buffer
253 **
254 *******************************************************************************/
255 UINT16 GKI_get_buf_size (void *p_buf)
256 {
257     BUFFER_HDR_T *header = (BUFFER_HDR_T *)p_buf - 1;
258     return header->size;
259 }
260
261 /*******************************************************************************
262 **
263 ** Function         GKI_enqueue
264 **
265 ** Description      Enqueue a buffer at the tail of the queue
266 **
267 ** Parameters:      p_q  -  (input) pointer to a queue.
268 **                  p_buf - (input) address of the buffer to enqueue
269 **
270 ** Returns          void
271 **
272 *******************************************************************************/
273 void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
274 {
275     BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
276     assert(p_hdr->status == BUF_STATUS_UNLINKED);
277
278     GKI_disable();
279
280     /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
281     if (p_q->_p_last) {
282         BUFFER_HDR_T *_p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_last - BUFFER_HDR_SIZE);
283         _p_last_hdr->p_next = p_hdr;
284     } else {
285         p_q->_p_first = p_buf;
286     }
287
288     p_q->_p_last = p_buf;
289     p_q->_count++;
290
291     p_hdr->p_next = NULL;
292     p_hdr->status = BUF_STATUS_QUEUED;
293
294     GKI_enable();
295 }
296
297 /*******************************************************************************
298 **
299 ** Function         GKI_dequeue
300 **
301 ** Description      Dequeues a buffer from the head of a queue
302 **
303 ** Parameters:      p_q  - (input) pointer to a queue.
304 **
305 ** Returns          NULL if queue is empty, else buffer
306 **
307 *******************************************************************************/
308 void *GKI_dequeue (BUFFER_Q *p_q)
309 {
310     BUFFER_HDR_T    *p_hdr;
311
312     GKI_disable();
313
314     if (!p_q || !p_q->_count) {
315         GKI_enable();
316         return (NULL);
317     }
318
319     p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
320
321     /* Keep buffers such that GKI header is invisible
322     */
323     if (p_hdr->p_next) {
324         p_q->_p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
325     } else {
326         p_q->_p_first = NULL;
327         p_q->_p_last  = NULL;
328     }
329
330     p_q->_count--;
331
332     p_hdr->p_next = NULL;
333     p_hdr->status = BUF_STATUS_UNLINKED;
334
335     GKI_enable();
336
337     return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
338 }
339
340 /*******************************************************************************
341 **
342 ** Function         GKI_remove_from_queue
343 **
344 ** Description      Dequeue a buffer from the middle of the queue
345 **
346 ** Parameters:      p_q  - (input) pointer to a queue.
347 **                  p_buf - (input) address of the buffer to enqueue
348 **
349 ** Returns          NULL if queue is empty, else buffer
350 **
351 *******************************************************************************/
352 void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
353 {
354     BUFFER_HDR_T    *p_prev;
355     BUFFER_HDR_T    *p_buf_hdr;
356
357     GKI_disable();
358
359     if (p_buf == p_q->_p_first) {
360         GKI_enable();
361         return (GKI_dequeue (p_q));
362     }
363
364     p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
365     p_prev    = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
366
367     for ( ; p_prev; p_prev = p_prev->p_next) {
368         /* If the previous points to this one, move the pointers around */
369         if (p_prev->p_next == p_buf_hdr) {
370             p_prev->p_next = p_buf_hdr->p_next;
371
372             /* If we are removing the last guy in the queue, update _p_last */
373             if (p_buf == p_q->_p_last) {
374                 p_q->_p_last = p_prev + 1;
375             }
376
377             /* One less in the queue */
378             p_q->_count--;
379
380             /* The buffer is now unlinked */
381             p_buf_hdr->p_next = NULL;
382             p_buf_hdr->status = BUF_STATUS_UNLINKED;
383
384             GKI_enable();
385             return (p_buf);
386         }
387     }
388
389     GKI_enable();
390     return (NULL);
391 }
392
393 /*******************************************************************************
394 **
395 ** Function         GKI_getfirst
396 **
397 ** Description      Return a pointer to the first buffer in a queue
398 **
399 ** Parameters:      p_q  - (input) pointer to a queue.
400 **
401 ** Returns          NULL if queue is empty, else buffer address
402 **
403 *******************************************************************************/
404 void *GKI_getfirst (BUFFER_Q *p_q)
405 {
406     return (p_q->_p_first);
407 }
408
409 /*******************************************************************************
410 **
411 ** Function         GKI_getlast
412 **
413 ** Description      Return a pointer to the last buffer in a queue
414 **
415 ** Parameters:      p_q  - (input) pointer to a queue.
416 **
417 ** Returns          NULL if queue is empty, else buffer address
418 **
419 *******************************************************************************/
420 void *GKI_getlast (BUFFER_Q *p_q)
421 {
422     return (p_q->_p_last);
423 }
424
425 /*******************************************************************************
426 **
427 ** Function         GKI_getnext
428 **
429 ** Description      Return a pointer to the next buffer in a queue
430 **
431 ** Parameters:      p_buf  - (input) pointer to the buffer to find the next one from.
432 **
433 ** Returns          NULL if no more buffers in the queue, else next buffer address
434 **
435 *******************************************************************************/
436 void *GKI_getnext (void *p_buf)
437 {
438     BUFFER_HDR_T    *p_hdr;
439
440     p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
441
442     if (p_hdr->p_next) {
443         return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
444     } else {
445         return (NULL);
446     }
447 }
448
449 /*******************************************************************************
450 **
451 ** Function         GKI_queue_is_empty
452 **
453 ** Description      Check the status of a queue.
454 **
455 ** Parameters:      p_q  - (input) pointer to a queue.
456 **
457 ** Returns          TRUE if queue is empty, else FALSE
458 **
459 *******************************************************************************/
460 BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
461 {
462     return ((BOOLEAN) (p_q->_count == 0));
463 }
464
465 UINT16 GKI_queue_length(BUFFER_Q *p_q)
466 {
467     return p_q->_count;
468 }
469
470 /*******************************************************************************
471 **
472 ** Function         GKI_poolcount
473 **
474 ** Description      Called by an application to get the total number of buffers
475 **                  in the specified buffer pool.
476 **
477 ** Parameters       pool_id - (input) pool ID to get the free count of.
478 **
479 ** Returns          the total number of buffers in the pool
480 **
481 *******************************************************************************/
482 UINT16 GKI_poolcount (UINT8 pool_id)
483 {
484     if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
485         return (0);
486     }
487
488     return (gki_cb.com.freeq[pool_id].total);
489 }
490
491 /*******************************************************************************
492 **
493 ** Function         GKI_poolfreecount
494 **
495 ** Description      Called by an application to get the number of free buffers
496 **                  in the specified buffer pool.
497 **
498 ** Parameters       pool_id - (input) pool ID to get the free count of.
499 **
500 ** Returns          the number of free buffers in the pool
501 **
502 *******************************************************************************/
503 UINT16 GKI_poolfreecount (UINT8 pool_id)
504 {
505     FREE_QUEUE_T  *Q;
506
507     if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
508         return (0);
509     }
510
511     Q  = &gki_cb.com.freeq[pool_id];
512
513     return ((UINT16)(Q->total - Q->cur_cnt));
514 }
515
516 /*******************************************************************************
517 **
518 ** Function         GKI_get_pool_bufsize
519 **
520 ** Description      Called by an application to get the size of buffers in a pool
521 **
522 ** Parameters       Pool ID.
523 **
524 ** Returns          the size of buffers in the pool
525 **
526 *******************************************************************************/
527 UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
528 {
529     if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) {
530         return (gki_cb.com.freeq[pool_id].size);
531     }
532
533     return (0);
534 }
535
536 /*******************************************************************************
537 **
538 ** Function         GKI_poolutilization
539 **
540 ** Description      Called by an application to get the buffer utilization
541 **                  in the specified buffer pool.
542 **
543 ** Parameters       pool_id - (input) pool ID to get the free count of.
544 **
545 ** Returns          % of buffers used from 0 to 100
546 **
547 *******************************************************************************/
548 UINT16 GKI_poolutilization (UINT8 pool_id)
549 {
550     FREE_QUEUE_T  *Q;
551
552     if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
553         return (100);
554     }
555
556     Q  = &gki_cb.com.freeq[pool_id];
557
558     if (Q->total == 0) {
559         return (100);
560     }
561
562     return ((Q->cur_cnt * 100) / Q->total);
563 }