18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/pci.h>
38c2ecf20Sopenharmony_ci#include <linux/printk.h>
48c2ecf20Sopenharmony_ci#include <linux/slab.h>
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "nitrox_dev.h"
78c2ecf20Sopenharmony_ci#include "nitrox_csr.h"
88c2ecf20Sopenharmony_ci#include "nitrox_common.h"
98c2ecf20Sopenharmony_ci#include "nitrox_hal.h"
108c2ecf20Sopenharmony_ci#include "nitrox_mbx.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/**
138c2ecf20Sopenharmony_ci * One vector for each type of ring
148c2ecf20Sopenharmony_ci *  - NPS packet ring, AQMQ ring and ZQMQ ring
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci#define NR_RING_VECTORS 3
178c2ecf20Sopenharmony_ci#define NR_NON_RING_VECTORS 1
188c2ecf20Sopenharmony_ci/* base entry for packet ring/port */
198c2ecf20Sopenharmony_ci#define PKT_RING_MSIX_BASE 0
208c2ecf20Sopenharmony_ci#define NON_RING_MSIX_BASE 192
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/**
238c2ecf20Sopenharmony_ci * nps_pkt_slc_isr - IRQ handler for NPS solicit port
248c2ecf20Sopenharmony_ci * @irq: irq number
258c2ecf20Sopenharmony_ci * @data: argument
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_cistatic irqreturn_t nps_pkt_slc_isr(int irq, void *data)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	struct nitrox_q_vector *qvec = data;
308c2ecf20Sopenharmony_ci	union nps_pkt_slc_cnts slc_cnts;
318c2ecf20Sopenharmony_ci	struct nitrox_cmdq *cmdq = qvec->cmdq;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	slc_cnts.value = readq(cmdq->compl_cnt_csr_addr);
348c2ecf20Sopenharmony_ci	/* New packet on SLC output port */
358c2ecf20Sopenharmony_ci	if (slc_cnts.s.slc_int)
368c2ecf20Sopenharmony_ci		tasklet_hi_schedule(&qvec->resp_tasklet);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic void clear_nps_core_err_intr(struct nitrox_device *ndev)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	u64 value;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	/* Write 1 to clear */
468c2ecf20Sopenharmony_ci	value = nitrox_read_csr(ndev, NPS_CORE_INT);
478c2ecf20Sopenharmony_ci	nitrox_write_csr(ndev, NPS_CORE_INT, value);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	dev_err_ratelimited(DEV(ndev), "NSP_CORE_INT  0x%016llx\n", value);
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistatic void clear_nps_pkt_err_intr(struct nitrox_device *ndev)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	union nps_pkt_int pkt_int;
558c2ecf20Sopenharmony_ci	unsigned long value, offset;
568c2ecf20Sopenharmony_ci	int i;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	pkt_int.value = nitrox_read_csr(ndev, NPS_PKT_INT);
598c2ecf20Sopenharmony_ci	dev_err_ratelimited(DEV(ndev), "NPS_PKT_INT  0x%016llx\n",
608c2ecf20Sopenharmony_ci			    pkt_int.value);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	if (pkt_int.s.slc_err) {
638c2ecf20Sopenharmony_ci		offset = NPS_PKT_SLC_ERR_TYPE;
648c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
658c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
668c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev),
678c2ecf20Sopenharmony_ci				    "NPS_PKT_SLC_ERR_TYPE  0x%016lx\n", value);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci		offset = NPS_PKT_SLC_RERR_LO;
708c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
718c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
728c2ecf20Sopenharmony_ci		/* enable the solicit ports */
738c2ecf20Sopenharmony_ci		for_each_set_bit(i, &value, BITS_PER_LONG)
748c2ecf20Sopenharmony_ci			enable_pkt_solicit_port(ndev, i);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev),
778c2ecf20Sopenharmony_ci				    "NPS_PKT_SLC_RERR_LO  0x%016lx\n", value);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci		offset = NPS_PKT_SLC_RERR_HI;
808c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
818c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
828c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev),
838c2ecf20Sopenharmony_ci				    "NPS_PKT_SLC_RERR_HI  0x%016lx\n", value);
848c2ecf20Sopenharmony_ci	}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if (pkt_int.s.in_err) {
878c2ecf20Sopenharmony_ci		offset = NPS_PKT_IN_ERR_TYPE;
888c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
898c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
908c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev),
918c2ecf20Sopenharmony_ci				    "NPS_PKT_IN_ERR_TYPE  0x%016lx\n", value);
928c2ecf20Sopenharmony_ci		offset = NPS_PKT_IN_RERR_LO;
938c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
948c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
958c2ecf20Sopenharmony_ci		/* enable the input ring */
968c2ecf20Sopenharmony_ci		for_each_set_bit(i, &value, BITS_PER_LONG)
978c2ecf20Sopenharmony_ci			enable_pkt_input_ring(ndev, i);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev),
1008c2ecf20Sopenharmony_ci				    "NPS_PKT_IN_RERR_LO  0x%016lx\n", value);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci		offset = NPS_PKT_IN_RERR_HI;
1038c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
1048c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
1058c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev),
1068c2ecf20Sopenharmony_ci				    "NPS_PKT_IN_RERR_HI  0x%016lx\n", value);
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic void clear_pom_err_intr(struct nitrox_device *ndev)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	u64 value;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	value = nitrox_read_csr(ndev, POM_INT);
1158c2ecf20Sopenharmony_ci	nitrox_write_csr(ndev, POM_INT, value);
1168c2ecf20Sopenharmony_ci	dev_err_ratelimited(DEV(ndev), "POM_INT  0x%016llx\n", value);
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic void clear_pem_err_intr(struct nitrox_device *ndev)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	u64 value;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	value = nitrox_read_csr(ndev, PEM0_INT);
1248c2ecf20Sopenharmony_ci	nitrox_write_csr(ndev, PEM0_INT, value);
1258c2ecf20Sopenharmony_ci	dev_err_ratelimited(DEV(ndev), "PEM(0)_INT  0x%016llx\n", value);
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic void clear_lbc_err_intr(struct nitrox_device *ndev)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	union lbc_int lbc_int;
1318c2ecf20Sopenharmony_ci	u64 value, offset;
1328c2ecf20Sopenharmony_ci	int i;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	lbc_int.value = nitrox_read_csr(ndev, LBC_INT);
1358c2ecf20Sopenharmony_ci	dev_err_ratelimited(DEV(ndev), "LBC_INT  0x%016llx\n", lbc_int.value);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	if (lbc_int.s.dma_rd_err) {
1388c2ecf20Sopenharmony_ci		for (i = 0; i < NR_CLUSTERS; i++) {
1398c2ecf20Sopenharmony_ci			offset = EFL_CORE_VF_ERR_INT0X(i);
1408c2ecf20Sopenharmony_ci			value = nitrox_read_csr(ndev, offset);
1418c2ecf20Sopenharmony_ci			nitrox_write_csr(ndev, offset, value);
1428c2ecf20Sopenharmony_ci			offset = EFL_CORE_VF_ERR_INT1X(i);
1438c2ecf20Sopenharmony_ci			value = nitrox_read_csr(ndev, offset);
1448c2ecf20Sopenharmony_ci			nitrox_write_csr(ndev, offset, value);
1458c2ecf20Sopenharmony_ci		}
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	if (lbc_int.s.cam_soft_err) {
1498c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev), "CAM_SOFT_ERR, invalidating LBC\n");
1508c2ecf20Sopenharmony_ci		invalidate_lbc(ndev);
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	if (lbc_int.s.pref_dat_len_mismatch_err) {
1548c2ecf20Sopenharmony_ci		offset = LBC_PLM_VF1_64_INT;
1558c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
1568c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
1578c2ecf20Sopenharmony_ci		offset = LBC_PLM_VF65_128_INT;
1588c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
1598c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	if (lbc_int.s.rd_dat_len_mismatch_err) {
1638c2ecf20Sopenharmony_ci		offset = LBC_ELM_VF1_64_INT;
1648c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
1658c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
1668c2ecf20Sopenharmony_ci		offset = LBC_ELM_VF65_128_INT;
1678c2ecf20Sopenharmony_ci		value = nitrox_read_csr(ndev, offset);
1688c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, value);
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci	nitrox_write_csr(ndev, LBC_INT, lbc_int.value);
1718c2ecf20Sopenharmony_ci}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistatic void clear_efl_err_intr(struct nitrox_device *ndev)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	int i;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	for (i = 0; i < NR_CLUSTERS; i++) {
1788c2ecf20Sopenharmony_ci		union efl_core_int core_int;
1798c2ecf20Sopenharmony_ci		u64 value, offset;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci		offset = EFL_CORE_INTX(i);
1828c2ecf20Sopenharmony_ci		core_int.value = nitrox_read_csr(ndev, offset);
1838c2ecf20Sopenharmony_ci		nitrox_write_csr(ndev, offset, core_int.value);
1848c2ecf20Sopenharmony_ci		dev_err_ratelimited(DEV(ndev), "ELF_CORE(%d)_INT  0x%016llx\n",
1858c2ecf20Sopenharmony_ci				    i, core_int.value);
1868c2ecf20Sopenharmony_ci		if (core_int.s.se_err) {
1878c2ecf20Sopenharmony_ci			offset = EFL_CORE_SE_ERR_INTX(i);
1888c2ecf20Sopenharmony_ci			value = nitrox_read_csr(ndev, offset);
1898c2ecf20Sopenharmony_ci			nitrox_write_csr(ndev, offset, value);
1908c2ecf20Sopenharmony_ci		}
1918c2ecf20Sopenharmony_ci	}
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic void clear_bmi_err_intr(struct nitrox_device *ndev)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	u64 value;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	value = nitrox_read_csr(ndev, BMI_INT);
1998c2ecf20Sopenharmony_ci	nitrox_write_csr(ndev, BMI_INT, value);
2008c2ecf20Sopenharmony_ci	dev_err_ratelimited(DEV(ndev), "BMI_INT  0x%016llx\n", value);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void nps_core_int_tasklet(unsigned long data)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct nitrox_q_vector *qvec = (void *)(uintptr_t)(data);
2068c2ecf20Sopenharmony_ci	struct nitrox_device *ndev = qvec->ndev;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* if pf mode do queue recovery */
2098c2ecf20Sopenharmony_ci	if (ndev->mode == __NDEV_MODE_PF) {
2108c2ecf20Sopenharmony_ci	} else {
2118c2ecf20Sopenharmony_ci		/**
2128c2ecf20Sopenharmony_ci		 * if VF(s) enabled communicate the error information
2138c2ecf20Sopenharmony_ci		 * to VF(s)
2148c2ecf20Sopenharmony_ci		 */
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci/**
2198c2ecf20Sopenharmony_ci * nps_core_int_isr - interrupt handler for NITROX errors and
2208c2ecf20Sopenharmony_ci *   mailbox communication
2218c2ecf20Sopenharmony_ci */
2228c2ecf20Sopenharmony_cistatic irqreturn_t nps_core_int_isr(int irq, void *data)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct nitrox_q_vector *qvec = data;
2258c2ecf20Sopenharmony_ci	struct nitrox_device *ndev = qvec->ndev;
2268c2ecf20Sopenharmony_ci	union nps_core_int_active core_int;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	core_int.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (core_int.s.nps_core)
2318c2ecf20Sopenharmony_ci		clear_nps_core_err_intr(ndev);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	if (core_int.s.nps_pkt)
2348c2ecf20Sopenharmony_ci		clear_nps_pkt_err_intr(ndev);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (core_int.s.pom)
2378c2ecf20Sopenharmony_ci		clear_pom_err_intr(ndev);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	if (core_int.s.pem)
2408c2ecf20Sopenharmony_ci		clear_pem_err_intr(ndev);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (core_int.s.lbc)
2438c2ecf20Sopenharmony_ci		clear_lbc_err_intr(ndev);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if (core_int.s.efl)
2468c2ecf20Sopenharmony_ci		clear_efl_err_intr(ndev);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	if (core_int.s.bmi)
2498c2ecf20Sopenharmony_ci		clear_bmi_err_intr(ndev);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	/* Mailbox interrupt */
2528c2ecf20Sopenharmony_ci	if (core_int.s.mbox)
2538c2ecf20Sopenharmony_ci		nitrox_pf2vf_mbox_handler(ndev);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	/* If more work callback the ISR, set resend */
2568c2ecf20Sopenharmony_ci	core_int.s.resend = 1;
2578c2ecf20Sopenharmony_ci	nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_civoid nitrox_unregister_interrupts(struct nitrox_device *ndev)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	struct pci_dev *pdev = ndev->pdev;
2658c2ecf20Sopenharmony_ci	int i;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	for (i = 0; i < ndev->num_vecs; i++) {
2688c2ecf20Sopenharmony_ci		struct nitrox_q_vector *qvec;
2698c2ecf20Sopenharmony_ci		int vec;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci		qvec = ndev->qvec + i;
2728c2ecf20Sopenharmony_ci		if (!qvec->valid)
2738c2ecf20Sopenharmony_ci			continue;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci		/* get the vector number */
2768c2ecf20Sopenharmony_ci		vec = pci_irq_vector(pdev, i);
2778c2ecf20Sopenharmony_ci		irq_set_affinity_hint(vec, NULL);
2788c2ecf20Sopenharmony_ci		free_irq(vec, qvec);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci		tasklet_disable(&qvec->resp_tasklet);
2818c2ecf20Sopenharmony_ci		tasklet_kill(&qvec->resp_tasklet);
2828c2ecf20Sopenharmony_ci		qvec->valid = false;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci	kfree(ndev->qvec);
2858c2ecf20Sopenharmony_ci	ndev->qvec = NULL;
2868c2ecf20Sopenharmony_ci	pci_free_irq_vectors(pdev);
2878c2ecf20Sopenharmony_ci}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ciint nitrox_register_interrupts(struct nitrox_device *ndev)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct pci_dev *pdev = ndev->pdev;
2928c2ecf20Sopenharmony_ci	struct nitrox_q_vector *qvec;
2938c2ecf20Sopenharmony_ci	int nr_vecs, vec, cpu;
2948c2ecf20Sopenharmony_ci	int ret, i;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/*
2978c2ecf20Sopenharmony_ci	 * PF MSI-X vectors
2988c2ecf20Sopenharmony_ci	 *
2998c2ecf20Sopenharmony_ci	 * Entry 0: NPS PKT ring 0
3008c2ecf20Sopenharmony_ci	 * Entry 1: AQMQ ring 0
3018c2ecf20Sopenharmony_ci	 * Entry 2: ZQM ring 0
3028c2ecf20Sopenharmony_ci	 * Entry 3: NPS PKT ring 1
3038c2ecf20Sopenharmony_ci	 * Entry 4: AQMQ ring 1
3048c2ecf20Sopenharmony_ci	 * Entry 5: ZQM ring 1
3058c2ecf20Sopenharmony_ci	 * ....
3068c2ecf20Sopenharmony_ci	 * Entry 192: NPS_CORE_INT_ACTIVE
3078c2ecf20Sopenharmony_ci	 */
3088c2ecf20Sopenharmony_ci	nr_vecs = pci_msix_vec_count(pdev);
3098c2ecf20Sopenharmony_ci	if (nr_vecs < 0) {
3108c2ecf20Sopenharmony_ci		dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs);
3118c2ecf20Sopenharmony_ci		return nr_vecs;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	/* Enable MSI-X */
3158c2ecf20Sopenharmony_ci	ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX);
3168c2ecf20Sopenharmony_ci	if (ret < 0) {
3178c2ecf20Sopenharmony_ci		dev_err(DEV(ndev), "msix vectors %d alloc failed\n", nr_vecs);
3188c2ecf20Sopenharmony_ci		return ret;
3198c2ecf20Sopenharmony_ci	}
3208c2ecf20Sopenharmony_ci	ndev->num_vecs = nr_vecs;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	ndev->qvec = kcalloc(nr_vecs, sizeof(*qvec), GFP_KERNEL);
3238c2ecf20Sopenharmony_ci	if (!ndev->qvec) {
3248c2ecf20Sopenharmony_ci		pci_free_irq_vectors(pdev);
3258c2ecf20Sopenharmony_ci		return -ENOMEM;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	/* request irqs for packet rings/ports */
3298c2ecf20Sopenharmony_ci	for (i = PKT_RING_MSIX_BASE; i < (nr_vecs - 1); i += NR_RING_VECTORS) {
3308c2ecf20Sopenharmony_ci		qvec = &ndev->qvec[i];
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci		qvec->ring = i / NR_RING_VECTORS;
3338c2ecf20Sopenharmony_ci		if (qvec->ring >= ndev->nr_queues)
3348c2ecf20Sopenharmony_ci			break;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci		qvec->cmdq = &ndev->pkt_inq[qvec->ring];
3378c2ecf20Sopenharmony_ci		snprintf(qvec->name, IRQ_NAMESZ, "nitrox-pkt%d", qvec->ring);
3388c2ecf20Sopenharmony_ci		/* get the vector number */
3398c2ecf20Sopenharmony_ci		vec = pci_irq_vector(pdev, i);
3408c2ecf20Sopenharmony_ci		ret = request_irq(vec, nps_pkt_slc_isr, 0, qvec->name, qvec);
3418c2ecf20Sopenharmony_ci		if (ret) {
3428c2ecf20Sopenharmony_ci			dev_err(DEV(ndev), "irq failed for pkt ring/port%d\n",
3438c2ecf20Sopenharmony_ci				qvec->ring);
3448c2ecf20Sopenharmony_ci			goto irq_fail;
3458c2ecf20Sopenharmony_ci		}
3468c2ecf20Sopenharmony_ci		cpu = qvec->ring % num_online_cpus();
3478c2ecf20Sopenharmony_ci		irq_set_affinity_hint(vec, get_cpu_mask(cpu));
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci		tasklet_init(&qvec->resp_tasklet, pkt_slc_resp_tasklet,
3508c2ecf20Sopenharmony_ci			     (unsigned long)qvec);
3518c2ecf20Sopenharmony_ci		qvec->valid = true;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	/* request irqs for non ring vectors */
3558c2ecf20Sopenharmony_ci	i = NON_RING_MSIX_BASE;
3568c2ecf20Sopenharmony_ci	qvec = &ndev->qvec[i];
3578c2ecf20Sopenharmony_ci	qvec->ndev = ndev;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", i);
3608c2ecf20Sopenharmony_ci	/* get the vector number */
3618c2ecf20Sopenharmony_ci	vec = pci_irq_vector(pdev, i);
3628c2ecf20Sopenharmony_ci	ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);
3638c2ecf20Sopenharmony_ci	if (ret) {
3648c2ecf20Sopenharmony_ci		dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n", i);
3658c2ecf20Sopenharmony_ci		goto irq_fail;
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci	cpu = num_online_cpus();
3688c2ecf20Sopenharmony_ci	irq_set_affinity_hint(vec, get_cpu_mask(cpu));
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,
3718c2ecf20Sopenharmony_ci		     (unsigned long)qvec);
3728c2ecf20Sopenharmony_ci	qvec->valid = true;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	return 0;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ciirq_fail:
3778c2ecf20Sopenharmony_ci	nitrox_unregister_interrupts(ndev);
3788c2ecf20Sopenharmony_ci	return ret;
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_civoid nitrox_sriov_unregister_interrupts(struct nitrox_device *ndev)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	struct pci_dev *pdev = ndev->pdev;
3848c2ecf20Sopenharmony_ci	int i;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	for (i = 0; i < ndev->num_vecs; i++) {
3878c2ecf20Sopenharmony_ci		struct nitrox_q_vector *qvec;
3888c2ecf20Sopenharmony_ci		int vec;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		qvec = ndev->qvec + i;
3918c2ecf20Sopenharmony_ci		if (!qvec->valid)
3928c2ecf20Sopenharmony_ci			continue;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		vec = ndev->iov.msix.vector;
3958c2ecf20Sopenharmony_ci		irq_set_affinity_hint(vec, NULL);
3968c2ecf20Sopenharmony_ci		free_irq(vec, qvec);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		tasklet_disable(&qvec->resp_tasklet);
3998c2ecf20Sopenharmony_ci		tasklet_kill(&qvec->resp_tasklet);
4008c2ecf20Sopenharmony_ci		qvec->valid = false;
4018c2ecf20Sopenharmony_ci	}
4028c2ecf20Sopenharmony_ci	kfree(ndev->qvec);
4038c2ecf20Sopenharmony_ci	ndev->qvec = NULL;
4048c2ecf20Sopenharmony_ci	pci_disable_msix(pdev);
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ciint nitrox_sriov_register_interupts(struct nitrox_device *ndev)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	struct pci_dev *pdev = ndev->pdev;
4108c2ecf20Sopenharmony_ci	struct nitrox_q_vector *qvec;
4118c2ecf20Sopenharmony_ci	int vec, cpu;
4128c2ecf20Sopenharmony_ci	int ret;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/**
4158c2ecf20Sopenharmony_ci	 * only non ring vectors i.e Entry 192 is available
4168c2ecf20Sopenharmony_ci	 * for PF in SR-IOV mode.
4178c2ecf20Sopenharmony_ci	 */
4188c2ecf20Sopenharmony_ci	ndev->iov.msix.entry = NON_RING_MSIX_BASE;
4198c2ecf20Sopenharmony_ci	ret = pci_enable_msix_exact(pdev, &ndev->iov.msix, NR_NON_RING_VECTORS);
4208c2ecf20Sopenharmony_ci	if (ret) {
4218c2ecf20Sopenharmony_ci		dev_err(DEV(ndev), "failed to allocate nps-core-int%d\n",
4228c2ecf20Sopenharmony_ci			NON_RING_MSIX_BASE);
4238c2ecf20Sopenharmony_ci		return ret;
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	qvec = kcalloc(NR_NON_RING_VECTORS, sizeof(*qvec), GFP_KERNEL);
4278c2ecf20Sopenharmony_ci	if (!qvec) {
4288c2ecf20Sopenharmony_ci		pci_disable_msix(pdev);
4298c2ecf20Sopenharmony_ci		return -ENOMEM;
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci	qvec->ndev = ndev;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	ndev->qvec = qvec;
4348c2ecf20Sopenharmony_ci	ndev->num_vecs = NR_NON_RING_VECTORS;
4358c2ecf20Sopenharmony_ci	snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d",
4368c2ecf20Sopenharmony_ci		 NON_RING_MSIX_BASE);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	vec = ndev->iov.msix.vector;
4398c2ecf20Sopenharmony_ci	ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);
4408c2ecf20Sopenharmony_ci	if (ret) {
4418c2ecf20Sopenharmony_ci		dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n",
4428c2ecf20Sopenharmony_ci			NON_RING_MSIX_BASE);
4438c2ecf20Sopenharmony_ci		goto iov_irq_fail;
4448c2ecf20Sopenharmony_ci	}
4458c2ecf20Sopenharmony_ci	cpu = num_online_cpus();
4468c2ecf20Sopenharmony_ci	irq_set_affinity_hint(vec, get_cpu_mask(cpu));
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,
4498c2ecf20Sopenharmony_ci		     (unsigned long)qvec);
4508c2ecf20Sopenharmony_ci	qvec->valid = true;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	return 0;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ciiov_irq_fail:
4558c2ecf20Sopenharmony_ci	nitrox_sriov_unregister_interrupts(ndev);
4568c2ecf20Sopenharmony_ci	return ret;
4578c2ecf20Sopenharmony_ci}
458