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 #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
28 #define BUF_STATUS_FREE 0
29 #define BUF_STATUS_UNLINKED 1
30 #define BUF_STATUS_QUEUED 2
32 /*******************************************************************************
34 ** Function gki_init_free_queue
36 ** Description Internal function called at startup to initialize a free
37 ** queue. It is called once for each free queue.
41 *******************************************************************************/
42 static void gki_init_free_queue (UINT8 id, UINT16 size, UINT16 total, void *p_mem)
47 BUFFER_HDR_T *hdr1 = NULL;
49 INT32 tempsize = size;
50 tGKI_COM_CB *p_cb = &gki_cb.com;
52 /* Ensure an even number of longwords */
53 tempsize = (INT32)ALIGN_POOL(size);
54 act_size = (UINT16)(tempsize + BUFFER_PADDING_SIZE);
56 /* Remember pool start and end addresses */
58 p_cb->pool_start[id] = (UINT8 *)p_mem;
59 p_cb->pool_end[id] = (UINT8 *)p_mem + (act_size * total);
62 p_cb->pool_size[id] = act_size;
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;
69 /* Initialize index table */
71 hdr = (BUFFER_HDR_T *)p_mem;
72 p_cb->freeq[id]._p_first = hdr;
73 for (i = 0; i < total; i++) {
75 hdr->status = BUF_STATUS_FREE;
76 magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + tempsize);
79 hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
83 p_cb->freeq[id]._p_last = hdr1;
87 void gki_buffer_cleanup(void)
90 tGKI_COM_CB *p_cb = &gki_cb.com;
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]);
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;
101 p_cb->pool_start[i] = NULL;
102 p_cb->pool_end[i] = NULL;
103 p_cb->pool_size[i] = 0;
108 /*******************************************************************************
110 ** Function gki_buffer_init
112 ** Description Called once internally by GKI at startup to initialize all
113 ** buffers and free buffer pools.
117 *******************************************************************************/
118 void gki_buffer_init(void)
120 static const struct {
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 },
136 tGKI_COM_CB *p_cb = &gki_cb.com;
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;
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;
151 /* Use default from target.h */
152 p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
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);
159 /*******************************************************************************
161 ** Function GKI_init_q
163 ** Description Called by an application to initialize a buffer queue.
167 *******************************************************************************/
168 void GKI_init_q (BUFFER_Q *p_q)
170 p_q->_p_first = p_q->_p_last = NULL;
174 /*******************************************************************************
176 ** Function GKI_getbuf
178 ** Description Called by an application to get a free buffer which
179 ** is of size greater or equal to the requested size.
181 ** Note: This routine only takes buffers from public pools.
182 ** It will not use any buffers from pools
183 ** marked GKI_RESTRICTED_POOL.
185 ** Parameters size - (input) number of bytes needed.
187 ** Returns A pointer to the buffer, or NULL if none available
189 *******************************************************************************/
190 void *GKI_getbuf (UINT16 size)
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;
207 /*******************************************************************************
209 ** Function GKI_getpoolbuf
211 ** Description Called by an application to get a free buffer from
212 ** a specific buffer pool.
214 ** Note: If there are no more buffers available from the pool,
215 ** the public buffers are searched for an available buffer.
217 ** Parameters pool_id - (input) pool ID to get a buffer out of.
219 ** Returns A pointer to the buffer, or NULL if none available
221 *******************************************************************************/
222 void *GKI_getpoolbuf (UINT8 pool_id)
224 return GKI_getbuf(gki_cb.com.pool_size[pool_id]);
227 /*******************************************************************************
229 ** Function GKI_freebuf
231 ** Description Called by an application to return a buffer to the free pool.
233 ** Parameters p_buf - (input) address of the beginning of a buffer.
237 *******************************************************************************/
238 void GKI_freebuf (void *p_buf)
240 osi_free((BUFFER_HDR_T *)p_buf - 1);
244 /*******************************************************************************
246 ** Function GKI_get_buf_size
248 ** Description Called by an application to get the size of a buffer.
250 ** Parameters p_buf - (input) address of the beginning of a buffer.
252 ** Returns the size of the buffer
254 *******************************************************************************/
255 UINT16 GKI_get_buf_size (void *p_buf)
257 BUFFER_HDR_T *header = (BUFFER_HDR_T *)p_buf - 1;
261 /*******************************************************************************
263 ** Function GKI_enqueue
265 ** Description Enqueue a buffer at the tail of the queue
267 ** Parameters: p_q - (input) pointer to a queue.
268 ** p_buf - (input) address of the buffer to enqueue
272 *******************************************************************************/
273 void GKI_enqueue (BUFFER_Q *p_q, void *p_buf)
275 BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
276 assert(p_hdr->status == BUF_STATUS_UNLINKED);
280 /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
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;
285 p_q->_p_first = p_buf;
288 p_q->_p_last = p_buf;
291 p_hdr->p_next = NULL;
292 p_hdr->status = BUF_STATUS_QUEUED;
297 /*******************************************************************************
299 ** Function GKI_dequeue
301 ** Description Dequeues a buffer from the head of a queue
303 ** Parameters: p_q - (input) pointer to a queue.
305 ** Returns NULL if queue is empty, else buffer
307 *******************************************************************************/
308 void *GKI_dequeue (BUFFER_Q *p_q)
314 if (!p_q || !p_q->_count) {
319 p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->_p_first - BUFFER_HDR_SIZE);
321 /* Keep buffers such that GKI header is invisible
324 p_q->_p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
326 p_q->_p_first = NULL;
332 p_hdr->p_next = NULL;
333 p_hdr->status = BUF_STATUS_UNLINKED;
337 return ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
340 /*******************************************************************************
342 ** Function GKI_remove_from_queue
344 ** Description Dequeue a buffer from the middle of the queue
346 ** Parameters: p_q - (input) pointer to a queue.
347 ** p_buf - (input) address of the buffer to enqueue
349 ** Returns NULL if queue is empty, else buffer
351 *******************************************************************************/
352 void *GKI_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
354 BUFFER_HDR_T *p_prev;
355 BUFFER_HDR_T *p_buf_hdr;
359 if (p_buf == p_q->_p_first) {
361 return (GKI_dequeue (p_q));
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);
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;
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;
377 /* One less in the queue */
380 /* The buffer is now unlinked */
381 p_buf_hdr->p_next = NULL;
382 p_buf_hdr->status = BUF_STATUS_UNLINKED;
393 /*******************************************************************************
395 ** Function GKI_getfirst
397 ** Description Return a pointer to the first buffer in a queue
399 ** Parameters: p_q - (input) pointer to a queue.
401 ** Returns NULL if queue is empty, else buffer address
403 *******************************************************************************/
404 void *GKI_getfirst (BUFFER_Q *p_q)
406 return (p_q->_p_first);
409 /*******************************************************************************
411 ** Function GKI_getlast
413 ** Description Return a pointer to the last buffer in a queue
415 ** Parameters: p_q - (input) pointer to a queue.
417 ** Returns NULL if queue is empty, else buffer address
419 *******************************************************************************/
420 void *GKI_getlast (BUFFER_Q *p_q)
422 return (p_q->_p_last);
425 /*******************************************************************************
427 ** Function GKI_getnext
429 ** Description Return a pointer to the next buffer in a queue
431 ** Parameters: p_buf - (input) pointer to the buffer to find the next one from.
433 ** Returns NULL if no more buffers in the queue, else next buffer address
435 *******************************************************************************/
436 void *GKI_getnext (void *p_buf)
440 p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
443 return ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
449 /*******************************************************************************
451 ** Function GKI_queue_is_empty
453 ** Description Check the status of a queue.
455 ** Parameters: p_q - (input) pointer to a queue.
457 ** Returns TRUE if queue is empty, else FALSE
459 *******************************************************************************/
460 BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
462 return ((BOOLEAN) (p_q->_count == 0));
465 UINT16 GKI_queue_length(BUFFER_Q *p_q)
470 /*******************************************************************************
472 ** Function GKI_poolcount
474 ** Description Called by an application to get the total number of buffers
475 ** in the specified buffer pool.
477 ** Parameters pool_id - (input) pool ID to get the free count of.
479 ** Returns the total number of buffers in the pool
481 *******************************************************************************/
482 UINT16 GKI_poolcount (UINT8 pool_id)
484 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
488 return (gki_cb.com.freeq[pool_id].total);
491 /*******************************************************************************
493 ** Function GKI_poolfreecount
495 ** Description Called by an application to get the number of free buffers
496 ** in the specified buffer pool.
498 ** Parameters pool_id - (input) pool ID to get the free count of.
500 ** Returns the number of free buffers in the pool
502 *******************************************************************************/
503 UINT16 GKI_poolfreecount (UINT8 pool_id)
507 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
511 Q = &gki_cb.com.freeq[pool_id];
513 return ((UINT16)(Q->total - Q->cur_cnt));
516 /*******************************************************************************
518 ** Function GKI_get_pool_bufsize
520 ** Description Called by an application to get the size of buffers in a pool
522 ** Parameters Pool ID.
524 ** Returns the size of buffers in the pool
526 *******************************************************************************/
527 UINT16 GKI_get_pool_bufsize (UINT8 pool_id)
529 if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) {
530 return (gki_cb.com.freeq[pool_id].size);
536 /*******************************************************************************
538 ** Function GKI_poolutilization
540 ** Description Called by an application to get the buffer utilization
541 ** in the specified buffer pool.
543 ** Parameters pool_id - (input) pool ID to get the free count of.
545 ** Returns % of buffers used from 0 to 100
547 *******************************************************************************/
548 UINT16 GKI_poolutilization (UINT8 pool_id)
552 if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) {
556 Q = &gki_cb.com.freeq[pool_id];
562 return ((Q->cur_cnt * 100) / Q->total);