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