Home | History | Annotate | Download | only in common
      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 #include <android-base/stringprintf.h>
     19 #include <base/logging.h>
     20 #include "gki_int.h"
     21 
     22 #if (GKI_NUM_TOTAL_BUF_POOLS > 16)
     23 #error Number of pools out of range (16 Max)!
     24 #endif
     25 
     26 #if (BTU_STACK_LITE_ENABLED == FALSE)
     27 static void gki_add_to_pool_list(uint8_t pool_id);
     28 static void gki_remove_from_pool_list(uint8_t pool_id);
     29 #endif /*  BTU_STACK_LITE_ENABLED == FALSE */
     30 
     31 using android::base::StringPrintf;
     32 
     33 /*******************************************************************************
     34 **
     35 ** Function         gki_init_free_queue
     36 **
     37 ** Description      Internal function called at startup to initialize a free
     38 **                  queue. It is called once for each free queue.
     39 **
     40 ** Returns          void
     41 **
     42 *******************************************************************************/
     43 static void gki_init_free_queue(uint8_t id, uint16_t size, uint16_t total,
     44                                 void* p_mem) {
     45   uint16_t i;
     46   uint16_t act_size;
     47   BUFFER_HDR_T* hdr;
     48   BUFFER_HDR_T* hdr1 = NULL;
     49   uint32_t* magic;
     50   int32_t tempsize = size;
     51   tGKI_COM_CB* p_cb = &gki_cb.com;
     52 
     53   /* Ensure an even number of longwords */
     54   tempsize = (int32_t)ALIGN_POOL(size);
     55   act_size = (uint16_t)(tempsize + BUFFER_PADDING_SIZE);
     56 
     57   /* Remember pool start and end addresses */
     58   if (p_mem) {
     59     p_cb->pool_start[id] = (uint8_t*)p_mem;
     60     p_cb->pool_end[id] = (uint8_t*)p_mem + (act_size * total);
     61   }
     62 
     63   p_cb->pool_size[id] = act_size;
     64 
     65   p_cb->freeq[id].size = (uint16_t)tempsize;
     66   p_cb->freeq[id].total = total;
     67   p_cb->freeq[id].cur_cnt = 0;
     68   p_cb->freeq[id].max_cnt = 0;
     69 
     70   /* Initialize  index table */
     71   if (p_mem) {
     72     hdr = (BUFFER_HDR_T*)p_mem;
     73     p_cb->freeq[id].p_first = hdr;
     74     for (i = 0; i < total; i++) {
     75       hdr->task_id = GKI_INVALID_TASK;
     76       hdr->q_id = id;
     77       hdr->status = BUF_STATUS_FREE;
     78       magic = (uint32_t*)((uint8_t*)hdr + BUFFER_HDR_SIZE + tempsize);
     79       *magic = MAGIC_NO;
     80       hdr1 = hdr;
     81       hdr = (BUFFER_HDR_T*)((uint8_t*)hdr + act_size);
     82       hdr1->p_next = hdr;
     83     }
     84     if (hdr1 != NULL) hdr = hdr1;
     85     hdr->p_next = NULL;
     86     p_cb->freeq[id].p_last = hdr;
     87   }
     88   return;
     89 }
     90 
     91 static bool gki_alloc_free_queue(uint8_t id) {
     92   FREE_QUEUE_T* Q;
     93   tGKI_COM_CB* p_cb = &gki_cb.com;
     94 
     95   Q = &p_cb->freeq[p_cb->pool_list[id]];
     96 
     97   if (Q->p_first == 0) {
     98     void* p_mem = GKI_os_malloc((Q->size + BUFFER_PADDING_SIZE) * Q->total);
     99     if (p_mem) {
    100       // re-initialize the queue with allocated memory
    101       gki_init_free_queue(id, Q->size, Q->total, p_mem);
    102       return true;
    103     }
    104     GKI_exception(GKI_ERROR_BUF_SIZE_TOOBIG,
    105                   "gki_alloc_free_queue: Not enough memory");
    106   }
    107   return false;
    108 }
    109 
    110 /*******************************************************************************
    111 **
    112 ** Function         gki_buffer_init
    113 **
    114 ** Description      Called once internally by GKI at startup to initialize all
    115 **                  buffers and free buffer pools.
    116 **
    117 ** Returns          void
    118 **
    119 *******************************************************************************/
    120 void gki_buffer_init(void) {
    121   uint8_t i, tt, mb;
    122   tGKI_COM_CB* p_cb = &gki_cb.com;
    123 
    124   /* Initialize mailboxes */
    125   for (tt = 0; tt < GKI_MAX_TASKS; tt++) {
    126     for (mb = 0; mb < NUM_TASK_MBOX; mb++) {
    127       p_cb->OSTaskQFirst[tt][mb] = NULL;
    128       p_cb->OSTaskQLast[tt][mb] = NULL;
    129     }
    130   }
    131 
    132   for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++) {
    133     p_cb->pool_start[tt] = NULL;
    134     p_cb->pool_end[tt] = NULL;
    135     p_cb->pool_size[tt] = 0;
    136 
    137     p_cb->freeq[tt].p_first = 0;
    138     p_cb->freeq[tt].p_last = 0;
    139     p_cb->freeq[tt].size = 0;
    140     p_cb->freeq[tt].total = 0;
    141     p_cb->freeq[tt].cur_cnt = 0;
    142     p_cb->freeq[tt].max_cnt = 0;
    143   }
    144 
    145   /* Use default from target.h */
    146   p_cb->pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
    147 
    148 #if (GKI_NUM_FIXED_BUF_POOLS > 0)
    149   gki_init_free_queue(0, GKI_BUF0_SIZE, GKI_BUF0_MAX, p_cb->bufpool0);
    150 #endif
    151 
    152 #if (GKI_NUM_FIXED_BUF_POOLS > 1)
    153   gki_init_free_queue(1, GKI_BUF1_SIZE, GKI_BUF1_MAX, p_cb->bufpool1);
    154 #endif
    155 
    156 #if (GKI_NUM_FIXED_BUF_POOLS > 2)
    157   gki_init_free_queue(2, GKI_BUF2_SIZE, GKI_BUF2_MAX, p_cb->bufpool2);
    158 #endif
    159 
    160 #if (GKI_NUM_FIXED_BUF_POOLS > 3)
    161   gki_init_free_queue(3, GKI_BUF3_SIZE, GKI_BUF3_MAX, p_cb->bufpool3);
    162 #endif
    163 
    164 #if (GKI_NUM_FIXED_BUF_POOLS > 4)
    165   gki_init_free_queue(4, GKI_BUF4_SIZE, GKI_BUF4_MAX, p_cb->bufpool4);
    166 #endif
    167 
    168 #if (GKI_NUM_FIXED_BUF_POOLS > 5)
    169   gki_init_free_queue(5, GKI_BUF5_SIZE, GKI_BUF5_MAX, p_cb->bufpool5);
    170 #endif
    171 
    172 #if (GKI_NUM_FIXED_BUF_POOLS > 6)
    173   gki_init_free_queue(6, GKI_BUF6_SIZE, GKI_BUF6_MAX, p_cb->bufpool6);
    174 #endif
    175 
    176 #if (GKI_NUM_FIXED_BUF_POOLS > 7)
    177   gki_init_free_queue(7, GKI_BUF7_SIZE, GKI_BUF7_MAX, p_cb->bufpool7);
    178 #endif
    179 
    180 #if (GKI_NUM_FIXED_BUF_POOLS > 8)
    181   gki_init_free_queue(8, GKI_BUF8_SIZE, GKI_BUF8_MAX, p_cb->bufpool8);
    182 #endif
    183 
    184 #if (GKI_NUM_FIXED_BUF_POOLS > 9)
    185   gki_init_free_queue(9, GKI_BUF9_SIZE, GKI_BUF9_MAX, p_cb->bufpool9);
    186 #endif
    187 
    188 #if (GKI_NUM_FIXED_BUF_POOLS > 10)
    189   gki_init_free_queue(10, GKI_BUF10_SIZE, GKI_BUF10_MAX, p_cb->bufpool10);
    190 #endif
    191 
    192 #if (GKI_NUM_FIXED_BUF_POOLS > 11)
    193   gki_init_free_queue(11, GKI_BUF11_SIZE, GKI_BUF11_MAX, p_cb->bufpool11);
    194 #endif
    195 
    196 #if (GKI_NUM_FIXED_BUF_POOLS > 12)
    197   gki_init_free_queue(12, GKI_BUF12_SIZE, GKI_BUF12_MAX, p_cb->bufpool12);
    198 #endif
    199 
    200 #if (GKI_NUM_FIXED_BUF_POOLS > 13)
    201   gki_init_free_queue(13, GKI_BUF13_SIZE, GKI_BUF13_MAX, p_cb->bufpool13);
    202 #endif
    203 
    204 #if (GKI_NUM_FIXED_BUF_POOLS > 14)
    205   gki_init_free_queue(14, GKI_BUF14_SIZE, GKI_BUF14_MAX, p_cb->bufpool14);
    206 #endif
    207 
    208 #if (GKI_NUM_FIXED_BUF_POOLS > 15)
    209   gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15);
    210 #endif
    211 
    212   /* add pools to the pool_list which is arranged in the order of size */
    213   for (i = 0; i < GKI_NUM_FIXED_BUF_POOLS; i++) {
    214     p_cb->pool_list[i] = i;
    215   }
    216 
    217   p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;
    218 
    219   return;
    220 }
    221 
    222 /*******************************************************************************
    223 **
    224 ** Function         GKI_init_q
    225 **
    226 ** Description      Called by an application to initialize a buffer queue.
    227 **
    228 ** Returns          void
    229 **
    230 *******************************************************************************/
    231 void GKI_init_q(BUFFER_Q* p_q) {
    232   p_q->p_first = p_q->p_last = NULL;
    233   p_q->count = 0;
    234 
    235   return;
    236 }
    237 
    238 /*******************************************************************************
    239 **
    240 ** Function         GKI_getbuf
    241 **
    242 ** Description      Called by an application to get a free buffer which
    243 **                  is of size greater or equal to the requested size.
    244 **
    245 **                  Note: This routine only takes buffers from public pools.
    246 **                        It will not use any buffers from pools
    247 **                        marked GKI_RESTRICTED_POOL.
    248 **
    249 ** Parameters       size - (input) number of bytes needed.
    250 **
    251 ** Returns          A pointer to the buffer, or NULL if none available
    252 **
    253 *******************************************************************************/
    254 void* GKI_getbuf(uint16_t size) {
    255   uint8_t i;
    256   FREE_QUEUE_T* Q;
    257   BUFFER_HDR_T* p_hdr;
    258   tGKI_COM_CB* p_cb = &gki_cb.com;
    259 
    260   if (size == 0) {
    261     GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
    262     return (NULL);
    263   }
    264 
    265   /* Find the first buffer pool that is public that can hold the desired size */
    266   for (i = 0; i < p_cb->curr_total_no_of_pools; i++) {
    267     if (size <= p_cb->freeq[p_cb->pool_list[i]].size) break;
    268   }
    269 
    270   if (i == p_cb->curr_total_no_of_pools) {
    271     GKI_exception(GKI_ERROR_BUF_SIZE_TOOBIG, "getbuf: Size is too big");
    272     return (NULL);
    273   }
    274 
    275   /* Make sure the buffers aren't disturbed til finished with allocation */
    276   GKI_disable();
    277 
    278   /* search the public buffer pools that are big enough to hold the size
    279    * until a free buffer is found */
    280   for (; i < p_cb->curr_total_no_of_pools; i++) {
    281     /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
    282     if (((uint16_t)1 << p_cb->pool_list[i]) & p_cb->pool_access_mask) continue;
    283 
    284     Q = &p_cb->freeq[p_cb->pool_list[i]];
    285     if (Q->cur_cnt < Q->total) {
    286       if (Q->p_first == 0 && gki_alloc_free_queue(i) != true) {
    287         LOG(ERROR) << StringPrintf("out of buffer");
    288         GKI_enable();
    289         return NULL;
    290       }
    291 
    292       if (Q->p_first == 0) {
    293         /* gki_alloc_free_queue() failed to alloc memory */
    294         LOG(ERROR) << StringPrintf("fail alloc free queue");
    295         GKI_enable();
    296         return NULL;
    297       }
    298 
    299       p_hdr = Q->p_first;
    300       Q->p_first = p_hdr->p_next;
    301 
    302       if (!Q->p_first) Q->p_last = NULL;
    303 
    304       if (++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt;
    305 
    306       GKI_enable();
    307 
    308       p_hdr->task_id = GKI_get_taskid();
    309 
    310       p_hdr->status = BUF_STATUS_UNLINKED;
    311       p_hdr->p_next = NULL;
    312       p_hdr->Type = 0;
    313       return ((void*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE));
    314     }
    315   }
    316 
    317   LOG(ERROR) << StringPrintf("unable to allocate buffer!!!!!");
    318 
    319   GKI_enable();
    320 
    321   return (NULL);
    322 }
    323 
    324 /*******************************************************************************
    325 **
    326 ** Function         GKI_getpoolbuf
    327 **
    328 ** Description      Called by an application to get a free buffer from
    329 **                  a specific buffer pool.
    330 **
    331 **                  Note: If there are no more buffers available from the pool,
    332 **                        the public buffers are searched for an available
    333 **                        buffer.
    334 **
    335 ** Parameters       pool_id - (input) pool ID to get a buffer out of.
    336 **
    337 ** Returns          A pointer to the buffer, or NULL if none available
    338 **
    339 *******************************************************************************/
    340 void* GKI_getpoolbuf(uint8_t pool_id) {
    341   FREE_QUEUE_T* Q;
    342   BUFFER_HDR_T* p_hdr;
    343   tGKI_COM_CB* p_cb = &gki_cb.com;
    344 
    345   if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (NULL);
    346 
    347   /* Make sure the buffers aren't disturbed til finished with allocation */
    348   GKI_disable();
    349 
    350   Q = &p_cb->freeq[pool_id];
    351   if (Q->cur_cnt < Q->total) {
    352     if (Q->p_first == 0 && gki_alloc_free_queue(pool_id) != true) return NULL;
    353 
    354     if (Q->p_first == 0) {
    355       /* gki_alloc_free_queue() failed to alloc memory */
    356       LOG(ERROR) << StringPrintf("fail alloc free queue");
    357       return NULL;
    358     }
    359 
    360     p_hdr = Q->p_first;
    361     Q->p_first = p_hdr->p_next;
    362 
    363     if (!Q->p_first) Q->p_last = NULL;
    364 
    365     if (++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt;
    366 
    367     GKI_enable();
    368 
    369     p_hdr->task_id = GKI_get_taskid();
    370 
    371     p_hdr->status = BUF_STATUS_UNLINKED;
    372     p_hdr->p_next = NULL;
    373     p_hdr->Type = 0;
    374 
    375     return ((void*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE));
    376   }
    377 
    378   /* If here, no buffers in the specified pool */
    379   GKI_enable();
    380 
    381   /* try for free buffers in public pools */
    382   return (GKI_getbuf(p_cb->freeq[pool_id].size));
    383 }
    384 
    385 /*******************************************************************************
    386 **
    387 ** Function         GKI_freebuf
    388 **
    389 ** Description      Called by an application to return a buffer to the free
    390 **                  pool.
    391 **
    392 ** Parameters       p_buf - (input) address of the beginning of a buffer.
    393 **
    394 ** Returns          void
    395 **
    396 *******************************************************************************/
    397 void GKI_freebuf(void* p_buf) {
    398   FREE_QUEUE_T* Q;
    399   BUFFER_HDR_T* p_hdr;
    400 
    401 #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
    402   if (!p_buf || gki_chk_buf_damage(p_buf)) {
    403     GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
    404     return;
    405   }
    406 #endif
    407 
    408   p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
    409 
    410   if (p_hdr->status != BUF_STATUS_UNLINKED) {
    411     GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
    412     return;
    413   }
    414 
    415   if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS) {
    416     GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
    417     return;
    418   }
    419 
    420   GKI_disable();
    421 
    422   /*
    423   ** Release the buffer
    424   */
    425   Q = &gki_cb.com.freeq[p_hdr->q_id];
    426   if (Q->p_last)
    427     Q->p_last->p_next = p_hdr;
    428   else
    429     Q->p_first = p_hdr;
    430 
    431   Q->p_last = p_hdr;
    432   p_hdr->p_next = NULL;
    433   p_hdr->status = BUF_STATUS_FREE;
    434   p_hdr->task_id = GKI_INVALID_TASK;
    435   if (Q->cur_cnt > 0) Q->cur_cnt--;
    436 
    437   GKI_enable();
    438 
    439   return;
    440 }
    441 
    442 /*******************************************************************************
    443 **
    444 ** Function         GKI_get_buf_size
    445 **
    446 ** Description      Called by an application to get the size of a buffer.
    447 **
    448 ** Parameters       p_buf - (input) address of the beginning of a buffer.
    449 **
    450 ** Returns          the size of the buffer
    451 **
    452 *******************************************************************************/
    453 uint16_t GKI_get_buf_size(void* p_buf) {
    454   BUFFER_HDR_T* p_hdr;
    455 
    456   p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
    457 
    458   if ((uintptr_t)p_hdr & 1) return (0);
    459 
    460   if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS) {
    461     return (gki_cb.com.freeq[p_hdr->q_id].size);
    462   }
    463 
    464   return (0);
    465 }
    466 
    467 /*******************************************************************************
    468 **
    469 ** Function         gki_chk_buf_damage
    470 **
    471 ** Description      Called internally by OSS to check for buffer corruption.
    472 **
    473 ** Returns          TRUE if there is a problem, else FALSE
    474 **
    475 *******************************************************************************/
    476 bool gki_chk_buf_damage(void* p_buf) {
    477 #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
    478 
    479   uint32_t* magic;
    480   magic = (uint32_t*)((uint8_t*)p_buf + GKI_get_buf_size(p_buf));
    481 
    482   if ((uintptr_t)magic & 1) return true;
    483 
    484   if (*magic == MAGIC_NO) return false;
    485 
    486   return true;
    487 
    488 #else
    489 
    490   return false;
    491 
    492 #endif
    493 }
    494 
    495 /*******************************************************************************
    496 **
    497 ** Function         GKI_send_msg
    498 **
    499 ** Description      Called by applications to send a buffer to a task
    500 **
    501 ** Returns          Nothing
    502 **
    503 *******************************************************************************/
    504 void GKI_send_msg(uint8_t task_id, uint8_t mbox, void* msg) {
    505   BUFFER_HDR_T* p_hdr;
    506   tGKI_COM_CB* p_cb = &gki_cb.com;
    507 
    508   /* If task non-existant or not started, drop buffer */
    509   if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) ||
    510       (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) {
    511     GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
    512     GKI_freebuf(msg);
    513     return;
    514   }
    515 
    516 #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
    517   if (gki_chk_buf_damage(msg)) {
    518     GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
    519     return;
    520   }
    521 #endif
    522 
    523   p_hdr = (BUFFER_HDR_T*)((uint8_t*)msg - BUFFER_HDR_SIZE);
    524 
    525   if (p_hdr->status != BUF_STATUS_UNLINKED) {
    526     GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
    527     return;
    528   }
    529 
    530   GKI_disable();
    531 
    532   if (p_cb->OSTaskQFirst[task_id][mbox])
    533     p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
    534   else
    535     p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
    536 
    537   p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
    538 
    539   p_hdr->p_next = NULL;
    540   p_hdr->status = BUF_STATUS_QUEUED;
    541   p_hdr->task_id = task_id;
    542 
    543   GKI_enable();
    544 
    545   GKI_send_event(task_id, (uint16_t)EVENT_MASK(mbox));
    546 
    547   return;
    548 }
    549 
    550 /*******************************************************************************
    551 **
    552 ** Function         GKI_read_mbox
    553 **
    554 ** Description      Called by applications to read a buffer from one of
    555 **                  the task mailboxes.  A task can only read its own mailbox.
    556 **
    557 ** Parameters:      mbox  - (input) mailbox ID to read (0, 1, 2, or 3)
    558 **
    559 ** Returns          NULL if the mailbox was empty, else the address of a buffer
    560 **
    561 *******************************************************************************/
    562 void* GKI_read_mbox(uint8_t mbox) {
    563   uint8_t task_id = GKI_get_taskid();
    564   void* p_buf = NULL;
    565   BUFFER_HDR_T* p_hdr;
    566 
    567   if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX)) return (NULL);
    568 
    569   GKI_disable();
    570 
    571   if (gki_cb.com.OSTaskQFirst[task_id][mbox]) {
    572     p_hdr = gki_cb.com.OSTaskQFirst[task_id][mbox];
    573     gki_cb.com.OSTaskQFirst[task_id][mbox] = p_hdr->p_next;
    574 
    575     p_hdr->p_next = NULL;
    576     p_hdr->status = BUF_STATUS_UNLINKED;
    577 
    578     p_buf = (uint8_t*)p_hdr + BUFFER_HDR_SIZE;
    579   }
    580 
    581   GKI_enable();
    582 
    583   return (p_buf);
    584 }
    585 
    586 /*******************************************************************************
    587 **
    588 ** Function         GKI_enqueue
    589 **
    590 ** Description      Enqueue a buffer at the tail of the queue
    591 **
    592 ** Parameters:      p_q  -  (input) pointer to a queue.
    593 **                  p_buf - (input) address of the buffer to enqueue
    594 **
    595 ** Returns          void
    596 **
    597 *******************************************************************************/
    598 void GKI_enqueue(BUFFER_Q* p_q, void* p_buf) {
    599   BUFFER_HDR_T* p_hdr;
    600 
    601 #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
    602   if (gki_chk_buf_damage(p_buf)) {
    603     GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
    604     return;
    605   }
    606 #endif
    607 
    608   p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
    609 
    610   if (p_hdr->status != BUF_STATUS_UNLINKED) {
    611     GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Eneueue - buf already linked");
    612     return;
    613   }
    614 
    615   GKI_disable();
    616 
    617   /* Since the queue is exposed (C vs C++), keep the pointers in exposed format
    618    */
    619   if (p_q->p_first) {
    620     BUFFER_HDR_T* p_last_hdr =
    621         (BUFFER_HDR_T*)((uint8_t*)p_q->p_last - BUFFER_HDR_SIZE);
    622     p_last_hdr->p_next = p_hdr;
    623   } else
    624     p_q->p_first = p_buf;
    625 
    626   p_q->p_last = p_buf;
    627   p_q->count++;
    628 
    629   p_hdr->p_next = NULL;
    630   p_hdr->status = BUF_STATUS_QUEUED;
    631 
    632   GKI_enable();
    633 
    634   return;
    635 }
    636 
    637 /*******************************************************************************
    638 **
    639 ** Function         GKI_enqueue_head
    640 **
    641 ** Description      Enqueue a buffer at the head of the queue
    642 **
    643 ** Parameters:      p_q  -  (input) pointer to a queue.
    644 **                  p_buf - (input) address of the buffer to enqueue
    645 **
    646 ** Returns          void
    647 **
    648 *******************************************************************************/
    649 void GKI_enqueue_head(BUFFER_Q* p_q, void* p_buf) {
    650   BUFFER_HDR_T* p_hdr;
    651 
    652 #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
    653   if (gki_chk_buf_damage(p_buf)) {
    654     GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
    655     return;
    656   }
    657 #endif
    658 
    659   p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
    660 
    661   if (p_hdr->status != BUF_STATUS_UNLINKED) {
    662     GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED,
    663                   "Eneueue head - buf already linked");
    664     return;
    665   }
    666 
    667   GKI_disable();
    668 
    669   if (p_q->p_first) {
    670     p_hdr->p_next = (BUFFER_HDR_T*)((uint8_t*)p_q->p_first - BUFFER_HDR_SIZE);
    671     p_q->p_first = p_buf;
    672   } else {
    673     p_q->p_first = p_buf;
    674     p_q->p_last = p_buf;
    675     p_hdr->p_next = NULL;
    676   }
    677   p_q->count++;
    678 
    679   p_hdr->status = BUF_STATUS_QUEUED;
    680 
    681   GKI_enable();
    682 
    683   return;
    684 }
    685 
    686 /*******************************************************************************
    687 **
    688 ** Function         GKI_dequeue
    689 **
    690 ** Description      Dequeues a buffer from the head of a queue
    691 **
    692 ** Parameters:      p_q  - (input) pointer to a queue.
    693 **
    694 ** Returns          NULL if queue is empty, else buffer
    695 **
    696 *******************************************************************************/
    697 void* GKI_dequeue(BUFFER_Q* p_q) {
    698   BUFFER_HDR_T* p_hdr;
    699 
    700   GKI_disable();
    701 
    702   if (!p_q || !p_q->count) {
    703     GKI_enable();
    704     return (NULL);
    705   }
    706 
    707   p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_q->p_first - BUFFER_HDR_SIZE);
    708 
    709   /* Keep buffers such that GKI header is invisible
    710   */
    711   if (p_hdr->p_next)
    712     p_q->p_first = ((uint8_t*)p_hdr->p_next + BUFFER_HDR_SIZE);
    713   else {
    714     p_q->p_first = NULL;
    715     p_q->p_last = NULL;
    716   }
    717 
    718   p_q->count--;
    719 
    720   p_hdr->p_next = NULL;
    721   p_hdr->status = BUF_STATUS_UNLINKED;
    722 
    723   GKI_enable();
    724 
    725   return ((uint8_t*)p_hdr + BUFFER_HDR_SIZE);
    726 }
    727 
    728 /*******************************************************************************
    729 **
    730 ** Function         GKI_remove_from_queue
    731 **
    732 ** Description      Dequeue a buffer from the middle of the queue
    733 **
    734 ** Parameters:      p_q  - (input) pointer to a queue.
    735 **                  p_buf - (input) address of the buffer to enqueue
    736 **
    737 ** Returns          NULL if queue is empty, else buffer
    738 **
    739 *******************************************************************************/
    740 void* GKI_remove_from_queue(BUFFER_Q* p_q, void* p_buf) {
    741   BUFFER_HDR_T* p_prev;
    742   BUFFER_HDR_T* p_buf_hdr;
    743 
    744   GKI_disable();
    745 
    746   if (p_buf == p_q->p_first) {
    747     GKI_enable();
    748     return (GKI_dequeue(p_q));
    749   }
    750 
    751   p_buf_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
    752   p_prev = (BUFFER_HDR_T*)((uint8_t*)p_q->p_first - BUFFER_HDR_SIZE);
    753 
    754   for (; p_prev; p_prev = p_prev->p_next) {
    755     /* If the previous points to this one, move the pointers around */
    756     if (p_prev->p_next == p_buf_hdr) {
    757       p_prev->p_next = p_buf_hdr->p_next;
    758 
    759       /* If we are removing the last guy in the queue, update p_last */
    760       if (p_buf == p_q->p_last) p_q->p_last = p_prev + 1;
    761 
    762       /* One less in the queue */
    763       p_q->count--;
    764 
    765       /* The buffer is now unlinked */
    766       p_buf_hdr->p_next = NULL;
    767       p_buf_hdr->status = BUF_STATUS_UNLINKED;
    768 
    769       GKI_enable();
    770       return (p_buf);
    771     }
    772   }
    773 
    774   GKI_enable();
    775   return (NULL);
    776 }
    777 
    778 /*******************************************************************************
    779 **
    780 ** Function         GKI_getfirst
    781 **
    782 ** Description      Return a pointer to the first buffer in a queue
    783 **
    784 ** Parameters:      p_q  - (input) pointer to a queue.
    785 **
    786 ** Returns          NULL if queue is empty, else buffer address
    787 **
    788 *******************************************************************************/
    789 void* GKI_getfirst(BUFFER_Q* p_q) { return (p_q->p_first); }
    790 
    791 /*******************************************************************************
    792 **
    793 ** Function         GKI_getlast
    794 **
    795 ** Description      Return a pointer to the last buffer in a queue
    796 **
    797 ** Parameters:      p_q  - (input) pointer to a queue.
    798 **
    799 ** Returns          NULL if queue is empty, else buffer address
    800 **
    801 *******************************************************************************/
    802 void* GKI_getlast(BUFFER_Q* p_q) { return (p_q->p_last); }
    803 
    804 /*******************************************************************************
    805 **
    806 ** Function         GKI_getnext
    807 **
    808 ** Description      Return a pointer to the next buffer in a queue
    809 **
    810 ** Parameters:      p_buf - (input) pointer to the buffer to find the next one
    811 **                                  from.
    812 **
    813 ** Returns          NULL if no more buffers in the queue, else next buffer
    814 **                  address
    815 **
    816 *******************************************************************************/
    817 void* GKI_getnext(void* p_buf) {
    818   BUFFER_HDR_T* p_hdr;
    819 
    820   p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
    821 
    822   if (p_hdr->p_next)
    823     return ((uint8_t*)p_hdr->p_next + BUFFER_HDR_SIZE);
    824   else
    825     return (NULL);
    826 }
    827 
    828 /*******************************************************************************
    829 **
    830 ** Function         GKI_queue_is_empty
    831 **
    832 ** Description      Check the status of a queue.
    833 **
    834 ** Parameters:      p_q  - (input) pointer to a queue.
    835 **
    836 ** Returns          TRUE if queue is empty, else FALSE
    837 **
    838 *******************************************************************************/
    839 bool GKI_queue_is_empty(BUFFER_Q* p_q) { return ((bool)(p_q->count == 0)); }
    840 
    841 /*******************************************************************************
    842 **
    843 ** Function         GKI_find_buf_start
    844 **
    845 ** Description      This function is called with an address inside a buffer,
    846 **                  and returns the start address ofthe buffer.
    847 **
    848 **                  The buffer should be one allocated from one of GKI's pools.
    849 **
    850 ** Parameters:      p_user_area - (input) address of anywhere in a GKI buffer.
    851 **
    852 ** Returns          void * - Address of the beginning of the specified buffer if
    853 **                           successful, otherwise NULL if unsuccessful
    854 **
    855 *******************************************************************************/
    856 void* GKI_find_buf_start(void* p_user_area) {
    857   uint16_t xx, size;
    858   uint32_t yy;
    859   tGKI_COM_CB* p_cb = &gki_cb.com;
    860   uint8_t* p_ua = (uint8_t*)p_user_area;
    861 
    862   for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) {
    863     if ((p_ua > p_cb->pool_start[xx]) && (p_ua < p_cb->pool_end[xx])) {
    864       yy = (uint32_t)(p_ua - p_cb->pool_start[xx]);
    865 
    866       size = p_cb->pool_size[xx];
    867 
    868       yy = (yy / size) * size;
    869 
    870       return ((void*)(p_cb->pool_start[xx] + yy + sizeof(BUFFER_HDR_T)));
    871     }
    872   }
    873 
    874   /* If here, invalid address - not in one of our buffers */
    875   GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr");
    876 
    877   return (NULL);
    878 }
    879 
    880 /********************************************************
    881 * The following functions are not needed for light stack
    882 *********************************************************/
    883 #ifndef BTU_STACK_LITE_ENABLED
    884 #define BTU_STACK_LITE_ENABLED FALSE
    885 #endif
    886 
    887 #if (BTU_STACK_LITE_ENABLED == FALSE)
    888 
    889 /*******************************************************************************
    890 **
    891 ** Function         GKI_set_pool_permission
    892 **
    893 ** Description      This function is called to set or change the permissions for
    894 **                  the specified pool ID.
    895 **
    896 ** Parameters       pool_id - (input) pool ID to be set or changed
    897 **                  permission - (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL
    898 **
    899 ** Returns          GKI_SUCCESS if successful
    900 **                  GKI_INVALID_POOL if unsuccessful
    901 **
    902 *******************************************************************************/
    903 uint8_t GKI_set_pool_permission(uint8_t pool_id, uint8_t permission) {
    904   tGKI_COM_CB* p_cb = &gki_cb.com;
    905 
    906   if (pool_id < GKI_NUM_TOTAL_BUF_POOLS) {
    907     if (permission == GKI_RESTRICTED_POOL)
    908       p_cb->pool_access_mask =
    909           (uint16_t)(p_cb->pool_access_mask | (1 << pool_id));
    910 
    911     else /* mark the pool as public */
    912       p_cb->pool_access_mask =
    913           (uint16_t)(p_cb->pool_access_mask & ~(1 << pool_id));
    914 
    915     return (GKI_SUCCESS);
    916   } else
    917     return (GKI_INVALID_POOL);
    918 }
    919 
    920 /*******************************************************************************
    921 **
    922 ** Function         gki_add_to_pool_list
    923 **
    924 ** Description      Adds pool to the pool list which is arranged in the
    925 **                  order of size
    926 **
    927 ** Returns          void
    928 **
    929 *******************************************************************************/
    930 static void gki_add_to_pool_list(uint8_t pool_id) {
    931   int32_t i, j;
    932   tGKI_COM_CB* p_cb = &gki_cb.com;
    933 
    934   /* Find the position where the specified pool should be inserted into the list
    935    */
    936   for (i = 0; i < p_cb->curr_total_no_of_pools; i++) {
    937     if (p_cb->freeq[pool_id].size <= p_cb->freeq[p_cb->pool_list[i]].size)
    938       break;
    939   }
    940 
    941   /* Insert the new buffer pool ID into the list of pools */
    942   for (j = p_cb->curr_total_no_of_pools; j > i; j--) {
    943     p_cb->pool_list[j] = p_cb->pool_list[j - 1];
    944   }
    945 
    946   p_cb->pool_list[i] = pool_id;
    947 
    948   return;
    949 }
    950 
    951 /*******************************************************************************
    952 **
    953 ** Function         gki_remove_from_pool_list
    954 **
    955 ** Description      Removes pool from the pool list. Called when a pool is
    956 **                  deleted
    957 **
    958 ** Returns          void
    959 **
    960 *******************************************************************************/
    961 static void gki_remove_from_pool_list(uint8_t pool_id) {
    962   tGKI_COM_CB* p_cb = &gki_cb.com;
    963   uint8_t i;
    964 
    965   for (i = 0; i < p_cb->curr_total_no_of_pools; i++) {
    966     if (pool_id == p_cb->pool_list[i]) break;
    967   }
    968 
    969   while (i < (p_cb->curr_total_no_of_pools - 1)) {
    970     p_cb->pool_list[i] = p_cb->pool_list[i + 1];
    971     i++;
    972   }
    973 
    974   return;
    975 }
    976 
    977 /*******************************************************************************
    978 **
    979 ** Function         GKI_poolcount
    980 **
    981 ** Description      Called by an application to get the total number of buffers
    982 **                  in the specified buffer pool.
    983 **
    984 ** Parameters       pool_id - (input) pool ID to get the free count of.
    985 **
    986 ** Returns          the total number of buffers in the pool
    987 **
    988 *******************************************************************************/
    989 uint16_t GKI_poolcount(uint8_t pool_id) {
    990   if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (0);
    991 
    992   return (gki_cb.com.freeq[pool_id].total);
    993 }
    994 
    995 /*******************************************************************************
    996 **
    997 ** Function         GKI_poolfreecount
    998 **
    999 ** Description      Called by an application to get the number of free buffers
   1000 **                  in the specified buffer pool.
   1001 **
   1002 ** Parameters       pool_id - (input) pool ID to get the free count of.
   1003 **
   1004 ** Returns          the number of free buffers in the pool
   1005 **
   1006 *******************************************************************************/
   1007 uint16_t GKI_poolfreecount(uint8_t pool_id) {
   1008   FREE_QUEUE_T* Q;
   1009 
   1010   if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (0);
   1011 
   1012   Q = &gki_cb.com.freeq[pool_id];
   1013 
   1014   return ((uint16_t)(Q->total - Q->cur_cnt));
   1015 }
   1016 
   1017 /*******************************************************************************
   1018 **
   1019 ** Function         GKI_change_buf_owner
   1020 **
   1021 ** Description      Called to change the task ownership of a buffer.
   1022 **
   1023 ** Parameters:      p_buf   - (input) pointer to the buffer
   1024 **                  task_id - (input) task id to change ownership to
   1025 **
   1026 ** Returns          void
   1027 **
   1028 *******************************************************************************/
   1029 void GKI_change_buf_owner(void* p_buf, uint8_t task_id) {
   1030   BUFFER_HDR_T* p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
   1031 
   1032   p_hdr->task_id = task_id;
   1033 
   1034   return;
   1035 }
   1036 
   1037 #if (GKI_SEND_MSG_FROM_ISR == TRUE)
   1038 /*******************************************************************************
   1039 **
   1040 ** Function         GKI_isend_msg
   1041 **
   1042 ** Description      Called from interrupt context to send a buffer to a task
   1043 **
   1044 ** Returns          Nothing
   1045 **
   1046 *******************************************************************************/
   1047 void GKI_isend_msg(uint8_t task_id, uint8_t mbox, void* msg) {
   1048   BUFFER_HDR_T* p_hdr;
   1049   tGKI_COM_CB* p_cb = &gki_cb.com;
   1050 
   1051   /* If task non-existant or not started, drop buffer */
   1052   if ((task_id >= GKI_MAX_TASKS) || (mbox >= NUM_TASK_MBOX) ||
   1053       (p_cb->OSRdyTbl[task_id] == TASK_DEAD)) {
   1054     GKI_exception(GKI_ERROR_SEND_MSG_BAD_DEST, "Sending to unknown dest");
   1055     GKI_freebuf(msg);
   1056     return;
   1057   }
   1058 
   1059 #if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
   1060   if (gki_chk_buf_damage(msg)) {
   1061     GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Send - Buffer corrupted");
   1062     return;
   1063   }
   1064 #endif
   1065 
   1066 #if (GKI_ENABLE_OWNER_CHECK == TRUE)
   1067   if (gki_chk_buf_owner(msg)) {
   1068     GKI_exception(GKI_ERROR_NOT_BUF_OWNER, "Send by non-owner");
   1069     return;
   1070   }
   1071 #endif
   1072 
   1073   p_hdr = (BUFFER_HDR_T*)((uint8_t*)msg - BUFFER_HDR_SIZE);
   1074 
   1075   if (p_hdr->status != BUF_STATUS_UNLINKED) {
   1076     GKI_exception(GKI_ERROR_SEND_MSG_BUF_LINKED, "Send - buffer linked");
   1077     return;
   1078   }
   1079 
   1080   if (p_cb->OSTaskQFirst[task_id][mbox])
   1081     p_cb->OSTaskQLast[task_id][mbox]->p_next = p_hdr;
   1082   else
   1083     p_cb->OSTaskQFirst[task_id][mbox] = p_hdr;
   1084 
   1085   p_cb->OSTaskQLast[task_id][mbox] = p_hdr;
   1086 
   1087   p_hdr->p_next = NULL;
   1088   p_hdr->status = BUF_STATUS_QUEUED;
   1089   p_hdr->task_id = task_id;
   1090 
   1091   GKI_isend_event(task_id, (uint16_t)EVENT_MASK(mbox));
   1092 
   1093   return;
   1094 }
   1095 #endif
   1096 
   1097 /*******************************************************************************
   1098 **
   1099 ** Function         GKI_create_pool
   1100 **
   1101 ** Description      Called by applications to create a buffer pool.
   1102 **
   1103 ** Parameters:      size - (input) length (in bytes) of each buffer in the pool
   1104 **                  count - (input) number of buffers to allocate for the pool
   1105 **                  permission - (input) restricted or public access?
   1106 **                                      (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL)
   1107 **                  p_mem_pool - (input) pointer to an OS memory pool, NULL if
   1108 **                                       not provided
   1109 **
   1110 ** Returns          the buffer pool ID, which should be used in calls to
   1111 **                  GKI_getpoolbuf(). If a pool could not be created, this
   1112 **                  function returns 0xff.
   1113 **
   1114 *******************************************************************************/
   1115 uint8_t GKI_create_pool(uint16_t size, uint16_t count, uint8_t permission,
   1116                         void* p_mem_pool) {
   1117   uint8_t xx;
   1118   uint32_t mem_needed;
   1119   int32_t tempsize = size;
   1120   tGKI_COM_CB* p_cb = &gki_cb.com;
   1121 
   1122   /* First make sure the size of each pool has a valid size with room for the
   1123    * header info */
   1124   if (size > MAX_USER_BUF_SIZE) return (GKI_INVALID_POOL);
   1125 
   1126   /* First, look for an unused pool */
   1127   for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++) {
   1128     if (!p_cb->pool_start[xx]) break;
   1129   }
   1130 
   1131   if (xx == GKI_NUM_TOTAL_BUF_POOLS) return (GKI_INVALID_POOL);
   1132 
   1133   /* Ensure an even number of longwords */
   1134   tempsize = (int32_t)ALIGN_POOL(size);
   1135 
   1136   mem_needed = (tempsize + BUFFER_PADDING_SIZE) * count;
   1137 
   1138   if (!p_mem_pool) p_mem_pool = GKI_os_malloc(mem_needed);
   1139 
   1140   if (p_mem_pool) {
   1141     /* Initialize the new pool */
   1142     gki_init_free_queue(xx, size, count, p_mem_pool);
   1143     gki_add_to_pool_list(xx);
   1144     (void)GKI_set_pool_permission(xx, permission);
   1145     p_cb->curr_total_no_of_pools++;
   1146 
   1147     return (xx);
   1148   } else
   1149     return (GKI_INVALID_POOL);
   1150 }
   1151 
   1152 /*******************************************************************************
   1153 **
   1154 ** Function         GKI_delete_pool
   1155 **
   1156 ** Description      Called by applications to delete a buffer pool.  The
   1157 **                  function calls the operating specific function to free the
   1158 **                  actual memory. An exception is generated if an error is
   1159 **                  detected.
   1160 **
   1161 ** Parameters:      pool_id - (input) Id of the poll being deleted.
   1162 **
   1163 ** Returns          void
   1164 **
   1165 *******************************************************************************/
   1166 void GKI_delete_pool(uint8_t pool_id) {
   1167   FREE_QUEUE_T* Q;
   1168   tGKI_COM_CB* p_cb = &gki_cb.com;
   1169 
   1170   if ((pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!p_cb->pool_start[pool_id]))
   1171     return;
   1172 
   1173   GKI_disable();
   1174   Q = &p_cb->freeq[pool_id];
   1175 
   1176   if (!Q->cur_cnt) {
   1177     Q->size = 0;
   1178     Q->total = 0;
   1179     Q->cur_cnt = 0;
   1180     Q->max_cnt = 0;
   1181     Q->p_first = NULL;
   1182     Q->p_last = NULL;
   1183 
   1184     GKI_os_free(p_cb->pool_start[pool_id]);
   1185 
   1186     p_cb->pool_start[pool_id] = NULL;
   1187     p_cb->pool_end[pool_id] = NULL;
   1188     p_cb->pool_size[pool_id] = 0;
   1189 
   1190     gki_remove_from_pool_list(pool_id);
   1191     p_cb->curr_total_no_of_pools--;
   1192   } else
   1193     GKI_exception(GKI_ERROR_DELETE_POOL_BAD_QID, "Deleting bad pool");
   1194 
   1195   GKI_enable();
   1196 
   1197   return;
   1198 }
   1199 
   1200 #endif /*  BTU_STACK_LITE_ENABLED == FALSE */
   1201 
   1202 /*******************************************************************************
   1203 **
   1204 ** Function         GKI_get_pool_bufsize
   1205 **
   1206 ** Description      Called by an application to get the size of buffers in a
   1207 **                  pool
   1208 **
   1209 ** Parameters       Pool ID.
   1210 **
   1211 ** Returns          the size of buffers in the pool
   1212 **
   1213 *******************************************************************************/
   1214 uint16_t GKI_get_pool_bufsize(uint8_t pool_id) {
   1215   if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
   1216     return (gki_cb.com.freeq[pool_id].size);
   1217 
   1218   return (0);
   1219 }
   1220 
   1221 /*******************************************************************************
   1222 **
   1223 ** Function         GKI_poolutilization
   1224 **
   1225 ** Description      Called by an application to get the buffer utilization
   1226 **                  in the specified buffer pool.
   1227 **
   1228 ** Parameters       pool_id - (input) pool ID to get the free count of.
   1229 **
   1230 ** Returns          % of buffers used from 0 to 100
   1231 **
   1232 *******************************************************************************/
   1233 uint16_t GKI_poolutilization(uint8_t pool_id) {
   1234   FREE_QUEUE_T* Q;
   1235 
   1236   if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) return (100);
   1237 
   1238   Q = &gki_cb.com.freeq[pool_id];
   1239 
   1240   if (Q->total == 0) return (100);
   1241 
   1242   return ((Q->cur_cnt * 100) / Q->total);
   1243 }
   1244