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