1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2018 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <inttypes.h> 7 8 #include <rte_malloc.h> 9 10 #include "bnxt.h" 11 #include "bnxt_cpr.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 static 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->def_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 while (1) { 34 if (!cpr || !cpr->cp_ring_struct || !cpr->cp_db.doorbell) 35 return; 36 37 cons = RING_CMP(cpr->cp_ring_struct, raw_cons); 38 cmp = &cpr->cp_desc_ring[cons]; 39 40 if (!CMP_VALID(cmp, raw_cons, cpr->cp_ring_struct)) 41 break; 42 43 bnxt_event_hwrm_resp_handler(bp, cmp); 44 raw_cons = NEXT_RAW_CMP(raw_cons); 45 }; 46 47 cpr->cp_raw_cons = raw_cons; 48 B_CP_DB_REARM(cpr, cpr->cp_raw_cons); 49 } 50 51 void bnxt_free_int(struct bnxt *bp) 52 { 53 struct bnxt_irq *irq; 54 55 if (bp->irq_tbl == NULL) 56 return; 57 58 irq = bp->irq_tbl; 59 if (irq) { 60 if (irq->requested) { 61 rte_intr_callback_unregister(&bp->pdev->intr_handle, 62 irq->handler, 63 (void *)bp->eth_dev); 64 irq->requested = 0; 65 } 66 rte_free((void *)bp->irq_tbl); 67 bp->irq_tbl = NULL; 68 } 69 } 70 71 void bnxt_disable_int(struct bnxt *bp) 72 { 73 struct bnxt_cp_ring_info *cpr = bp->def_cp_ring; 74 75 /* Only the default completion ring */ 76 if (cpr != NULL && cpr->cp_db.doorbell != NULL) 77 B_CP_DB_DISARM(cpr); 78 } 79 80 void bnxt_enable_int(struct bnxt *bp) 81 { 82 struct bnxt_cp_ring_info *cpr = bp->def_cp_ring; 83 84 /* Only the default completion ring */ 85 if (cpr != NULL && cpr->cp_db.doorbell != NULL) 86 B_CP_DB_ARM(cpr); 87 } 88 89 int bnxt_setup_int(struct bnxt *bp) 90 { 91 uint16_t total_vecs; 92 const int len = sizeof(bp->irq_tbl[0].name); 93 int i, rc = 0; 94 95 /* DPDK host only supports 1 MSI-X vector */ 96 total_vecs = 1; 97 bp->irq_tbl = rte_calloc("bnxt_irq_tbl", total_vecs, 98 sizeof(struct bnxt_irq), 0); 99 if (bp->irq_tbl) { 100 for (i = 0; i < total_vecs; i++) { 101 bp->irq_tbl[i].vector = i; 102 snprintf(bp->irq_tbl[i].name, len, 103 "%s-%d", bp->eth_dev->device->name, i); 104 bp->irq_tbl[i].handler = bnxt_int_handler; 105 } 106 } else { 107 rc = -ENOMEM; 108 goto setup_exit; 109 } 110 return 0; 111 112 setup_exit: 113 PMD_DRV_LOG(ERR, "bnxt_irq_tbl setup failed\n"); 114 return rc; 115 } 116 117 int bnxt_request_int(struct bnxt *bp) 118 { 119 int rc = 0; 120 121 struct bnxt_irq *irq = bp->irq_tbl; 122 123 rte_intr_callback_register(&bp->pdev->intr_handle, irq->handler, 124 (void *)bp->eth_dev); 125 126 irq->requested = 1; 127 return rc; 128 } 129