Path: blob/master/drivers/crypto/cavium/nitrox/nitrox_isr.c
26285 views
// SPDX-License-Identifier: GPL-2.01#include <linux/pci.h>2#include <linux/printk.h>3#include <linux/slab.h>45#include "nitrox_dev.h"6#include "nitrox_csr.h"7#include "nitrox_common.h"8#include "nitrox_hal.h"9#include "nitrox_isr.h"10#include "nitrox_mbx.h"1112/*13* One vector for each type of ring14* - NPS packet ring, AQMQ ring and ZQMQ ring15*/16#define NR_RING_VECTORS 317#define NR_NON_RING_VECTORS 118/* base entry for packet ring/port */19#define PKT_RING_MSIX_BASE 020#define NON_RING_MSIX_BASE 1922122/**23* nps_pkt_slc_isr - IRQ handler for NPS solicit port24* @irq: irq number25* @data: argument26*/27static irqreturn_t nps_pkt_slc_isr(int irq, void *data)28{29struct nitrox_q_vector *qvec = data;30union nps_pkt_slc_cnts slc_cnts;31struct nitrox_cmdq *cmdq = qvec->cmdq;3233slc_cnts.value = readq(cmdq->compl_cnt_csr_addr);34/* New packet on SLC output port */35if (slc_cnts.s.slc_int)36tasklet_hi_schedule(&qvec->resp_tasklet);3738return IRQ_HANDLED;39}4041static void clear_nps_core_err_intr(struct nitrox_device *ndev)42{43u64 value;4445/* Write 1 to clear */46value = nitrox_read_csr(ndev, NPS_CORE_INT);47nitrox_write_csr(ndev, NPS_CORE_INT, value);4849dev_err_ratelimited(DEV(ndev), "NSP_CORE_INT 0x%016llx\n", value);50}5152static void clear_nps_pkt_err_intr(struct nitrox_device *ndev)53{54union nps_pkt_int pkt_int;55unsigned long value, offset;56int i;5758pkt_int.value = nitrox_read_csr(ndev, NPS_PKT_INT);59dev_err_ratelimited(DEV(ndev), "NPS_PKT_INT 0x%016llx\n",60pkt_int.value);6162if (pkt_int.s.slc_err) {63offset = NPS_PKT_SLC_ERR_TYPE;64value = nitrox_read_csr(ndev, offset);65nitrox_write_csr(ndev, offset, value);66dev_err_ratelimited(DEV(ndev),67"NPS_PKT_SLC_ERR_TYPE 0x%016lx\n", value);6869offset = NPS_PKT_SLC_RERR_LO;70value = nitrox_read_csr(ndev, offset);71nitrox_write_csr(ndev, offset, value);72/* enable the solicit ports */73for_each_set_bit(i, &value, BITS_PER_LONG)74enable_pkt_solicit_port(ndev, i);7576dev_err_ratelimited(DEV(ndev),77"NPS_PKT_SLC_RERR_LO 0x%016lx\n", value);7879offset = NPS_PKT_SLC_RERR_HI;80value = nitrox_read_csr(ndev, offset);81nitrox_write_csr(ndev, offset, value);82dev_err_ratelimited(DEV(ndev),83"NPS_PKT_SLC_RERR_HI 0x%016lx\n", value);84}8586if (pkt_int.s.in_err) {87offset = NPS_PKT_IN_ERR_TYPE;88value = nitrox_read_csr(ndev, offset);89nitrox_write_csr(ndev, offset, value);90dev_err_ratelimited(DEV(ndev),91"NPS_PKT_IN_ERR_TYPE 0x%016lx\n", value);92offset = NPS_PKT_IN_RERR_LO;93value = nitrox_read_csr(ndev, offset);94nitrox_write_csr(ndev, offset, value);95/* enable the input ring */96for_each_set_bit(i, &value, BITS_PER_LONG)97enable_pkt_input_ring(ndev, i);9899dev_err_ratelimited(DEV(ndev),100"NPS_PKT_IN_RERR_LO 0x%016lx\n", value);101102offset = NPS_PKT_IN_RERR_HI;103value = nitrox_read_csr(ndev, offset);104nitrox_write_csr(ndev, offset, value);105dev_err_ratelimited(DEV(ndev),106"NPS_PKT_IN_RERR_HI 0x%016lx\n", value);107}108}109110static void clear_pom_err_intr(struct nitrox_device *ndev)111{112u64 value;113114value = nitrox_read_csr(ndev, POM_INT);115nitrox_write_csr(ndev, POM_INT, value);116dev_err_ratelimited(DEV(ndev), "POM_INT 0x%016llx\n", value);117}118119static void clear_pem_err_intr(struct nitrox_device *ndev)120{121u64 value;122123value = nitrox_read_csr(ndev, PEM0_INT);124nitrox_write_csr(ndev, PEM0_INT, value);125dev_err_ratelimited(DEV(ndev), "PEM(0)_INT 0x%016llx\n", value);126}127128static void clear_lbc_err_intr(struct nitrox_device *ndev)129{130union lbc_int lbc_int;131u64 value, offset;132int i;133134lbc_int.value = nitrox_read_csr(ndev, LBC_INT);135dev_err_ratelimited(DEV(ndev), "LBC_INT 0x%016llx\n", lbc_int.value);136137if (lbc_int.s.dma_rd_err) {138for (i = 0; i < NR_CLUSTERS; i++) {139offset = EFL_CORE_VF_ERR_INT0X(i);140value = nitrox_read_csr(ndev, offset);141nitrox_write_csr(ndev, offset, value);142offset = EFL_CORE_VF_ERR_INT1X(i);143value = nitrox_read_csr(ndev, offset);144nitrox_write_csr(ndev, offset, value);145}146}147148if (lbc_int.s.cam_soft_err) {149dev_err_ratelimited(DEV(ndev), "CAM_SOFT_ERR, invalidating LBC\n");150invalidate_lbc(ndev);151}152153if (lbc_int.s.pref_dat_len_mismatch_err) {154offset = LBC_PLM_VF1_64_INT;155value = nitrox_read_csr(ndev, offset);156nitrox_write_csr(ndev, offset, value);157offset = LBC_PLM_VF65_128_INT;158value = nitrox_read_csr(ndev, offset);159nitrox_write_csr(ndev, offset, value);160}161162if (lbc_int.s.rd_dat_len_mismatch_err) {163offset = LBC_ELM_VF1_64_INT;164value = nitrox_read_csr(ndev, offset);165nitrox_write_csr(ndev, offset, value);166offset = LBC_ELM_VF65_128_INT;167value = nitrox_read_csr(ndev, offset);168nitrox_write_csr(ndev, offset, value);169}170nitrox_write_csr(ndev, LBC_INT, lbc_int.value);171}172173static void clear_efl_err_intr(struct nitrox_device *ndev)174{175int i;176177for (i = 0; i < NR_CLUSTERS; i++) {178union efl_core_int core_int;179u64 value, offset;180181offset = EFL_CORE_INTX(i);182core_int.value = nitrox_read_csr(ndev, offset);183nitrox_write_csr(ndev, offset, core_int.value);184dev_err_ratelimited(DEV(ndev), "ELF_CORE(%d)_INT 0x%016llx\n",185i, core_int.value);186if (core_int.s.se_err) {187offset = EFL_CORE_SE_ERR_INTX(i);188value = nitrox_read_csr(ndev, offset);189nitrox_write_csr(ndev, offset, value);190}191}192}193194static void clear_bmi_err_intr(struct nitrox_device *ndev)195{196u64 value;197198value = nitrox_read_csr(ndev, BMI_INT);199nitrox_write_csr(ndev, BMI_INT, value);200dev_err_ratelimited(DEV(ndev), "BMI_INT 0x%016llx\n", value);201}202203static void nps_core_int_tasklet(unsigned long data)204{205struct nitrox_q_vector *qvec = (void *)(uintptr_t)(data);206struct nitrox_device *ndev = qvec->ndev;207208/* if pf mode do queue recovery */209if (ndev->mode == __NDEV_MODE_PF) {210} else {211/**212* if VF(s) enabled communicate the error information213* to VF(s)214*/215}216}217218/*219* nps_core_int_isr - interrupt handler for NITROX errors and220* mailbox communication221*/222static irqreturn_t nps_core_int_isr(int irq, void *data)223{224struct nitrox_q_vector *qvec = data;225struct nitrox_device *ndev = qvec->ndev;226union nps_core_int_active core_int;227228core_int.value = nitrox_read_csr(ndev, NPS_CORE_INT_ACTIVE);229230if (core_int.s.nps_core)231clear_nps_core_err_intr(ndev);232233if (core_int.s.nps_pkt)234clear_nps_pkt_err_intr(ndev);235236if (core_int.s.pom)237clear_pom_err_intr(ndev);238239if (core_int.s.pem)240clear_pem_err_intr(ndev);241242if (core_int.s.lbc)243clear_lbc_err_intr(ndev);244245if (core_int.s.efl)246clear_efl_err_intr(ndev);247248if (core_int.s.bmi)249clear_bmi_err_intr(ndev);250251/* Mailbox interrupt */252if (core_int.s.mbox)253nitrox_pf2vf_mbox_handler(ndev);254255/* If more work callback the ISR, set resend */256core_int.s.resend = 1;257nitrox_write_csr(ndev, NPS_CORE_INT_ACTIVE, core_int.value);258259return IRQ_HANDLED;260}261262void nitrox_unregister_interrupts(struct nitrox_device *ndev)263{264struct pci_dev *pdev = ndev->pdev;265int i;266267for (i = 0; i < ndev->num_vecs; i++) {268struct nitrox_q_vector *qvec;269int vec;270271qvec = ndev->qvec + i;272if (!qvec->valid)273continue;274275/* get the vector number */276vec = pci_irq_vector(pdev, i);277irq_set_affinity_hint(vec, NULL);278free_irq(vec, qvec);279280tasklet_disable(&qvec->resp_tasklet);281tasklet_kill(&qvec->resp_tasklet);282qvec->valid = false;283}284kfree(ndev->qvec);285ndev->qvec = NULL;286pci_free_irq_vectors(pdev);287}288289int nitrox_register_interrupts(struct nitrox_device *ndev)290{291struct pci_dev *pdev = ndev->pdev;292struct nitrox_q_vector *qvec;293int nr_vecs, vec, cpu;294int ret, i;295296/*297* PF MSI-X vectors298*299* Entry 0: NPS PKT ring 0300* Entry 1: AQMQ ring 0301* Entry 2: ZQM ring 0302* Entry 3: NPS PKT ring 1303* Entry 4: AQMQ ring 1304* Entry 5: ZQM ring 1305* ....306* Entry 192: NPS_CORE_INT_ACTIVE307*/308nr_vecs = pci_msix_vec_count(pdev);309if (nr_vecs < 0) {310dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs);311return nr_vecs;312}313314/* Enable MSI-X */315ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX);316if (ret < 0) {317dev_err(DEV(ndev), "msix vectors %d alloc failed\n", nr_vecs);318return ret;319}320ndev->num_vecs = nr_vecs;321322ndev->qvec = kcalloc(nr_vecs, sizeof(*qvec), GFP_KERNEL);323if (!ndev->qvec) {324pci_free_irq_vectors(pdev);325return -ENOMEM;326}327328/* request irqs for packet rings/ports */329for (i = PKT_RING_MSIX_BASE; i < (nr_vecs - 1); i += NR_RING_VECTORS) {330qvec = &ndev->qvec[i];331332qvec->ring = i / NR_RING_VECTORS;333if (qvec->ring >= ndev->nr_queues)334break;335336qvec->cmdq = &ndev->pkt_inq[qvec->ring];337snprintf(qvec->name, IRQ_NAMESZ, "nitrox-pkt%d", qvec->ring);338/* get the vector number */339vec = pci_irq_vector(pdev, i);340ret = request_irq(vec, nps_pkt_slc_isr, 0, qvec->name, qvec);341if (ret) {342dev_err(DEV(ndev), "irq failed for pkt ring/port%d\n",343qvec->ring);344goto irq_fail;345}346cpu = qvec->ring % num_online_cpus();347irq_set_affinity_hint(vec, get_cpu_mask(cpu));348349tasklet_init(&qvec->resp_tasklet, pkt_slc_resp_tasklet,350(unsigned long)qvec);351qvec->valid = true;352}353354/* request irqs for non ring vectors */355i = NON_RING_MSIX_BASE;356qvec = &ndev->qvec[i];357qvec->ndev = ndev;358359snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d", i);360/* get the vector number */361vec = pci_irq_vector(pdev, i);362ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);363if (ret) {364dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n", i);365goto irq_fail;366}367cpu = num_online_cpus();368irq_set_affinity_hint(vec, get_cpu_mask(cpu));369370tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,371(unsigned long)qvec);372qvec->valid = true;373374return 0;375376irq_fail:377nitrox_unregister_interrupts(ndev);378return ret;379}380381void nitrox_sriov_unregister_interrupts(struct nitrox_device *ndev)382{383struct pci_dev *pdev = ndev->pdev;384int i;385386for (i = 0; i < ndev->num_vecs; i++) {387struct nitrox_q_vector *qvec;388int vec;389390qvec = ndev->qvec + i;391if (!qvec->valid)392continue;393394vec = ndev->iov.msix.vector;395irq_set_affinity_hint(vec, NULL);396free_irq(vec, qvec);397398tasklet_disable(&qvec->resp_tasklet);399tasklet_kill(&qvec->resp_tasklet);400qvec->valid = false;401}402kfree(ndev->qvec);403ndev->qvec = NULL;404pci_disable_msix(pdev);405}406407int nitrox_sriov_register_interupts(struct nitrox_device *ndev)408{409struct pci_dev *pdev = ndev->pdev;410struct nitrox_q_vector *qvec;411int vec, cpu;412int ret;413414/**415* only non ring vectors i.e Entry 192 is available416* for PF in SR-IOV mode.417*/418ndev->iov.msix.entry = NON_RING_MSIX_BASE;419ret = pci_enable_msix_exact(pdev, &ndev->iov.msix, NR_NON_RING_VECTORS);420if (ret) {421dev_err(DEV(ndev), "failed to allocate nps-core-int%d\n",422NON_RING_MSIX_BASE);423return ret;424}425426qvec = kcalloc(NR_NON_RING_VECTORS, sizeof(*qvec), GFP_KERNEL);427if (!qvec) {428pci_disable_msix(pdev);429return -ENOMEM;430}431qvec->ndev = ndev;432433ndev->qvec = qvec;434ndev->num_vecs = NR_NON_RING_VECTORS;435snprintf(qvec->name, IRQ_NAMESZ, "nitrox-core-int%d",436NON_RING_MSIX_BASE);437438vec = ndev->iov.msix.vector;439ret = request_irq(vec, nps_core_int_isr, 0, qvec->name, qvec);440if (ret) {441dev_err(DEV(ndev), "irq failed for nitrox-core-int%d\n",442NON_RING_MSIX_BASE);443goto iov_irq_fail;444}445cpu = num_online_cpus();446irq_set_affinity_hint(vec, get_cpu_mask(cpu));447448tasklet_init(&qvec->resp_tasklet, nps_core_int_tasklet,449(unsigned long)qvec);450qvec->valid = true;451452return 0;453454iov_irq_fail:455nitrox_sriov_unregister_interrupts(ndev);456return ret;457}458459460