xref: /dpdk/drivers/net/bnxt/bnxt_irq.c (revision e99981af34632ecce3bac82d05db97b08308f9b5)
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