nitrox_isr.c (11373B)
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/pci.h> 3#include <linux/printk.h> 4#include <linux/slab.h> 5 6#include "nitrox_dev.h" 7#include "nitrox_csr.h" 8#include "nitrox_common.h" 9#include "nitrox_hal.h" 10#include "nitrox_isr.h" 11#include "nitrox_mbx.h" 12 13/* 14 * One vector for each type of ring 15 * - NPS packet ring, AQMQ ring and ZQMQ ring 16 */ 17#define NR_RING_VECTORS 3 18#define NR_NON_RING_VECTORS 1 19/* base entry for packet ring/port */ 20#define PKT_RING_MSIX_BASE 0 21#define NON_RING_MSIX_BASE 192 22 23/** 24 * nps_pkt_slc_isr - IRQ handler for NPS solicit port 25 * @irq: irq number 26 * @data: argument 27 */ 28static irqreturn_t nps_pkt_slc_isr(int irq, void *data) 29{ 30 struct nitrox_q_vector *qvec = data; 31 union nps_pkt_slc_cnts slc_cnts; 32 struct nitrox_cmdq *cmdq = qvec->cmdq; 33 34 slc_cnts.value = readq(cmdq->compl_cnt_csr_addr); 35 /* New packet on SLC output port */ 36 if (slc_cnts.s.slc_int) 37 tasklet_hi_schedule(&qvec->resp_tasklet); 38 39 return IRQ_HANDLED; 40} 41 42static void clear_nps_core_err_intr(struct nitrox_device *ndev) 43{ 44 u64 value; 45 46 /* Write 1 to clear */ 47 value = nitrox_read_csr(ndev, NPS_CORE_INT); 48 nitrox_write_csr(ndev, NPS_CORE_INT, value); 49 50 dev_err_ratelimited(DEV(ndev), "NSP_CORE_INT 0x%016llx\n", value); 51} 52 53static void clear_nps_pkt_err_intr(struct nitrox_device *ndev) 54{ 55 union nps_pkt_int pkt_int; 56 unsigned long value, offset; 57 int i; 58 59 pkt_int.value = nitrox_read_csr(ndev, NPS_PKT_INT); 60 dev_err_ratelimited(DEV(ndev), "NPS_PKT_INT 0x%016llx\n", 61 pkt_int.value); 62 63 if (pkt_int.s.slc_err) { 64 offset = NPS_PKT_SLC_ERR_TYPE; 65 value = nitrox_read_csr(ndev, offset); 66 nitrox_write_csr(ndev, offset, value); 67 dev_err_ratelimited(DEV(ndev), 68 "NPS_PKT_SLC_ERR_TYPE 0x%016lx\n", value); 69 70 offset = NPS_PKT_SLC_RERR_LO; 71 value = nitrox_read_csr(ndev, offset); 72 nitrox_write_csr(ndev, offset, value); 73 /* enable the solicit ports */ 74 for_each_set_bit(i, &value, BITS_PER_LONG) 75 enable_pkt_solicit_port(ndev, i); 76 77 dev_err_ratelimited(DEV(ndev), 78 "NPS_PKT_SLC_RERR_LO 0x%016lx\n", value); 79 80 offset = NPS_PKT_SLC_RERR_HI; 81 value = nitrox_read_csr(ndev, offset); 82 nitrox_write_csr(ndev, offset, value); 83 dev_err_ratelimited(DEV(ndev), 84 "NPS_PKT_SLC_RERR_HI 0x%016lx\n", value); 85 } 86 87 if (pkt_int.s.in_err) { 88 offset = NPS_PKT_IN_ERR_TYPE; 89 value = nitrox_read_csr(ndev, offset); 90 nitrox_write_csr(ndev, offset, value); 91 dev_err_ratelimited(DEV(ndev), 92 "NPS_PKT_IN_ERR_TYPE 0x%016lx\n", value); 93 offset = NPS_PKT_IN_RERR_LO; 94 value = nitrox_read_csr(ndev, offset); 95 nitrox_write_csr(ndev, offset, value); 96 /* enable the input ring */ 97 for_each_set_bit(i, &value, BITS_PER_LONG) 98 enable_pkt_input_ring(ndev, i); 99 100 dev_err_ratelimited(DEV(ndev), 101 "NPS_PKT_IN_RERR_LO 0x%016lx\n", value); 102 103 offset = NPS_PKT_IN_RERR_HI; 104 value = nitrox_read_csr(ndev, offset); 105 nitrox_write_csr(ndev, offset, value); 106 dev_err_ratelimited(DEV(ndev), 107 "NPS_PKT_IN_RERR_HI 0x%016lx\n", value); 108 } 109} 110 111static void clear_pom_err_intr(struct nitrox_device *ndev) 112{ 113 u64 value; 114 115 value = nitrox_read_csr(ndev, POM_INT); 116 nitrox_write_csr(ndev, POM_INT, value); 117 dev_err_ratelimited(DEV(ndev), "POM_INT 0x%016llx\n", value); 118} 119 120static void clear_pem_err_intr(struct nitrox_device *ndev) 121{ 122 u64 value; 123 124 value = nitrox_read_csr(ndev, PEM0_INT); 125 nitrox_write_csr(ndev, PEM0_INT, value); 126 dev_err_ratelimited(DEV(ndev), "PEM(0)_INT 0x%016llx\n", value); 127} 128 129static void clear_lbc_err_intr(struct nitrox_device *ndev) 130{ 131 union lbc_int lbc_int; 132 u64 value, offset; 133 int i; 134 135 lbc_int.value = nitrox_read_csr(ndev, LBC_INT); 136 dev_err_ratelimited(DEV(ndev), "LBC_INT 0x%016llx\n", lbc_int.value); 137 138 if (lbc_int.s.dma_rd_err) { 139 for (i = 0; i < NR_CLUSTERS; i++) { 140 offset = EFL_CORE_VF_ERR_INT0X(i); 141 value = nitrox_read_csr(ndev, offset); 142 nitrox_write_csr(ndev, offset, value); 143 offset = EFL_CORE_VF_ERR_INT1X(i); 144 value = nitrox_read_csr(ndev, offset); 145 nitrox_write_csr(ndev, offset, value); 146 } 147 } 148 149 if (lbc_int.s.cam_soft_err) { 150 dev_err_ratelimited(DEV(ndev), "CAM_SOFT_ERR, invalidating LBC\n"); 151 invalidate_lbc(ndev); 152 } 153 154 if (lbc_int.s.pref_dat_len_mismatch_err) { 155 offset = LBC_PLM_VF1_64_INT; 156 value = nitrox_read_csr(ndev, offset); 157 nitrox_write_csr(ndev, offset, value); 158 offset = LBC_PLM_VF65_128_INT; 159 value = nitrox_read_csr(ndev, offset); 160 nitrox_write_csr(ndev, offset, value); 161 } 162 163 if (lbc_int.s.rd_dat_len_mismatch_err) { 164 offset = LBC_ELM_VF1_64_INT; 165 value = nitrox_read_csr(ndev, offset); 166 nitrox_write_csr(ndev, offset, value); 167 offset = LBC_ELM_VF65_128_INT; 168 value = nitrox_read_csr(ndev, offset); 169 nitrox_write_csr(ndev, offset, value); 170 } 171 nitrox_write_csr(ndev, LBC_INT, lbc_int.value); 172} 173 174static void clear_efl_err_intr(struct nitrox_device *ndev) 175{ 176 int i; 177 178 for (i = 0; i < NR_CLUSTERS; i++) { 179 union efl_core_int core_int; 180 u64 value, offset; 181 182 offset = EFL_CORE_INTX(i); 183 core_int.value = nitrox_read_csr(ndev, offset); 184 nitrox_write_csr(ndev, offset, core_int.value); 185 dev_err_ratelimited(DEV(ndev), "ELF_CORE(%d)_INT 0x%016llx\n", 186 i, core_int.value); 187 if (core_int.s.se_err) { 188 offset = EFL_CORE_SE_ERR_INTX(i); 189 value = nitrox_read_csr(ndev, offset); 190 nitrox_write_csr(ndev, offset, value); 191 } 192 } 193} 194 195static void clear_bmi_err_intr(struct nitrox_device *ndev) 196{ 197 u64 value; 198 199 value = nitrox_read_csr(ndev, BMI_INT); 200 nitrox_write_csr(ndev, BMI_INT, value); 201 dev_err_ratelimited(DEV(ndev), "BMI_INT 0x%016llx\n", value); 202} 203 204static void nps_core_int_tasklet(unsigned long data) 205{ 206 struct nitrox_q_vector *qvec = (void *)(uintptr_t)(data); 207 struct nitrox_device *ndev = qvec->ndev; 208 209 /* if pf mode do queue recovery */ 210 if (ndev->mode == __NDEV_MODE_PF) { 211 } else { 212 /** 213 * if VF(s) enabled communicate the error information 214 * to VF(s) 215 */ 216 } 217} 218 219/* 220 * nps_core_int_isr - interrupt handler for NITROX errors and 221 * mailbox communication 222 */ 223static irqreturn_t nps_core_int_isr(int irq, void *data) 224{ 225 struct nitrox_q_vector *qvec = data; 226 struct nitrox_device *ndev = qvec->ndev; 227 union nps_core_int_active core_int; 228 229 core_int.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE); 230 231 if (core_int.s.nps_core) 232 clear_nps_core_err_intr(ndev); 233 234 if (core_int.s.nps_pkt) 235 clear_nps_pkt_err_intr(ndev); 236 237 if (core_int.s.pom) 238 clear_pom_err_intr(ndev); 239 240 if (core_int.s.pem) 241 clear_pem_err_intr(ndev); 242 243 if (core_int.s.lbc) 244 clear_lbc_err_intr(ndev); 245 246 if (core_int.s.efl) 247 clear_efl_err_intr(ndev); 248 249 if (core_int.s.bmi) 250 clear_bmi_err_intr(ndev); 251 252 /* Mailbox interrupt */ 253 if (core_int.s.mbox) 254 nitrox_pf2vf_mbox_handler(ndev); 255 256 /* If more work callback the ISR, set resend */ 257 core_int.s.resend = 1; 258 nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value); 259 260 return IRQ_HANDLED; 261} 262 263void nitrox_unregister_interrupts(struct nitrox_device *ndev) 264{ 265 struct pci_dev *pdev = ndev->pdev; 266 int i; 267 268 for (i = 0; i < ndev->num_vecs; i++) { 269 struct nitrox_q_vector *qvec; 270 int vec; 271 272 qvec = ndev->qvec + i; 273 if (!qvec->valid) 274 continue; 275 276 /* get the vector number */ 277 vec = pci_irq_vector(pdev, i); 278 irq_set_affinity_hint(vec, NULL); 279 free_irq(vec, qvec); 280 281 tasklet_disable(&qvec->resp_tasklet); 282 tasklet_kill(&qvec->resp_tasklet); 283 qvec->valid = false; 284 } 285 kfree(ndev->qvec); 286 ndev->qvec = NULL; 287 pci_free_irq_vectors(pdev); 288} 289 290int nitrox_register_interrupts(struct nitrox_device *ndev) 291{ 292 struct pci_dev *pdev = ndev->pdev; 293 struct nitrox_q_vector *qvec; 294 int nr_vecs, vec, cpu; 295 int ret, i; 296 297 /* 298 * PF MSI-X vectors 299 * 300 * Entry 0: NPS PKT ring 0 301 * Entry 1: AQMQ ring 0 302 * Entry 2: ZQM ring 0 303 * Entry 3: NPS PKT ring 1 304 * Entry 4: AQMQ ring 1 305 * Entry 5: ZQM ring 1 306 * .... 307 * Entry 192: NPS_CORE_INT_ACTIVE 308 */ 309 nr_vecs = pci_msix_vec_count(pdev); 310 if (nr_vecs < 0) { 311 dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs); 312 return nr_vecs; 313 } 314 315 /* Enable MSI-X */ 316 ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX); 317 if (ret < 0) { 318 dev_err(DEV(ndev), "msix vectors %d alloc failed\n", nr_vecs); 319 return ret; 320 } 321 ndev->num_vecs = nr_vecs; 322 323 ndev->qvec = kcalloc(nr_vecs, sizeof(*qvec), GFP_KERNEL); 324 if (!ndev->qvec) { 325 pci_free_irq_vectors(pdev); 326 return -ENOMEM; 327 } 328 329 /* request irqs for packet rings/ports */ 330 for (i = PKT_RING_MSIX_BASE; i < (nr_vecs - 1); i += NR_RING_VECTORS) { 331 qvec = &ndev->qvec[i]; 332 333 qvec->ring = i / NR_RING_VECTORS; 334 if (qvec->ring >= ndev->nr_queues) 335 break; 336 337 qvec->cmdq = &ndev->pkt_inq[qvec->ring]; 338 snprintf(qvec->name, IRQ_NAMESZ, "nitrox-pkt%d", qvec->ring); 339 /* get the vector number */ 340 vec = pci_irq_vector(pdev, i); 341 ret = request_irq(vec, nps_pkt_slc_isr, 0, qvec->name, qvec); 342 if (ret) { 343 dev_err(DEV(ndev), "irq failed for pkt ring/port%d\n", 344 qvec->ring); 345 goto irq_fail; 346 } 347 cpu = qvec->ring % num_online_cpus(); 348 irq_set_affinity_hint(vec, get_cpu_mask(cpu)); 349 350 tasklet_init(&qvec->resp_tasklet, pkt_slc_resp_tasklet, 351 (unsigned long)qvec); 352 qvec->valid = true; 353 } 354 355 /* request irqs for non ring vectors */ 356 i = NON_RING_MSIX_BASE; 357 qvec = &ndev->qvec[i]; 358 qvec->ndev = ndev; 359 360 snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", i); 361 /* get the vector number */ 362 vec = pci_irq_vector(pdev, i); 363 ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec); 364 if (ret) { 365 dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n", i); 366 goto irq_fail; 367 } 368 cpu = num_online_cpus(); 369 irq_set_affinity_hint(vec, get_cpu_mask(cpu)); 370 371 tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet, 372 (unsigned long)qvec); 373 qvec->valid = true; 374 375 return 0; 376 377irq_fail: 378 nitrox_unregister_interrupts(ndev); 379 return ret; 380} 381 382void nitrox_sriov_unregister_interrupts(struct nitrox_device *ndev) 383{ 384 struct pci_dev *pdev = ndev->pdev; 385 int i; 386 387 for (i = 0; i < ndev->num_vecs; i++) { 388 struct nitrox_q_vector *qvec; 389 int vec; 390 391 qvec = ndev->qvec + i; 392 if (!qvec->valid) 393 continue; 394 395 vec = ndev->iov.msix.vector; 396 irq_set_affinity_hint(vec, NULL); 397 free_irq(vec, qvec); 398 399 tasklet_disable(&qvec->resp_tasklet); 400 tasklet_kill(&qvec->resp_tasklet); 401 qvec->valid = false; 402 } 403 kfree(ndev->qvec); 404 ndev->qvec = NULL; 405 pci_disable_msix(pdev); 406} 407 408int nitrox_sriov_register_interupts(struct nitrox_device *ndev) 409{ 410 struct pci_dev *pdev = ndev->pdev; 411 struct nitrox_q_vector *qvec; 412 int vec, cpu; 413 int ret; 414 415 /** 416 * only non ring vectors i.e Entry 192 is available 417 * for PF in SR-IOV mode. 418 */ 419 ndev->iov.msix.entry = NON_RING_MSIX_BASE; 420 ret = pci_enable_msix_exact(pdev, &ndev->iov.msix, NR_NON_RING_VECTORS); 421 if (ret) { 422 dev_err(DEV(ndev), "failed to allocate nps-core-int%d\n", 423 NON_RING_MSIX_BASE); 424 return ret; 425 } 426 427 qvec = kcalloc(NR_NON_RING_VECTORS, sizeof(*qvec), GFP_KERNEL); 428 if (!qvec) { 429 pci_disable_msix(pdev); 430 return -ENOMEM; 431 } 432 qvec->ndev = ndev; 433 434 ndev->qvec = qvec; 435 ndev->num_vecs = NR_NON_RING_VECTORS; 436 snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", 437 NON_RING_MSIX_BASE); 438 439 vec = ndev->iov.msix.vector; 440 ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec); 441 if (ret) { 442 dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n", 443 NON_RING_MSIX_BASE); 444 goto iov_irq_fail; 445 } 446 cpu = num_online_cpus(); 447 irq_set_affinity_hint(vec, get_cpu_mask(cpu)); 448 449 tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet, 450 (unsigned long)qvec); 451 qvec->valid = true; 452 453 return 0; 454 455iov_irq_fail: 456 nitrox_sriov_unregister_interrupts(ndev); 457 return ret; 458}