162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (C) 2020 Marvell. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/firmware.h> 562306a36Sopenharmony_ci#include "otx2_cpt_hw_types.h" 662306a36Sopenharmony_ci#include "otx2_cpt_common.h" 762306a36Sopenharmony_ci#include "otx2_cpt_devlink.h" 862306a36Sopenharmony_ci#include "otx2_cptpf_ucode.h" 962306a36Sopenharmony_ci#include "otx2_cptpf.h" 1062306a36Sopenharmony_ci#include "cn10k_cpt.h" 1162306a36Sopenharmony_ci#include "rvu_reg.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define OTX2_CPT_DRV_NAME "rvu_cptpf" 1462306a36Sopenharmony_ci#define OTX2_CPT_DRV_STRING "Marvell RVU CPT Physical Function Driver" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define CPT_UC_RID_CN9K_B0 1 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic void cptpf_enable_vfpf_mbox_intr(struct otx2_cptpf_dev *cptpf, 1962306a36Sopenharmony_ci int num_vfs) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci int ena_bits; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci /* Clear any pending interrupts */ 2462306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 2562306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INTX(0), ~0x0ULL); 2662306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 2762306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INTX(1), ~0x0ULL); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci /* Enable VF interrupts for VFs from 0 to 63 */ 3062306a36Sopenharmony_ci ena_bits = ((num_vfs - 1) % 64); 3162306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 3262306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INT_ENA_W1SX(0), 3362306a36Sopenharmony_ci GENMASK_ULL(ena_bits, 0)); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci if (num_vfs > 64) { 3662306a36Sopenharmony_ci /* Enable VF interrupts for VFs from 64 to 127 */ 3762306a36Sopenharmony_ci ena_bits = num_vfs - 64 - 1; 3862306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 3962306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INT_ENA_W1SX(1), 4062306a36Sopenharmony_ci GENMASK_ULL(ena_bits, 0)); 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic void cptpf_disable_vfpf_mbox_intr(struct otx2_cptpf_dev *cptpf, 4562306a36Sopenharmony_ci int num_vfs) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci int vector; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci /* Disable VF-PF interrupts */ 5062306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 5162306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INT_ENA_W1CX(0), ~0ULL); 5262306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 5362306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INT_ENA_W1CX(1), ~0ULL); 5462306a36Sopenharmony_ci /* Clear any pending interrupts */ 5562306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 5662306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INTX(0), ~0ULL); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci vector = pci_irq_vector(cptpf->pdev, RVU_PF_INT_VEC_VFPF_MBOX0); 5962306a36Sopenharmony_ci free_irq(vector, cptpf); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (num_vfs > 64) { 6262306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 6362306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INTX(1), ~0ULL); 6462306a36Sopenharmony_ci vector = pci_irq_vector(cptpf->pdev, RVU_PF_INT_VEC_VFPF_MBOX1); 6562306a36Sopenharmony_ci free_irq(vector, cptpf); 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic void cptpf_enable_vf_flr_me_intrs(struct otx2_cptpf_dev *cptpf, 7062306a36Sopenharmony_ci int num_vfs) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci /* Clear FLR interrupt if any */ 7362306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_VFFLR_INTX(0), 7462306a36Sopenharmony_ci INTR_MASK(num_vfs)); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* Enable VF FLR interrupts */ 7762306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 7862306a36Sopenharmony_ci RVU_PF_VFFLR_INT_ENA_W1SX(0), INTR_MASK(num_vfs)); 7962306a36Sopenharmony_ci /* Clear ME interrupt if any */ 8062306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_VFME_INTX(0), 8162306a36Sopenharmony_ci INTR_MASK(num_vfs)); 8262306a36Sopenharmony_ci /* Enable VF ME interrupts */ 8362306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 8462306a36Sopenharmony_ci RVU_PF_VFME_INT_ENA_W1SX(0), INTR_MASK(num_vfs)); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (num_vfs <= 64) 8762306a36Sopenharmony_ci return; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_VFFLR_INTX(1), 9062306a36Sopenharmony_ci INTR_MASK(num_vfs - 64)); 9162306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 9262306a36Sopenharmony_ci RVU_PF_VFFLR_INT_ENA_W1SX(1), INTR_MASK(num_vfs - 64)); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_VFME_INTX(1), 9562306a36Sopenharmony_ci INTR_MASK(num_vfs - 64)); 9662306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 9762306a36Sopenharmony_ci RVU_PF_VFME_INT_ENA_W1SX(1), INTR_MASK(num_vfs - 64)); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void cptpf_disable_vf_flr_me_intrs(struct otx2_cptpf_dev *cptpf, 10162306a36Sopenharmony_ci int num_vfs) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci int vector; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Disable VF FLR interrupts */ 10662306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 10762306a36Sopenharmony_ci RVU_PF_VFFLR_INT_ENA_W1CX(0), INTR_MASK(num_vfs)); 10862306a36Sopenharmony_ci vector = pci_irq_vector(cptpf->pdev, RVU_PF_INT_VEC_VFFLR0); 10962306a36Sopenharmony_ci free_irq(vector, cptpf); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* Disable VF ME interrupts */ 11262306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 11362306a36Sopenharmony_ci RVU_PF_VFME_INT_ENA_W1CX(0), INTR_MASK(num_vfs)); 11462306a36Sopenharmony_ci vector = pci_irq_vector(cptpf->pdev, RVU_PF_INT_VEC_VFME0); 11562306a36Sopenharmony_ci free_irq(vector, cptpf); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (num_vfs <= 64) 11862306a36Sopenharmony_ci return; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 12162306a36Sopenharmony_ci RVU_PF_VFFLR_INT_ENA_W1CX(1), INTR_MASK(num_vfs - 64)); 12262306a36Sopenharmony_ci vector = pci_irq_vector(cptpf->pdev, RVU_PF_INT_VEC_VFFLR1); 12362306a36Sopenharmony_ci free_irq(vector, cptpf); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 12662306a36Sopenharmony_ci RVU_PF_VFME_INT_ENA_W1CX(1), INTR_MASK(num_vfs - 64)); 12762306a36Sopenharmony_ci vector = pci_irq_vector(cptpf->pdev, RVU_PF_INT_VEC_VFME1); 12862306a36Sopenharmony_ci free_irq(vector, cptpf); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic void cptpf_flr_wq_handler(struct work_struct *work) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct cptpf_flr_work *flr_work; 13462306a36Sopenharmony_ci struct otx2_cptpf_dev *pf; 13562306a36Sopenharmony_ci struct mbox_msghdr *req; 13662306a36Sopenharmony_ci struct otx2_mbox *mbox; 13762306a36Sopenharmony_ci int vf, reg = 0; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci flr_work = container_of(work, struct cptpf_flr_work, work); 14062306a36Sopenharmony_ci pf = flr_work->pf; 14162306a36Sopenharmony_ci mbox = &pf->afpf_mbox; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci vf = flr_work - pf->flr_work; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci mutex_lock(&pf->lock); 14662306a36Sopenharmony_ci req = otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req), 14762306a36Sopenharmony_ci sizeof(struct msg_rsp)); 14862306a36Sopenharmony_ci if (!req) { 14962306a36Sopenharmony_ci mutex_unlock(&pf->lock); 15062306a36Sopenharmony_ci return; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci req->sig = OTX2_MBOX_REQ_SIG; 15462306a36Sopenharmony_ci req->id = MBOX_MSG_VF_FLR; 15562306a36Sopenharmony_ci req->pcifunc &= RVU_PFVF_FUNC_MASK; 15662306a36Sopenharmony_ci req->pcifunc |= (vf + 1) & RVU_PFVF_FUNC_MASK; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci otx2_cpt_send_mbox_msg(mbox, pf->pdev); 15962306a36Sopenharmony_ci if (!otx2_cpt_sync_mbox_msg(&pf->afpf_mbox)) { 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (vf >= 64) { 16262306a36Sopenharmony_ci reg = 1; 16362306a36Sopenharmony_ci vf = vf - 64; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci /* Clear transaction pending register */ 16662306a36Sopenharmony_ci otx2_cpt_write64(pf->reg_base, BLKADDR_RVUM, 0, 16762306a36Sopenharmony_ci RVU_PF_VFTRPENDX(reg), BIT_ULL(vf)); 16862306a36Sopenharmony_ci otx2_cpt_write64(pf->reg_base, BLKADDR_RVUM, 0, 16962306a36Sopenharmony_ci RVU_PF_VFFLR_INT_ENA_W1SX(reg), BIT_ULL(vf)); 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci mutex_unlock(&pf->lock); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic irqreturn_t cptpf_vf_flr_intr(int __always_unused irq, void *arg) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci int reg, dev, vf, start_vf, num_reg = 1; 17762306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = arg; 17862306a36Sopenharmony_ci u64 intr; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (cptpf->max_vfs > 64) 18162306a36Sopenharmony_ci num_reg = 2; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci for (reg = 0; reg < num_reg; reg++) { 18462306a36Sopenharmony_ci intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, 18562306a36Sopenharmony_ci RVU_PF_VFFLR_INTX(reg)); 18662306a36Sopenharmony_ci if (!intr) 18762306a36Sopenharmony_ci continue; 18862306a36Sopenharmony_ci start_vf = 64 * reg; 18962306a36Sopenharmony_ci for (vf = 0; vf < 64; vf++) { 19062306a36Sopenharmony_ci if (!(intr & BIT_ULL(vf))) 19162306a36Sopenharmony_ci continue; 19262306a36Sopenharmony_ci dev = vf + start_vf; 19362306a36Sopenharmony_ci queue_work(cptpf->flr_wq, &cptpf->flr_work[dev].work); 19462306a36Sopenharmony_ci /* Clear interrupt */ 19562306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 19662306a36Sopenharmony_ci RVU_PF_VFFLR_INTX(reg), BIT_ULL(vf)); 19762306a36Sopenharmony_ci /* Disable the interrupt */ 19862306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 19962306a36Sopenharmony_ci RVU_PF_VFFLR_INT_ENA_W1CX(reg), 20062306a36Sopenharmony_ci BIT_ULL(vf)); 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci return IRQ_HANDLED; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic irqreturn_t cptpf_vf_me_intr(int __always_unused irq, void *arg) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = arg; 20962306a36Sopenharmony_ci int reg, vf, num_reg = 1; 21062306a36Sopenharmony_ci u64 intr; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (cptpf->max_vfs > 64) 21362306a36Sopenharmony_ci num_reg = 2; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci for (reg = 0; reg < num_reg; reg++) { 21662306a36Sopenharmony_ci intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, 21762306a36Sopenharmony_ci RVU_PF_VFME_INTX(reg)); 21862306a36Sopenharmony_ci if (!intr) 21962306a36Sopenharmony_ci continue; 22062306a36Sopenharmony_ci for (vf = 0; vf < 64; vf++) { 22162306a36Sopenharmony_ci if (!(intr & BIT_ULL(vf))) 22262306a36Sopenharmony_ci continue; 22362306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 22462306a36Sopenharmony_ci RVU_PF_VFTRPENDX(reg), BIT_ULL(vf)); 22562306a36Sopenharmony_ci /* Clear interrupt */ 22662306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, 22762306a36Sopenharmony_ci RVU_PF_VFME_INTX(reg), BIT_ULL(vf)); 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci return IRQ_HANDLED; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic void cptpf_unregister_vfpf_intr(struct otx2_cptpf_dev *cptpf, 23462306a36Sopenharmony_ci int num_vfs) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci cptpf_disable_vfpf_mbox_intr(cptpf, num_vfs); 23762306a36Sopenharmony_ci cptpf_disable_vf_flr_me_intrs(cptpf, num_vfs); 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic int cptpf_register_vfpf_intr(struct otx2_cptpf_dev *cptpf, int num_vfs) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct pci_dev *pdev = cptpf->pdev; 24362306a36Sopenharmony_ci struct device *dev = &pdev->dev; 24462306a36Sopenharmony_ci int ret, vector; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFPF_MBOX0); 24762306a36Sopenharmony_ci /* Register VF-PF mailbox interrupt handler */ 24862306a36Sopenharmony_ci ret = request_irq(vector, otx2_cptpf_vfpf_mbox_intr, 0, "CPTVFPF Mbox0", 24962306a36Sopenharmony_ci cptpf); 25062306a36Sopenharmony_ci if (ret) { 25162306a36Sopenharmony_ci dev_err(dev, 25262306a36Sopenharmony_ci "IRQ registration failed for PFVF mbox0 irq\n"); 25362306a36Sopenharmony_ci return ret; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFFLR0); 25662306a36Sopenharmony_ci /* Register VF FLR interrupt handler */ 25762306a36Sopenharmony_ci ret = request_irq(vector, cptpf_vf_flr_intr, 0, "CPTPF FLR0", cptpf); 25862306a36Sopenharmony_ci if (ret) { 25962306a36Sopenharmony_ci dev_err(dev, 26062306a36Sopenharmony_ci "IRQ registration failed for VFFLR0 irq\n"); 26162306a36Sopenharmony_ci goto free_mbox0_irq; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFME0); 26462306a36Sopenharmony_ci /* Register VF ME interrupt handler */ 26562306a36Sopenharmony_ci ret = request_irq(vector, cptpf_vf_me_intr, 0, "CPTPF ME0", cptpf); 26662306a36Sopenharmony_ci if (ret) { 26762306a36Sopenharmony_ci dev_err(dev, 26862306a36Sopenharmony_ci "IRQ registration failed for PFVF mbox0 irq\n"); 26962306a36Sopenharmony_ci goto free_flr0_irq; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (num_vfs > 64) { 27362306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFPF_MBOX1); 27462306a36Sopenharmony_ci ret = request_irq(vector, otx2_cptpf_vfpf_mbox_intr, 0, 27562306a36Sopenharmony_ci "CPTVFPF Mbox1", cptpf); 27662306a36Sopenharmony_ci if (ret) { 27762306a36Sopenharmony_ci dev_err(dev, 27862306a36Sopenharmony_ci "IRQ registration failed for PFVF mbox1 irq\n"); 27962306a36Sopenharmony_ci goto free_me0_irq; 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFFLR1); 28262306a36Sopenharmony_ci /* Register VF FLR interrupt handler */ 28362306a36Sopenharmony_ci ret = request_irq(vector, cptpf_vf_flr_intr, 0, "CPTPF FLR1", 28462306a36Sopenharmony_ci cptpf); 28562306a36Sopenharmony_ci if (ret) { 28662306a36Sopenharmony_ci dev_err(dev, 28762306a36Sopenharmony_ci "IRQ registration failed for VFFLR1 irq\n"); 28862306a36Sopenharmony_ci goto free_mbox1_irq; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFME1); 29162306a36Sopenharmony_ci /* Register VF FLR interrupt handler */ 29262306a36Sopenharmony_ci ret = request_irq(vector, cptpf_vf_me_intr, 0, "CPTPF ME1", 29362306a36Sopenharmony_ci cptpf); 29462306a36Sopenharmony_ci if (ret) { 29562306a36Sopenharmony_ci dev_err(dev, 29662306a36Sopenharmony_ci "IRQ registration failed for VFFLR1 irq\n"); 29762306a36Sopenharmony_ci goto free_flr1_irq; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci cptpf_enable_vfpf_mbox_intr(cptpf, num_vfs); 30162306a36Sopenharmony_ci cptpf_enable_vf_flr_me_intrs(cptpf, num_vfs); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cifree_flr1_irq: 30662306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFFLR1); 30762306a36Sopenharmony_ci free_irq(vector, cptpf); 30862306a36Sopenharmony_cifree_mbox1_irq: 30962306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFPF_MBOX1); 31062306a36Sopenharmony_ci free_irq(vector, cptpf); 31162306a36Sopenharmony_cifree_me0_irq: 31262306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFME0); 31362306a36Sopenharmony_ci free_irq(vector, cptpf); 31462306a36Sopenharmony_cifree_flr0_irq: 31562306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFFLR0); 31662306a36Sopenharmony_ci free_irq(vector, cptpf); 31762306a36Sopenharmony_cifree_mbox0_irq: 31862306a36Sopenharmony_ci vector = pci_irq_vector(pdev, RVU_PF_INT_VEC_VFPF_MBOX0); 31962306a36Sopenharmony_ci free_irq(vector, cptpf); 32062306a36Sopenharmony_ci return ret; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic void cptpf_flr_wq_destroy(struct otx2_cptpf_dev *pf) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci if (!pf->flr_wq) 32662306a36Sopenharmony_ci return; 32762306a36Sopenharmony_ci destroy_workqueue(pf->flr_wq); 32862306a36Sopenharmony_ci pf->flr_wq = NULL; 32962306a36Sopenharmony_ci kfree(pf->flr_work); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic int cptpf_flr_wq_init(struct otx2_cptpf_dev *cptpf, int num_vfs) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci int vf; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci cptpf->flr_wq = alloc_ordered_workqueue("cptpf_flr_wq", 0); 33762306a36Sopenharmony_ci if (!cptpf->flr_wq) 33862306a36Sopenharmony_ci return -ENOMEM; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci cptpf->flr_work = kcalloc(num_vfs, sizeof(struct cptpf_flr_work), 34162306a36Sopenharmony_ci GFP_KERNEL); 34262306a36Sopenharmony_ci if (!cptpf->flr_work) 34362306a36Sopenharmony_ci goto destroy_wq; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci for (vf = 0; vf < num_vfs; vf++) { 34662306a36Sopenharmony_ci cptpf->flr_work[vf].pf = cptpf; 34762306a36Sopenharmony_ci INIT_WORK(&cptpf->flr_work[vf].work, cptpf_flr_wq_handler); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci return 0; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cidestroy_wq: 35262306a36Sopenharmony_ci destroy_workqueue(cptpf->flr_wq); 35362306a36Sopenharmony_ci return -ENOMEM; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic int cptpf_vfpf_mbox_init(struct otx2_cptpf_dev *cptpf, int num_vfs) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct device *dev = &cptpf->pdev->dev; 35962306a36Sopenharmony_ci u64 vfpf_mbox_base; 36062306a36Sopenharmony_ci int err, i; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci cptpf->vfpf_mbox_wq = 36362306a36Sopenharmony_ci alloc_ordered_workqueue("cpt_vfpf_mailbox", 36462306a36Sopenharmony_ci WQ_HIGHPRI | WQ_MEM_RECLAIM); 36562306a36Sopenharmony_ci if (!cptpf->vfpf_mbox_wq) 36662306a36Sopenharmony_ci return -ENOMEM; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* Map VF-PF mailbox memory */ 36962306a36Sopenharmony_ci if (test_bit(CN10K_MBOX, &cptpf->cap_flag)) 37062306a36Sopenharmony_ci vfpf_mbox_base = readq(cptpf->reg_base + RVU_PF_VF_MBOX_ADDR); 37162306a36Sopenharmony_ci else 37262306a36Sopenharmony_ci vfpf_mbox_base = readq(cptpf->reg_base + RVU_PF_VF_BAR4_ADDR); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (!vfpf_mbox_base) { 37562306a36Sopenharmony_ci dev_err(dev, "VF-PF mailbox address not configured\n"); 37662306a36Sopenharmony_ci err = -ENOMEM; 37762306a36Sopenharmony_ci goto free_wqe; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci cptpf->vfpf_mbox_base = devm_ioremap_wc(dev, vfpf_mbox_base, 38062306a36Sopenharmony_ci MBOX_SIZE * cptpf->max_vfs); 38162306a36Sopenharmony_ci if (!cptpf->vfpf_mbox_base) { 38262306a36Sopenharmony_ci dev_err(dev, "Mapping of VF-PF mailbox address failed\n"); 38362306a36Sopenharmony_ci err = -ENOMEM; 38462306a36Sopenharmony_ci goto free_wqe; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci err = otx2_mbox_init(&cptpf->vfpf_mbox, cptpf->vfpf_mbox_base, 38762306a36Sopenharmony_ci cptpf->pdev, cptpf->reg_base, MBOX_DIR_PFVF, 38862306a36Sopenharmony_ci num_vfs); 38962306a36Sopenharmony_ci if (err) 39062306a36Sopenharmony_ci goto free_wqe; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci for (i = 0; i < num_vfs; i++) { 39362306a36Sopenharmony_ci cptpf->vf[i].vf_id = i; 39462306a36Sopenharmony_ci cptpf->vf[i].cptpf = cptpf; 39562306a36Sopenharmony_ci cptpf->vf[i].intr_idx = i % 64; 39662306a36Sopenharmony_ci INIT_WORK(&cptpf->vf[i].vfpf_mbox_work, 39762306a36Sopenharmony_ci otx2_cptpf_vfpf_mbox_handler); 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci return 0; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cifree_wqe: 40262306a36Sopenharmony_ci destroy_workqueue(cptpf->vfpf_mbox_wq); 40362306a36Sopenharmony_ci return err; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic void cptpf_vfpf_mbox_destroy(struct otx2_cptpf_dev *cptpf) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci destroy_workqueue(cptpf->vfpf_mbox_wq); 40962306a36Sopenharmony_ci otx2_mbox_destroy(&cptpf->vfpf_mbox); 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic void cptpf_disable_afpf_mbox_intr(struct otx2_cptpf_dev *cptpf) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci /* Disable AF-PF interrupt */ 41562306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT_ENA_W1C, 41662306a36Sopenharmony_ci 0x1ULL); 41762306a36Sopenharmony_ci /* Clear interrupt if any */ 41862306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 0x1ULL); 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic int cptpf_register_afpf_mbox_intr(struct otx2_cptpf_dev *cptpf) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci struct pci_dev *pdev = cptpf->pdev; 42462306a36Sopenharmony_ci struct device *dev = &pdev->dev; 42562306a36Sopenharmony_ci int ret, irq; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci irq = pci_irq_vector(pdev, RVU_PF_INT_VEC_AFPF_MBOX); 42862306a36Sopenharmony_ci /* Register AF-PF mailbox interrupt handler */ 42962306a36Sopenharmony_ci ret = devm_request_irq(dev, irq, otx2_cptpf_afpf_mbox_intr, 0, 43062306a36Sopenharmony_ci "CPTAFPF Mbox", cptpf); 43162306a36Sopenharmony_ci if (ret) { 43262306a36Sopenharmony_ci dev_err(dev, 43362306a36Sopenharmony_ci "IRQ registration failed for PFAF mbox irq\n"); 43462306a36Sopenharmony_ci return ret; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci /* Clear interrupt if any, to avoid spurious interrupts */ 43762306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 0x1ULL); 43862306a36Sopenharmony_ci /* Enable AF-PF interrupt */ 43962306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT_ENA_W1S, 44062306a36Sopenharmony_ci 0x1ULL); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci ret = otx2_cpt_send_ready_msg(&cptpf->afpf_mbox, cptpf->pdev); 44362306a36Sopenharmony_ci if (ret) { 44462306a36Sopenharmony_ci dev_warn(dev, 44562306a36Sopenharmony_ci "AF not responding to mailbox, deferring probe\n"); 44662306a36Sopenharmony_ci cptpf_disable_afpf_mbox_intr(cptpf); 44762306a36Sopenharmony_ci return -EPROBE_DEFER; 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci return 0; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct pci_dev *pdev = cptpf->pdev; 45562306a36Sopenharmony_ci resource_size_t offset; 45662306a36Sopenharmony_ci int err; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci cptpf->afpf_mbox_wq = 45962306a36Sopenharmony_ci alloc_ordered_workqueue("cpt_afpf_mailbox", 46062306a36Sopenharmony_ci WQ_HIGHPRI | WQ_MEM_RECLAIM); 46162306a36Sopenharmony_ci if (!cptpf->afpf_mbox_wq) 46262306a36Sopenharmony_ci return -ENOMEM; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci offset = pci_resource_start(pdev, PCI_MBOX_BAR_NUM); 46562306a36Sopenharmony_ci /* Map AF-PF mailbox memory */ 46662306a36Sopenharmony_ci cptpf->afpf_mbox_base = devm_ioremap_wc(&pdev->dev, offset, MBOX_SIZE); 46762306a36Sopenharmony_ci if (!cptpf->afpf_mbox_base) { 46862306a36Sopenharmony_ci dev_err(&pdev->dev, "Unable to map BAR4\n"); 46962306a36Sopenharmony_ci err = -ENOMEM; 47062306a36Sopenharmony_ci goto error; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci err = otx2_mbox_init(&cptpf->afpf_mbox, cptpf->afpf_mbox_base, 47462306a36Sopenharmony_ci pdev, cptpf->reg_base, MBOX_DIR_PFAF, 1); 47562306a36Sopenharmony_ci if (err) 47662306a36Sopenharmony_ci goto error; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci err = otx2_mbox_init(&cptpf->afpf_mbox_up, cptpf->afpf_mbox_base, 47962306a36Sopenharmony_ci pdev, cptpf->reg_base, MBOX_DIR_PFAF_UP, 1); 48062306a36Sopenharmony_ci if (err) 48162306a36Sopenharmony_ci goto mbox_cleanup; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci INIT_WORK(&cptpf->afpf_mbox_work, otx2_cptpf_afpf_mbox_handler); 48462306a36Sopenharmony_ci INIT_WORK(&cptpf->afpf_mbox_up_work, otx2_cptpf_afpf_mbox_up_handler); 48562306a36Sopenharmony_ci mutex_init(&cptpf->lock); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cimbox_cleanup: 49062306a36Sopenharmony_ci otx2_mbox_destroy(&cptpf->afpf_mbox); 49162306a36Sopenharmony_cierror: 49262306a36Sopenharmony_ci destroy_workqueue(cptpf->afpf_mbox_wq); 49362306a36Sopenharmony_ci return err; 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cistatic void cptpf_afpf_mbox_destroy(struct otx2_cptpf_dev *cptpf) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci destroy_workqueue(cptpf->afpf_mbox_wq); 49962306a36Sopenharmony_ci otx2_mbox_destroy(&cptpf->afpf_mbox); 50062306a36Sopenharmony_ci otx2_mbox_destroy(&cptpf->afpf_mbox_up); 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_cistatic ssize_t sso_pf_func_ovrd_show(struct device *dev, 50462306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 50562306a36Sopenharmony_ci{ 50662306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return sprintf(buf, "%d\n", cptpf->sso_pf_func_ovrd); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic ssize_t sso_pf_func_ovrd_store(struct device *dev, 51262306a36Sopenharmony_ci struct device_attribute *attr, 51362306a36Sopenharmony_ci const char *buf, size_t count) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); 51662306a36Sopenharmony_ci u8 sso_pf_func_ovrd; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci if (!(cptpf->pdev->revision == CPT_UC_RID_CN9K_B0)) 51962306a36Sopenharmony_ci return count; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (kstrtou8(buf, 0, &sso_pf_func_ovrd)) 52262306a36Sopenharmony_ci return -EINVAL; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci cptpf->sso_pf_func_ovrd = sso_pf_func_ovrd; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci return count; 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic ssize_t kvf_limits_show(struct device *dev, 53062306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci return sprintf(buf, "%d\n", cptpf->kvf_limits); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic ssize_t kvf_limits_store(struct device *dev, 53862306a36Sopenharmony_ci struct device_attribute *attr, 53962306a36Sopenharmony_ci const char *buf, size_t count) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev); 54262306a36Sopenharmony_ci int lfs_num; 54362306a36Sopenharmony_ci int ret; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci ret = kstrtoint(buf, 0, &lfs_num); 54662306a36Sopenharmony_ci if (ret) 54762306a36Sopenharmony_ci return ret; 54862306a36Sopenharmony_ci if (lfs_num < 1 || lfs_num > num_online_cpus()) { 54962306a36Sopenharmony_ci dev_err(dev, "lfs count %d must be in range [1 - %d]\n", 55062306a36Sopenharmony_ci lfs_num, num_online_cpus()); 55162306a36Sopenharmony_ci return -EINVAL; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci cptpf->kvf_limits = lfs_num; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci return count; 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic DEVICE_ATTR_RW(kvf_limits); 55962306a36Sopenharmony_cistatic DEVICE_ATTR_RW(sso_pf_func_ovrd); 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_cistatic struct attribute *cptpf_attrs[] = { 56262306a36Sopenharmony_ci &dev_attr_kvf_limits.attr, 56362306a36Sopenharmony_ci &dev_attr_sso_pf_func_ovrd.attr, 56462306a36Sopenharmony_ci NULL 56562306a36Sopenharmony_ci}; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic const struct attribute_group cptpf_sysfs_group = { 56862306a36Sopenharmony_ci .attrs = cptpf_attrs, 56962306a36Sopenharmony_ci}; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic int cpt_is_pf_usable(struct otx2_cptpf_dev *cptpf) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci u64 rev; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci rev = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, 57662306a36Sopenharmony_ci RVU_PF_BLOCK_ADDRX_DISC(BLKADDR_RVUM)); 57762306a36Sopenharmony_ci rev = (rev >> 12) & 0xFF; 57862306a36Sopenharmony_ci /* 57962306a36Sopenharmony_ci * Check if AF has setup revision for RVUM block, otherwise 58062306a36Sopenharmony_ci * driver probe should be deferred until AF driver comes up 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ci if (!rev) { 58362306a36Sopenharmony_ci dev_warn(&cptpf->pdev->dev, 58462306a36Sopenharmony_ci "AF is not initialized, deferring probe\n"); 58562306a36Sopenharmony_ci return -EPROBE_DEFER; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci return 0; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic int cptx_device_reset(struct otx2_cptpf_dev *cptpf, int blkaddr) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci int timeout = 10, ret; 59362306a36Sopenharmony_ci u64 reg = 0; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev, 59662306a36Sopenharmony_ci CPT_AF_BLK_RST, 0x1, blkaddr); 59762306a36Sopenharmony_ci if (ret) 59862306a36Sopenharmony_ci return ret; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci do { 60162306a36Sopenharmony_ci ret = otx2_cpt_read_af_reg(&cptpf->afpf_mbox, cptpf->pdev, 60262306a36Sopenharmony_ci CPT_AF_BLK_RST, ®, blkaddr); 60362306a36Sopenharmony_ci if (ret) 60462306a36Sopenharmony_ci return ret; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci if (!((reg >> 63) & 0x1)) 60762306a36Sopenharmony_ci break; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci usleep_range(10000, 20000); 61062306a36Sopenharmony_ci if (timeout-- < 0) 61162306a36Sopenharmony_ci return -EBUSY; 61262306a36Sopenharmony_ci } while (1); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci return ret; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_cistatic int cptpf_device_reset(struct otx2_cptpf_dev *cptpf) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci int ret = 0; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (cptpf->has_cpt1) { 62262306a36Sopenharmony_ci ret = cptx_device_reset(cptpf, BLKADDR_CPT1); 62362306a36Sopenharmony_ci if (ret) 62462306a36Sopenharmony_ci return ret; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci return cptx_device_reset(cptpf, BLKADDR_CPT0); 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic void cptpf_check_block_implemented(struct otx2_cptpf_dev *cptpf) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci u64 cfg; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci cfg = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, 63462306a36Sopenharmony_ci RVU_PF_BLOCK_ADDRX_DISC(BLKADDR_CPT1)); 63562306a36Sopenharmony_ci if (cfg & BIT_ULL(11)) 63662306a36Sopenharmony_ci cptpf->has_cpt1 = true; 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistatic int cptpf_device_init(struct otx2_cptpf_dev *cptpf) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci union otx2_cptx_af_constants1 af_cnsts1 = {0}; 64262306a36Sopenharmony_ci int ret = 0; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* check if 'implemented' bit is set for block BLKADDR_CPT1 */ 64562306a36Sopenharmony_ci cptpf_check_block_implemented(cptpf); 64662306a36Sopenharmony_ci /* Reset the CPT PF device */ 64762306a36Sopenharmony_ci ret = cptpf_device_reset(cptpf); 64862306a36Sopenharmony_ci if (ret) 64962306a36Sopenharmony_ci return ret; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci /* Get number of SE, IE and AE engines */ 65262306a36Sopenharmony_ci ret = otx2_cpt_read_af_reg(&cptpf->afpf_mbox, cptpf->pdev, 65362306a36Sopenharmony_ci CPT_AF_CONSTANTS1, &af_cnsts1.u, 65462306a36Sopenharmony_ci BLKADDR_CPT0); 65562306a36Sopenharmony_ci if (ret) 65662306a36Sopenharmony_ci return ret; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci cptpf->eng_grps.avail.max_se_cnt = af_cnsts1.s.se; 65962306a36Sopenharmony_ci cptpf->eng_grps.avail.max_ie_cnt = af_cnsts1.s.ie; 66062306a36Sopenharmony_ci cptpf->eng_grps.avail.max_ae_cnt = af_cnsts1.s.ae; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci /* Disable all cores */ 66362306a36Sopenharmony_ci ret = otx2_cpt_disable_all_cores(cptpf); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci return ret; 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic int cptpf_sriov_disable(struct pci_dev *pdev) 66962306a36Sopenharmony_ci{ 67062306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = pci_get_drvdata(pdev); 67162306a36Sopenharmony_ci int num_vfs = pci_num_vf(pdev); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (!num_vfs) 67462306a36Sopenharmony_ci return 0; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci pci_disable_sriov(pdev); 67762306a36Sopenharmony_ci cptpf_unregister_vfpf_intr(cptpf, num_vfs); 67862306a36Sopenharmony_ci cptpf_flr_wq_destroy(cptpf); 67962306a36Sopenharmony_ci cptpf_vfpf_mbox_destroy(cptpf); 68062306a36Sopenharmony_ci module_put(THIS_MODULE); 68162306a36Sopenharmony_ci cptpf->enabled_vfs = 0; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return 0; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic int cptpf_sriov_enable(struct pci_dev *pdev, int num_vfs) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = pci_get_drvdata(pdev); 68962306a36Sopenharmony_ci int ret; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci /* Initialize VF<=>PF mailbox */ 69262306a36Sopenharmony_ci ret = cptpf_vfpf_mbox_init(cptpf, num_vfs); 69362306a36Sopenharmony_ci if (ret) 69462306a36Sopenharmony_ci return ret; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci ret = cptpf_flr_wq_init(cptpf, num_vfs); 69762306a36Sopenharmony_ci if (ret) 69862306a36Sopenharmony_ci goto destroy_mbox; 69962306a36Sopenharmony_ci /* Register VF<=>PF mailbox interrupt */ 70062306a36Sopenharmony_ci ret = cptpf_register_vfpf_intr(cptpf, num_vfs); 70162306a36Sopenharmony_ci if (ret) 70262306a36Sopenharmony_ci goto destroy_flr; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* Get CPT HW capabilities using LOAD_FVC operation. */ 70562306a36Sopenharmony_ci ret = otx2_cpt_discover_eng_capabilities(cptpf); 70662306a36Sopenharmony_ci if (ret) 70762306a36Sopenharmony_ci goto disable_intr; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci ret = otx2_cpt_create_eng_grps(cptpf, &cptpf->eng_grps); 71062306a36Sopenharmony_ci if (ret) 71162306a36Sopenharmony_ci goto disable_intr; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci cptpf->enabled_vfs = num_vfs; 71462306a36Sopenharmony_ci ret = pci_enable_sriov(pdev, num_vfs); 71562306a36Sopenharmony_ci if (ret) 71662306a36Sopenharmony_ci goto disable_intr; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci dev_notice(&cptpf->pdev->dev, "VFs enabled: %d\n", num_vfs); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci try_module_get(THIS_MODULE); 72162306a36Sopenharmony_ci return num_vfs; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_cidisable_intr: 72462306a36Sopenharmony_ci cptpf_unregister_vfpf_intr(cptpf, num_vfs); 72562306a36Sopenharmony_ci cptpf->enabled_vfs = 0; 72662306a36Sopenharmony_cidestroy_flr: 72762306a36Sopenharmony_ci cptpf_flr_wq_destroy(cptpf); 72862306a36Sopenharmony_cidestroy_mbox: 72962306a36Sopenharmony_ci cptpf_vfpf_mbox_destroy(cptpf); 73062306a36Sopenharmony_ci return ret; 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cistatic int otx2_cptpf_sriov_configure(struct pci_dev *pdev, int num_vfs) 73462306a36Sopenharmony_ci{ 73562306a36Sopenharmony_ci if (num_vfs > 0) { 73662306a36Sopenharmony_ci return cptpf_sriov_enable(pdev, num_vfs); 73762306a36Sopenharmony_ci } else { 73862306a36Sopenharmony_ci return cptpf_sriov_disable(pdev); 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic int otx2_cptpf_probe(struct pci_dev *pdev, 74362306a36Sopenharmony_ci const struct pci_device_id *ent) 74462306a36Sopenharmony_ci{ 74562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 74662306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf; 74762306a36Sopenharmony_ci int err; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci cptpf = devm_kzalloc(dev, sizeof(*cptpf), GFP_KERNEL); 75062306a36Sopenharmony_ci if (!cptpf) 75162306a36Sopenharmony_ci return -ENOMEM; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci err = pcim_enable_device(pdev); 75462306a36Sopenharmony_ci if (err) { 75562306a36Sopenharmony_ci dev_err(dev, "Failed to enable PCI device\n"); 75662306a36Sopenharmony_ci goto clear_drvdata; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)); 76062306a36Sopenharmony_ci if (err) { 76162306a36Sopenharmony_ci dev_err(dev, "Unable to get usable DMA configuration\n"); 76262306a36Sopenharmony_ci goto clear_drvdata; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci /* Map PF's configuration registers */ 76562306a36Sopenharmony_ci err = pcim_iomap_regions_request_all(pdev, 1 << PCI_PF_REG_BAR_NUM, 76662306a36Sopenharmony_ci OTX2_CPT_DRV_NAME); 76762306a36Sopenharmony_ci if (err) { 76862306a36Sopenharmony_ci dev_err(dev, "Couldn't get PCI resources 0x%x\n", err); 76962306a36Sopenharmony_ci goto clear_drvdata; 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci pci_set_master(pdev); 77262306a36Sopenharmony_ci pci_set_drvdata(pdev, cptpf); 77362306a36Sopenharmony_ci cptpf->pdev = pdev; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci cptpf->reg_base = pcim_iomap_table(pdev)[PCI_PF_REG_BAR_NUM]; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* Check if AF driver is up, otherwise defer probe */ 77862306a36Sopenharmony_ci err = cpt_is_pf_usable(cptpf); 77962306a36Sopenharmony_ci if (err) 78062306a36Sopenharmony_ci goto clear_drvdata; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci err = pci_alloc_irq_vectors(pdev, RVU_PF_INT_VEC_CNT, 78362306a36Sopenharmony_ci RVU_PF_INT_VEC_CNT, PCI_IRQ_MSIX); 78462306a36Sopenharmony_ci if (err < 0) { 78562306a36Sopenharmony_ci dev_err(dev, "Request for %d msix vectors failed\n", 78662306a36Sopenharmony_ci RVU_PF_INT_VEC_CNT); 78762306a36Sopenharmony_ci goto clear_drvdata; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci otx2_cpt_set_hw_caps(pdev, &cptpf->cap_flag); 79062306a36Sopenharmony_ci /* Initialize AF-PF mailbox */ 79162306a36Sopenharmony_ci err = cptpf_afpf_mbox_init(cptpf); 79262306a36Sopenharmony_ci if (err) 79362306a36Sopenharmony_ci goto clear_drvdata; 79462306a36Sopenharmony_ci /* Register mailbox interrupt */ 79562306a36Sopenharmony_ci err = cptpf_register_afpf_mbox_intr(cptpf); 79662306a36Sopenharmony_ci if (err) 79762306a36Sopenharmony_ci goto destroy_afpf_mbox; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci cptpf->max_vfs = pci_sriov_get_totalvfs(pdev); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci err = cn10k_cptpf_lmtst_init(cptpf); 80262306a36Sopenharmony_ci if (err) 80362306a36Sopenharmony_ci goto unregister_intr; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci /* Initialize CPT PF device */ 80662306a36Sopenharmony_ci err = cptpf_device_init(cptpf); 80762306a36Sopenharmony_ci if (err) 80862306a36Sopenharmony_ci goto unregister_intr; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* Initialize engine groups */ 81162306a36Sopenharmony_ci err = otx2_cpt_init_eng_grps(pdev, &cptpf->eng_grps); 81262306a36Sopenharmony_ci if (err) 81362306a36Sopenharmony_ci goto unregister_intr; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci err = sysfs_create_group(&dev->kobj, &cptpf_sysfs_group); 81662306a36Sopenharmony_ci if (err) 81762306a36Sopenharmony_ci goto cleanup_eng_grps; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci err = otx2_cpt_register_dl(cptpf); 82062306a36Sopenharmony_ci if (err) 82162306a36Sopenharmony_ci goto sysfs_grp_del; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci return 0; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_cisysfs_grp_del: 82662306a36Sopenharmony_ci sysfs_remove_group(&dev->kobj, &cptpf_sysfs_group); 82762306a36Sopenharmony_cicleanup_eng_grps: 82862306a36Sopenharmony_ci otx2_cpt_cleanup_eng_grps(pdev, &cptpf->eng_grps); 82962306a36Sopenharmony_ciunregister_intr: 83062306a36Sopenharmony_ci cptpf_disable_afpf_mbox_intr(cptpf); 83162306a36Sopenharmony_cidestroy_afpf_mbox: 83262306a36Sopenharmony_ci cptpf_afpf_mbox_destroy(cptpf); 83362306a36Sopenharmony_ciclear_drvdata: 83462306a36Sopenharmony_ci pci_set_drvdata(pdev, NULL); 83562306a36Sopenharmony_ci return err; 83662306a36Sopenharmony_ci} 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_cistatic void otx2_cptpf_remove(struct pci_dev *pdev) 83962306a36Sopenharmony_ci{ 84062306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = pci_get_drvdata(pdev); 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci if (!cptpf) 84362306a36Sopenharmony_ci return; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci cptpf_sriov_disable(pdev); 84662306a36Sopenharmony_ci otx2_cpt_unregister_dl(cptpf); 84762306a36Sopenharmony_ci /* Delete sysfs entry created for kernel VF limits */ 84862306a36Sopenharmony_ci sysfs_remove_group(&pdev->dev.kobj, &cptpf_sysfs_group); 84962306a36Sopenharmony_ci /* Cleanup engine groups */ 85062306a36Sopenharmony_ci otx2_cpt_cleanup_eng_grps(pdev, &cptpf->eng_grps); 85162306a36Sopenharmony_ci /* Disable AF-PF mailbox interrupt */ 85262306a36Sopenharmony_ci cptpf_disable_afpf_mbox_intr(cptpf); 85362306a36Sopenharmony_ci /* Destroy AF-PF mbox */ 85462306a36Sopenharmony_ci cptpf_afpf_mbox_destroy(cptpf); 85562306a36Sopenharmony_ci pci_set_drvdata(pdev, NULL); 85662306a36Sopenharmony_ci} 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci/* Supported devices */ 85962306a36Sopenharmony_cistatic const struct pci_device_id otx2_cpt_id_table[] = { 86062306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OTX2_CPT_PCI_PF_DEVICE_ID) }, 86162306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, CN10K_CPT_PCI_PF_DEVICE_ID) }, 86262306a36Sopenharmony_ci { 0, } /* end of table */ 86362306a36Sopenharmony_ci}; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cistatic struct pci_driver otx2_cpt_pci_driver = { 86662306a36Sopenharmony_ci .name = OTX2_CPT_DRV_NAME, 86762306a36Sopenharmony_ci .id_table = otx2_cpt_id_table, 86862306a36Sopenharmony_ci .probe = otx2_cptpf_probe, 86962306a36Sopenharmony_ci .remove = otx2_cptpf_remove, 87062306a36Sopenharmony_ci .sriov_configure = otx2_cptpf_sriov_configure 87162306a36Sopenharmony_ci}; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cimodule_pci_driver(otx2_cpt_pci_driver); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ciMODULE_IMPORT_NS(CRYPTO_DEV_OCTEONTX2_CPT); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ciMODULE_AUTHOR("Marvell"); 87862306a36Sopenharmony_ciMODULE_DESCRIPTION(OTX2_CPT_DRV_STRING); 87962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 88062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, otx2_cpt_id_table); 881