xref: /freebsd/contrib/ofed/libbnxtre/db.c (revision 9207f9d206a4017001f01ca27d3d25a26c268a95)
1*9207f9d2SChandrakanth patil /*
2*9207f9d2SChandrakanth patil  * Copyright (c) 2024, Broadcom. All rights reserved.  The term
3*9207f9d2SChandrakanth patil  * Broadcom refers to Broadcom Limited and/or its subsidiaries.
4*9207f9d2SChandrakanth patil  *
5*9207f9d2SChandrakanth patil  * Redistribution and use in source and binary forms, with or without
6*9207f9d2SChandrakanth patil  * modification, are permitted provided that the following conditions
7*9207f9d2SChandrakanth patil  * are met:
8*9207f9d2SChandrakanth patil  *
9*9207f9d2SChandrakanth patil  * 1. Redistributions of source code must retain the above copyright
10*9207f9d2SChandrakanth patil  *    notice, this list of conditions and the following disclaimer.
11*9207f9d2SChandrakanth patil  * 2. Redistributions in binary form must reproduce the above copyright
12*9207f9d2SChandrakanth patil  *    notice, this list of conditions and the following disclaimer in
13*9207f9d2SChandrakanth patil  *    the documentation and/or other materials provided with the
14*9207f9d2SChandrakanth patil  *    distribution.
15*9207f9d2SChandrakanth patil  *
16*9207f9d2SChandrakanth patil  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
17*9207f9d2SChandrakanth patil  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18*9207f9d2SChandrakanth patil  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*9207f9d2SChandrakanth patil  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
20*9207f9d2SChandrakanth patil  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*9207f9d2SChandrakanth patil  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*9207f9d2SChandrakanth patil  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23*9207f9d2SChandrakanth patil  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24*9207f9d2SChandrakanth patil  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25*9207f9d2SChandrakanth patil  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26*9207f9d2SChandrakanth patil  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*9207f9d2SChandrakanth patil  *
28*9207f9d2SChandrakanth patil  * Description: Doorbell handling functions.
29*9207f9d2SChandrakanth patil  */
30*9207f9d2SChandrakanth patil 
31*9207f9d2SChandrakanth patil #include <malloc.h>
32*9207f9d2SChandrakanth patil #include <unistd.h>
33*9207f9d2SChandrakanth patil 
34*9207f9d2SChandrakanth patil #include "abi.h"
35*9207f9d2SChandrakanth patil #include "main.h"
36*9207f9d2SChandrakanth patil 
37*9207f9d2SChandrakanth patil #define BNXT_RE_DB_FIFO_ROOM_MASK_P5	0x1FFF8000
38*9207f9d2SChandrakanth patil #define BNXT_RE_MAX_FIFO_DEPTH_P5	0x2c00
39*9207f9d2SChandrakanth patil 
40*9207f9d2SChandrakanth patil #define BNXT_RE_DB_FIFO_ROOM_MASK_P7	0x3FFF8000
41*9207f9d2SChandrakanth patil #define BNXT_RE_MAX_FIFO_DEPTH_P7	0x8000
42*9207f9d2SChandrakanth patil 
43*9207f9d2SChandrakanth patil #define BNXT_RE_DB_FIFO_ROOM_SHIFT      15
44*9207f9d2SChandrakanth patil #define BNXT_RE_DB_THRESHOLD		20
45*9207f9d2SChandrakanth patil 
46*9207f9d2SChandrakanth patil #define BNXT_RE_DB_FIFO_ROOM_MASK(ctx)	\
47*9207f9d2SChandrakanth patil 	(_is_chip_thor2((ctx)) ? \
48*9207f9d2SChandrakanth patil 	 BNXT_RE_DB_FIFO_ROOM_MASK_P7 :\
49*9207f9d2SChandrakanth patil 	 BNXT_RE_DB_FIFO_ROOM_MASK_P5)
50*9207f9d2SChandrakanth patil #define BNXT_RE_MAX_FIFO_DEPTH(ctx)	\
51*9207f9d2SChandrakanth patil 	(_is_chip_thor2((ctx)) ? \
52*9207f9d2SChandrakanth patil 	 BNXT_RE_MAX_FIFO_DEPTH_P7 :\
53*9207f9d2SChandrakanth patil 	 BNXT_RE_MAX_FIFO_DEPTH_P5)
54*9207f9d2SChandrakanth patil 
55*9207f9d2SChandrakanth patil static uint32_t xorshift32(struct xorshift32_state *state)
56*9207f9d2SChandrakanth patil {
57*9207f9d2SChandrakanth patil 	/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
58*9207f9d2SChandrakanth patil 	uint32_t x = state->seed;
59*9207f9d2SChandrakanth patil 
60*9207f9d2SChandrakanth patil 	x ^= x << 13;
61*9207f9d2SChandrakanth patil 	x ^= x >> 17;
62*9207f9d2SChandrakanth patil 	x ^= x << 5;
63*9207f9d2SChandrakanth patil 	return state->seed = x;
64*9207f9d2SChandrakanth patil }
65*9207f9d2SChandrakanth patil 
66*9207f9d2SChandrakanth patil static uint16_t rnd(struct xorshift32_state *state, uint16_t range)
67*9207f9d2SChandrakanth patil {
68*9207f9d2SChandrakanth patil 	/* range must be a power of 2 - 1 */
69*9207f9d2SChandrakanth patil 	return (xorshift32(state) & range);
70*9207f9d2SChandrakanth patil }
71*9207f9d2SChandrakanth patil 
72*9207f9d2SChandrakanth patil static int calculate_fifo_occupancy(struct bnxt_re_context *cntx)
73*9207f9d2SChandrakanth patil {
74*9207f9d2SChandrakanth patil 	uint32_t *dbr_map = cntx->bar_map + 0x1a8;
75*9207f9d2SChandrakanth patil 	uint32_t read_val, fifo_occup;
76*9207f9d2SChandrakanth patil 
77*9207f9d2SChandrakanth patil 	read_val = *dbr_map;
78*9207f9d2SChandrakanth patil 	fifo_occup = BNXT_RE_MAX_FIFO_DEPTH(cntx->cctx) -
79*9207f9d2SChandrakanth patil 		((read_val & BNXT_RE_DB_FIFO_ROOM_MASK(cntx->cctx)) >>
80*9207f9d2SChandrakanth patil 		 BNXT_RE_DB_FIFO_ROOM_SHIFT);
81*9207f9d2SChandrakanth patil 
82*9207f9d2SChandrakanth patil 	return fifo_occup;
83*9207f9d2SChandrakanth patil }
84*9207f9d2SChandrakanth patil 
85*9207f9d2SChandrakanth patil static inline uint32_t find_min(uint32_t x, uint32_t y)
86*9207f9d2SChandrakanth patil {
87*9207f9d2SChandrakanth patil 	return (y > x ? x : y);
88*9207f9d2SChandrakanth patil }
89*9207f9d2SChandrakanth patil 
90*9207f9d2SChandrakanth patil int bnxt_re_do_pacing(struct bnxt_re_context *cntx, struct xorshift32_state *state)
91*9207f9d2SChandrakanth patil {
92*9207f9d2SChandrakanth patil 	/* First 4 bytes  of shared page (pacing_info) contains the DBR
93*9207f9d2SChandrakanth patil 	 * pacing information. Second 4 bytes (pacing_th)  contains
94*9207f9d2SChandrakanth patil 	 * the pacing threshold value to determine whether to
95*9207f9d2SChandrakanth patil 	 * add delay or not
96*9207f9d2SChandrakanth patil 	 */
97*9207f9d2SChandrakanth patil 	struct bnxt_re_pacing_data *pacing_data =
98*9207f9d2SChandrakanth patil 		(struct bnxt_re_pacing_data *)cntx->dbr_page;
99*9207f9d2SChandrakanth patil 	uint32_t wait_time = 1;
100*9207f9d2SChandrakanth patil 	uint32_t fifo_occup;
101*9207f9d2SChandrakanth patil 
102*9207f9d2SChandrakanth patil 	if (!pacing_data)
103*9207f9d2SChandrakanth patil 		return 0;
104*9207f9d2SChandrakanth patil 	/* If the device in error recovery state, return error to
105*9207f9d2SChandrakanth patil 	 * not to ring new doorbells in this state.
106*9207f9d2SChandrakanth patil 	 */
107*9207f9d2SChandrakanth patil 	if (pacing_data->dev_err_state)
108*9207f9d2SChandrakanth patil 		return -EFAULT;
109*9207f9d2SChandrakanth patil 
110*9207f9d2SChandrakanth patil 	if (rnd(state, BNXT_RE_MAX_DO_PACING) < pacing_data->do_pacing) {
111*9207f9d2SChandrakanth patil 		while ((fifo_occup = calculate_fifo_occupancy(cntx))
112*9207f9d2SChandrakanth patil 			>  pacing_data->pacing_th) {
113*9207f9d2SChandrakanth patil 			struct bnxt_re_cq *cq;
114*9207f9d2SChandrakanth patil 			uint32_t usec_wait;
115*9207f9d2SChandrakanth patil 
116*9207f9d2SChandrakanth patil 			if (pacing_data->alarm_th && fifo_occup > pacing_data->alarm_th) {
117*9207f9d2SChandrakanth patil 				cq = container_of(cntx->dbr_cq, struct bnxt_re_cq, ibvcq);
118*9207f9d2SChandrakanth patil 				bnxt_re_poll_kernel_cq(cq);
119*9207f9d2SChandrakanth patil 			}
120*9207f9d2SChandrakanth patil 			usec_wait = rnd(state, wait_time - 1);
121*9207f9d2SChandrakanth patil 			if (usec_wait)
122*9207f9d2SChandrakanth patil 				bnxt_re_sub_sec_busy_wait(usec_wait * 1000);
123*9207f9d2SChandrakanth patil 			/* wait time capped at 128 us */
124*9207f9d2SChandrakanth patil 			wait_time = find_min(wait_time * 2, 128);
125*9207f9d2SChandrakanth patil 		}
126*9207f9d2SChandrakanth patil 	}
127*9207f9d2SChandrakanth patil 	return 0;
128*9207f9d2SChandrakanth patil }
129*9207f9d2SChandrakanth patil 
130*9207f9d2SChandrakanth patil static inline void bnxt_re_ring_db(struct bnxt_re_dpi *dpi, __u64 key,
131*9207f9d2SChandrakanth patil 				   uint64_t *db_key, uint8_t *lock)
132*9207f9d2SChandrakanth patil {
133*9207f9d2SChandrakanth patil 	while (1) {
134*9207f9d2SChandrakanth patil 		if (__sync_bool_compare_and_swap(lock, 0, 1)) {
135*9207f9d2SChandrakanth patil 			*db_key = key;
136*9207f9d2SChandrakanth patil 			bnxt_re_wm_barrier();
137*9207f9d2SChandrakanth patil 			iowrite64(dpi->dbpage, key);
138*9207f9d2SChandrakanth patil 			bnxt_re_wm_barrier();
139*9207f9d2SChandrakanth patil 			*lock = 0;
140*9207f9d2SChandrakanth patil 			break;
141*9207f9d2SChandrakanth patil 		}
142*9207f9d2SChandrakanth patil 	}
143*9207f9d2SChandrakanth patil }
144*9207f9d2SChandrakanth patil 
145*9207f9d2SChandrakanth patil static inline void bnxt_re_init_push_hdr(struct bnxt_re_db_hdr *hdr,
146*9207f9d2SChandrakanth patil 					 uint32_t indx, uint32_t qid,
147*9207f9d2SChandrakanth patil 					 uint32_t typ, uint32_t pidx)
148*9207f9d2SChandrakanth patil {
149*9207f9d2SChandrakanth patil 	__u64 key_lo, key_hi;
150*9207f9d2SChandrakanth patil 
151*9207f9d2SChandrakanth patil 	key_lo = (((pidx & BNXT_RE_DB_PILO_MASK) << BNXT_RE_DB_PILO_SHIFT) |
152*9207f9d2SChandrakanth patil 		  (indx & BNXT_RE_DB_INDX_MASK));
153*9207f9d2SChandrakanth patil 	key_hi = ((((pidx & BNXT_RE_DB_PIHI_MASK) << BNXT_RE_DB_PIHI_SHIFT) |
154*9207f9d2SChandrakanth patil 		   (qid & BNXT_RE_DB_QID_MASK)) |
155*9207f9d2SChandrakanth patil 		  ((typ & BNXT_RE_DB_TYP_MASK) << BNXT_RE_DB_TYP_SHIFT) |
156*9207f9d2SChandrakanth patil 		  (0x1UL << BNXT_RE_DB_VALID_SHIFT));
157*9207f9d2SChandrakanth patil 	hdr->typ_qid_indx = htole64((key_lo | (key_hi << 32)));
158*9207f9d2SChandrakanth patil }
159*9207f9d2SChandrakanth patil 
160*9207f9d2SChandrakanth patil static inline void bnxt_re_init_db_hdr(struct bnxt_re_db_hdr *hdr,
161*9207f9d2SChandrakanth patil 				       uint32_t indx, uint32_t toggle,
162*9207f9d2SChandrakanth patil 				       uint32_t qid, uint32_t typ)
163*9207f9d2SChandrakanth patil {
164*9207f9d2SChandrakanth patil 	__u64 key_lo, key_hi;
165*9207f9d2SChandrakanth patil 
166*9207f9d2SChandrakanth patil 	key_lo = htole32(indx | toggle);
167*9207f9d2SChandrakanth patil 	key_hi = ((qid & BNXT_RE_DB_QID_MASK) |
168*9207f9d2SChandrakanth patil 		  ((typ & BNXT_RE_DB_TYP_MASK) << BNXT_RE_DB_TYP_SHIFT) |
169*9207f9d2SChandrakanth patil 		  (0x1UL << BNXT_RE_DB_VALID_SHIFT));
170*9207f9d2SChandrakanth patil 	hdr->typ_qid_indx = htole64((key_lo | (key_hi << 32)));
171*9207f9d2SChandrakanth patil }
172*9207f9d2SChandrakanth patil 
173*9207f9d2SChandrakanth patil static inline void __bnxt_re_ring_pend_db(__u64 *ucdb, __u64 key,
174*9207f9d2SChandrakanth patil 					  struct  bnxt_re_qp *qp)
175*9207f9d2SChandrakanth patil {
176*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
177*9207f9d2SChandrakanth patil 
178*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr,
179*9207f9d2SChandrakanth patil 			    (*qp->jsqq->hwque->dbtail |
180*9207f9d2SChandrakanth patil 			     ((qp->jsqq->hwque->flags &
181*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_TAIL_MASK) <<
182*9207f9d2SChandrakanth patil 			    BNXT_RE_DB_EPOCH_TAIL_SHIFT)), 0,
183*9207f9d2SChandrakanth patil 			    qp->qpid,
184*9207f9d2SChandrakanth patil 			    BNXT_RE_QUE_TYPE_SQ);
185*9207f9d2SChandrakanth patil 
186*9207f9d2SChandrakanth patil 	while (1) {
187*9207f9d2SChandrakanth patil 		if (__sync_bool_compare_and_swap(&qp->sq_dbr_lock, 0, 1)) {
188*9207f9d2SChandrakanth patil 			qp->sq_shadow_db_key = hdr.typ_qid_indx;
189*9207f9d2SChandrakanth patil 			bnxt_re_wm_barrier();
190*9207f9d2SChandrakanth patil 			iowrite64(ucdb, key);
191*9207f9d2SChandrakanth patil 			bnxt_re_wm_barrier();
192*9207f9d2SChandrakanth patil 			qp->sq_dbr_lock = 0;
193*9207f9d2SChandrakanth patil 			break;
194*9207f9d2SChandrakanth patil 		}
195*9207f9d2SChandrakanth patil 	}
196*9207f9d2SChandrakanth patil }
197*9207f9d2SChandrakanth patil 
198*9207f9d2SChandrakanth patil void bnxt_re_ring_rq_db(struct bnxt_re_qp *qp)
199*9207f9d2SChandrakanth patil {
200*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
201*9207f9d2SChandrakanth patil 
202*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(qp->cntx, &qp->rand))
203*9207f9d2SChandrakanth patil 		return;
204*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr,
205*9207f9d2SChandrakanth patil 			    (*qp->jrqq->hwque->dbtail |
206*9207f9d2SChandrakanth patil 			     ((qp->jrqq->hwque->flags &
207*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_TAIL_MASK) <<
208*9207f9d2SChandrakanth patil 			      BNXT_RE_DB_EPOCH_TAIL_SHIFT)), 0,
209*9207f9d2SChandrakanth patil 			    qp->qpid,
210*9207f9d2SChandrakanth patil 			    BNXT_RE_QUE_TYPE_RQ);
211*9207f9d2SChandrakanth patil 	bnxt_re_ring_db(qp->udpi, hdr.typ_qid_indx, &qp->rq_shadow_db_key,
212*9207f9d2SChandrakanth patil 			&qp->rq_dbr_lock);
213*9207f9d2SChandrakanth patil }
214*9207f9d2SChandrakanth patil 
215*9207f9d2SChandrakanth patil void bnxt_re_ring_sq_db(struct bnxt_re_qp *qp)
216*9207f9d2SChandrakanth patil {
217*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
218*9207f9d2SChandrakanth patil 
219*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(qp->cntx, &qp->rand))
220*9207f9d2SChandrakanth patil 		return;
221*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr,
222*9207f9d2SChandrakanth patil 			    (*qp->jsqq->hwque->dbtail |
223*9207f9d2SChandrakanth patil 			     ((qp->jsqq->hwque->flags &
224*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_TAIL_MASK) <<
225*9207f9d2SChandrakanth patil 			     BNXT_RE_DB_EPOCH_TAIL_SHIFT)), 0,
226*9207f9d2SChandrakanth patil 			    qp->qpid,
227*9207f9d2SChandrakanth patil 			    BNXT_RE_QUE_TYPE_SQ);
228*9207f9d2SChandrakanth patil 	bnxt_re_ring_db(qp->udpi, hdr.typ_qid_indx, &qp->sq_shadow_db_key,
229*9207f9d2SChandrakanth patil 			&qp->sq_dbr_lock);
230*9207f9d2SChandrakanth patil }
231*9207f9d2SChandrakanth patil 
232*9207f9d2SChandrakanth patil void bnxt_re_ring_srq_db(struct bnxt_re_srq *srq)
233*9207f9d2SChandrakanth patil {
234*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
235*9207f9d2SChandrakanth patil 
236*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(srq->uctx, &srq->rand))
237*9207f9d2SChandrakanth patil 		return;
238*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr,
239*9207f9d2SChandrakanth patil 			    (srq->srqq->tail |
240*9207f9d2SChandrakanth patil 			     ((srq->srqq->flags &
241*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_TAIL_MASK) <<
242*9207f9d2SChandrakanth patil 			     BNXT_RE_DB_EPOCH_TAIL_SHIFT)), 0,
243*9207f9d2SChandrakanth patil 			    srq->srqid, BNXT_RE_QUE_TYPE_SRQ);
244*9207f9d2SChandrakanth patil 	bnxt_re_ring_db(srq->udpi, hdr.typ_qid_indx, &srq->shadow_db_key,
245*9207f9d2SChandrakanth patil 			&srq->dbr_lock);
246*9207f9d2SChandrakanth patil }
247*9207f9d2SChandrakanth patil 
248*9207f9d2SChandrakanth patil void bnxt_re_ring_srq_arm(struct bnxt_re_srq *srq)
249*9207f9d2SChandrakanth patil {
250*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
251*9207f9d2SChandrakanth patil 
252*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(srq->uctx, &srq->rand))
253*9207f9d2SChandrakanth patil 		return;
254*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr, srq->cap.srq_limit, 0, srq->srqid,
255*9207f9d2SChandrakanth patil 			    BNXT_RE_QUE_TYPE_SRQ_ARM);
256*9207f9d2SChandrakanth patil 	bnxt_re_ring_db(srq->udpi, hdr.typ_qid_indx, &srq->shadow_db_key,
257*9207f9d2SChandrakanth patil 			&srq->dbr_lock);
258*9207f9d2SChandrakanth patil }
259*9207f9d2SChandrakanth patil 
260*9207f9d2SChandrakanth patil void bnxt_re_ring_cq_db(struct bnxt_re_cq *cq)
261*9207f9d2SChandrakanth patil {
262*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
263*9207f9d2SChandrakanth patil 
264*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(cq->cntx, &cq->rand))
265*9207f9d2SChandrakanth patil 		return;
266*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr,
267*9207f9d2SChandrakanth patil 			    (cq->cqq->head |
268*9207f9d2SChandrakanth patil 			     ((cq->cqq->flags &
269*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_HEAD_MASK) <<
270*9207f9d2SChandrakanth patil 			     BNXT_RE_DB_EPOCH_HEAD_SHIFT)), 0,
271*9207f9d2SChandrakanth patil 			    cq->cqid,
272*9207f9d2SChandrakanth patil 			    BNXT_RE_QUE_TYPE_CQ);
273*9207f9d2SChandrakanth patil 	bnxt_re_ring_db(cq->udpi, hdr.typ_qid_indx, &cq->shadow_db_key,
274*9207f9d2SChandrakanth patil 			&cq->dbr_lock);
275*9207f9d2SChandrakanth patil }
276*9207f9d2SChandrakanth patil 
277*9207f9d2SChandrakanth patil void bnxt_re_ring_cq_arm_db(struct bnxt_re_cq *cq, uint8_t aflag)
278*9207f9d2SChandrakanth patil {
279*9207f9d2SChandrakanth patil 	uint32_t *cq_page = cq->cq_page;
280*9207f9d2SChandrakanth patil 	struct bnxt_re_db_hdr hdr;
281*9207f9d2SChandrakanth patil 	uint32_t toggle = 0;
282*9207f9d2SChandrakanth patil 
283*9207f9d2SChandrakanth patil 	if (cq_page)
284*9207f9d2SChandrakanth patil 		toggle = *cq_page;
285*9207f9d2SChandrakanth patil 
286*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(cq->cntx, &cq->rand))
287*9207f9d2SChandrakanth patil 		return;
288*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&hdr,
289*9207f9d2SChandrakanth patil 			    (cq->cqq->head |
290*9207f9d2SChandrakanth patil 			     ((cq->cqq->flags &
291*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_HEAD_MASK) <<
292*9207f9d2SChandrakanth patil 			     BNXT_RE_DB_EPOCH_HEAD_SHIFT)),
293*9207f9d2SChandrakanth patil 			     toggle << BNXT_RE_DB_TOGGLE_SHIFT,
294*9207f9d2SChandrakanth patil 			    cq->cqid, aflag);
295*9207f9d2SChandrakanth patil 	bnxt_re_ring_db(cq->udpi, hdr.typ_qid_indx, &cq->shadow_db_key,
296*9207f9d2SChandrakanth patil 			&cq->dbr_lock);
297*9207f9d2SChandrakanth patil }
298*9207f9d2SChandrakanth patil 
299*9207f9d2SChandrakanth patil void bnxt_re_ring_pstart_db(struct bnxt_re_qp *qp,
300*9207f9d2SChandrakanth patil 			    struct bnxt_re_push_buffer *pbuf)
301*9207f9d2SChandrakanth patil {
302*9207f9d2SChandrakanth patil 	__u64 key;
303*9207f9d2SChandrakanth patil 
304*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(qp->cntx, &qp->rand))
305*9207f9d2SChandrakanth patil 		return;
306*9207f9d2SChandrakanth patil 	key = ((((pbuf->wcdpi & BNXT_RE_DB_PIHI_MASK) <<
307*9207f9d2SChandrakanth patil 		  BNXT_RE_DB_PIHI_SHIFT) | (pbuf->qpid & BNXT_RE_DB_QID_MASK)) |
308*9207f9d2SChandrakanth patil 	       ((BNXT_RE_PUSH_TYPE_START & BNXT_RE_DB_TYP_MASK) <<
309*9207f9d2SChandrakanth patil 		 BNXT_RE_DB_TYP_SHIFT) | (0x1UL << BNXT_RE_DB_VALID_SHIFT));
310*9207f9d2SChandrakanth patil 	key <<= 32;
311*9207f9d2SChandrakanth patil 	key |= ((((__u32)pbuf->wcdpi & BNXT_RE_DB_PILO_MASK) <<
312*9207f9d2SChandrakanth patil 		  BNXT_RE_DB_PILO_SHIFT) | (pbuf->st_idx &
313*9207f9d2SChandrakanth patil 					    BNXT_RE_DB_INDX_MASK));
314*9207f9d2SChandrakanth patil 	bnxt_re_wm_barrier();
315*9207f9d2SChandrakanth patil 	iowrite64(pbuf->ucdb, key);
316*9207f9d2SChandrakanth patil }
317*9207f9d2SChandrakanth patil 
318*9207f9d2SChandrakanth patil void bnxt_re_ring_pend_db(struct bnxt_re_qp *qp,
319*9207f9d2SChandrakanth patil 			  struct bnxt_re_push_buffer *pbuf)
320*9207f9d2SChandrakanth patil {
321*9207f9d2SChandrakanth patil 	__u64 key;
322*9207f9d2SChandrakanth patil 
323*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(qp->cntx, &qp->rand))
324*9207f9d2SChandrakanth patil 		return;
325*9207f9d2SChandrakanth patil 	key = ((((pbuf->wcdpi & BNXT_RE_DB_PIHI_MASK) <<
326*9207f9d2SChandrakanth patil 		  BNXT_RE_DB_PIHI_SHIFT) | (pbuf->qpid & BNXT_RE_DB_QID_MASK)) |
327*9207f9d2SChandrakanth patil 	       ((BNXT_RE_PUSH_TYPE_END & BNXT_RE_DB_TYP_MASK) <<
328*9207f9d2SChandrakanth patil 		 BNXT_RE_DB_TYP_SHIFT) | (0x1UL << BNXT_RE_DB_VALID_SHIFT));
329*9207f9d2SChandrakanth patil 	key <<= 32;
330*9207f9d2SChandrakanth patil 	key |= ((((__u32)pbuf->wcdpi & BNXT_RE_DB_PILO_MASK) <<
331*9207f9d2SChandrakanth patil 		  BNXT_RE_DB_PILO_SHIFT) | (pbuf->tail &
332*9207f9d2SChandrakanth patil 					    BNXT_RE_DB_INDX_MASK));
333*9207f9d2SChandrakanth patil 	__bnxt_re_ring_pend_db(pbuf->ucdb, key, qp);
334*9207f9d2SChandrakanth patil }
335*9207f9d2SChandrakanth patil 
336*9207f9d2SChandrakanth patil void bnxt_re_fill_ppp(struct bnxt_re_push_buffer *pbuf,
337*9207f9d2SChandrakanth patil 		      struct bnxt_re_qp *qp, uint8_t len, uint32_t idx)
338*9207f9d2SChandrakanth patil {
339*9207f9d2SChandrakanth patil 	struct bnxt_re_db_ppp_hdr phdr = {};
340*9207f9d2SChandrakanth patil 	__u64 *dst, *src;
341*9207f9d2SChandrakanth patil 	__u8 plen;
342*9207f9d2SChandrakanth patil 	int indx;
343*9207f9d2SChandrakanth patil 
344*9207f9d2SChandrakanth patil 	src = (__u64 *)&phdr;
345*9207f9d2SChandrakanth patil 	plen = len + sizeof(phdr) + bnxt_re_get_sqe_hdr_sz();
346*9207f9d2SChandrakanth patil 
347*9207f9d2SChandrakanth patil 	bnxt_re_init_db_hdr(&phdr.db_hdr,
348*9207f9d2SChandrakanth patil 			    (*qp->jsqq->hwque->dbtail |
349*9207f9d2SChandrakanth patil 			     ((qp->jsqq->hwque->flags &
350*9207f9d2SChandrakanth patil 			       BNXT_RE_FLAG_EPOCH_TAIL_MASK) <<
351*9207f9d2SChandrakanth patil 			     BNXT_RE_DB_EPOCH_TAIL_SHIFT)), 0,
352*9207f9d2SChandrakanth patil 			    qp->qpid,
353*9207f9d2SChandrakanth patil 			    BNXT_RE_QUE_TYPE_SQ);
354*9207f9d2SChandrakanth patil 
355*9207f9d2SChandrakanth patil 	phdr.rsv_psz_pidx = ((pbuf->st_idx & BNXT_RE_DB_INDX_MASK) |
356*9207f9d2SChandrakanth patil 			     (((plen % 8 ? (plen / 8) + 1 :
357*9207f9d2SChandrakanth patil 				plen / 8) & BNXT_RE_PUSH_SIZE_MASK) <<
358*9207f9d2SChandrakanth patil 			       BNXT_RE_PUSH_SIZE_SHIFT));
359*9207f9d2SChandrakanth patil 
360*9207f9d2SChandrakanth patil 	bnxt_re_wm_barrier();
361*9207f9d2SChandrakanth patil 	for (indx = 0; indx < 2; indx++) {
362*9207f9d2SChandrakanth patil 		dst = (__u64 *)(pbuf->pbuf + indx);
363*9207f9d2SChandrakanth patil 		iowrite64(dst, *src);
364*9207f9d2SChandrakanth patil 		src++;
365*9207f9d2SChandrakanth patil 	}
366*9207f9d2SChandrakanth patil 	bnxt_re_copy_data_to_pb(pbuf, 1, idx);
367*9207f9d2SChandrakanth patil 	mmio_flush_writes();
368*9207f9d2SChandrakanth patil }
369*9207f9d2SChandrakanth patil 
370*9207f9d2SChandrakanth patil void bnxt_re_fill_push_wcb(struct bnxt_re_qp *qp,
371*9207f9d2SChandrakanth patil 			   struct bnxt_re_push_buffer *pbuf, uint32_t idx)
372*9207f9d2SChandrakanth patil {
373*9207f9d2SChandrakanth patil 	bnxt_re_ring_pstart_db(qp, pbuf);
374*9207f9d2SChandrakanth patil 	mmio_wc_start();
375*9207f9d2SChandrakanth patil 	bnxt_re_copy_data_to_pb(pbuf, 0, idx);
376*9207f9d2SChandrakanth patil 	/* Flush WQE write before push end db. */
377*9207f9d2SChandrakanth patil 	mmio_flush_writes();
378*9207f9d2SChandrakanth patil 	bnxt_re_ring_pend_db(qp, pbuf);
379*9207f9d2SChandrakanth patil }
380*9207f9d2SChandrakanth patil 
381*9207f9d2SChandrakanth patil int bnxt_re_init_pbuf_list(struct bnxt_re_context *ucntx)
382*9207f9d2SChandrakanth patil {
383*9207f9d2SChandrakanth patil 	struct bnxt_re_push_buffer *pbuf;
384*9207f9d2SChandrakanth patil 	int indx, wqesz;
385*9207f9d2SChandrakanth patil 	int size, offt;
386*9207f9d2SChandrakanth patil 	__u64 wcpage;
387*9207f9d2SChandrakanth patil 	__u64 dbpage;
388*9207f9d2SChandrakanth patil 	void *base;
389*9207f9d2SChandrakanth patil 
390*9207f9d2SChandrakanth patil 	size = (sizeof(*ucntx->pbrec) +
391*9207f9d2SChandrakanth patil 		16 * (sizeof(*ucntx->pbrec->pbuf) +
392*9207f9d2SChandrakanth patil 		      sizeof(struct bnxt_re_push_wqe)));
393*9207f9d2SChandrakanth patil 	ucntx->pbrec = calloc(1, size);
394*9207f9d2SChandrakanth patil 	if (!ucntx->pbrec)
395*9207f9d2SChandrakanth patil 		goto out;
396*9207f9d2SChandrakanth patil 
397*9207f9d2SChandrakanth patil 	offt = sizeof(*ucntx->pbrec);
398*9207f9d2SChandrakanth patil 	base = ucntx->pbrec;
399*9207f9d2SChandrakanth patil 	ucntx->pbrec->pbuf = (base + offt);
400*9207f9d2SChandrakanth patil 	ucntx->pbrec->pbmap = ~0x00;
401*9207f9d2SChandrakanth patil 	ucntx->pbrec->pbmap &= ~0x7fff; /* 15 bits */
402*9207f9d2SChandrakanth patil 	ucntx->pbrec->udpi = &ucntx->udpi;
403*9207f9d2SChandrakanth patil 
404*9207f9d2SChandrakanth patil 	wqesz = sizeof(struct bnxt_re_push_wqe);
405*9207f9d2SChandrakanth patil 	wcpage = (__u64)ucntx->udpi.wcdbpg;
406*9207f9d2SChandrakanth patil 	dbpage = (__u64)ucntx->udpi.dbpage;
407*9207f9d2SChandrakanth patil 	offt = sizeof(*ucntx->pbrec->pbuf) * 16;
408*9207f9d2SChandrakanth patil 	base = (char *)ucntx->pbrec->pbuf + offt;
409*9207f9d2SChandrakanth patil 	for (indx = 0; indx < 16; indx++) {
410*9207f9d2SChandrakanth patil 		pbuf = &ucntx->pbrec->pbuf[indx];
411*9207f9d2SChandrakanth patil 		pbuf->wqe = base + indx * wqesz;
412*9207f9d2SChandrakanth patil 		pbuf->pbuf = (__u64 *)(wcpage + indx * wqesz);
413*9207f9d2SChandrakanth patil 		pbuf->ucdb = (__u64 *)(dbpage + (indx + 1) * sizeof(__u64));
414*9207f9d2SChandrakanth patil 		pbuf->wcdpi = ucntx->udpi.wcdpi;
415*9207f9d2SChandrakanth patil 	}
416*9207f9d2SChandrakanth patil 
417*9207f9d2SChandrakanth patil 	return 0;
418*9207f9d2SChandrakanth patil out:
419*9207f9d2SChandrakanth patil 	return -ENOMEM;
420*9207f9d2SChandrakanth patil }
421*9207f9d2SChandrakanth patil 
422*9207f9d2SChandrakanth patil struct bnxt_re_push_buffer *bnxt_re_get_pbuf(uint8_t *push_st_en,
423*9207f9d2SChandrakanth patil 					     uint8_t ppp_idx,
424*9207f9d2SChandrakanth patil 					     struct bnxt_re_context *cntx)
425*9207f9d2SChandrakanth patil {
426*9207f9d2SChandrakanth patil 	struct bnxt_re_push_buffer *pbuf = NULL;
427*9207f9d2SChandrakanth patil 	uint8_t buf_state = 0;
428*9207f9d2SChandrakanth patil 	__u32 old;
429*9207f9d2SChandrakanth patil 	int bit;
430*9207f9d2SChandrakanth patil 
431*9207f9d2SChandrakanth patil 	if (_is_chip_thor2(cntx->cctx)) {
432*9207f9d2SChandrakanth patil 		buf_state = !!(*push_st_en & BNXT_RE_PPP_STATE_MASK);
433*9207f9d2SChandrakanth patil 		pbuf = &cntx->pbrec->pbuf[(ppp_idx * 2) + buf_state];
434*9207f9d2SChandrakanth patil 		/* Flip */
435*9207f9d2SChandrakanth patil 		*push_st_en ^= 1UL << BNXT_RE_PPP_ST_SHIFT;
436*9207f9d2SChandrakanth patil 	} else {
437*9207f9d2SChandrakanth patil 		old = cntx->pbrec->pbmap;
438*9207f9d2SChandrakanth patil 		while ((bit = __builtin_ffs(~cntx->pbrec->pbmap)) != 0) {
439*9207f9d2SChandrakanth patil 			if (__sync_bool_compare_and_swap
440*9207f9d2SChandrakanth patil 						(&cntx->pbrec->pbmap,
441*9207f9d2SChandrakanth patil 						 old,
442*9207f9d2SChandrakanth patil 						 (old | 0x01 << (bit - 1))))
443*9207f9d2SChandrakanth patil 				break;
444*9207f9d2SChandrakanth patil 			old = cntx->pbrec->pbmap;
445*9207f9d2SChandrakanth patil 		}
446*9207f9d2SChandrakanth patil 
447*9207f9d2SChandrakanth patil 		if (bit) {
448*9207f9d2SChandrakanth patil 			pbuf = &cntx->pbrec->pbuf[bit];
449*9207f9d2SChandrakanth patil 			pbuf->nbit = bit;
450*9207f9d2SChandrakanth patil 		}
451*9207f9d2SChandrakanth patil 	}
452*9207f9d2SChandrakanth patil 
453*9207f9d2SChandrakanth patil 	return pbuf;
454*9207f9d2SChandrakanth patil }
455*9207f9d2SChandrakanth patil 
456*9207f9d2SChandrakanth patil void bnxt_re_put_pbuf(struct bnxt_re_context *cntx,
457*9207f9d2SChandrakanth patil 		      struct bnxt_re_push_buffer *pbuf)
458*9207f9d2SChandrakanth patil {
459*9207f9d2SChandrakanth patil 	struct bnxt_re_push_rec *pbrec;
460*9207f9d2SChandrakanth patil 	__u32 old;
461*9207f9d2SChandrakanth patil 	int bit;
462*9207f9d2SChandrakanth patil 
463*9207f9d2SChandrakanth patil 	if (_is_chip_thor2(cntx->cctx))
464*9207f9d2SChandrakanth patil 		return;
465*9207f9d2SChandrakanth patil 
466*9207f9d2SChandrakanth patil 	pbrec = cntx->pbrec;
467*9207f9d2SChandrakanth patil 
468*9207f9d2SChandrakanth patil 	if (pbuf->nbit) {
469*9207f9d2SChandrakanth patil 		bit = pbuf->nbit;
470*9207f9d2SChandrakanth patil 		pbuf->nbit = 0;
471*9207f9d2SChandrakanth patil 		old = pbrec->pbmap;
472*9207f9d2SChandrakanth patil 		while (!__sync_bool_compare_and_swap(&pbrec->pbmap, old,
473*9207f9d2SChandrakanth patil 						     (old & (~(0x01 <<
474*9207f9d2SChandrakanth patil 							       (bit - 1))))))
475*9207f9d2SChandrakanth patil 			old = pbrec->pbmap;
476*9207f9d2SChandrakanth patil 	}
477*9207f9d2SChandrakanth patil }
478*9207f9d2SChandrakanth patil 
479*9207f9d2SChandrakanth patil void bnxt_re_destroy_pbuf_list(struct bnxt_re_context *cntx)
480*9207f9d2SChandrakanth patil {
481*9207f9d2SChandrakanth patil 	free(cntx->pbrec);
482*9207f9d2SChandrakanth patil }
483*9207f9d2SChandrakanth patil 
484*9207f9d2SChandrakanth patil void bnxt_re_replay_db(struct bnxt_re_context *cntx,
485*9207f9d2SChandrakanth patil 		       struct xorshift32_state *state, struct bnxt_re_dpi *dpi,
486*9207f9d2SChandrakanth patil 		       uint64_t *shadow_key, uint8_t *dbr_lock)
487*9207f9d2SChandrakanth patil {
488*9207f9d2SChandrakanth patil 	if (bnxt_re_do_pacing(cntx, state))
489*9207f9d2SChandrakanth patil 		return;
490*9207f9d2SChandrakanth patil 	cntx->replay_cnt++;
491*9207f9d2SChandrakanth patil 	if (cntx->replay_cnt % BNXT_RE_DB_REPLAY_YIELD_CNT == 0)
492*9207f9d2SChandrakanth patil 		pthread_yield();
493*9207f9d2SChandrakanth patil 	if (__sync_bool_compare_and_swap(dbr_lock, 0, 1)) {
494*9207f9d2SChandrakanth patil 		bnxt_re_wm_barrier();
495*9207f9d2SChandrakanth patil 		if (*shadow_key == BNXT_RE_DB_KEY_INVALID) {
496*9207f9d2SChandrakanth patil 			*dbr_lock = 0;
497*9207f9d2SChandrakanth patil 			return;
498*9207f9d2SChandrakanth patil 		}
499*9207f9d2SChandrakanth patil 		iowrite64(dpi->dbpage, *shadow_key);
500*9207f9d2SChandrakanth patil 		bnxt_re_wm_barrier();
501*9207f9d2SChandrakanth patil 		*dbr_lock = 0;
502*9207f9d2SChandrakanth patil 	}
503*9207f9d2SChandrakanth patil }
504*9207f9d2SChandrakanth patil 
505*9207f9d2SChandrakanth patil void bnxt_re_db_recovery(struct bnxt_re_context *cntx)
506*9207f9d2SChandrakanth patil {
507*9207f9d2SChandrakanth patil 	struct bnxt_re_list_node *cur, *tmp;
508*9207f9d2SChandrakanth patil 	struct bnxt_re_qp *qp;
509*9207f9d2SChandrakanth patil 	struct bnxt_re_cq *cq;
510*9207f9d2SChandrakanth patil 	struct bnxt_re_srq *srq;
511*9207f9d2SChandrakanth patil 
512*9207f9d2SChandrakanth patil 	pthread_spin_lock(&cntx->qp_dbr_res.lock);
513*9207f9d2SChandrakanth patil 	list_for_each_node_safe(cur, tmp, &cntx->qp_dbr_res.head) {
514*9207f9d2SChandrakanth patil 		qp = list_node(cur, struct bnxt_re_qp, dbnode);
515*9207f9d2SChandrakanth patil 		bnxt_re_replay_db(cntx, &qp->rand, qp->udpi,
516*9207f9d2SChandrakanth patil 				  &qp->sq_shadow_db_key, &qp->sq_dbr_lock);
517*9207f9d2SChandrakanth patil 		bnxt_re_replay_db(cntx, &qp->rand, qp->udpi,
518*9207f9d2SChandrakanth patil 				  &qp->rq_shadow_db_key, &qp->rq_dbr_lock);
519*9207f9d2SChandrakanth patil 	}
520*9207f9d2SChandrakanth patil 	pthread_spin_unlock(&cntx->qp_dbr_res.lock);
521*9207f9d2SChandrakanth patil 	pthread_spin_lock(&cntx->cq_dbr_res.lock);
522*9207f9d2SChandrakanth patil 	list_for_each_node_safe(cur, tmp, &cntx->cq_dbr_res.head) {
523*9207f9d2SChandrakanth patil 		cq = list_node(cur, struct bnxt_re_cq, dbnode);
524*9207f9d2SChandrakanth patil 		bnxt_re_replay_db(cntx, &cq->rand, cq->udpi,
525*9207f9d2SChandrakanth patil 				  &cq->shadow_db_key, &cq->dbr_lock);
526*9207f9d2SChandrakanth patil 	}
527*9207f9d2SChandrakanth patil 	pthread_spin_unlock(&cntx->cq_dbr_res.lock);
528*9207f9d2SChandrakanth patil 	pthread_spin_lock(&cntx->srq_dbr_res.lock);
529*9207f9d2SChandrakanth patil 	list_for_each_node_safe(cur, tmp, &cntx->srq_dbr_res.head) {
530*9207f9d2SChandrakanth patil 		srq = list_node(cur, struct bnxt_re_srq, dbnode);
531*9207f9d2SChandrakanth patil 		bnxt_re_replay_db(cntx, &srq->rand, srq->udpi,
532*9207f9d2SChandrakanth patil 				  &srq->shadow_db_key, &srq->dbr_lock);
533*9207f9d2SChandrakanth patil 	}
534*9207f9d2SChandrakanth patil 	pthread_spin_unlock(&cntx->srq_dbr_res.lock);
535*9207f9d2SChandrakanth patil }
536*9207f9d2SChandrakanth patil 
537*9207f9d2SChandrakanth patil void *bnxt_re_dbr_thread(void *arg)
538*9207f9d2SChandrakanth patil {
539*9207f9d2SChandrakanth patil 	uint32_t *epoch, *epoch_ack, usr_epoch;
540*9207f9d2SChandrakanth patil 	struct bnxt_re_context *cntx = arg;
541*9207f9d2SChandrakanth patil 	struct ibv_cq *ev_cq;
542*9207f9d2SChandrakanth patil 	void *ev_ctx;
543*9207f9d2SChandrakanth patil 	int ret;
544*9207f9d2SChandrakanth patil 
545*9207f9d2SChandrakanth patil 	while (1) {
546*9207f9d2SChandrakanth patil 		ret = ibv_get_cq_event(cntx->dbr_ev_chan, &ev_cq, &ev_ctx);
547*9207f9d2SChandrakanth patil 		if (ret) {
548*9207f9d2SChandrakanth patil 			fprintf(stderr, "Failed to get cq_event\n");
549*9207f9d2SChandrakanth patil 			pthread_exit(NULL);
550*9207f9d2SChandrakanth patil 		}
551*9207f9d2SChandrakanth patil 		epoch = cntx->db_recovery_page;
552*9207f9d2SChandrakanth patil 		epoch_ack = epoch + 1;
553*9207f9d2SChandrakanth patil 		if (!epoch || !epoch_ack) {
554*9207f9d2SChandrakanth patil 			fprintf(stderr, "DB reovery page is NULL\n");
555*9207f9d2SChandrakanth patil 			pthread_exit(NULL);
556*9207f9d2SChandrakanth patil 		}
557*9207f9d2SChandrakanth patil 		if (*epoch == *epoch_ack) {
558*9207f9d2SChandrakanth patil 			ibv_ack_cq_events(ev_cq, 1);
559*9207f9d2SChandrakanth patil 			continue;
560*9207f9d2SChandrakanth patil 		}
561*9207f9d2SChandrakanth patil 		usr_epoch = *epoch;
562*9207f9d2SChandrakanth patil 		bnxt_re_db_recovery(cntx);
563*9207f9d2SChandrakanth patil 		*epoch_ack = usr_epoch;
564*9207f9d2SChandrakanth patil 		ibv_ack_cq_events(ev_cq, 1);
565*9207f9d2SChandrakanth patil 	}
566*9207f9d2SChandrakanth patil }
567