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 : void bnxt_int_handler(void *param) 21 : : { 22 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param; 23 : 0 : struct bnxt *bp = eth_dev->data->dev_private; 24 : : uint32_t cons, raw_cons, cp_ring_size; 25 : : struct bnxt_cp_ring_info *cpr; 26 : : struct cmpl_base *cmp; 27 : : 28 : : 29 [ # # ]: 0 : if (bp == NULL) 30 : : return; 31 : 0 : cpr = bp->async_cp_ring; 32 [ # # ]: 0 : if (cpr == NULL) 33 : : return; 34 : : 35 : 0 : raw_cons = cpr->cp_raw_cons; 36 : 0 : pthread_mutex_lock(&bp->def_cp_lock); 37 : : while (1) { 38 [ # # # # ]: 0 : if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) { 39 : 0 : pthread_mutex_unlock(&bp->def_cp_lock); 40 : 0 : return; 41 : : } 42 : : 43 [ # # ]: 0 : if (is_bnxt_in_error(bp)) { 44 : 0 : pthread_mutex_unlock(&bp->def_cp_lock); 45 : 0 : return; 46 : : } 47 : : 48 : 0 : cp_ring_size = cpr->cp_ring_struct->ring_size; 49 : 0 : cons = RING_CMP(cpr->cp_ring_struct, raw_cons); 50 [ # # ]: 0 : cmp = &cpr->cp_desc_ring[cons]; 51 : : 52 : : if (!bnxt_cpr_cmp_valid(cmp, raw_cons, cp_ring_size)) 53 : : break; 54 : : 55 : 0 : bnxt_event_hwrm_resp_handler(bp, cmp); 56 : 0 : raw_cons = NEXT_RAW_CMP(raw_cons); 57 : : } 58 : : 59 : 0 : cpr->cp_raw_cons = raw_cons; 60 [ # # ]: 0 : if (BNXT_HAS_NQ(bp)) 61 : : bnxt_db_nq_arm(cpr); 62 : : else 63 : 0 : B_CP_DB_REARM(cpr, cpr->cp_raw_cons); 64 : : 65 : 0 : pthread_mutex_unlock(&bp->def_cp_lock); 66 : : } 67 : : 68 : 0 : int bnxt_free_int(struct bnxt *bp) 69 : : { 70 : 0 : struct rte_intr_handle *intr_handle = bp->pdev->intr_handle; 71 : 0 : struct bnxt_irq *irq = bp->irq_tbl; 72 : : int rc = 0; 73 : : 74 [ # # ]: 0 : if (!irq) 75 : : return 0; 76 : : 77 [ # # ]: 0 : if (irq->requested) { 78 : : int count = 0; 79 : : 80 : : /* 81 : : * Callback deregistration will fail with rc -EAGAIN if the 82 : : * callback is currently active. Retry every 50 ms until 83 : : * successful or 500 ms has elapsed. 84 : : */ 85 : : do { 86 : 0 : rc = rte_intr_callback_unregister(intr_handle, 87 : : irq->handler, 88 : 0 : bp->eth_dev); 89 [ # # ]: 0 : if (rc >= 0) { 90 : 0 : irq->requested = 0; 91 : 0 : break; 92 : : } 93 : : rte_delay_ms(50); 94 [ # # ]: 0 : } while (count++ < 10); 95 : : 96 [ # # ]: 0 : if (rc < 0) { 97 : 0 : PMD_DRV_LOG(ERR, "irq cb unregister failed rc: %d\n", 98 : : rc); 99 : 0 : return rc; 100 : : } 101 : : } 102 : : 103 : 0 : rte_free(bp->irq_tbl); 104 : 0 : bp->irq_tbl = NULL; 105 : : 106 : 0 : return 0; 107 : : } 108 : : 109 : 0 : void bnxt_disable_int(struct bnxt *bp) 110 : : { 111 : 0 : struct bnxt_cp_ring_info *cpr = bp->async_cp_ring; 112 : : 113 : : if (BNXT_NUM_ASYNC_CPR(bp) == 0) 114 : : return; 115 : : 116 [ # # ]: 0 : if (is_bnxt_in_error(bp)) 117 : : return; 118 : : 119 [ # # # # ]: 0 : if (!cpr || !cpr->cp_db.doorbell) 120 : : return; 121 : : 122 : : /* Only the default completion ring */ 123 [ # # ]: 0 : if (BNXT_HAS_NQ(bp)) 124 : : bnxt_db_nq(cpr); 125 : : else 126 : 0 : B_CP_DB_DISARM(cpr); 127 : : } 128 : : 129 : 0 : void bnxt_enable_int(struct bnxt *bp) 130 : : { 131 : 0 : struct bnxt_cp_ring_info *cpr = bp->async_cp_ring; 132 : : 133 : : if (BNXT_NUM_ASYNC_CPR(bp) == 0) 134 : : return; 135 : : 136 [ # # # # ]: 0 : if (!cpr || !cpr->cp_db.doorbell) 137 : : return; 138 : : 139 : : /* Only the default completion ring */ 140 [ # # ]: 0 : if (BNXT_HAS_NQ(bp)) 141 : : bnxt_db_nq_arm(cpr); 142 : : else 143 : : B_CP_DB_ARM(cpr); 144 : : } 145 : : 146 : 0 : int bnxt_setup_int(struct bnxt *bp) 147 : : { 148 : : uint16_t total_vecs; 149 : : const int len = sizeof(bp->irq_tbl[0].name); 150 : : int i; 151 : : 152 : : /* DPDK host only supports 1 MSI-X vector */ 153 : : total_vecs = 1; 154 : 0 : bp->irq_tbl = rte_calloc("bnxt_irq_tbl", total_vecs, 155 : : sizeof(struct bnxt_irq), 0); 156 [ # # ]: 0 : if (bp->irq_tbl) { 157 [ # # ]: 0 : for (i = 0; i < total_vecs; i++) { 158 : 0 : bp->irq_tbl[i].vector_idx = i; 159 : 0 : snprintf(bp->irq_tbl[i].name, len, 160 : 0 : "%s-%d", bp->eth_dev->device->name, i); 161 : 0 : bp->irq_tbl[i].handler = bnxt_int_handler; 162 : : } 163 : : } else { 164 : 0 : PMD_DRV_LOG(ERR, "bnxt_irq_tbl setup failed\n"); 165 : 0 : return -ENOMEM; 166 : : } 167 : : 168 : : return 0; 169 : : } 170 : : 171 : 0 : int bnxt_request_int(struct bnxt *bp) 172 : : { 173 : 0 : struct rte_intr_handle *intr_handle = bp->pdev->intr_handle; 174 : 0 : struct bnxt_irq *irq = bp->irq_tbl; 175 : : int rc = 0; 176 : : 177 [ # # ]: 0 : if (!irq) 178 : : return 0; 179 : : 180 [ # # ]: 0 : if (!irq->requested) { 181 : 0 : rc = rte_intr_callback_register(intr_handle, 182 : : irq->handler, 183 : 0 : bp->eth_dev); 184 [ # # ]: 0 : if (!rc) 185 : 0 : irq->requested = 1; 186 : : } 187 : : 188 : : #ifdef RTE_EXEC_ENV_FREEBSD 189 : : /** 190 : : * In FreeBSD OS, nic_uio does not support interrupts and 191 : : * interrupt register callback will fail. 192 : : */ 193 : : rc = 0; 194 : : #endif 195 : : 196 : : return rc; 197 : : }