1fd710bb1SScott Branden /* SPDX-License-Identifier: BSD-3-Clause 2e6e8f03eSRandy Schacher * Copyright(c) 2014-2023 Broadcom 37bc8e9a2SAjit Khaparde * All rights reserved. 47bc8e9a2SAjit Khaparde */ 57bc8e9a2SAjit Khaparde 67bc8e9a2SAjit Khaparde #include <inttypes.h> 77bc8e9a2SAjit Khaparde 843f78b38SLance Richardson #include <rte_cycles.h> 97bc8e9a2SAjit Khaparde #include <rte_malloc.h> 107bc8e9a2SAjit Khaparde 117bc8e9a2SAjit Khaparde #include "bnxt.h" 127bc8e9a2SAjit Khaparde #include "bnxt_irq.h" 137bc8e9a2SAjit Khaparde #include "bnxt_ring.h" 147bc8e9a2SAjit Khaparde #include "hsi_struct_def_dpdk.h" 157bc8e9a2SAjit Khaparde 167bc8e9a2SAjit Khaparde /* 177bc8e9a2SAjit Khaparde * Interrupts 187bc8e9a2SAjit Khaparde */ 197bc8e9a2SAjit Khaparde 20627c5855SAjit Khaparde static inline void bnxt_int_handler_rearm(struct bnxt *bp, 21627c5855SAjit Khaparde struct bnxt_cp_ring_info *cpr, 22627c5855SAjit Khaparde uint32_t raw_cons) 23627c5855SAjit Khaparde { 24627c5855SAjit Khaparde cpr->cp_raw_cons = raw_cons; 25627c5855SAjit Khaparde if (BNXT_HAS_NQ(bp)) 26627c5855SAjit Khaparde bnxt_db_nq_arm(cpr); 27627c5855SAjit Khaparde else 28627c5855SAjit Khaparde B_CP_DB_REARM(cpr, cpr->cp_raw_cons); 29627c5855SAjit Khaparde } 30627c5855SAjit Khaparde 31627c5855SAjit Khaparde /* ARM the default CQ/NQ at intervals of 1/8th of ring size */ 32627c5855SAjit Khaparde #define BNXT_DB_REARM_FACTOR 8 33c023cd5bSAjit Khaparde void bnxt_int_handler(void *param) 347bc8e9a2SAjit Khaparde { 357bc8e9a2SAjit Khaparde struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param; 3678466c95SStephen Hemminger struct bnxt *bp = eth_dev->data->dev_private; 375ed30db8SLance Richardson uint32_t cons, raw_cons, cp_ring_size; 38dc59260fSThierry Herbelot struct bnxt_cp_ring_info *cpr; 397bc8e9a2SAjit Khaparde struct cmpl_base *cmp; 40627c5855SAjit Khaparde uint16_t cnt = 0; 415ed30db8SLance Richardson 427bc8e9a2SAjit Khaparde 43dc59260fSThierry Herbelot if (bp == NULL) 44dc59260fSThierry Herbelot return; 45dc59260fSThierry Herbelot cpr = bp->async_cp_ring; 468ec40353SAjit Khaparde if (cpr == NULL) 478ec40353SAjit Khaparde return; 488ec40353SAjit Khaparde 498ec40353SAjit Khaparde raw_cons = cpr->cp_raw_cons; 505526c802SSomnath Kotur pthread_mutex_lock(&bp->def_cp_lock); 517bc8e9a2SAjit Khaparde while (1) { 525526c802SSomnath Kotur if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) { 535526c802SSomnath Kotur pthread_mutex_unlock(&bp->def_cp_lock); 54f7ecea91SAjit Khaparde return; 555526c802SSomnath Kotur } 56f7ecea91SAjit Khaparde 57bfbfe4aaSKalesh AP if (is_bnxt_in_error(bp)) { 58bfbfe4aaSKalesh AP pthread_mutex_unlock(&bp->def_cp_lock); 59bfbfe4aaSKalesh AP return; 60bfbfe4aaSKalesh AP } 61bfbfe4aaSKalesh AP 623f44ec48SKalesh AP cp_ring_size = cpr->cp_ring_struct->ring_size; 637bc8e9a2SAjit Khaparde cons = RING_CMP(cpr->cp_ring_struct, raw_cons); 647bc8e9a2SAjit Khaparde cmp = &cpr->cp_desc_ring[cons]; 657bc8e9a2SAjit Khaparde 665ed30db8SLance Richardson if (!bnxt_cpr_cmp_valid(cmp, raw_cons, cp_ring_size)) 677bc8e9a2SAjit Khaparde break; 687bc8e9a2SAjit Khaparde 692b947bd2SAjit Khaparde bnxt_event_hwrm_resp_handler(bp, cmp); 707bc8e9a2SAjit Khaparde raw_cons = NEXT_RAW_CMP(raw_cons); 71627c5855SAjit Khaparde if (++cnt >= cp_ring_size / BNXT_DB_REARM_FACTOR) { 72627c5855SAjit Khaparde bnxt_int_handler_rearm(bp, cpr, raw_cons); 73627c5855SAjit Khaparde cnt = 0; 74627c5855SAjit Khaparde } 75bd0a14c9SLance Richardson } 762b947bd2SAjit Khaparde 77627c5855SAjit Khaparde /* cnt = 0 means no work or we rearmed already */ 78627c5855SAjit Khaparde if (cnt > 0) 79627c5855SAjit Khaparde bnxt_int_handler_rearm(bp, cpr, raw_cons); 805526c802SSomnath Kotur 815526c802SSomnath Kotur pthread_mutex_unlock(&bp->def_cp_lock); 827bc8e9a2SAjit Khaparde } 837bc8e9a2SAjit Khaparde 8443f78b38SLance Richardson int bnxt_free_int(struct bnxt *bp) 857bc8e9a2SAjit Khaparde { 86d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = bp->pdev->intr_handle; 8743f78b38SLance Richardson struct bnxt_irq *irq = bp->irq_tbl; 8843f78b38SLance Richardson int rc = 0; 897bc8e9a2SAjit Khaparde 9043f78b38SLance Richardson if (!irq) 9143f78b38SLance Richardson return 0; 922c43b439SKalesh AP 937bc8e9a2SAjit Khaparde if (irq->requested) { 9443f78b38SLance Richardson int count = 0; 9543f78b38SLance Richardson 9643f78b38SLance Richardson /* 9743f78b38SLance Richardson * Callback deregistration will fail with rc -EAGAIN if the 9843f78b38SLance Richardson * callback is currently active. Retry every 50 ms until 9943f78b38SLance Richardson * successful or 500 ms has elapsed. 10043f78b38SLance Richardson */ 10143f78b38SLance Richardson do { 10243f78b38SLance Richardson rc = rte_intr_callback_unregister(intr_handle, 1037bc8e9a2SAjit Khaparde irq->handler, 10443f78b38SLance Richardson bp->eth_dev); 10543f78b38SLance Richardson if (rc >= 0) { 1067bc8e9a2SAjit Khaparde irq->requested = 0; 10743f78b38SLance Richardson break; 1087bc8e9a2SAjit Khaparde } 10943f78b38SLance Richardson rte_delay_ms(50); 11043f78b38SLance Richardson } while (count++ < 10); 11143f78b38SLance Richardson 11243f78b38SLance Richardson if (rc < 0) { 113*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "irq cb unregister failed rc: %d", 11443f78b38SLance Richardson rc); 11543f78b38SLance Richardson return rc; 11643f78b38SLance Richardson } 11743f78b38SLance Richardson } 11843f78b38SLance Richardson 11943f78b38SLance Richardson rte_free(bp->irq_tbl); 1207bc8e9a2SAjit Khaparde bp->irq_tbl = NULL; 12143f78b38SLance Richardson 12243f78b38SLance Richardson return 0; 1237bc8e9a2SAjit Khaparde } 1247bc8e9a2SAjit Khaparde 1257bc8e9a2SAjit Khaparde void bnxt_disable_int(struct bnxt *bp) 1267bc8e9a2SAjit Khaparde { 127bd0a14c9SLance Richardson struct bnxt_cp_ring_info *cpr = bp->async_cp_ring; 128bd0a14c9SLance Richardson 129bd0a14c9SLance Richardson if (BNXT_NUM_ASYNC_CPR(bp) == 0) 130bd0a14c9SLance Richardson return; 131bd0a14c9SLance Richardson 132bfbfe4aaSKalesh AP if (is_bnxt_in_error(bp)) 133bfbfe4aaSKalesh AP return; 134bfbfe4aaSKalesh AP 135bd0a14c9SLance Richardson if (!cpr || !cpr->cp_db.doorbell) 136bd0a14c9SLance Richardson return; 1377bc8e9a2SAjit Khaparde 1387bc8e9a2SAjit Khaparde /* Only the default completion ring */ 139bd0a14c9SLance Richardson if (BNXT_HAS_NQ(bp)) 140bd0a14c9SLance Richardson bnxt_db_nq(cpr); 141bd0a14c9SLance Richardson else 1424535cad3SAjit Khaparde B_CP_DB_DISARM(cpr); 1437bc8e9a2SAjit Khaparde } 1447bc8e9a2SAjit Khaparde 1457bc8e9a2SAjit Khaparde void bnxt_enable_int(struct bnxt *bp) 1467bc8e9a2SAjit Khaparde { 147bd0a14c9SLance Richardson struct bnxt_cp_ring_info *cpr = bp->async_cp_ring; 148bd0a14c9SLance Richardson 149bd0a14c9SLance Richardson if (BNXT_NUM_ASYNC_CPR(bp) == 0) 150bd0a14c9SLance Richardson return; 151bd0a14c9SLance Richardson 152bd0a14c9SLance Richardson if (!cpr || !cpr->cp_db.doorbell) 153bd0a14c9SLance Richardson return; 1547bc8e9a2SAjit Khaparde 1552b947bd2SAjit Khaparde /* Only the default completion ring */ 156bd0a14c9SLance Richardson if (BNXT_HAS_NQ(bp)) 157bd0a14c9SLance Richardson bnxt_db_nq_arm(cpr); 158bd0a14c9SLance Richardson else 1594535cad3SAjit Khaparde B_CP_DB_ARM(cpr); 1607bc8e9a2SAjit Khaparde } 1617bc8e9a2SAjit Khaparde 1627bc8e9a2SAjit Khaparde int bnxt_setup_int(struct bnxt *bp) 1637bc8e9a2SAjit Khaparde { 1647bc8e9a2SAjit Khaparde uint16_t total_vecs; 1657bc8e9a2SAjit Khaparde const int len = sizeof(bp->irq_tbl[0].name); 166bd0a14c9SLance Richardson int i; 1677bc8e9a2SAjit Khaparde 1687bc8e9a2SAjit Khaparde /* DPDK host only supports 1 MSI-X vector */ 1697bc8e9a2SAjit Khaparde total_vecs = 1; 1707bc8e9a2SAjit Khaparde bp->irq_tbl = rte_calloc("bnxt_irq_tbl", total_vecs, 1717bc8e9a2SAjit Khaparde sizeof(struct bnxt_irq), 0); 1727bc8e9a2SAjit Khaparde if (bp->irq_tbl) { 1737bc8e9a2SAjit Khaparde for (i = 0; i < total_vecs; i++) { 17487a8fa12SAjit Khaparde bp->irq_tbl[i].vector_idx = i; 1757bc8e9a2SAjit Khaparde snprintf(bp->irq_tbl[i].name, len, 1764be4659aSFerruh Yigit "%s-%d", bp->eth_dev->device->name, i); 1777bc8e9a2SAjit Khaparde bp->irq_tbl[i].handler = bnxt_int_handler; 1787bc8e9a2SAjit Khaparde } 1797bc8e9a2SAjit Khaparde } else { 180*e99981afSDavid Marchand PMD_DRV_LOG_LINE(ERR, "bnxt_irq_tbl setup failed"); 181bd0a14c9SLance Richardson return -ENOMEM; 182bd0a14c9SLance Richardson } 183bd0a14c9SLance Richardson 184bd0a14c9SLance Richardson return 0; 1857bc8e9a2SAjit Khaparde } 1867bc8e9a2SAjit Khaparde 1877bc8e9a2SAjit Khaparde int bnxt_request_int(struct bnxt *bp) 1887bc8e9a2SAjit Khaparde { 189d61138d4SHarman Kalra struct rte_intr_handle *intr_handle = bp->pdev->intr_handle; 19043f78b38SLance Richardson struct bnxt_irq *irq = bp->irq_tbl; 1917bc8e9a2SAjit Khaparde int rc = 0; 1927bc8e9a2SAjit Khaparde 19343f78b38SLance Richardson if (!irq) 19443f78b38SLance Richardson return 0; 1957bc8e9a2SAjit Khaparde 19643f78b38SLance Richardson if (!irq->requested) { 19743f78b38SLance Richardson rc = rte_intr_callback_register(intr_handle, 19843f78b38SLance Richardson irq->handler, 19943f78b38SLance Richardson bp->eth_dev); 20043f78b38SLance Richardson if (!rc) 2017bc8e9a2SAjit Khaparde irq->requested = 1; 20243f78b38SLance Richardson } 20343f78b38SLance Richardson 204d9fc6a0dSKalesh AP #ifdef RTE_EXEC_ENV_FREEBSD 205d9fc6a0dSKalesh AP /** 206d9fc6a0dSKalesh AP * In FreeBSD OS, nic_uio does not support interrupts and 207d9fc6a0dSKalesh AP * interrupt register callback will fail. 208d9fc6a0dSKalesh AP */ 209d9fc6a0dSKalesh AP rc = 0; 210d9fc6a0dSKalesh AP #endif 211d9fc6a0dSKalesh AP 2127bc8e9a2SAjit Khaparde return rc; 2137bc8e9a2SAjit Khaparde } 214