Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2014-2023 Broadcom 3 : : * All rights reserved. 4 : : */ 5 : : 6 : : #include <inttypes.h> 7 : : 8 : : #include <rte_cycles.h> 9 : : #include <rte_malloc.h> 10 : : 11 : : #include "bnxt.h" 12 : : #include "bnxt_irq.h" 13 : : #include "bnxt_ring.h" 14 : : #include "hsi_struct_def_dpdk.h" 15 : : 16 : : /* 17 : : * Interrupts 18 : : */ 19 : : 20 : 0 : static inline void bnxt_int_handler_rearm(struct bnxt *bp, 21 : : struct bnxt_cp_ring_info *cpr, 22 : : uint32_t raw_cons) 23 : : { 24 : 0 : cpr->cp_raw_cons = raw_cons; 25 [ # # ]: 0 : if (BNXT_HAS_NQ(bp)) 26 : : bnxt_db_nq_arm(cpr); 27 : : else 28 [ # # ]: 0 : B_CP_DB_REARM(cpr, cpr->cp_raw_cons); 29 : 0 : } 30 : : 31 : : /* ARM the default CQ/NQ at intervals of 1/8th of ring size */ 32 : : #define BNXT_DB_REARM_FACTOR 8 33 : 0 : void bnxt_int_handler(void *param) 34 : : { 35 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param; 36 : 0 : struct bnxt *bp = eth_dev->data->dev_private; 37 : : uint32_t cons, raw_cons, cp_ring_size; 38 : : struct bnxt_cp_ring_info *cpr; 39 : : struct cmpl_base *cmp; 40 : : uint16_t cnt = 0; 41 : : 42 : : 43 [ # # ]: 0 : if (bp == NULL) 44 : : return; 45 : 0 : cpr = bp->async_cp_ring; 46 [ # # ]: 0 : if (cpr == NULL) 47 : : return; 48 : : 49 : 0 : raw_cons = cpr->cp_raw_cons; 50 : 0 : pthread_mutex_lock(&bp->def_cp_lock); 51 : : while (1) { 52 [ # # # # ]: 0 : if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) { 53 : 0 : pthread_mutex_unlock(&bp->def_cp_lock); 54 : 0 : return; 55 : : } 56 : : 57 [ # # ]: 0 : if (is_bnxt_in_error(bp)) { 58 : 0 : pthread_mutex_unlock(&bp->def_cp_lock); 59 : 0 : return; 60 : : } 61 : : 62 : 0 : cp_ring_size = cpr->cp_ring_struct->ring_size; 63 : 0 : cons = RING_CMP(cpr->cp_ring_struct, raw_cons); 64 [ # # ]: 0 : cmp = &cpr->cp_desc_ring[cons]; 65 : : 66 : : if (!bnxt_cpr_cmp_valid(cmp, raw_cons, cp_ring_size)) 67 : : break; 68 : : 69 : 0 : bnxt_event_hwrm_resp_handler(bp, cmp); 70 : 0 : raw_cons = NEXT_RAW_CMP(raw_cons); 71 [ # # ]: 0 : if (++cnt >= cp_ring_size / BNXT_DB_REARM_FACTOR) { 72 : 0 : bnxt_int_handler_rearm(bp, cpr, raw_cons); 73 : : cnt = 0; 74 : : } 75 : : } 76 : : 77 : : /* cnt = 0 means no work or we rearmed already */ 78 [ # # ]: 0 : if (cnt > 0) 79 : 0 : bnxt_int_handler_rearm(bp, cpr, raw_cons); 80 : : 81 : 0 : pthread_mutex_unlock(&bp->def_cp_lock); 82 : : } 83 : : 84 : 0 : int bnxt_free_int(struct bnxt *bp) 85 : : { 86 : 0 : struct rte_intr_handle *intr_handle = bp->pdev->intr_handle; 87 : 0 : struct bnxt_irq *irq = bp->irq_tbl; 88 : : int rc = 0; 89 : : 90 [ # # ]: 0 : if (!irq) 91 : : return 0; 92 : : 93 [ # # ]: 0 : if (irq->requested) { 94 : : int count = 0; 95 : : 96 : : /* 97 : : * Callback deregistration will fail with rc -EAGAIN if the 98 : : * callback is currently active. Retry every 50 ms until 99 : : * successful or 500 ms has elapsed. 100 : : */ 101 : : do { 102 : 0 : rc = rte_intr_callback_unregister(intr_handle, 103 : : irq->handler, 104 : 0 : bp->eth_dev); 105 [ # # ]: 0 : if (rc >= 0) { 106 : 0 : irq->requested = 0; 107 : 0 : break; 108 : : } 109 : : rte_delay_ms(50); 110 [ # # ]: 0 : } while (count++ < 10); 111 : : 112 [ # # ]: 0 : if (rc < 0) { 113 : 0 : PMD_DRV_LOG_LINE(ERR, "irq cb unregister failed rc: %d", 114 : : rc); 115 : 0 : return rc; 116 : : } 117 : : } 118 : : 119 : 0 : rte_free(bp->irq_tbl); 120 : 0 : bp->irq_tbl = NULL; 121 : : 122 : 0 : return 0; 123 : : } 124 : : 125 : 0 : void bnxt_disable_int(struct bnxt *bp) 126 : : { 127 : 0 : struct bnxt_cp_ring_info *cpr = bp->async_cp_ring; 128 : : 129 : : if (BNXT_NUM_ASYNC_CPR(bp) == 0) 130 : : return; 131 : : 132 [ # # ]: 0 : if (is_bnxt_in_error(bp)) 133 : : return; 134 : : 135 [ # # # # ]: 0 : if (!cpr || !cpr->cp_db.doorbell) 136 : : return; 137 : : 138 : : /* Only the default completion ring */ 139 [ # # ]: 0 : if (BNXT_HAS_NQ(bp)) 140 : : bnxt_db_nq(cpr); 141 : : else 142 : 0 : B_CP_DB_DISARM(cpr); 143 : : } 144 : : 145 : 0 : void bnxt_enable_int(struct bnxt *bp) 146 : : { 147 : 0 : struct bnxt_cp_ring_info *cpr = bp->async_cp_ring; 148 : : 149 : : if (BNXT_NUM_ASYNC_CPR(bp) == 0) 150 : : return; 151 : : 152 [ # # # # ]: 0 : if (!cpr || !cpr->cp_db.doorbell) 153 : : return; 154 : : 155 : : /* Only the default completion ring */ 156 [ # # ]: 0 : if (BNXT_HAS_NQ(bp)) 157 : : bnxt_db_nq_arm(cpr); 158 : : else 159 : : B_CP_DB_ARM(cpr); 160 : : } 161 : : 162 : 0 : int bnxt_setup_int(struct bnxt *bp) 163 : : { 164 : : uint16_t total_vecs; 165 : : const int len = sizeof(bp->irq_tbl[0].name); 166 : : int i; 167 : : 168 : : /* DPDK host only supports 1 MSI-X vector */ 169 : : total_vecs = 1; 170 : 0 : bp->irq_tbl = rte_calloc("bnxt_irq_tbl", total_vecs, 171 : : sizeof(struct bnxt_irq), 0); 172 [ # # ]: 0 : if (bp->irq_tbl) { 173 [ # # ]: 0 : for (i = 0; i < total_vecs; i++) { 174 : 0 : bp->irq_tbl[i].vector_idx = i; 175 : 0 : snprintf(bp->irq_tbl[i].name, len, 176 : 0 : "%s-%d", bp->eth_dev->device->name, i); 177 : 0 : bp->irq_tbl[i].handler = bnxt_int_handler; 178 : : } 179 : : } else { 180 : 0 : PMD_DRV_LOG_LINE(ERR, "bnxt_irq_tbl setup failed"); 181 : 0 : return -ENOMEM; 182 : : } 183 : : 184 : : return 0; 185 : : } 186 : : 187 : 0 : int bnxt_request_int(struct bnxt *bp) 188 : : { 189 : 0 : struct rte_intr_handle *intr_handle = bp->pdev->intr_handle; 190 : 0 : struct bnxt_irq *irq = bp->irq_tbl; 191 : : int rc = 0; 192 : : 193 [ # # ]: 0 : if (!irq) 194 : : return 0; 195 : : 196 [ # # ]: 0 : if (!irq->requested) { 197 : 0 : rc = rte_intr_callback_register(intr_handle, 198 : : irq->handler, 199 : 0 : bp->eth_dev); 200 [ # # ]: 0 : if (!rc) 201 : 0 : irq->requested = 1; 202 : : } 203 : : 204 : : #ifdef RTE_EXEC_ENV_FREEBSD 205 : : /** 206 : : * In FreeBSD OS, nic_uio does not support interrupts and 207 : : * interrupt register callback will fail. 208 : : */ 209 : : rc = 0; 210 : : #endif 211 : : 212 : : return rc; 213 : : }