1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * HND generic packet pool operation primitives 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Portions of this code are copyright (c) 2021 Cypress Semiconductor Corporation 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Copyright (C) 1999-2017, Broadcom Corporation 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * Unless you and Broadcom execute a separate written software license 9*4882a593Smuzhiyun * agreement governing use of this software, this software is licensed to you 10*4882a593Smuzhiyun * under the terms of the GNU General Public License version 2 (the "GPL"), 11*4882a593Smuzhiyun * available at http://www.broadcom.com/licenses/GPLv2.php, with the 12*4882a593Smuzhiyun * following added to such license: 13*4882a593Smuzhiyun * 14*4882a593Smuzhiyun * As a special exception, the copyright holders of this software give you 15*4882a593Smuzhiyun * permission to link this software with independent modules, and to copy and 16*4882a593Smuzhiyun * distribute the resulting executable under terms of your choice, provided that 17*4882a593Smuzhiyun * you also meet, for each linked independent module, the terms and conditions of 18*4882a593Smuzhiyun * the license of that module. An independent module is a module which is not 19*4882a593Smuzhiyun * derived from this software. The special exception does not apply to any 20*4882a593Smuzhiyun * modifications of the software. 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * Notwithstanding the above, under no circumstances may you combine this 23*4882a593Smuzhiyun * software in any way with any other Broadcom software provided under a license 24*4882a593Smuzhiyun * other than the GPL, without Broadcom's express prior written consent. 25*4882a593Smuzhiyun * 26*4882a593Smuzhiyun * 27*4882a593Smuzhiyun * <<Broadcom-WL-IPTag/Open:>> 28*4882a593Smuzhiyun * 29*4882a593Smuzhiyun * $Id: hnd_pktpool.h 633941 2016-04-26 07:04:26Z $ 30*4882a593Smuzhiyun */ 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun #ifndef _hnd_pktpool_h_ 33*4882a593Smuzhiyun #define _hnd_pktpool_h_ 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun #include <osl_ext.h> 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun #ifdef __cplusplus 38*4882a593Smuzhiyun extern "C" { 39*4882a593Smuzhiyun #endif // endif 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun /* mutex macros for thread safe */ 42*4882a593Smuzhiyun #ifdef HND_PKTPOOL_THREAD_SAFE 43*4882a593Smuzhiyun #define HND_PKTPOOL_MUTEX_DECL(mutex) OSL_EXT_MUTEX_DECL(mutex) 44*4882a593Smuzhiyun #else 45*4882a593Smuzhiyun #define HND_PKTPOOL_MUTEX_DECL(mutex) 46*4882a593Smuzhiyun #endif // endif 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun #ifdef BCMPKTPOOL 49*4882a593Smuzhiyun #define POOL_ENAB(pool) ((pool) && (pool)->inited) 50*4882a593Smuzhiyun #else /* BCMPKTPOOL */ 51*4882a593Smuzhiyun #define POOL_ENAB(bus) 0 52*4882a593Smuzhiyun #endif /* BCMPKTPOOL */ 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun #ifndef PKTPOOL_LEN_MAX 55*4882a593Smuzhiyun #define PKTPOOL_LEN_MAX 40 56*4882a593Smuzhiyun #endif /* PKTPOOL_LEN_MAX */ 57*4882a593Smuzhiyun #define PKTPOOL_CB_MAX 3 58*4882a593Smuzhiyun #define PKTPOOL_CB_MAX_AVL 4 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun /* REMOVE_RXCPLID is an arg for pktpool callback function for removing rxcplID 61*4882a593Smuzhiyun * and host addr associated with the rxfrag or shared pool buffer during pktpool_reclaim(). 62*4882a593Smuzhiyun */ 63*4882a593Smuzhiyun #define REMOVE_RXCPLID 2 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun /* forward declaration */ 66*4882a593Smuzhiyun struct pktpool; 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); 69*4882a593Smuzhiyun typedef struct { 70*4882a593Smuzhiyun pktpool_cb_t cb; 71*4882a593Smuzhiyun void *arg; 72*4882a593Smuzhiyun uint8 refcnt; 73*4882a593Smuzhiyun } pktpool_cbinfo_t; 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun /** PCIe SPLITRX related: call back fn extension to populate host address in pool pkt */ 76*4882a593Smuzhiyun typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg1, void* pkt, int arg2); 77*4882a593Smuzhiyun typedef struct { 78*4882a593Smuzhiyun pktpool_cb_extn_t cb; 79*4882a593Smuzhiyun void *arg; 80*4882a593Smuzhiyun } pktpool_cbextn_info_t; 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun #ifdef BCMDBG_POOL 83*4882a593Smuzhiyun /* pkt pool debug states */ 84*4882a593Smuzhiyun #define POOL_IDLE 0 85*4882a593Smuzhiyun #define POOL_RXFILL 1 86*4882a593Smuzhiyun #define POOL_RXDH 2 87*4882a593Smuzhiyun #define POOL_RXD11 3 88*4882a593Smuzhiyun #define POOL_TXDH 4 89*4882a593Smuzhiyun #define POOL_TXD11 5 90*4882a593Smuzhiyun #define POOL_AMPDU 6 91*4882a593Smuzhiyun #define POOL_TXENQ 7 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun typedef struct { 94*4882a593Smuzhiyun void *p; 95*4882a593Smuzhiyun uint32 cycles; 96*4882a593Smuzhiyun uint32 dur; 97*4882a593Smuzhiyun } pktpool_dbg_t; 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun typedef struct { 100*4882a593Smuzhiyun uint8 txdh; /* tx to host */ 101*4882a593Smuzhiyun uint8 txd11; /* tx to d11 */ 102*4882a593Smuzhiyun uint8 enq; /* waiting in q */ 103*4882a593Smuzhiyun uint8 rxdh; /* rx from host */ 104*4882a593Smuzhiyun uint8 rxd11; /* rx from d11 */ 105*4882a593Smuzhiyun uint8 rxfill; /* dma_rxfill */ 106*4882a593Smuzhiyun uint8 idle; /* avail in pool */ 107*4882a593Smuzhiyun } pktpool_stats_t; 108*4882a593Smuzhiyun #endif /* BCMDBG_POOL */ 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun typedef struct pktpool { 111*4882a593Smuzhiyun bool inited; /**< pktpool_init was successful */ 112*4882a593Smuzhiyun uint8 type; /**< type of lbuf: basic, frag, etc */ 113*4882a593Smuzhiyun uint8 id; /**< pktpool ID: index in registry */ 114*4882a593Smuzhiyun bool istx; /**< direction: transmit or receive data path */ 115*4882a593Smuzhiyun HND_PKTPOOL_MUTEX_DECL(mutex) /**< thread-safe mutex */ 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun void * freelist; /**< free list: see PKTNEXTFREE(), PKTSETNEXTFREE() */ 118*4882a593Smuzhiyun uint16 avail; /**< number of packets in pool's free list */ 119*4882a593Smuzhiyun uint16 n_pkts; /**< number of packets managed by pool */ 120*4882a593Smuzhiyun uint16 maxlen; /**< maximum size of pool <= PKTPOOL_LEN_MAX */ 121*4882a593Smuzhiyun uint16 max_pkt_bytes; /**< size of pkt buffer in [bytes], excluding lbuf|lbuf_frag */ 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun bool empty; 124*4882a593Smuzhiyun uint8 cbtoggle; 125*4882a593Smuzhiyun uint8 cbcnt; 126*4882a593Smuzhiyun uint8 ecbcnt; 127*4882a593Smuzhiyun uint8 emptycb_disable; /**< Value of type enum pktpool_empty_cb_state */ 128*4882a593Smuzhiyun pktpool_cbinfo_t *availcb_excl; 129*4882a593Smuzhiyun pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX_AVL]; 130*4882a593Smuzhiyun pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; 131*4882a593Smuzhiyun pktpool_cbextn_info_t cbext; /**< PCIe SPLITRX related */ 132*4882a593Smuzhiyun pktpool_cbextn_info_t rxcplidfn; 133*4882a593Smuzhiyun #ifdef BCMDBG_POOL 134*4882a593Smuzhiyun uint8 dbg_cbcnt; 135*4882a593Smuzhiyun pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; 136*4882a593Smuzhiyun uint16 dbg_qlen; 137*4882a593Smuzhiyun pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; 138*4882a593Smuzhiyun #endif // endif 139*4882a593Smuzhiyun pktpool_cbinfo_t dmarxfill; 140*4882a593Smuzhiyun } pktpool_t; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun pktpool_t *get_pktpools_registry(int id); 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun /* Incarnate a pktpool registry. On success returns total_pools. */ 145*4882a593Smuzhiyun extern int pktpool_attach(osl_t *osh, uint32 total_pools); 146*4882a593Smuzhiyun extern int pktpool_dettach(osl_t *osh); /* Relinquish registry */ 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *n_pkts, int max_pkt_bytes, bool istx, 149*4882a593Smuzhiyun uint8 type); 150*4882a593Smuzhiyun extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); 151*4882a593Smuzhiyun extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); 152*4882a593Smuzhiyun extern int pktpool_empty(osl_t *osh, pktpool_t *pktp); 153*4882a593Smuzhiyun extern uint16 pktpool_reclaim(osl_t *osh, pktpool_t *pktp, uint16 free_cnt); 154*4882a593Smuzhiyun extern void* pktpool_get(pktpool_t *pktp); 155*4882a593Smuzhiyun extern void pktpool_free(pktpool_t *pktp, void *p); 156*4882a593Smuzhiyun extern int pktpool_add(pktpool_t *pktp, void *p); 157*4882a593Smuzhiyun extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); 158*4882a593Smuzhiyun extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); 159*4882a593Smuzhiyun extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 160*4882a593Smuzhiyun extern int pktpool_avail_deregister(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 161*4882a593Smuzhiyun extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 162*4882a593Smuzhiyun extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 max_pkts); 163*4882a593Smuzhiyun extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 max_pkts); 164*4882a593Smuzhiyun extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); 165*4882a593Smuzhiyun extern bool pktpool_emptycb_disabled(pktpool_t *pktp); 166*4882a593Smuzhiyun extern int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg1); 167*4882a593Smuzhiyun extern int pktpool_rxcplid_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg); 168*4882a593Smuzhiyun extern void pktpool_invoke_dmarxfill(pktpool_t *pktp); 169*4882a593Smuzhiyun extern int pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun #define POOLPTR(pp) ((pktpool_t *)(pp)) 172*4882a593Smuzhiyun #define POOLID(pp) (POOLPTR(pp)->id) 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun #define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid)) 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun #define pktpool_tot_pkts(pp) (POOLPTR(pp)->n_pkts) /**< n_pkts = avail + in_use <= max_pkts */ 177*4882a593Smuzhiyun #define pktpool_avail(pp) (POOLPTR(pp)->avail) 178*4882a593Smuzhiyun #define pktpool_max_pkt_bytes(pp) (POOLPTR(pp)->max_pkt_bytes) 179*4882a593Smuzhiyun #define pktpool_max_pkts(pp) (POOLPTR(pp)->maxlen) 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun /* 182*4882a593Smuzhiyun * ---------------------------------------------------------------------------- 183*4882a593Smuzhiyun * A pool ID is assigned with a pkt pool during pool initialization. This is 184*4882a593Smuzhiyun * done by maintaining a registry of all initialized pools, and the registry 185*4882a593Smuzhiyun * index at which the pool is registered is used as the pool's unique ID. 186*4882a593Smuzhiyun * ID 0 is reserved and is used to signify an invalid pool ID. 187*4882a593Smuzhiyun * All packets henceforth allocated from a pool will be tagged with the pool's 188*4882a593Smuzhiyun * unique ID. Packets allocated from the heap will use the reserved ID = 0. 189*4882a593Smuzhiyun * Packets with non-zero pool id signify that they were allocated from a pool. 190*4882a593Smuzhiyun * A maximum of 15 pools are supported, allowing a 4bit pool ID to be used 191*4882a593Smuzhiyun * in place of a 32bit pool pointer in each packet. 192*4882a593Smuzhiyun * ---------------------------------------------------------------------------- 193*4882a593Smuzhiyun */ 194*4882a593Smuzhiyun #define PKTPOOL_INVALID_ID (0) 195*4882a593Smuzhiyun #define PKTPOOL_MAXIMUM_ID (15) 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun /* Registry of pktpool(s) */ 198*4882a593Smuzhiyun /* Pool ID to/from Pool Pointer converters */ 199*4882a593Smuzhiyun #define PKTPOOL_ID2PTR(id) (get_pktpools_registry(id)) 200*4882a593Smuzhiyun #define PKTPOOL_PTR2ID(pp) (POOLID(pp)) 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun #ifdef BCMDBG_POOL 203*4882a593Smuzhiyun extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); 204*4882a593Smuzhiyun extern int pktpool_start_trigger(pktpool_t *pktp, void *p); 205*4882a593Smuzhiyun extern int pktpool_dbg_dump(pktpool_t *pktp); 206*4882a593Smuzhiyun extern int pktpool_dbg_notify(pktpool_t *pktp); 207*4882a593Smuzhiyun extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); 208*4882a593Smuzhiyun #endif /* BCMDBG_POOL */ 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun #ifdef BCMPKTPOOL 211*4882a593Smuzhiyun #define SHARED_POOL (pktpool_shared) 212*4882a593Smuzhiyun extern pktpool_t *pktpool_shared; 213*4882a593Smuzhiyun #ifdef BCMFRAGPOOL 214*4882a593Smuzhiyun #define SHARED_FRAG_POOL (pktpool_shared_lfrag) 215*4882a593Smuzhiyun extern pktpool_t *pktpool_shared_lfrag; 216*4882a593Smuzhiyun #endif // endif 217*4882a593Smuzhiyun 218*4882a593Smuzhiyun #ifdef BCMRESVFRAGPOOL 219*4882a593Smuzhiyun #define RESV_FRAG_POOL (pktpool_resv_lfrag) 220*4882a593Smuzhiyun #define RESV_POOL_INFO (resv_pool_info) 221*4882a593Smuzhiyun #else 222*4882a593Smuzhiyun #define RESV_FRAG_POOL ((struct pktpool *)NULL) 223*4882a593Smuzhiyun #define RESV_POOL_INFO (NULL) 224*4882a593Smuzhiyun #endif /* BCMRESVFRAGPOOL */ 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun /** PCIe SPLITRX related */ 227*4882a593Smuzhiyun #define SHARED_RXFRAG_POOL (pktpool_shared_rxlfrag) 228*4882a593Smuzhiyun extern pktpool_t *pktpool_shared_rxlfrag; 229*4882a593Smuzhiyun 230*4882a593Smuzhiyun int hnd_pktpool_init(osl_t *osh); 231*4882a593Smuzhiyun int hnd_pktpool_fill(pktpool_t *pktpool, bool minimal); 232*4882a593Smuzhiyun void hnd_pktpool_refill(bool minimal); 233*4882a593Smuzhiyun #ifdef BCMRESVFRAGPOOL 234*4882a593Smuzhiyun extern pktpool_t *pktpool_resv_lfrag; 235*4882a593Smuzhiyun extern struct resv_info *resv_pool_info; 236*4882a593Smuzhiyun #endif /* BCMRESVFRAGPOOL */ 237*4882a593Smuzhiyun #else /* BCMPKTPOOL */ 238*4882a593Smuzhiyun #define SHARED_POOL ((struct pktpool *)NULL) 239*4882a593Smuzhiyun #endif /* BCMPKTPOOL */ 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun #ifdef __cplusplus 242*4882a593Smuzhiyun } 243*4882a593Smuzhiyun #endif // endif 244*4882a593Smuzhiyun 245*4882a593Smuzhiyun #endif /* _hnd_pktpool_h_ */ 246