1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
214fa93cdSSrikanth Jampala #include <linux/pci.h>
314fa93cdSSrikanth Jampala #include <linux/printk.h>
414fa93cdSSrikanth Jampala #include <linux/slab.h>
514fa93cdSSrikanth Jampala 
614fa93cdSSrikanth Jampala #include "nitrox_dev.h"
714fa93cdSSrikanth Jampala #include "nitrox_csr.h"
814fa93cdSSrikanth Jampala #include "nitrox_common.h"
941a9aca6SSrikanth Jampala #include "nitrox_hal.h"
1014fa93cdSSrikanth Jampala 
1114fa93cdSSrikanth Jampala #define NR_RING_VECTORS 3
1214fa93cdSSrikanth Jampala #define NPS_CORE_INT_ACTIVE_ENTRY 192
1314fa93cdSSrikanth Jampala 
1414fa93cdSSrikanth Jampala /**
1514fa93cdSSrikanth Jampala  * nps_pkt_slc_isr - IRQ handler for NPS solicit port
1614fa93cdSSrikanth Jampala  * @irq: irq number
1714fa93cdSSrikanth Jampala  * @data: argument
1814fa93cdSSrikanth Jampala  */
1914fa93cdSSrikanth Jampala static irqreturn_t nps_pkt_slc_isr(int irq, void *data)
2014fa93cdSSrikanth Jampala {
2114fa93cdSSrikanth Jampala 	struct bh_data *slc = data;
2214fa93cdSSrikanth Jampala 	union nps_pkt_slc_cnts pkt_slc_cnts;
2314fa93cdSSrikanth Jampala 
2414fa93cdSSrikanth Jampala 	pkt_slc_cnts.value = readq(slc->completion_cnt_csr_addr);
2514fa93cdSSrikanth Jampala 	/* New packet on SLC output port */
2614fa93cdSSrikanth Jampala 	if (pkt_slc_cnts.s.slc_int)
2714fa93cdSSrikanth Jampala 		tasklet_hi_schedule(&slc->resp_handler);
2814fa93cdSSrikanth Jampala 
2914fa93cdSSrikanth Jampala 	return IRQ_HANDLED;
3014fa93cdSSrikanth Jampala }
3114fa93cdSSrikanth Jampala 
3214fa93cdSSrikanth Jampala static void clear_nps_core_err_intr(struct nitrox_device *ndev)
3314fa93cdSSrikanth Jampala {
3414fa93cdSSrikanth Jampala 	u64 value;
3514fa93cdSSrikanth Jampala 
3614fa93cdSSrikanth Jampala 	/* Write 1 to clear */
3714fa93cdSSrikanth Jampala 	value = nitrox_read_csr(ndev, NPS_CORE_INT);
3814fa93cdSSrikanth Jampala 	nitrox_write_csr(ndev, NPS_CORE_INT, value);
3914fa93cdSSrikanth Jampala 
4014fa93cdSSrikanth Jampala 	dev_err_ratelimited(DEV(ndev), "NSP_CORE_INT  0x%016llx\n", value);
4114fa93cdSSrikanth Jampala }
4214fa93cdSSrikanth Jampala 
4314fa93cdSSrikanth Jampala static void clear_nps_pkt_err_intr(struct nitrox_device *ndev)
4414fa93cdSSrikanth Jampala {
4514fa93cdSSrikanth Jampala 	union nps_pkt_int pkt_int;
4614fa93cdSSrikanth Jampala 	unsigned long value, offset;
4714fa93cdSSrikanth Jampala 	int i;
4814fa93cdSSrikanth Jampala 
4914fa93cdSSrikanth Jampala 	pkt_int.value = nitrox_read_csr(ndev, NPS_PKT_INT);
5014fa93cdSSrikanth Jampala 	dev_err_ratelimited(DEV(ndev), "NPS_PKT_INT  0x%016llx\n",
5114fa93cdSSrikanth Jampala 			    pkt_int.value);
5214fa93cdSSrikanth Jampala 
5314fa93cdSSrikanth Jampala 	if (pkt_int.s.slc_err) {
5414fa93cdSSrikanth Jampala 		offset = NPS_PKT_SLC_ERR_TYPE;
5514fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
5614fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
5714fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev),
5814fa93cdSSrikanth Jampala 				    "NPS_PKT_SLC_ERR_TYPE  0x%016lx\n", value);
5914fa93cdSSrikanth Jampala 
6014fa93cdSSrikanth Jampala 		offset = NPS_PKT_SLC_RERR_LO;
6114fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
6214fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
6314fa93cdSSrikanth Jampala 		/* enable the solicit ports */
6414fa93cdSSrikanth Jampala 		for_each_set_bit(i, &value, BITS_PER_LONG)
6514fa93cdSSrikanth Jampala 			enable_pkt_solicit_port(ndev, i);
6614fa93cdSSrikanth Jampala 
6714fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev),
6814fa93cdSSrikanth Jampala 				    "NPS_PKT_SLC_RERR_LO  0x%016lx\n", value);
6914fa93cdSSrikanth Jampala 
7014fa93cdSSrikanth Jampala 		offset = NPS_PKT_SLC_RERR_HI;
7114fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
7214fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
7314fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev),
7414fa93cdSSrikanth Jampala 				    "NPS_PKT_SLC_RERR_HI  0x%016lx\n", value);
7514fa93cdSSrikanth Jampala 	}
7614fa93cdSSrikanth Jampala 
7714fa93cdSSrikanth Jampala 	if (pkt_int.s.in_err) {
7814fa93cdSSrikanth Jampala 		offset = NPS_PKT_IN_ERR_TYPE;
7914fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
8014fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
8114fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev),
8214fa93cdSSrikanth Jampala 				    "NPS_PKT_IN_ERR_TYPE  0x%016lx\n", value);
8314fa93cdSSrikanth Jampala 		offset = NPS_PKT_IN_RERR_LO;
8414fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
8514fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
8614fa93cdSSrikanth Jampala 		/* enable the input ring */
8714fa93cdSSrikanth Jampala 		for_each_set_bit(i, &value, BITS_PER_LONG)
8814fa93cdSSrikanth Jampala 			enable_pkt_input_ring(ndev, i);
8914fa93cdSSrikanth Jampala 
9014fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev),
9114fa93cdSSrikanth Jampala 				    "NPS_PKT_IN_RERR_LO  0x%016lx\n", value);
9214fa93cdSSrikanth Jampala 
9314fa93cdSSrikanth Jampala 		offset = NPS_PKT_IN_RERR_HI;
9414fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
9514fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
9614fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev),
9714fa93cdSSrikanth Jampala 				    "NPS_PKT_IN_RERR_HI  0x%016lx\n", value);
9814fa93cdSSrikanth Jampala 	}
9914fa93cdSSrikanth Jampala }
10014fa93cdSSrikanth Jampala 
10114fa93cdSSrikanth Jampala static void clear_pom_err_intr(struct nitrox_device *ndev)
10214fa93cdSSrikanth Jampala {
10314fa93cdSSrikanth Jampala 	u64 value;
10414fa93cdSSrikanth Jampala 
10514fa93cdSSrikanth Jampala 	value = nitrox_read_csr(ndev, POM_INT);
10614fa93cdSSrikanth Jampala 	nitrox_write_csr(ndev, POM_INT, value);
10714fa93cdSSrikanth Jampala 	dev_err_ratelimited(DEV(ndev), "POM_INT  0x%016llx\n", value);
10814fa93cdSSrikanth Jampala }
10914fa93cdSSrikanth Jampala 
11014fa93cdSSrikanth Jampala static void clear_pem_err_intr(struct nitrox_device *ndev)
11114fa93cdSSrikanth Jampala {
11214fa93cdSSrikanth Jampala 	u64 value;
11314fa93cdSSrikanth Jampala 
11414fa93cdSSrikanth Jampala 	value = nitrox_read_csr(ndev, PEM0_INT);
11514fa93cdSSrikanth Jampala 	nitrox_write_csr(ndev, PEM0_INT, value);
11614fa93cdSSrikanth Jampala 	dev_err_ratelimited(DEV(ndev), "PEM(0)_INT  0x%016llx\n", value);
11714fa93cdSSrikanth Jampala }
11814fa93cdSSrikanth Jampala 
11914fa93cdSSrikanth Jampala static void clear_lbc_err_intr(struct nitrox_device *ndev)
12014fa93cdSSrikanth Jampala {
12114fa93cdSSrikanth Jampala 	union lbc_int lbc_int;
12214fa93cdSSrikanth Jampala 	u64 value, offset;
12314fa93cdSSrikanth Jampala 	int i;
12414fa93cdSSrikanth Jampala 
12514fa93cdSSrikanth Jampala 	lbc_int.value = nitrox_read_csr(ndev, LBC_INT);
12614fa93cdSSrikanth Jampala 	dev_err_ratelimited(DEV(ndev), "LBC_INT  0x%016llx\n", lbc_int.value);
12714fa93cdSSrikanth Jampala 
12814fa93cdSSrikanth Jampala 	if (lbc_int.s.dma_rd_err) {
12914fa93cdSSrikanth Jampala 		for (i = 0; i < NR_CLUSTERS; i++) {
13014fa93cdSSrikanth Jampala 			offset = EFL_CORE_VF_ERR_INT0X(i);
13114fa93cdSSrikanth Jampala 			value = nitrox_read_csr(ndev, offset);
13214fa93cdSSrikanth Jampala 			nitrox_write_csr(ndev, offset, value);
13314fa93cdSSrikanth Jampala 			offset = EFL_CORE_VF_ERR_INT1X(i);
13414fa93cdSSrikanth Jampala 			value = nitrox_read_csr(ndev, offset);
13514fa93cdSSrikanth Jampala 			nitrox_write_csr(ndev, offset, value);
13614fa93cdSSrikanth Jampala 		}
13714fa93cdSSrikanth Jampala 	}
13814fa93cdSSrikanth Jampala 
13914fa93cdSSrikanth Jampala 	if (lbc_int.s.cam_soft_err) {
14014fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev), "CAM_SOFT_ERR, invalidating LBC\n");
14114fa93cdSSrikanth Jampala 		invalidate_lbc(ndev);
14214fa93cdSSrikanth Jampala 	}
14314fa93cdSSrikanth Jampala 
14414fa93cdSSrikanth Jampala 	if (lbc_int.s.pref_dat_len_mismatch_err) {
14514fa93cdSSrikanth Jampala 		offset = LBC_PLM_VF1_64_INT;
14614fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
14714fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
14814fa93cdSSrikanth Jampala 		offset = LBC_PLM_VF65_128_INT;
14914fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
15014fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
15114fa93cdSSrikanth Jampala 	}
15214fa93cdSSrikanth Jampala 
15314fa93cdSSrikanth Jampala 	if (lbc_int.s.rd_dat_len_mismatch_err) {
15414fa93cdSSrikanth Jampala 		offset = LBC_ELM_VF1_64_INT;
15514fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
15614fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
15714fa93cdSSrikanth Jampala 		offset = LBC_ELM_VF65_128_INT;
15814fa93cdSSrikanth Jampala 		value = nitrox_read_csr(ndev, offset);
15914fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, value);
16014fa93cdSSrikanth Jampala 	}
16114fa93cdSSrikanth Jampala 	nitrox_write_csr(ndev, LBC_INT, lbc_int.value);
16214fa93cdSSrikanth Jampala }
16314fa93cdSSrikanth Jampala 
16414fa93cdSSrikanth Jampala static void clear_efl_err_intr(struct nitrox_device *ndev)
16514fa93cdSSrikanth Jampala {
16614fa93cdSSrikanth Jampala 	int i;
16714fa93cdSSrikanth Jampala 
16814fa93cdSSrikanth Jampala 	for (i = 0; i < NR_CLUSTERS; i++) {
16914fa93cdSSrikanth Jampala 		union efl_core_int core_int;
17014fa93cdSSrikanth Jampala 		u64 value, offset;
17114fa93cdSSrikanth Jampala 
17214fa93cdSSrikanth Jampala 		offset = EFL_CORE_INTX(i);
17314fa93cdSSrikanth Jampala 		core_int.value = nitrox_read_csr(ndev, offset);
17414fa93cdSSrikanth Jampala 		nitrox_write_csr(ndev, offset, core_int.value);
17514fa93cdSSrikanth Jampala 		dev_err_ratelimited(DEV(ndev), "ELF_CORE(%d)_INT  0x%016llx\n",
17614fa93cdSSrikanth Jampala 				    i, core_int.value);
17714fa93cdSSrikanth Jampala 		if (core_int.s.se_err) {
17814fa93cdSSrikanth Jampala 			offset = EFL_CORE_SE_ERR_INTX(i);
17914fa93cdSSrikanth Jampala 			value = nitrox_read_csr(ndev, offset);
18014fa93cdSSrikanth Jampala 			nitrox_write_csr(ndev, offset, value);
18114fa93cdSSrikanth Jampala 		}
18214fa93cdSSrikanth Jampala 	}
18314fa93cdSSrikanth Jampala }
18414fa93cdSSrikanth Jampala 
18514fa93cdSSrikanth Jampala static void clear_bmi_err_intr(struct nitrox_device *ndev)
18614fa93cdSSrikanth Jampala {
18714fa93cdSSrikanth Jampala 	u64 value;
18814fa93cdSSrikanth Jampala 
18914fa93cdSSrikanth Jampala 	value = nitrox_read_csr(ndev, BMI_INT);
19014fa93cdSSrikanth Jampala 	nitrox_write_csr(ndev, BMI_INT, value);
19114fa93cdSSrikanth Jampala 	dev_err_ratelimited(DEV(ndev), "BMI_INT  0x%016llx\n", value);
19214fa93cdSSrikanth Jampala }
19314fa93cdSSrikanth Jampala 
19414fa93cdSSrikanth Jampala /**
19514fa93cdSSrikanth Jampala  * clear_nps_core_int_active - clear NPS_CORE_INT_ACTIVE interrupts
19614fa93cdSSrikanth Jampala  * @ndev: NITROX device
19714fa93cdSSrikanth Jampala  */
19814fa93cdSSrikanth Jampala static void clear_nps_core_int_active(struct nitrox_device *ndev)
19914fa93cdSSrikanth Jampala {
20014fa93cdSSrikanth Jampala 	union nps_core_int_active core_int_active;
20114fa93cdSSrikanth Jampala 
20214fa93cdSSrikanth Jampala 	core_int_active.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE);
20314fa93cdSSrikanth Jampala 
20414fa93cdSSrikanth Jampala 	if (core_int_active.s.nps_core)
20514fa93cdSSrikanth Jampala 		clear_nps_core_err_intr(ndev);
20614fa93cdSSrikanth Jampala 
20714fa93cdSSrikanth Jampala 	if (core_int_active.s.nps_pkt)
20814fa93cdSSrikanth Jampala 		clear_nps_pkt_err_intr(ndev);
20914fa93cdSSrikanth Jampala 
21014fa93cdSSrikanth Jampala 	if (core_int_active.s.pom)
21114fa93cdSSrikanth Jampala 		clear_pom_err_intr(ndev);
21214fa93cdSSrikanth Jampala 
21314fa93cdSSrikanth Jampala 	if (core_int_active.s.pem)
21414fa93cdSSrikanth Jampala 		clear_pem_err_intr(ndev);
21514fa93cdSSrikanth Jampala 
21614fa93cdSSrikanth Jampala 	if (core_int_active.s.lbc)
21714fa93cdSSrikanth Jampala 		clear_lbc_err_intr(ndev);
21814fa93cdSSrikanth Jampala 
21914fa93cdSSrikanth Jampala 	if (core_int_active.s.efl)
22014fa93cdSSrikanth Jampala 		clear_efl_err_intr(ndev);
22114fa93cdSSrikanth Jampala 
22214fa93cdSSrikanth Jampala 	if (core_int_active.s.bmi)
22314fa93cdSSrikanth Jampala 		clear_bmi_err_intr(ndev);
22414fa93cdSSrikanth Jampala 
22514fa93cdSSrikanth Jampala 	/* If more work callback the ISR, set resend */
22614fa93cdSSrikanth Jampala 	core_int_active.s.resend = 1;
22714fa93cdSSrikanth Jampala 	nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int_active.value);
22814fa93cdSSrikanth Jampala }
22914fa93cdSSrikanth Jampala 
23014fa93cdSSrikanth Jampala static irqreturn_t nps_core_int_isr(int irq, void *data)
23114fa93cdSSrikanth Jampala {
23214fa93cdSSrikanth Jampala 	struct nitrox_device *ndev = data;
23314fa93cdSSrikanth Jampala 
23414fa93cdSSrikanth Jampala 	clear_nps_core_int_active(ndev);
23514fa93cdSSrikanth Jampala 
23614fa93cdSSrikanth Jampala 	return IRQ_HANDLED;
23714fa93cdSSrikanth Jampala }
23814fa93cdSSrikanth Jampala 
23914fa93cdSSrikanth Jampala static int nitrox_enable_msix(struct nitrox_device *ndev)
24014fa93cdSSrikanth Jampala {
24114fa93cdSSrikanth Jampala 	struct msix_entry *entries;
24214fa93cdSSrikanth Jampala 	char **names;
24314fa93cdSSrikanth Jampala 	int i, nr_entries, ret;
24414fa93cdSSrikanth Jampala 
24514fa93cdSSrikanth Jampala 	/*
24614fa93cdSSrikanth Jampala 	 * PF MSI-X vectors
24714fa93cdSSrikanth Jampala 	 *
24814fa93cdSSrikanth Jampala 	 * Entry 0: NPS PKT ring 0
24914fa93cdSSrikanth Jampala 	 * Entry 1: AQMQ ring 0
25014fa93cdSSrikanth Jampala 	 * Entry 2: ZQM ring 0
25114fa93cdSSrikanth Jampala 	 * Entry 3: NPS PKT ring 1
25214fa93cdSSrikanth Jampala 	 * Entry 4: AQMQ ring 1
25314fa93cdSSrikanth Jampala 	 * Entry 5: ZQM ring 1
25414fa93cdSSrikanth Jampala 	 * ....
25514fa93cdSSrikanth Jampala 	 * Entry 192: NPS_CORE_INT_ACTIVE
25614fa93cdSSrikanth Jampala 	 */
25714fa93cdSSrikanth Jampala 	nr_entries = (ndev->nr_queues * NR_RING_VECTORS) + 1;
258590b5b7dSKees Cook 	entries = kcalloc_node(nr_entries, sizeof(struct msix_entry),
25914fa93cdSSrikanth Jampala 			       GFP_KERNEL, ndev->node);
26014fa93cdSSrikanth Jampala 	if (!entries)
26114fa93cdSSrikanth Jampala 		return -ENOMEM;
26214fa93cdSSrikanth Jampala 
26314fa93cdSSrikanth Jampala 	names = kcalloc(nr_entries, sizeof(char *), GFP_KERNEL);
26414fa93cdSSrikanth Jampala 	if (!names) {
26514fa93cdSSrikanth Jampala 		kfree(entries);
26614fa93cdSSrikanth Jampala 		return -ENOMEM;
26714fa93cdSSrikanth Jampala 	}
26814fa93cdSSrikanth Jampala 
26914fa93cdSSrikanth Jampala 	/* fill entires */
27014fa93cdSSrikanth Jampala 	for (i = 0; i < (nr_entries - 1); i++)
27114fa93cdSSrikanth Jampala 		entries[i].entry = i;
27214fa93cdSSrikanth Jampala 
27314fa93cdSSrikanth Jampala 	entries[i].entry = NPS_CORE_INT_ACTIVE_ENTRY;
27414fa93cdSSrikanth Jampala 
27514fa93cdSSrikanth Jampala 	for (i = 0; i < nr_entries; i++) {
27614fa93cdSSrikanth Jampala 		*(names + i) = kzalloc(MAX_MSIX_VECTOR_NAME, GFP_KERNEL);
27714fa93cdSSrikanth Jampala 		if (!(*(names + i))) {
27814fa93cdSSrikanth Jampala 			ret = -ENOMEM;
27914fa93cdSSrikanth Jampala 			goto msix_fail;
28014fa93cdSSrikanth Jampala 		}
28114fa93cdSSrikanth Jampala 	}
28214fa93cdSSrikanth Jampala 	ndev->msix.entries = entries;
28314fa93cdSSrikanth Jampala 	ndev->msix.names = names;
28414fa93cdSSrikanth Jampala 	ndev->msix.nr_entries = nr_entries;
28514fa93cdSSrikanth Jampala 
28614fa93cdSSrikanth Jampala 	ret = pci_enable_msix_exact(ndev->pdev, ndev->msix.entries,
28714fa93cdSSrikanth Jampala 				    ndev->msix.nr_entries);
28814fa93cdSSrikanth Jampala 	if (ret) {
28914fa93cdSSrikanth Jampala 		dev_err(&ndev->pdev->dev, "Failed to enable MSI-X IRQ(s) %d\n",
29014fa93cdSSrikanth Jampala 			ret);
29114fa93cdSSrikanth Jampala 		goto msix_fail;
29214fa93cdSSrikanth Jampala 	}
29314fa93cdSSrikanth Jampala 	return 0;
29414fa93cdSSrikanth Jampala 
29514fa93cdSSrikanth Jampala msix_fail:
29614fa93cdSSrikanth Jampala 	for (i = 0; i < nr_entries; i++)
29714fa93cdSSrikanth Jampala 		kfree(*(names + i));
29814fa93cdSSrikanth Jampala 
29914fa93cdSSrikanth Jampala 	kfree(entries);
30014fa93cdSSrikanth Jampala 	kfree(names);
30114fa93cdSSrikanth Jampala 	return ret;
30214fa93cdSSrikanth Jampala }
30314fa93cdSSrikanth Jampala 
30414fa93cdSSrikanth Jampala static void nitrox_cleanup_pkt_slc_bh(struct nitrox_device *ndev)
30514fa93cdSSrikanth Jampala {
30614fa93cdSSrikanth Jampala 	int i;
30714fa93cdSSrikanth Jampala 
30814fa93cdSSrikanth Jampala 	if (!ndev->bh.slc)
30914fa93cdSSrikanth Jampala 		return;
31014fa93cdSSrikanth Jampala 
31114fa93cdSSrikanth Jampala 	for (i = 0; i < ndev->nr_queues; i++) {
31214fa93cdSSrikanth Jampala 		struct bh_data *bh = &ndev->bh.slc[i];
31314fa93cdSSrikanth Jampala 
31414fa93cdSSrikanth Jampala 		tasklet_disable(&bh->resp_handler);
31514fa93cdSSrikanth Jampala 		tasklet_kill(&bh->resp_handler);
31614fa93cdSSrikanth Jampala 	}
31714fa93cdSSrikanth Jampala 	kfree(ndev->bh.slc);
31814fa93cdSSrikanth Jampala 	ndev->bh.slc = NULL;
31914fa93cdSSrikanth Jampala }
32014fa93cdSSrikanth Jampala 
32114fa93cdSSrikanth Jampala static int nitrox_setup_pkt_slc_bh(struct nitrox_device *ndev)
32214fa93cdSSrikanth Jampala {
32314fa93cdSSrikanth Jampala 	u32 size;
32414fa93cdSSrikanth Jampala 	int i;
32514fa93cdSSrikanth Jampala 
32614fa93cdSSrikanth Jampala 	size = ndev->nr_queues * sizeof(struct bh_data);
32714fa93cdSSrikanth Jampala 	ndev->bh.slc = kzalloc(size, GFP_KERNEL);
32814fa93cdSSrikanth Jampala 	if (!ndev->bh.slc)
32914fa93cdSSrikanth Jampala 		return -ENOMEM;
33014fa93cdSSrikanth Jampala 
33114fa93cdSSrikanth Jampala 	for (i = 0; i < ndev->nr_queues; i++) {
33214fa93cdSSrikanth Jampala 		struct bh_data *bh = &ndev->bh.slc[i];
33314fa93cdSSrikanth Jampala 		u64 offset;
33414fa93cdSSrikanth Jampala 
33514fa93cdSSrikanth Jampala 		offset = NPS_PKT_SLC_CNTSX(i);
33614fa93cdSSrikanth Jampala 		/* pre calculate completion count address */
33714fa93cdSSrikanth Jampala 		bh->completion_cnt_csr_addr = NITROX_CSR_ADDR(ndev, offset);
33814fa93cdSSrikanth Jampala 		bh->cmdq = &ndev->pkt_cmdqs[i];
33914fa93cdSSrikanth Jampala 
34014fa93cdSSrikanth Jampala 		tasklet_init(&bh->resp_handler, pkt_slc_resp_handler,
34114fa93cdSSrikanth Jampala 			     (unsigned long)bh);
34214fa93cdSSrikanth Jampala 	}
34314fa93cdSSrikanth Jampala 
34414fa93cdSSrikanth Jampala 	return 0;
34514fa93cdSSrikanth Jampala }
34614fa93cdSSrikanth Jampala 
34714fa93cdSSrikanth Jampala static int nitrox_request_irqs(struct nitrox_device *ndev)
34814fa93cdSSrikanth Jampala {
34914fa93cdSSrikanth Jampala 	struct pci_dev *pdev = ndev->pdev;
35014fa93cdSSrikanth Jampala 	struct msix_entry *msix_ent = ndev->msix.entries;
35114fa93cdSSrikanth Jampala 	int nr_ring_vectors, i = 0, ring, cpu, ret;
35214fa93cdSSrikanth Jampala 	char *name;
35314fa93cdSSrikanth Jampala 
35414fa93cdSSrikanth Jampala 	/*
35514fa93cdSSrikanth Jampala 	 * PF MSI-X vectors
35614fa93cdSSrikanth Jampala 	 *
35714fa93cdSSrikanth Jampala 	 * Entry 0: NPS PKT ring 0
35814fa93cdSSrikanth Jampala 	 * Entry 1: AQMQ ring 0
35914fa93cdSSrikanth Jampala 	 * Entry 2: ZQM ring 0
36014fa93cdSSrikanth Jampala 	 * Entry 3: NPS PKT ring 1
36114fa93cdSSrikanth Jampala 	 * ....
36214fa93cdSSrikanth Jampala 	 * Entry 192: NPS_CORE_INT_ACTIVE
36314fa93cdSSrikanth Jampala 	 */
36414fa93cdSSrikanth Jampala 	nr_ring_vectors = ndev->nr_queues * NR_RING_VECTORS;
36514fa93cdSSrikanth Jampala 
36614fa93cdSSrikanth Jampala 	/* request irq for pkt ring/ports only */
36714fa93cdSSrikanth Jampala 	while (i < nr_ring_vectors) {
36814fa93cdSSrikanth Jampala 		name = *(ndev->msix.names + i);
36914fa93cdSSrikanth Jampala 		ring = (i / NR_RING_VECTORS);
37014fa93cdSSrikanth Jampala 		snprintf(name, MAX_MSIX_VECTOR_NAME, "n5(%d)-slc-ring%d",
37114fa93cdSSrikanth Jampala 			 ndev->idx, ring);
37214fa93cdSSrikanth Jampala 
37314fa93cdSSrikanth Jampala 		ret = request_irq(msix_ent[i].vector, nps_pkt_slc_isr, 0,
37414fa93cdSSrikanth Jampala 				  name, &ndev->bh.slc[ring]);
37514fa93cdSSrikanth Jampala 		if (ret) {
37614fa93cdSSrikanth Jampala 			dev_err(&pdev->dev, "failed to get irq %d for %s\n",
37714fa93cdSSrikanth Jampala 				msix_ent[i].vector, name);
37814fa93cdSSrikanth Jampala 			return ret;
37914fa93cdSSrikanth Jampala 		}
38014fa93cdSSrikanth Jampala 		cpu = ring % num_online_cpus();
38114fa93cdSSrikanth Jampala 		irq_set_affinity_hint(msix_ent[i].vector, get_cpu_mask(cpu));
38214fa93cdSSrikanth Jampala 
38314fa93cdSSrikanth Jampala 		set_bit(i, ndev->msix.irqs);
38414fa93cdSSrikanth Jampala 		i += NR_RING_VECTORS;
38514fa93cdSSrikanth Jampala 	}
38614fa93cdSSrikanth Jampala 
38714fa93cdSSrikanth Jampala 	/* Request IRQ for NPS_CORE_INT_ACTIVE */
38814fa93cdSSrikanth Jampala 	name = *(ndev->msix.names + i);
38914fa93cdSSrikanth Jampala 	snprintf(name, MAX_MSIX_VECTOR_NAME, "n5(%d)-nps-core-int", ndev->idx);
39014fa93cdSSrikanth Jampala 	ret = request_irq(msix_ent[i].vector, nps_core_int_isr, 0, name, ndev);
39114fa93cdSSrikanth Jampala 	if (ret) {
39214fa93cdSSrikanth Jampala 		dev_err(&pdev->dev, "failed to get irq %d for %s\n",
39314fa93cdSSrikanth Jampala 			msix_ent[i].vector, name);
39414fa93cdSSrikanth Jampala 		return ret;
39514fa93cdSSrikanth Jampala 	}
39614fa93cdSSrikanth Jampala 	set_bit(i, ndev->msix.irqs);
39714fa93cdSSrikanth Jampala 
39814fa93cdSSrikanth Jampala 	return 0;
39914fa93cdSSrikanth Jampala }
40014fa93cdSSrikanth Jampala 
40114fa93cdSSrikanth Jampala static void nitrox_disable_msix(struct nitrox_device *ndev)
40214fa93cdSSrikanth Jampala {
40314fa93cdSSrikanth Jampala 	struct msix_entry *msix_ent = ndev->msix.entries;
40414fa93cdSSrikanth Jampala 	char **names = ndev->msix.names;
40514fa93cdSSrikanth Jampala 	int i = 0, ring, nr_ring_vectors;
40614fa93cdSSrikanth Jampala 
40714fa93cdSSrikanth Jampala 	nr_ring_vectors = ndev->msix.nr_entries - 1;
40814fa93cdSSrikanth Jampala 
40914fa93cdSSrikanth Jampala 	/* clear pkt ring irqs */
41014fa93cdSSrikanth Jampala 	while (i < nr_ring_vectors) {
41114fa93cdSSrikanth Jampala 		if (test_and_clear_bit(i, ndev->msix.irqs)) {
41214fa93cdSSrikanth Jampala 			ring = (i / NR_RING_VECTORS);
41314fa93cdSSrikanth Jampala 			irq_set_affinity_hint(msix_ent[i].vector, NULL);
41414fa93cdSSrikanth Jampala 			free_irq(msix_ent[i].vector, &ndev->bh.slc[ring]);
41514fa93cdSSrikanth Jampala 		}
41614fa93cdSSrikanth Jampala 		i += NR_RING_VECTORS;
41714fa93cdSSrikanth Jampala 	}
41814fa93cdSSrikanth Jampala 	irq_set_affinity_hint(msix_ent[i].vector, NULL);
41914fa93cdSSrikanth Jampala 	free_irq(msix_ent[i].vector, ndev);
42014fa93cdSSrikanth Jampala 	clear_bit(i, ndev->msix.irqs);
42114fa93cdSSrikanth Jampala 
42214fa93cdSSrikanth Jampala 	kfree(ndev->msix.entries);
42314fa93cdSSrikanth Jampala 	for (i = 0; i < ndev->msix.nr_entries; i++)
42414fa93cdSSrikanth Jampala 		kfree(*(names + i));
42514fa93cdSSrikanth Jampala 
42614fa93cdSSrikanth Jampala 	kfree(names);
42714fa93cdSSrikanth Jampala 	pci_disable_msix(ndev->pdev);
42814fa93cdSSrikanth Jampala }
42914fa93cdSSrikanth Jampala 
43014fa93cdSSrikanth Jampala /**
43114fa93cdSSrikanth Jampala  * nitrox_pf_cleanup_isr: Cleanup PF MSI-X and IRQ
43214fa93cdSSrikanth Jampala  * @ndev: NITROX device
43314fa93cdSSrikanth Jampala  */
43414fa93cdSSrikanth Jampala void nitrox_pf_cleanup_isr(struct nitrox_device *ndev)
43514fa93cdSSrikanth Jampala {
43614fa93cdSSrikanth Jampala 	nitrox_disable_msix(ndev);
43714fa93cdSSrikanth Jampala 	nitrox_cleanup_pkt_slc_bh(ndev);
43814fa93cdSSrikanth Jampala }
43914fa93cdSSrikanth Jampala 
44014fa93cdSSrikanth Jampala /**
44114fa93cdSSrikanth Jampala  * nitrox_init_isr - Initialize PF MSI-X vectors and IRQ
44214fa93cdSSrikanth Jampala  * @ndev: NITROX device
44314fa93cdSSrikanth Jampala  *
44414fa93cdSSrikanth Jampala  * Return: 0 on success, a negative value on failure.
44514fa93cdSSrikanth Jampala  */
44614fa93cdSSrikanth Jampala int nitrox_pf_init_isr(struct nitrox_device *ndev)
44714fa93cdSSrikanth Jampala {
44814fa93cdSSrikanth Jampala 	int err;
44914fa93cdSSrikanth Jampala 
45014fa93cdSSrikanth Jampala 	err = nitrox_setup_pkt_slc_bh(ndev);
45114fa93cdSSrikanth Jampala 	if (err)
45214fa93cdSSrikanth Jampala 		return err;
45314fa93cdSSrikanth Jampala 
45414fa93cdSSrikanth Jampala 	err = nitrox_enable_msix(ndev);
45514fa93cdSSrikanth Jampala 	if (err)
45614fa93cdSSrikanth Jampala 		goto msix_fail;
45714fa93cdSSrikanth Jampala 
45814fa93cdSSrikanth Jampala 	err = nitrox_request_irqs(ndev);
45914fa93cdSSrikanth Jampala 	if (err)
46014fa93cdSSrikanth Jampala 		goto irq_fail;
46114fa93cdSSrikanth Jampala 
46214fa93cdSSrikanth Jampala 	return 0;
46314fa93cdSSrikanth Jampala 
46414fa93cdSSrikanth Jampala irq_fail:
46514fa93cdSSrikanth Jampala 	nitrox_disable_msix(ndev);
46614fa93cdSSrikanth Jampala msix_fail:
46714fa93cdSSrikanth Jampala 	nitrox_cleanup_pkt_slc_bh(ndev);
46814fa93cdSSrikanth Jampala 	return err;
46914fa93cdSSrikanth Jampala }
470