openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

rx_pool.c (18872B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        rx_pool.c
      8  * Purpose:     Receive packet pool code
      9  * Requires:
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/core/libc.h>
     15 
     16 #include <soc/drv.h>
     17 #include <soc/higig.h>
     18 #include <soc/property.h>
     19 
     20 #include <bcm_int/common/rx.h>
     21 #include <bcm_int/control.h>
     22 #include <bcm/rx.h>
     23 #include <bcm/stack.h>
     24 
     25 
     26 /****************************************************************
     27  *
     28  * RX POOL CODE:
     29  *
     30  *     Default allocation and free routines
     31  *
     32  * This code sets up a very simple pool of packet buffers for RX.
     33  * The buffer pool holds a fixed number of fixed size packets.
     34  * If the pool is exhausted, the allocation returns NULL.
     35  */
     36 
     37 static uint8 *rxp_all_bufs;      /* Allocation pointer */
     38 #if defined(BCM_RXP_DEBUG)
     39 static uint8 *rxp_end_bufs;      /* Points to first byte after all bufs */
     40 #endif
     41 static uint8 *rxp_free_list;     /* Free list pointer */
     42 static int rxp_pkt_size;         /* Base packet size */
     43 static int rxp_pkt_count;        /* How many packets in pool */
     44 
     45 static sal_mutex_t rxp_mutex;
     46 
     47 int rxp_memory_source_heap = 0; /* Mem source is not heap to begin-with */
     48 static void *bcm_rx_pool_memory_alloc(unsigned int size, char *locus);
     49 static void bcm_rx_pool_memory_free(void *rx_pool_addr);
     50 
     51 #ifdef BCM_RX_REFILL_FROM_INTR
     52 /* Must be interrupt-safe in this mode */
     53 #define RXP_LOCK       RX_INTR_LOCK
     54 #define RXP_UNLOCK     RX_INTR_UNLOCK
     55 #else
     56 #define RXP_LOCK       sal_mutex_take(rxp_mutex, sal_mutex_FOREVER)
     57 #define RXP_UNLOCK     sal_mutex_give(rxp_mutex)
     58 #endif
     59 
     60 /*
     61  * Define buffer alignment in physical memory.
     62  *
     63  * This is a system-specific parameter, but it is currently not possible
     64  * to retrieve this information through the SAL or BDE interfaces.
     65  */
     66 #ifndef BCM_CACHE_LINE_BYTES
     67 #define BCM_CACHE_LINE_BYTES 128 /* Should be fine on most platforms */
     68 #endif
     69 #define RXP_ALIGN(_a) \
     70     ((_a + (BCM_CACHE_LINE_BYTES - 1)) & ~(BCM_CACHE_LINE_BYTES - 1))
     71 
     72 #define RXP_INIT                                                        \
     73     if (rxp_mutex == NULL &&                                            \
     74             (rxp_mutex = sal_mutex_create("rx_pool")) == NULL)          \
     75         return BCM_E_MEMORY
     76 
     77 /* Define function interfaces to RX pool memory allocator
     78 
     79    External functions must provide the same interface as
     80    sal_dma_alloc() and sal_dma_free().
     81 
     82    BCM_RX_POOL_MEM_ALLOC() is called once during bcm_rx_pool_setup()
     83    to allocate RX buffer memory.
     84 
     85    BCM_RX_POOL_MEM_FREE() is called once during bcm_rx_pool_cleanup()
     86    to release allocated RX buffer memory if memory was allocated. Once
     87    allocated memory is freed, BCM_RX_POOL_MEM_FREE() will not be
     88    called again until after the next call to bcm_rx_pool_setup().
     89 
     90 */
     91 #ifndef BCM_RX_POOL_MEM_ALLOC
     92 #define BCM_RX_POOL_MEM_ALLOC bcm_rx_pool_memory_alloc
     93 #endif
     94 
     95 #ifndef BCM_RX_POOL_MEM_FREE
     96 #define BCM_RX_POOL_MEM_FREE bcm_rx_pool_memory_free
     97 #endif
     98 
     99 /* Any byte in a buffer may be used to reference that buffer when freeing */
    100 
    101 /* Buffer index; use any byte in buffer to get proper index */
    102 #define RXP_BUF_IDX(buf)  \
    103     ( ((buf) - rxp_all_bufs) / rxp_pkt_size )
    104 
    105 /*
    106  * Get the start/end addresses of a buffer given the index of the pkt
    107  */
    108 
    109 #define RXP_BUF_START(idx)  \
    110     (rxp_all_bufs + ((idx) * rxp_pkt_size))
    111 
    112 /*
    113  * Get the start address of a buffer given a pointer to any byte in the
    114  * buffer.
    115  */
    116 
    117 #define RXP_PTR_TO_START(ptr) RXP_BUF_START(RXP_BUF_IDX(ptr))
    118 
    119 /*
    120  * When buffers are not allocated, the first word is used as a pointer
    121  * for linked lists.  Requires alignment of the buffers.
    122  */
    123 #define RXP_PKT_NEXT(buf) ( ((uint8 **)(RXP_PTR_TO_START(buf)))[0])
    124 
    125 #if defined(BCM_RXP_DEBUG)
    126 
    127 /*
    128  * Does "val" point into the buffer space at all?
    129  */
    130 
    131 #define RXP_IN_BUFFER_SPACE(val) \
    132     (((val) < rxp_end_bufs) && ((val) >= rxp_all_bufs))
    133 
    134 /*
    135  * Does "val" point to the start of a buffer?
    136  */
    137 
    138 #define RXP_IS_BUF_START(val) \
    139     (RXP_IN_BUFFER_SPACE(val) &&   \
    140      (((val) - rxp_all_bufs) % rxp_pkt_size == 0))
    141 
    142 /*
    143  * Keep pointer to "owner" for each packet
    144  *
    145  * Buffers are filled with 0xee (empty) when on free list;
    146  * Filled with 0xaa when allocated
    147  */
    148 
    149 typedef struct {
    150     int state;
    151     const char *owner;
    152     int alloc;
    153     int free;
    154 } RXP_TRACK_t;
    155 
    156 static RXP_TRACK_t *rxp_tracker;
    157 static int rxp_tot_alloc_count;
    158 static int rxp_tot_free_count;
    159 static int rxp_alloc_fail;
    160 
    161 static int bcm_rx_pool_free_buf_verify(void *buf);
    162 static int bcm_rx_pool_free_verify_p(void);
    163 
    164 #endif /* BCM_RXP_DEBUG */
    165 
    166 static int rxp_alloc_count;
    167 
    168 /*
    169  * Function:
    170  *      bcm_rx_pool_memory_alloc
    171  * Purpose:
    172  *      Allocate memory for RX Pool
    173  * Parameters:
    174  *      size   - Number of bytes to be allocated
    175  *      locus  - User defined memory description
    176  * Returns:
    177  *      Valid Address, if allocation successful else NULL.
    178  * Notes:
    179  *      The function allocates the memory from heap if directed
    180  *      so based on the global variable rxp_memory_source_heap.
    181  */
    182 static void *
    183 bcm_rx_pool_memory_alloc(unsigned int size, char *locus)
    184 {
    185     return (rxp_memory_source_heap ?
    186                 sal_alloc(size, locus) : sal_dma_alloc(size, locus));
    187 }
    188 
    189 /*
    190  * Function:
    191  *      bcm_rx_pool_memory_free
    192  * Purpose:
    193  *      Deallocate given memory from RX Pool
    194  * Parameters:
    195  *      ptr   - Address of the RX pool
    196  * Returns:
    197  *      None
    198  * Notes:
    199  *      1) Function assumes given address is valid RX pool buffer address
    200  *      2) It releases memory to heap instead of DMA pool if directed so
    201  */
    202 static void
    203 bcm_rx_pool_memory_free(void *rx_pool_addr)
    204 {
    205     rxp_memory_source_heap ?
    206         sal_free(rx_pool_addr) : sal_dma_free(rx_pool_addr);
    207 }
    208 
    209 
    210 /*
    211  * Function:
    212  *      bcm_rx_pool_setup
    213  * Purpose:
    214  *      Setup the RX packet pool
    215  * Parameters:
    216  *      pkt_count      - How many pkts in pool.  < 0 ==> default
    217  *      bytes_per_pkt  - Packet allocation size
    218  * Returns:
    219  *      BCM_E_XXX
    220  * Notes:
    221  *      Force alignment of the words so the pointers are safe
    222  *
    223  *      The pool cannot be setup up twice without calling cleanup
    224  *      to deallocate pointers.
    225  */
    226 
    227 int
    228 bcm_rx_pool_setup(int pkt_count, int bytes_per_pkt)
    229 {
    230     uint8 *buf, *next_buf;
    231     int i;
    232 
    233     RXP_INIT;
    234 
    235     if (rxp_all_bufs != NULL) {
    236         return BCM_E_BUSY;
    237     }
    238 
    239     if (pkt_count < 0) {
    240         pkt_count = BCM_RX_POOL_COUNT_DEFAULT;
    241     }
    242     if (bytes_per_pkt < 0) {
    243         bytes_per_pkt = BCM_RX_POOL_BYTES_DEFAULT;
    244     } else {
    245         /* Add 14 dwords worth extra space for HG and other Module headers */
    246         bytes_per_pkt += 56;
    247     }
    248 
    249     /* Force packet alignment */
    250     bytes_per_pkt = RXP_ALIGN(bytes_per_pkt);
    251     rxp_pkt_size = bytes_per_pkt;
    252     rxp_pkt_count = pkt_count;
    253     rxp_all_bufs = BCM_RX_POOL_MEM_ALLOC(pkt_count * rxp_pkt_size, "bcm_rx_pool");
    254     if (rxp_all_bufs == NULL) {
    255         return BCM_E_MEMORY;
    256     }
    257     /* Set to all 0xee for RXP debug */
    258     sal_memset(rxp_all_bufs, 0xee, rxp_pkt_count * rxp_pkt_size);
    259 
    260     RXP_LOCK;
    261     buf = rxp_all_bufs;
    262     rxp_free_list = buf;
    263     for (i = 0; i < pkt_count - 1; i++) {
    264         next_buf = buf + rxp_pkt_size;
    265         RXP_PKT_NEXT(buf) = next_buf;
    266         buf = next_buf;
    267     }
    268 
    269     RXP_PKT_NEXT(buf) = NULL;
    270 
    271 #if defined(BCM_RXP_DEBUG)
    272     {
    273         int bytes;
    274         int idx;
    275         bytes = sizeof(RXP_TRACK_t) * pkt_count;
    276         rxp_tracker = sal_alloc(bytes, "rx_pool_dbg");
    277         for (idx = 0; idx < pkt_count; idx++) {
    278             rxp_tracker[idx].owner = "";
    279             rxp_tracker[idx].state = 0;
    280             rxp_tracker[idx].alloc = 0;
    281             rxp_tracker[idx].free = 0;
    282         }
    283         rxp_tot_alloc_count = 0;
    284         rxp_tot_free_count = 0;
    285         rxp_alloc_fail = 0;
    286         rxp_end_bufs = rxp_all_bufs + rxp_pkt_count * rxp_pkt_size;
    287     }
    288 #endif
    289     rxp_alloc_count = 0;
    290     RXP_UNLOCK;
    291 
    292     return BCM_E_NONE;
    293 }
    294 
    295 
    296 /*
    297  * Function:
    298  *      bcm_rx_pool_setup_done
    299  * Purpose:
    300  *      Indicate if setup is complete
    301  * Returns:
    302  *      Boolean:  True if setup is done
    303  */
    304 
    305 int
    306 bcm_rx_pool_setup_done(void)
    307 {
    308     return rxp_all_bufs != NULL;
    309 }
    310 
    311 
    312 /*
    313  * Function:
    314  *      bcm_rx_pool_cleanup
    315  * Purpose:
    316  *      Deallocate the rx buffer pool
    317  * Returns:
    318  *      BCM_E_XXX
    319  * Notes:
    320  *      No checking is done to see if pointers are outstanding.
    321  */
    322 
    323 int
    324 bcm_rx_pool_cleanup(void)
    325 {
    326     if (rxp_all_bufs == NULL) {
    327         return BCM_E_NONE;
    328     }
    329 
    330     RXP_LOCK;
    331 
    332 #ifndef BCM_SAND_SUPPORT
    333     /* If any pkt data block is still in use then return BUSY err code */
    334     if (rxp_alloc_count) {
    335         RXP_UNLOCK;
    336         return BCM_E_BUSY;
    337     }
    338 #endif
    339 
    340     BCM_RX_POOL_MEM_FREE(rxp_all_bufs);
    341 
    342     rxp_all_bufs = NULL;
    343     rxp_free_list = NULL;
    344 
    345 #if defined(BCM_RXP_DEBUG)
    346     sal_free(rxp_tracker);
    347     rxp_tracker = NULL;
    348 #endif
    349     RXP_UNLOCK;
    350 
    351     return BCM_E_NONE;
    352 }
    353 
    354 /*
    355  * Function:
    356  *      bcm_rx_pool_alloc
    357  * Purpose:
    358  *      Allocate a buffer from a fixed pool configured
    359  *      by bcm_rx_pool_setup.
    360  * Parameters:
    361  *      unit          - Ignored
    362  *      size          - Size of buffer to allocate
    363  *      flags         - Ignored
    364  * Returns:
    365  *      Pointer to buffer if successful, NULL if failure.
    366  * Notes:
    367  *      Can fail for:
    368  *
    369  *      1.  One size fits all....if size > how the list was set up,
    370  *          then the function fails.
    371  *      2.  Not initialized
    372  *      3.  No free buffers
    373  *
    374  *      The first word of the buffer is used as a "next" pointer when
    375  *      the buffer is in the free list.
    376  */
    377 
    378 int
    379 bcm_rx_pool_alloc(int unit, int size, uint32 flags, void **pool)
    380 {
    381     uint8 *rv;
    382 
    383     COMPILER_REFERENCE(unit);
    384     COMPILER_REFERENCE(flags);
    385 
    386     if (rxp_mutex == NULL) {
    387         *pool = NULL;
    388         return BCM_E_TIMEOUT;
    389     }
    390 
    391     if (rxp_pkt_size > 0) {
    392         size = rxp_pkt_size;
    393     }
    394 
    395     if (size > rxp_pkt_size) {
    396         LOG_ERROR(BSL_LS_BCM_COMMON,
    397                   (BSL_META_U(unit,
    398                               "bcm_rx_pool_alloc: %d > %d\n"),
    399                    size, rxp_pkt_size));
    400         *pool = NULL;
    401         return BCM_E_MEMORY;
    402     }
    403 
    404     RXP_LOCK;
    405     if (rxp_free_list == NULL) {
    406 #if defined(BCM_RXP_DEBUG)
    407         ++rxp_alloc_fail;
    408 #endif
    409         RXP_UNLOCK;
    410         *pool = NULL;
    411         return BCM_E_MEMORY;
    412     }
    413     rv = rxp_free_list;
    414     rxp_free_list = RXP_PKT_NEXT(rxp_free_list);
    415 
    416 #if defined(BCM_RXP_DEBUG)
    417     {
    418         int idx;
    419         static const char *track_name = "rx_pool_alloc";
    420 
    421         assert(RXP_IS_BUF_START(rv));
    422         if (rxp_free_list != NULL) {
    423             assert(RXP_IS_BUF_START(rxp_free_list));
    424         }
    425 
    426         idx = RXP_BUF_IDX(rv);
    427         rxp_tracker[idx].owner = track_name;
    428         rxp_tracker[idx].state = 1;
    429         rxp_tracker[idx].alloc++;
    430         if (bcm_rx_pool_free_buf_verify(rv) != BCM_E_NONE) {
    431             assert(0);
    432         }
    433 
    434         /* Fill allocated buffer with 0xaa */
    435         sal_memset(rv, 0xaa, rxp_pkt_size);
    436         ++rxp_tot_alloc_count;
    437     }
    438 #endif /* BCM_RXP_DEBUG */
    439     ++rxp_alloc_count;
    440 
    441     RXP_UNLOCK;
    442 
    443     *pool = (void *)rv;
    444     return BCM_E_NONE;
    445 }
    446 
    447 /*
    448  * Function:
    449  *      bcm_rx_pool_free
    450  * Purpose:
    451  *      Return a buffer allocated by bcm_rx_pool_alloc to the free list
    452  * Parameters:
    453  *      unit       - Ignored
    454  *      buf        - The buffer to free
    455  * Returns:
    456  *      BCM_E_XXX
    457  */
    458 
    459 int
    460 bcm_rx_pool_free(int unit, void *buf)
    461 {
    462     uint8 *start;
    463     uint8 *buf8;
    464 
    465     COMPILER_REFERENCE(unit);
    466 
    467     RXP_LOCK;
    468 
    469     if (rxp_all_bufs == NULL) { /* not running */
    470         RXP_UNLOCK;
    471         return BCM_E_MEMORY;
    472     }
    473 
    474     buf8 = (uint8 *)buf;
    475     start = RXP_PTR_TO_START(buf8);
    476 
    477 #if defined(BCM_RXP_DEBUG)
    478     {
    479         int idx, i;
    480         uint32 *ptr;
    481 
    482         COMPILER_REFERENCE(ptr);
    483         COMPILER_REFERENCE(i);
    484         idx = RXP_BUF_IDX(buf8);
    485         assert((idx >= 0 && idx < rxp_pkt_count));
    486         rxp_tracker[idx].free++;
    487         if (rxp_tracker[idx].state == 0) {
    488             /* Buffers should never be freed more than once, but
    489                distinguish the error between a freed buffer that gets
    490                reused vs. one that doesn't. */
    491             LOG_WARN(BSL_LS_BCM_COMMON,
    492                      (BSL_META_U(unit,
    493                                  "Double free of buffer %d\n"),
    494                       idx));
    495             if (bcm_rx_pool_free_buf_verify(buf) != BCM_E_NONE) {
    496                 assert(0);
    497             }
    498             assert(0);
    499         }
    500         rxp_tracker[idx].state = 0;
    501         /* Fill buffer with 0xee, except for first word */
    502         sal_memset(RXP_BUF_START(idx) + sizeof(void *), 0xee,
    503                    rxp_pkt_size - sizeof(void *));
    504 #if 1 /* Turn this on to verify the entire free list */
    505         if (bcm_rx_pool_free_verify_p() != BCM_E_NONE) {
    506             LOG_WARN(BSL_LS_BCM_COMMON,
    507                      (BSL_META_U(unit,
    508                                  "RX Pool error while checking %d\n"),
    509                       idx));
    510             assert(0);
    511         }
    512 #else
    513         /* Check head of free list for good measure */
    514         if (rxp_free_list != NULL) {
    515             if (bcm_rx_pool_free_buf_verify(rxp_free_list) != BCM_E_NONE) {
    516                 assert(0);
    517             }
    518         }
    519 #endif
    520         ++rxp_tot_free_count;
    521     }
    522 #endif /* BCM_RXP_DEBUG */
    523 
    524     rxp_alloc_count--;
    525 
    526     RXP_PKT_NEXT(start) = rxp_free_list;
    527     rxp_free_list = start;
    528     RXP_UNLOCK;
    529 
    530     return BCM_E_NONE;
    531 }
    532 
    533 
    534 #if defined(BCM_RXP_DEBUG)
    535 
    536 void
    537 bcm_rx_pool_dump(int min, int max)
    538 {
    539     int i;
    540     uint32 *ptr;
    541 
    542     if (min < 0) {
    543         min = 0;
    544     }
    545     if (max > rxp_pkt_count) {
    546         max = rxp_pkt_count;
    547     }
    548     for (i = min; i < max; i++) {
    549         ptr = (uint32 *)RXP_BUF_START(i);
    550         LOG_WARN(BSL_LS_BCM_COMMON,
    551                  (BSL_META("Pkt %d: %p. [0] 0x%x [1] 0x%x [2] 0x%x\n"),
    552                   i,
    553                   ptr, ptr[0], ptr[1], ptr[2]));
    554     }
    555 }
    556 
    557 /* Check a buffer in the free pool */
    558 
    559 #define FREE_STATE 0xeeeeeeee
    560 #define ALLOC_STATE 0xaaaaaaaa
    561 
    562 void
    563 bcm_rx_pool_buf_dump(void *buf, int until)
    564 {
    565     int i;
    566     uint32 *ptr;
    567 
    568     ptr = ((uint32 *)RXP_PTR_TO_START((uint8 *)buf)) + 1;
    569     for (i = 0; i < rxp_pkt_size - sizeof(void *); i += sizeof(uint32)) {
    570         if ((i & 31) == 0) {
    571             if (i > until && (*ptr == FREE_STATE || *ptr == ALLOC_STATE)) {
    572                 break;
    573             }
    574             LOG_ERROR(BSL_LS_BCM_COMMON,
    575                       (BSL_META("\n%p:"),
    576                        ptr));
    577         }
    578         LOG_ERROR(BSL_LS_BCM_COMMON,
    579                   (BSL_META(" %08x"),
    580                    *ptr));
    581         ptr++;
    582     }
    583     LOG_ERROR(BSL_LS_BCM_COMMON,
    584               (BSL_META("\n")));
    585 }
    586 
    587 
    588 static int
    589 bcm_rx_pool_free_buf_verify(void *buf)
    590 {
    591     int i;
    592     uint32 *ptr;
    593 
    594     ptr = (uint32 *)(RXP_PTR_TO_START((uint8 *)buf) + sizeof (void *));
    595     for (i = 0; i < rxp_pkt_size - sizeof(void *); i += sizeof(uint32)) {
    596         if (*ptr != FREE_STATE) {
    597             return BCM_E_INTERNAL;
    598         }
    599         ptr++;
    600     }
    601     return BCM_E_NONE;
    602 }
    603 
    604 /* Check the entire free pool and return BCM_E_NONE if OK or BCM_E_INTERNAL if there
    605    was some sort of inconsistency detected. */
    606 static int
    607 bcm_rx_pool_free_verify_p(void)
    608 {
    609     uint8 *buf;
    610     uint8 *last_buf = NULL;
    611     int idx;
    612     int rc = BCM_E_NONE;
    613 
    614     for (buf = rxp_free_list; buf != NULL; buf = RXP_PKT_NEXT(buf)) {
    615         idx = RXP_BUF_IDX(buf);
    616         if (!(idx >= 0 && idx < rxp_pkt_count)) {
    617             LOG_WARN(BSL_LS_BCM_COMMON,
    618                      (BSL_META("RXP BAD BUFFER %p. idx %d\n"),
    619                       buf, idx));
    620             if (last_buf != NULL) {
    621                 LOG_WARN(BSL_LS_BCM_COMMON,
    622                          (BSL_META("RXP BAD BUFFER: Previous buf %p idx %d\n"),
    623                           last_buf, RXP_BUF_IDX(last_buf)));
    624             } else {
    625                 LOG_WARN(BSL_LS_BCM_COMMON,
    626                          (BSL_META("RXP BAD BUFFER: First elt of free list\n")));
    627             }
    628             if (idx >= 0 && idx < rxp_pkt_count) {
    629                 LOG_WARN(BSL_LS_BCM_COMMON,
    630                          (BSL_META("RXP IDX %d out of range (0,%d)"),
    631                           idx, rxp_pkt_count));
    632             }
    633             return BCM_E_INTERNAL;
    634         }
    635         last_buf = buf;
    636         if ((rc=bcm_rx_pool_free_buf_verify(buf)) != BCM_E_NONE) {
    637             return rc;
    638         }
    639     }
    640     return rc;
    641 }
    642 
    643 /* API call */
    644 void
    645 bcm_rx_pool_free_verify(void)
    646 {
    647     (void)bcm_rx_pool_free_verify_p();
    648 }
    649 
    650 void
    651 bcm_rx_pool_own(void *buf, void *owner)
    652 {
    653 #if defined(LINUX) || defined(__KERNEL__)
    654     /* Need to fix this */
    655     return;
    656 #else
    657     int idx;
    658     idx = RXP_BUF_IDX((uint8 *)buf);
    659 
    660 #if 1  /* Turn this off to give warning rather than assert */
    661     assert((idx >= 0) && (idx < rxp_pkt_count));
    662     rxp_tracker[idx].owner = (char *)owner;
    663 #else
    664     if ((idx < 0) || (idx >= rxp_pkt_count)) {
    665         LOG_WARN(BSL_LS_BCM_COMMON,
    666                  (BSL_META("RXP: Buffer %p (idx %d) out of range "
    667                   "max %d, owner %s\n"), buf, idx,
    668                   rxp_pkt_count, (char *)owner));
    669     } else {
    670         /*    assert((idx > 0) && (idx < rxp_pkt_count)); */
    671         rxp_tracker[idx].owner = (char *)owner;
    672     }
    673 #endif
    674 #endif
    675 }
    676 
    677 #define _ISALPHA(c) \
    678     ((c[0] >= 'A' && c[0] <= 'Z') || (c[0] >= 'a' && c[0] <= 'z'))
    679 
    680 /* Check that a buffer is in use, or free and not corrupted */
    681 static int rx_pool_buf_ok(int idx)
    682 {
    683     if (rxp_tracker[idx].state == 0) {
    684         return bcm_rx_pool_free_buf_verify(RXP_BUF_START(idx));
    685     }
    686     return BCM_E_NONE;
    687 }
    688 
    689 void
    690 bcm_rx_pool_report(int min, int max)
    691 {
    692     int i, count = 0;
    693     const char *str;
    694 
    695     for (i = 0; i < rxp_pkt_count; i++) {
    696         if (rxp_tracker[i].state != 0) {
    697             count++;
    698         }
    699     }
    700     LOG_ERROR(BSL_LS_BCM_COMMON,
    701               (BSL_META(" #  s  alloc    free     owner\n")));
    702     LOG_ERROR(BSL_LS_BCM_COMMON,
    703               (BSL_META("--- -  -------- -------- ------------\n")));
    704     for (i = min; i < max; i++) {
    705         str = rxp_tracker[i].owner;
    706         LOG_ERROR(BSL_LS_BCM_COMMON,
    707                   (BSL_META("%3d %1d%s %8d %8d %p %s\n"),
    708                    i,
    709                    rxp_tracker[i].state,
    710                    rx_pool_buf_ok(i)? "?" : " ",
    711                    rxp_tracker[i].alloc,
    712                    rxp_tracker[i].free,
    713                    str,
    714                    _ISALPHA(str) ? str : "?"));
    715     }
    716 
    717     LOG_ERROR(BSL_LS_BCM_COMMON,
    718               (BSL_META("  RXPool Used %d. Failed %d. Tot alloc %d. "
    719                "Tot free %d. Size %d. Count %d.\n"), rxp_alloc_count, rxp_alloc_fail,
    720                rxp_tot_alloc_count, rxp_tot_free_count, rxp_pkt_size, rxp_pkt_count));
    721     if (count != rxp_alloc_count) {
    722         LOG_ERROR(BSL_LS_BCM_COMMON,
    723                   (BSL_META("  RXP WARNING:  Alloc %d, counted %d\n"),
    724                    rxp_alloc_count, count));
    725     }
    726 }
    727 #undef _ISALPHA
    728 
    729 #endif /* BCM_RXP_DEBUG */