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