1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
22 #include "osi/include/allocator.h"
25 #if (GKI_NUM_TOTAL_BUF_POOLS > 16)
26 #error Number of pools out of range (16 Max)!
29 #define ALIGN_POOL(pl_size) ( (((pl_size) + 3) / sizeof(UINT32)) * sizeof(UINT32))
30 #define BUFFER_HDR_SIZE (sizeof(BUFFER_HDR_T)) /* Offset past header */
31 #define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */
32 #define MAGIC_NO 0xDDBADDBA
34 #define BUF_STATUS_FREE 0
35 #define BUF_STATUS_UNLINKED 1
36 #define BUF_STATUS_QUEUED 2
38 /*******************************************************************************
40 ** Function gki_init_free_queue
42 ** Description Internal function called at startup to initialize a free
43 ** queue. It is called once for each free queue.
47 *******************************************************************************/
48 static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
53 BUFFER_HDR_T *hdr1 = NULL;
55 INT32 tempsize = size;
56 tGKI_COM_CB *p_cb = &gki_cb.com;
58 /* Ensure an even number of longwords */
59 tempsize = (INT32)ALIGN_POOL(size);
60 act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
62 /* Remember pool start and end addresses */
65 p_cb->pool_start[id] = (UINT8 *)p_mem;
66 p_cb->pool_end[id] = (UINT8 *)p_mem + (act_size * total);
69 p_cb->pool_size[id] = act_size;
71 p_cb->freeq[id].size = (UINT16) tempsize;
72 p_cb->freeq[id].total = total;
73 p_cb->freeq[id].cur_cnt = 0;
74 p_cb->freeq[id].max_cnt = 0;
76 /* Initialize index table */
79 hdr = (BUFFER_HDR_T *)p_mem;
80 p_cb->freeq[id]._p_first = hdr;
81 for (i = 0; i < total; i++)
84 hdr->status = BUF_STATUS_FREE;
85 magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
88 hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
92 p_cb->freeq[id]._p_last = hdr1;
96 void gki_buffer_cleanup(void)
99 tGKI_COM_CB *p_cb = &gki_cb.com;
101 for (i=0; i < GKI_NUM_FIXED_BUF_POOLS; i++)
103 if ( 0 < p_cb->freeq[i].max_cnt )
105 osi_free(p_cb->pool_start[i]);
107 p_cb->freeq[i].cur_cnt = 0;
108 p_cb->freeq[i].max_cnt = 0;
109 p_cb->freeq[i]._p_first = NULL;
110 p_cb->freeq[i]._p_last = NULL;
112 p_cb->pool_start[i] = NULL;
113 p_cb->pool_end[i] = NULL;
114 p_cb->pool_size[i] = 0;
119 /*******************************************************************************
121 ** Function gki_buffer_init
123 ** Description Called once internally by GKI at startup to initialize all
124 ** buffers and free buffer pools.
128 *******************************************************************************/
129 void gki_buffer_init(void)
131 static const struct {
134 } buffer_info[GKI_NUM_FIXED_BUF_POOLS] = {
135 { GKI_BUF0_SIZE, GKI_BUF0_MAX },
136 { GKI_BUF1_SIZE, GKI_BUF1_MAX },
137 { GKI_BUF2_SIZE, GKI_BUF2_MAX },
138 { GKI_BUF3_SIZE, GKI_BUF3_MAX },
139 { GKI_BUF4_SIZE, GKI_BUF4_MAX },
140 { GKI_BUF5_SIZE, GKI_BUF5_MAX },
141 { GKI_BUF6_SIZE, GKI_BUF6_MAX },
142 { GKI_BUF7_SIZE, GKI_BUF7_MAX },
143 { GKI_BUF8_SIZE, GKI_BUF8_MAX },
144 { GKI_BUF9_SIZE, GKI_BUF9_MAX },
147 tGKI_COM_CB *p_cb = &gki_cb.com;
149 for (int i = 0; i < GKI_NUM_TOTAL_BUF_POOLS; i++)
151 p_cb->pool_start[i] = NULL;
152 p_cb->pool_end[i] = NULL;
153 p_cb->pool_size[i] = 0;
155 p_cb->freeq[i]._p_first = 0;
156 p_cb->freeq[i]._p_last = 0;
157 p_cb->freeq[i].size = 0;
158 p_cb->freeq[i].total = 0;
159 p_cb->freeq[i].cur_cnt = 0;
160 p_cb->freeq[i].max_cnt = 0;
163 /* Use default from target.h */
164 p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
166 for (int i = 0; i < GKI_NUM_FIXED_BUF_POOLS; ++i) {
167 gki_init_free_queue(i, buffer_info[i].size, buffer_info[i].count, NULL);
171 /*******************************************************************************
173 ** Function GKI_init_q
175 ** Description Called by an application to initialize a buffer queue.
179 *******************************************************************************/
180 void GKI_init_q (BUFFER_Q *p_q)
182 p_q->_p_first = p_q->_p_last = NULL;
186 /*******************************************************************************
188 ** Function GKI_getbuf
190 ** Description Called by an application to get a free buffer which
191 ** is of size greater or equal to the requested size.
193 ** Note: This routine only takes buffers from public pools.
194 ** It will not use any buffers from pools
195 ** marked GKI_RESTRICTED_POOL.
197 ** Parameters size - (input) number of bytes needed.
199 ** Returns A pointer to the buffer, or NULL if none available
201 *******************************************************************************/
202 void *GKI_getbuf (UINT16 size)
204 BUFFER_HDR_T *header = malloc(size + BUFFER_HDR_SIZE);
205 header->status = BUF_STATUS_UNLINKED;
206 header->p_next = NULL;
213 /*******************************************************************************
215 ** Function GKI_getpoolbuf
217 ** Description Called by an application to get a free buffer from
218 ** a specific buffer pool.
220 ** Note: If there are no more buffers available from the pool,
221 ** the public buffers are searched for an available buffer.
223 ** Parameters pool_id - (input) pool ID to get a buffer out of.
225 ** Returns A pointer to the buffer, or NULL if none available
227 *******************************************************************************/
228 void *GKI_getpoolbuf (UINT8 pool_id)
230 return GKI_getbuf(gki_cb.com.pool_size[pool_id]);
233 /*******************************************************************************
235 ** Function GKI_freebuf
237 ** Description Called by an application to return a buffer to the free pool.
239 ** Parameters p_buf - (input) address of the beginning of a buffer.
243 *******************************************************************************/
244 void GKI_freebuf (void *p_buf)
246 free((BUFFER_HDR_T *)p_buf - 1);
250 /*******************************************************************************
252 ** Function GKI_get_buf_size
254 ** Description Called by an application to get the size of a buffer.
256 ** Parameters p_buf - (input) address of the beginning of a buffer.
258 ** Returns the size of the buffer
260 *******************************************************************************/
261 UINT16 GKI_get_buf_size (void *p_buf)
263 BUFFER_HDR_T *header = (BUFFER_HDR_T *)p_buf - 1;
267 /*******************************************************************************
269 ** Function GKI_enqueue
271 ** Description Enqueue a buffer at the tail of the queue
273 ** Parameters: p_q - (input) pointer to a queue.
274 ** p_buf - (input) address of the buffer to enqueue
278 *******************************************************************************/
279 void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
281 BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
282 assert(p_hdr->status == BUF_STATUS_UNLINKED);
286 /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
289 BUFFER_HDR_T *_p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_last - BUFFER_HDR_SIZE);
290 _p_last_hdr->p_next = p_hdr;
293 p_q->_p_first = p_buf;
295 p_q->_p_last = p_buf;
298 p_hdr->p_next = NULL;
299 p_hdr->status = BUF_STATUS_QUEUED;
304 /*******************************************************************************
306 ** Function GKI_dequeue
308 ** Description Dequeues a buffer from the head of a queue
310 ** Parameters: p_q - (input) pointer to a queue.
312 ** Returns NULL if queue is empty, else buffer
314 *******************************************************************************/
315 void *GKI_dequeue (BUFFER_Q *p_q)
321 if (!p_q || !p_q->_count)
327 p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
329 /* Keep buffers such that GKI header is invisible
332 p_q->_p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
335 p_q->_p_first = NULL;
341 p_hdr->p_next = NULL;
342 p_hdr->status = BUF_STATUS_UNLINKED;
346 return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
349 /*******************************************************************************
351 ** Function GKI_remove_from_queue
353 ** Description Dequeue a buffer from the middle of the queue
355 ** Parameters: p_q - (input) pointer to a queue.
356 ** p_buf - (input) address of the buffer to enqueue
358 ** Returns NULL if queue is empty, else buffer
360 *******************************************************************************/
361 void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
363 BUFFER_HDR_T *p_prev;
364 BUFFER_HDR_T *p_buf_hdr;
368 if (p_buf == p_q->_p_first)
371 return (GKI_dequeue (p_q));
374 p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
375 p_prev = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
377 for ( ; p_prev; p_prev = p_prev->p_next)
379 /* If the previous points to this one, move the pointers around */
380 if (p_prev->p_next == p_buf_hdr)
382 p_prev->p_next = p_buf_hdr->p_next;
384 /* If we are removing the last guy in the queue, update _p_last */
385 if (p_buf == p_q->_p_last)
386 p_q->_p_last = p_prev + 1;
388 /* One less in the queue */
391 /* The buffer is now unlinked */
392 p_buf_hdr->p_next = NULL;
393 p_buf_hdr->status = BUF_STATUS_UNLINKED;
404 /*******************************************************************************
406 ** Function GKI_getfirst
408 ** Description Return a pointer to the first buffer in a queue
410 ** Parameters: p_q - (input) pointer to a queue.
412 ** Returns NULL if queue is empty, else buffer address
414 *******************************************************************************/
415 void *GKI_getfirst (BUFFER_Q *p_q)
417 return (p_q->_p_first);
420 /*******************************************************************************
422 ** Function GKI_getlast
424 ** Description Return a pointer to the last buffer in a queue
426 ** Parameters: p_q - (input) pointer to a queue.
428 ** Returns NULL if queue is empty, else buffer address
430 *******************************************************************************/
431 void *GKI_getlast (BUFFER_Q *p_q)
433 return (p_q->_p_last);
436 /*******************************************************************************
438 ** Function GKI_getnext
440 ** Description Return a pointer to the next buffer in a queue
442 ** Parameters: p_buf - (input) pointer to the buffer to find the next one from.
444 ** Returns NULL if no more buffers in the queue, else next buffer address
446 *******************************************************************************/
447 void *GKI_getnext (void *p_buf)
451 p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
454 return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
459 /*******************************************************************************
461 ** Function GKI_queue_is_empty
463 ** Description Check the status of a queue.
465 ** Parameters: p_q - (input) pointer to a queue.
467 ** Returns TRUE if queue is empty, else FALSE
469 *******************************************************************************/
470 BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
472 return ((BOOLEAN) (p_q->_count == 0));
475 UINT16 GKI_queue_length(BUFFER_Q *p_q)
480 /*******************************************************************************
482 ** Function GKI_poolcount
484 ** Description Called by an application to get the total number of buffers
485 ** in the specified buffer pool.
487 ** Parameters pool_id - (input) pool ID to get the free count of.
489 ** Returns the total number of buffers in the pool
491 *******************************************************************************/
492 UINT16 GKI_poolcount (UINT8 pool_id)
494 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
497 return (gki_cb.com.freeq[pool_id].total);
500 /*******************************************************************************
502 ** Function GKI_poolfreecount
504 ** Description Called by an application to get the number of free buffers
505 ** in the specified buffer pool.
507 ** Parameters pool_id - (input) pool ID to get the free count of.
509 ** Returns the number of free buffers in the pool
511 *******************************************************************************/
512 UINT16 GKI_poolfreecount (UINT8 pool_id)
516 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
519 Q = &gki_cb.com.freeq[pool_id];
521 return ((UINT16)(Q->total - Q->cur_cnt));
524 /*******************************************************************************
526 ** Function GKI_get_pool_bufsize
528 ** Description Called by an application to get the size of buffers in a pool
530 ** Parameters Pool ID.
532 ** Returns the size of buffers in the pool
534 *******************************************************************************/
535 UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
537 if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
538 return (gki_cb.com.freeq[pool_id].size);
543 /*******************************************************************************
545 ** Function GKI_poolutilization
547 ** Description Called by an application to get the buffer utilization
548 ** in the specified buffer pool.
550 ** Parameters pool_id - (input) pool ID to get the free count of.
552 ** Returns % of buffers used from 0 to 100
554 *******************************************************************************/
555 UINT16 GKI_poolutilization (UINT8 pool_id)
559 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
562 Q = &gki_cb.com.freeq[pool_id];
567 return ((Q->cur_cnt * 100) / Q->total);