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