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 ******************************************************************************/
20 #include "allocator.h"
23 /*******************************************************************************
25 ** Function gki_init_free_queue
27 ** Description Internal function called at startup to initialize a free
28 ** queue. It is called once for each free queue.
32 *******************************************************************************/
33 static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
38 BUFFER_HDR_T *hdr1 = NULL;
40 INT32 tempsize = size;
41 tGKI_COM_CB *p_cb = &gki_cb.com;
43 /* Ensure an even number of longwords */
44 tempsize = (INT32)ALIGN_POOL(size);
45 act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
47 /* Remember pool start and end addresses */
49 p_cb->pool_start[id] = (UINT8 *)p_mem;
50 p_cb->pool_end[id] = (UINT8 *)p_mem + (act_size * total);
53 p_cb->pool_size[id] = act_size;
55 p_cb->freeq[id].size = (UINT16) tempsize;
56 p_cb->freeq[id].total = total;
57 p_cb->freeq[id].cur_cnt = 0;
58 p_cb->freeq[id].max_cnt = 0;
60 /* Initialize index table */
62 hdr = (BUFFER_HDR_T *)p_mem;
63 p_cb->freeq[id]._p_first = hdr;
64 for (i = 0; i < total; i++) {
66 hdr->status = BUF_STATUS_FREE;
67 magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
70 hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
74 p_cb->freeq[id]._p_last = hdr1;
78 void gki_buffer_cleanup(void)
81 tGKI_COM_CB *p_cb = &gki_cb.com;
83 for (i = 0; i < GKI_NUM_FIXED_BUF_POOLS; i++) {
84 if ( 0 < p_cb->freeq[i].max_cnt ) {
85 osi_free(p_cb->pool_start[i]);
87 p_cb->freeq[i].cur_cnt = 0;
88 p_cb->freeq[i].max_cnt = 0;
89 p_cb->freeq[i]._p_first = NULL;
90 p_cb->freeq[i]._p_last = NULL;
92 p_cb->pool_start[i] = NULL;
93 p_cb->pool_end[i] = NULL;
94 p_cb->pool_size[i] = 0;
99 /*******************************************************************************
101 ** Function gki_buffer_init
103 ** Description Called once internally by GKI at startup to initialize all
104 ** buffers and free buffer pools.
108 *******************************************************************************/
109 void gki_buffer_init(void)
111 static const struct {
114 } buffer_info[GKI_NUM_FIXED_BUF_POOLS] = {
115 { GKI_BUF0_SIZE, GKI_BUF0_MAX },
116 { GKI_BUF1_SIZE, GKI_BUF1_MAX },
117 { GKI_BUF2_SIZE, GKI_BUF2_MAX },
118 { GKI_BUF3_SIZE, GKI_BUF3_MAX },
119 { GKI_BUF4_SIZE, GKI_BUF4_MAX },
120 { GKI_BUF5_SIZE, GKI_BUF5_MAX },
121 { GKI_BUF6_SIZE, GKI_BUF6_MAX },
122 { GKI_BUF7_SIZE, GKI_BUF7_MAX },
123 { GKI_BUF8_SIZE, GKI_BUF8_MAX },
124 { GKI_BUF9_SIZE, GKI_BUF9_MAX },
127 tGKI_COM_CB *p_cb = &gki_cb.com;
129 for (int i = 0; i < GKI_NUM_TOTAL_BUF_POOLS; i++) {
130 p_cb->pool_start[i] = NULL;
131 p_cb->pool_end[i] = NULL;
132 p_cb->pool_size[i] = 0;
134 p_cb->freeq[i]._p_first = 0;
135 p_cb->freeq[i]._p_last = 0;
136 p_cb->freeq[i].size = 0;
137 p_cb->freeq[i].total = 0;
138 p_cb->freeq[i].cur_cnt = 0;
139 p_cb->freeq[i].max_cnt = 0;
142 /* Use default from target.h */
143 p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
145 for (int i = 0; i < GKI_NUM_FIXED_BUF_POOLS; ++i) {
146 gki_init_free_queue(i, buffer_info[i].size, buffer_info[i].count, NULL);
150 /*******************************************************************************
152 ** Function GKI_init_q
154 ** Description Called by an application to initialize a buffer queue.
158 *******************************************************************************/
159 void GKI_init_q (BUFFER_Q *p_q)
161 p_q->_p_first = p_q->_p_last = NULL;
165 /*******************************************************************************
167 ** Function GKI_getbuf_func
169 ** Description Called by an application to get a free buffer which
170 ** is of size greater or equal to the requested size.
172 ** Note: This routine only takes buffers from public pools.
173 ** It will not use any buffers from pools
174 ** marked GKI_RESTRICTED_POOL.
176 ** Parameters size - (input) number of bytes needed.
178 ** Returns A pointer to the buffer, or NULL if none available
180 *******************************************************************************/
181 void *GKI_getbuf_func(UINT16 size)
183 BUFFER_HDR_T *header = osi_malloc(size + BUFFER_HDR_SIZE);
184 assert(header != NULL);
185 if (header != NULL) {
186 header->status = BUF_STATUS_UNLINKED;
187 header->p_next = NULL;
197 /*******************************************************************************
199 ** Function GKI_getpoolbuf_func
201 ** Description Called by an application to get a free buffer from
202 ** a specific buffer pool.
204 ** Note: If there are no more buffers available from the pool,
205 ** the public buffers are searched for an available buffer.
207 ** Parameters pool_id - (input) pool ID to get a buffer out of.
209 ** Returns A pointer to the buffer, or NULL if none available
211 *******************************************************************************/
212 void *GKI_getpoolbuf_func(UINT8 pool_id)
214 return GKI_getbuf_func(gki_cb.com.pool_size[pool_id]);
217 /*******************************************************************************
219 ** Function GKI_freebuf
221 ** Description Called by an application to return a buffer to the free pool.
223 ** Parameters p_buf - (input) address of the beginning of a buffer.
227 *******************************************************************************/
228 void GKI_freebuf (void *p_buf)
230 osi_free((BUFFER_HDR_T *)p_buf - 1);
233 /*******************************************************************************
235 ** Function GKI_get_buf_size
237 ** Description Called by an application to get the size of a buffer.
239 ** Parameters p_buf - (input) address of the beginning of a buffer.
241 ** Returns the size of the buffer
243 *******************************************************************************/
244 UINT16 GKI_get_buf_size (void *p_buf)
246 BUFFER_HDR_T *header = (BUFFER_HDR_T *)p_buf - 1;
250 /*******************************************************************************
252 ** Function GKI_enqueue
254 ** Description Enqueue a buffer at the tail of the queue
256 ** Parameters: p_q - (input) pointer to a queue.
257 ** p_buf - (input) address of the buffer to enqueue
261 *******************************************************************************/
262 void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
264 BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
265 assert(p_hdr->status == BUF_STATUS_UNLINKED);
269 /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
271 BUFFER_HDR_T *_p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_last - BUFFER_HDR_SIZE);
272 _p_last_hdr->p_next = p_hdr;
274 p_q->_p_first = p_buf;
277 p_q->_p_last = p_buf;
280 p_hdr->p_next = NULL;
281 p_hdr->status = BUF_STATUS_QUEUED;
286 /*******************************************************************************
288 ** Function GKI_dequeue
290 ** Description Dequeues a buffer from the head of a queue
292 ** Parameters: p_q - (input) pointer to a queue.
294 ** Returns NULL if queue is empty, else buffer
296 *******************************************************************************/
297 void *GKI_dequeue (BUFFER_Q *p_q)
303 if (!p_q || !p_q->_count) {
308 p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
310 /* Keep buffers such that GKI header is invisible
313 p_q->_p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
315 p_q->_p_first = NULL;
321 p_hdr->p_next = NULL;
322 p_hdr->status = BUF_STATUS_UNLINKED;
326 return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
329 /*******************************************************************************
331 ** Function GKI_remove_from_queue
333 ** Description Dequeue a buffer from the middle of the queue
335 ** Parameters: p_q - (input) pointer to a queue.
336 ** p_buf - (input) address of the buffer to enqueue
338 ** Returns NULL if queue is empty, else buffer
340 *******************************************************************************/
341 void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
343 BUFFER_HDR_T *p_prev;
344 BUFFER_HDR_T *p_buf_hdr;
348 if (p_buf == p_q->_p_first) {
350 return (GKI_dequeue (p_q));
353 p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
354 p_prev = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
356 for ( ; p_prev; p_prev = p_prev->p_next) {
357 /* If the previous points to this one, move the pointers around */
358 if (p_prev->p_next == p_buf_hdr) {
359 p_prev->p_next = p_buf_hdr->p_next;
361 /* If we are removing the last guy in the queue, update _p_last */
362 if (p_buf == p_q->_p_last) {
363 p_q->_p_last = p_prev + 1;
366 /* One less in the queue */
369 /* The buffer is now unlinked */
370 p_buf_hdr->p_next = NULL;
371 p_buf_hdr->status = BUF_STATUS_UNLINKED;
382 /*******************************************************************************
384 ** Function GKI_getfirst
386 ** Description Return a pointer to the first buffer in a queue
388 ** Parameters: p_q - (input) pointer to a queue.
390 ** Returns NULL if queue is empty, else buffer address
392 *******************************************************************************/
393 void *GKI_getfirst (BUFFER_Q *p_q)
395 return (p_q->_p_first);
398 /*******************************************************************************
400 ** Function GKI_getlast
402 ** Description Return a pointer to the last buffer in a queue
404 ** Parameters: p_q - (input) pointer to a queue.
406 ** Returns NULL if queue is empty, else buffer address
408 *******************************************************************************/
409 void *GKI_getlast (BUFFER_Q *p_q)
411 return (p_q->_p_last);
414 /*******************************************************************************
416 ** Function GKI_getnext
418 ** Description Return a pointer to the next buffer in a queue
420 ** Parameters: p_buf - (input) pointer to the buffer to find the next one from.
422 ** Returns NULL if no more buffers in the queue, else next buffer address
424 *******************************************************************************/
425 void *GKI_getnext (void *p_buf)
429 p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
432 return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
438 /*******************************************************************************
440 ** Function GKI_queue_is_empty
442 ** Description Check the status of a queue.
444 ** Parameters: p_q - (input) pointer to a queue.
446 ** Returns TRUE if queue is empty, else FALSE
448 *******************************************************************************/
449 BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
451 return ((BOOLEAN) (p_q->_count == 0));
454 UINT16 GKI_queue_length(BUFFER_Q *p_q)
459 /*******************************************************************************
461 ** Function GKI_poolcount
463 ** Description Called by an application to get the total number of buffers
464 ** in the specified buffer pool.
466 ** Parameters pool_id - (input) pool ID to get the free count of.
468 ** Returns the total number of buffers in the pool
470 *******************************************************************************/
471 UINT16 GKI_poolcount (UINT8 pool_id)
473 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
477 return (gki_cb.com.freeq[pool_id].total);
480 /*******************************************************************************
482 ** Function GKI_poolfreecount
484 ** Description Called by an application to get the number of free buffers
485 ** in the specified buffer pool.
487 ** Parameters pool_id - (input) pool ID to get the free count of.
489 ** Returns the number of free buffers in the pool
491 *******************************************************************************/
492 UINT16 GKI_poolfreecount (UINT8 pool_id)
496 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
500 Q = &gki_cb.com.freeq[pool_id];
502 return ((UINT16)(Q->total - Q->cur_cnt));
505 /*******************************************************************************
507 ** Function GKI_get_pool_bufsize
509 ** Description Called by an application to get the size of buffers in a pool
511 ** Parameters Pool ID.
513 ** Returns the size of buffers in the pool
515 *******************************************************************************/
516 UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
518 if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) {
519 return (gki_cb.com.freeq[pool_id].size);
525 /*******************************************************************************
527 ** Function GKI_poolutilization
529 ** Description Called by an application to get the buffer utilization
530 ** in the specified buffer pool.
532 ** Parameters pool_id - (input) pool ID to get the free count of.
534 ** Returns % of buffers used from 0 to 100
536 *******************************************************************************/
537 UINT16 GKI_poolutilization (UINT8 pool_id)
541 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
545 Q = &gki_cb.com.freeq[pool_id];
551 return ((Q->cur_cnt * 100) / Q->total);