linux/drivers/crypto/cavium/nitrox/nitrox_isr.c
<<
>>
Prefs
   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}
 459