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