|  | /* | 
|  | * HND generic packet pool operation primitives | 
|  | * | 
|  | * Copyright (C) 2020, Broadcom. | 
|  | * | 
|  | *      Unless you and Broadcom execute a separate written software license | 
|  | * agreement governing use of this software, this software is licensed to you | 
|  | * under the terms of the GNU General Public License version 2 (the "GPL"), | 
|  | * available at http://www.broadcom.com/licenses/GPLv2.php, with the | 
|  | * following added to such license: | 
|  | * | 
|  | *      As a special exception, the copyright holders of this software give you | 
|  | * permission to link this software with independent modules, and to copy and | 
|  | * distribute the resulting executable under terms of your choice, provided that | 
|  | * you also meet, for each linked independent module, the terms and conditions of | 
|  | * the license of that module.  An independent module is a module which is not | 
|  | * derived from this software.  The special exception does not apply to any | 
|  | * modifications of the software. | 
|  | * | 
|  | * | 
|  | * <<Broadcom-WL-IPTag/Dual:>> | 
|  | */ | 
|  |  | 
|  | #ifndef _hnd_pktpool_h_ | 
|  | #define _hnd_pktpool_h_ | 
|  |  | 
|  | #include <typedefs.h> | 
|  | #include <osl.h> | 
|  | #include <osl_ext.h> | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | /* mutex macros for thread safe */ | 
|  | #ifdef HND_PKTPOOL_THREAD_SAFE | 
|  | #define HND_PKTPOOL_MUTEX_DECL(mutex)		OSL_EXT_MUTEX_DECL(mutex) | 
|  | #else | 
|  | #define HND_PKTPOOL_MUTEX_DECL(mutex) | 
|  | #endif | 
|  |  | 
|  | #ifdef BCMPKTPOOL | 
|  | #define POOL_ENAB(pool)		((pool) && (pool)->inited) | 
|  | #else /* BCMPKTPOOL */ | 
|  | #define POOL_ENAB(bus)		0 | 
|  | #endif /* BCMPKTPOOL */ | 
|  |  | 
|  | #ifndef PKTPOOL_LEN_MAX | 
|  | #define PKTPOOL_LEN_MAX		40 | 
|  | #endif /* PKTPOOL_LEN_MAX */ | 
|  | #define PKTPOOL_CB_MAX		3 | 
|  | #define PKTPOOL_CB_MAX_AVL	4 | 
|  |  | 
|  | /* REMOVE_RXCPLID is an arg for pktpool callback function for removing rxcplID | 
|  | * and host addr associated with the rxfrag or shared pool buffer during pktpool_reclaim(). | 
|  | */ | 
|  | #define REMOVE_RXCPLID            2 | 
|  |  | 
|  | #define FREE_ALL_PKTS		0 | 
|  | #define FREE_ALL_FRAG_PKTS	1 | 
|  |  | 
|  | /* forward declaration */ | 
|  | struct pktpool; | 
|  |  | 
|  | typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); | 
|  | typedef struct { | 
|  | pktpool_cb_t cb; | 
|  | void *arg; | 
|  | uint8 refcnt; | 
|  | } pktpool_cbinfo_t; | 
|  |  | 
|  | /** PCIe SPLITRX related: call back fn extension to populate host address in pool pkt */ | 
|  | typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg1, void* pkt, int arg2, | 
|  | uint *pktcnt); | 
|  | typedef struct { | 
|  | pktpool_cb_extn_t cb; | 
|  | void *arg; | 
|  | } pktpool_cbextn_info_t; | 
|  |  | 
|  | #ifdef BCMDBG_POOL | 
|  | /* pkt pool debug states */ | 
|  | #define POOL_IDLE	0 | 
|  | #define POOL_RXFILL	1 | 
|  | #define POOL_RXDH	2 | 
|  | #define POOL_RXD11	3 | 
|  | #define POOL_TXDH	4 | 
|  | #define POOL_TXD11	5 | 
|  | #define POOL_AMPDU	6 | 
|  | #define POOL_TXENQ	7 | 
|  |  | 
|  | typedef struct { | 
|  | void *p; | 
|  | uint32 cycles; | 
|  | uint32 dur; | 
|  | } pktpool_dbg_t; | 
|  |  | 
|  | typedef struct { | 
|  | uint8 txdh;	/* tx to host */ | 
|  | uint8 txd11;	/* tx to d11 */ | 
|  | uint8 enq;	/* waiting in q */ | 
|  | uint8 rxdh;	/* rx from host */ | 
|  | uint8 rxd11;	/* rx from d11 */ | 
|  | uint8 rxfill;	/* dma_rxfill */ | 
|  | uint8 idle;	/* avail in pool */ | 
|  | } pktpool_stats_t; | 
|  | #endif /* BCMDBG_POOL */ | 
|  |  | 
|  | typedef struct pktpool { | 
|  | bool inited;            /**< pktpool_init was successful */ | 
|  | uint8 type;             /**< type of lbuf: basic, frag, etc */ | 
|  | uint8 id;               /**< pktpool ID:  index in registry */ | 
|  | bool istx;              /**< direction: transmit or receive data path */ | 
|  | HND_PKTPOOL_MUTEX_DECL(mutex)	/**< thread-safe mutex */ | 
|  |  | 
|  | void * freelist;        /**< free list: see PKTNEXTFREE(), PKTSETNEXTFREE() */ | 
|  | uint16 avail;           /**< number of packets in pool's free list */ | 
|  | uint16 n_pkts;             /**< number of packets managed by pool */ | 
|  | uint16 maxlen;          /**< maximum size of pool <= PKTPOOL_LEN_MAX */ | 
|  | uint16 max_pkt_bytes;   /**< size of pkt buffer in [bytes], excluding lbuf|lbuf_frag */ | 
|  |  | 
|  | bool empty; | 
|  | uint8 cbtoggle; | 
|  | uint8 cbcnt; | 
|  | uint8 ecbcnt; | 
|  | uint8 emptycb_disable;	/**< Value of type enum pktpool_empty_cb_state */ | 
|  | pktpool_cbinfo_t *availcb_excl; | 
|  | pktpool_cbinfo_t cbs[PKTPOOL_CB_MAX_AVL]; | 
|  | pktpool_cbinfo_t ecbs[PKTPOOL_CB_MAX]; | 
|  | pktpool_cbextn_info_t cbext;	/**< PCIe SPLITRX related */ | 
|  | pktpool_cbextn_info_t rxcplidfn; | 
|  | pktpool_cbinfo_t dmarxfill; | 
|  | /* variables for pool_heap management */ | 
|  | uint32 poolheap_flag; | 
|  | uint16 poolheap_count;	/* Number of allocation done from this pool */ | 
|  | uint16 min_backup_buf;	/* Minimum number of buffer that should be kept in pool */ | 
|  | bool is_heap_pool;	/* Whether this pool can be used as heap */ | 
|  | bool release_active; | 
|  | uint8 mem_handle; | 
|  | #ifdef BCMDBG_POOL | 
|  | uint8 dbg_cbcnt; | 
|  | pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; | 
|  | uint16 dbg_qlen; | 
|  | pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; | 
|  | #endif | 
|  | } pktpool_t; | 
|  |  | 
|  | pktpool_t *get_pktpools_registry(int id); | 
|  | #define pktpool_get(pktp)	(pktpool_get_ext((pktp), (pktp)->type, NULL)) | 
|  |  | 
|  | /* Incarnate a pktpool registry. On success returns total_pools. */ | 
|  | extern int pktpool_attach(osl_t *osh, uint32 total_pools); | 
|  | extern int pktpool_dettach(osl_t *osh); /* Relinquish registry */ | 
|  |  | 
|  | extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx, uint8 type, | 
|  | bool is_heap_pool, uint32 heap_pool_flag, uint16 min_backup_buf); | 
|  | extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); | 
|  | extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); | 
|  | extern int pktpool_empty(osl_t *osh, pktpool_t *pktp); | 
|  | extern uint16 pktpool_reclaim(osl_t *osh, pktpool_t *pktp, uint16 free_cnt, uint8 action); | 
|  | void pktpool_update_freelist(pktpool_t *pktp, void *p, uint pkts_consumed); | 
|  | extern void* pktpool_get_ext(pktpool_t *pktp, uint8 type, uint *pktcnt); | 
|  | extern void pktpool_free(pktpool_t *pktp, void *p); | 
|  | void pktpool_nfree(pktpool_t *pktp, void *head, void *tail, uint count); | 
|  | extern int pktpool_add(pktpool_t *pktp, void *p); | 
|  | extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); | 
|  | extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); | 
|  | extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); | 
|  | extern int pktpool_avail_deregister(pktpool_t *pktp, pktpool_cb_t cb, void *arg); | 
|  | extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); | 
|  | extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 max_pkts); | 
|  | extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 max_pkts); | 
|  | extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); | 
|  | extern bool pktpool_emptycb_disabled(pktpool_t *pktp); | 
|  | extern int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg1); | 
|  | extern int pktpool_rxcplid_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg); | 
|  | extern void pktpool_invoke_dmarxfill(pktpool_t *pktp); | 
|  | extern int pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void *arg); | 
|  | extern int pktpool_avail(pktpool_t *pktpool); | 
|  |  | 
|  | #define POOLPTR(pp)         ((pktpool_t *)(pp)) | 
|  | #define POOLID(pp)          (POOLPTR(pp)->id) | 
|  |  | 
|  | #define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid)) | 
|  |  | 
|  | #define pktpool_tot_pkts(pp)  (POOLPTR(pp)->n_pkts)   /**< n_pkts = avail + in_use <= max_pkts */ | 
|  | #define pktpool_max_pkt_bytes(pp)    (POOLPTR(pp)->max_pkt_bytes) | 
|  | #define pktpool_max_pkts(pp)  (POOLPTR(pp)->maxlen) | 
|  |  | 
|  | /* | 
|  | * ---------------------------------------------------------------------------- | 
|  | * A pool ID is assigned with a pkt pool during pool initialization. This is | 
|  | * done by maintaining a registry of all initialized pools, and the registry | 
|  | * index at which the pool is registered is used as the pool's unique ID. | 
|  | * ID 0 is reserved and is used to signify an invalid pool ID. | 
|  | * All packets henceforth allocated from a pool will be tagged with the pool's | 
|  | * unique ID. Packets allocated from the heap will use the reserved ID = 0. | 
|  | * Packets with non-zero pool id signify that they were allocated from a pool. | 
|  | * A maximum of 15 pools are supported, allowing a 4bit pool ID to be used | 
|  | * in place of a 32bit pool pointer in each packet. | 
|  | * ---------------------------------------------------------------------------- | 
|  | */ | 
|  | #define PKTPOOL_INVALID_ID          (0) | 
|  | #define PKTPOOL_MAXIMUM_ID          (15) | 
|  |  | 
|  | /* Registry of pktpool(s) */ | 
|  | /* Pool ID to/from Pool Pointer converters */ | 
|  | #define PKTPOOL_ID2PTR(id)          (get_pktpools_registry(id)) | 
|  | #define PKTPOOL_PTR2ID(pp)          (POOLID(pp)) | 
|  |  | 
|  | #ifndef PKTID_POOL | 
|  | /* max pktids reserved for pktpool is updated properly in Makeconf */ | 
|  | #define PKTID_POOL		    (PKT_MAXIMUM_ID - 32u) | 
|  | #endif /* PKTID_POOL */ | 
|  | extern uint32 total_pool_pktid_count; | 
|  |  | 
|  | #ifdef BCMDBG_POOL | 
|  | extern int pktpool_dbg_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); | 
|  | extern int pktpool_start_trigger(pktpool_t *pktp, void *p); | 
|  | extern int pktpool_dbg_dump(pktpool_t *pktp); | 
|  | extern int pktpool_dbg_notify(pktpool_t *pktp); | 
|  | extern int pktpool_stats_dump(pktpool_t *pktp, pktpool_stats_t *stats); | 
|  | #endif /* BCMDBG_POOL */ | 
|  |  | 
|  | #ifdef BCMPKTPOOL | 
|  | #define SHARED_POOL		(pktpool_shared) | 
|  | extern pktpool_t *pktpool_shared; | 
|  | #ifdef BCMFRAGPOOL | 
|  | #define SHARED_FRAG_POOL	(pktpool_shared_lfrag) | 
|  | extern pktpool_t *pktpool_shared_lfrag; | 
|  | #endif | 
|  |  | 
|  | #ifdef BCMALFRAGPOOL | 
|  | #define SHARED_ALFRAG_POOL	(pktpool_shared_alfrag) | 
|  | extern pktpool_t *pktpool_shared_alfrag; | 
|  |  | 
|  | #define SHARED_ALFRAG_DATA_POOL	(pktpool_shared_alfrag_data) | 
|  | extern pktpool_t *pktpool_shared_alfrag_data; | 
|  | #endif | 
|  |  | 
|  | #ifdef BCMRESVFRAGPOOL | 
|  | #define RESV_FRAG_POOL		(pktpool_resv_lfrag) | 
|  | #define RESV_POOL_INFO		(resv_pool_info) | 
|  | #else | 
|  | #define RESV_FRAG_POOL		((struct pktpool *)NULL) | 
|  | #define RESV_POOL_INFO		(NULL) | 
|  | #endif /* BCMRESVFRAGPOOL */ | 
|  |  | 
|  | /** PCIe SPLITRX related */ | 
|  | #define SHARED_RXFRAG_POOL	(pktpool_shared_rxlfrag) | 
|  | extern pktpool_t *pktpool_shared_rxlfrag; | 
|  |  | 
|  | #define SHARED_RXDATA_POOL	(pktpool_shared_rxdata) | 
|  | extern pktpool_t *pktpool_shared_rxdata; | 
|  |  | 
|  | int hnd_pktpool_init(osl_t *osh); | 
|  | void hnd_pktpool_deinit(osl_t *osh); | 
|  | int hnd_pktpool_fill(pktpool_t *pktpool, bool minimal); | 
|  | void hnd_pktpool_refill(bool minimal); | 
|  |  | 
|  | #ifdef BCMRESVFRAGPOOL | 
|  | extern pktpool_t *pktpool_resv_lfrag; | 
|  | extern struct resv_info *resv_pool_info; | 
|  | #endif /* BCMRESVFRAGPOOL */ | 
|  |  | 
|  | /* Current identified use case flags for pool heap manager */ | 
|  | #define POOL_HEAP_FLAG_D3	(1 << 0) | 
|  | #define POOL_HEAP_FLAG_RSRVPOOL	(1 << 1) | 
|  |  | 
|  | #ifdef POOL_HEAP_RECONFIG | 
|  | typedef void (*pktpool_heap_cb_t)(void *arg, bool entry); | 
|  |  | 
|  | extern void hnd_pktpool_heap_handle(osl_t *osh, uint32 flag, bool enable); | 
|  | extern int hnd_pktpool_heap_register_cb(pktpool_heap_cb_t fn, void *ctxt, uint32 flag); | 
|  | extern int hnd_pktpool_heap_deregister_cb(pktpool_heap_cb_t fn); | 
|  | extern void *hnd_pktpool_freelist_alloc(uint size, uint alignbits, uint32 flag); | 
|  | extern uint16 hnd_pktpool_get_min_bkup_buf(pktpool_t *pktp); | 
|  | #endif /* POOL_HEAP_RECONFIG */ | 
|  | extern uint32 hnd_pktpool_get_total_poolheap_count(void); | 
|  |  | 
|  | #else /* BCMPKTPOOL */ | 
|  | #define SHARED_POOL		((struct pktpool *)NULL) | 
|  | #endif /* BCMPKTPOOL */ | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #endif /* _hnd_pktpool_h_ */ |