1*19d8e8c7SSrujana Challa // SPDX-License-Identifier: GPL-2.0-only 2*19d8e8c7SSrujana Challa /* Copyright (C) 2020 Marvell. */ 3*19d8e8c7SSrujana Challa 4*19d8e8c7SSrujana Challa #include "otx2_cpt_common.h" 5*19d8e8c7SSrujana Challa #include "otx2_cptvf.h" 6*19d8e8c7SSrujana Challa #include <rvu_reg.h> 7*19d8e8c7SSrujana Challa 8*19d8e8c7SSrujana Challa irqreturn_t otx2_cptvf_pfvf_mbox_intr(int __always_unused irq, void *arg) 9*19d8e8c7SSrujana Challa { 10*19d8e8c7SSrujana Challa struct otx2_cptvf_dev *cptvf = arg; 11*19d8e8c7SSrujana Challa u64 intr; 12*19d8e8c7SSrujana Challa 13*19d8e8c7SSrujana Challa /* Read the interrupt bits */ 14*19d8e8c7SSrujana Challa intr = otx2_cpt_read64(cptvf->reg_base, BLKADDR_RVUM, 0, 15*19d8e8c7SSrujana Challa OTX2_RVU_VF_INT); 16*19d8e8c7SSrujana Challa 17*19d8e8c7SSrujana Challa if (intr & 0x1ULL) { 18*19d8e8c7SSrujana Challa /* Schedule work queue function to process the MBOX request */ 19*19d8e8c7SSrujana Challa queue_work(cptvf->pfvf_mbox_wq, &cptvf->pfvf_mbox_work); 20*19d8e8c7SSrujana Challa /* Clear and ack the interrupt */ 21*19d8e8c7SSrujana Challa otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, 22*19d8e8c7SSrujana Challa OTX2_RVU_VF_INT, 0x1ULL); 23*19d8e8c7SSrujana Challa } 24*19d8e8c7SSrujana Challa return IRQ_HANDLED; 25*19d8e8c7SSrujana Challa } 26*19d8e8c7SSrujana Challa 27*19d8e8c7SSrujana Challa static void process_pfvf_mbox_mbox_msg(struct otx2_cptvf_dev *cptvf, 28*19d8e8c7SSrujana Challa struct mbox_msghdr *msg) 29*19d8e8c7SSrujana Challa { 30*19d8e8c7SSrujana Challa struct otx2_cptlfs_info *lfs = &cptvf->lfs; 31*19d8e8c7SSrujana Challa struct cpt_rd_wr_reg_msg *rsp_reg; 32*19d8e8c7SSrujana Challa struct msix_offset_rsp *rsp_msix; 33*19d8e8c7SSrujana Challa int i; 34*19d8e8c7SSrujana Challa 35*19d8e8c7SSrujana Challa if (msg->id >= MBOX_MSG_MAX) { 36*19d8e8c7SSrujana Challa dev_err(&cptvf->pdev->dev, 37*19d8e8c7SSrujana Challa "MBOX msg with unknown ID %d\n", msg->id); 38*19d8e8c7SSrujana Challa return; 39*19d8e8c7SSrujana Challa } 40*19d8e8c7SSrujana Challa if (msg->sig != OTX2_MBOX_RSP_SIG) { 41*19d8e8c7SSrujana Challa dev_err(&cptvf->pdev->dev, 42*19d8e8c7SSrujana Challa "MBOX msg with wrong signature %x, ID %d\n", 43*19d8e8c7SSrujana Challa msg->sig, msg->id); 44*19d8e8c7SSrujana Challa return; 45*19d8e8c7SSrujana Challa } 46*19d8e8c7SSrujana Challa switch (msg->id) { 47*19d8e8c7SSrujana Challa case MBOX_MSG_READY: 48*19d8e8c7SSrujana Challa cptvf->vf_id = ((msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) 49*19d8e8c7SSrujana Challa & RVU_PFVF_FUNC_MASK) - 1; 50*19d8e8c7SSrujana Challa break; 51*19d8e8c7SSrujana Challa case MBOX_MSG_ATTACH_RESOURCES: 52*19d8e8c7SSrujana Challa /* Check if resources were successfully attached */ 53*19d8e8c7SSrujana Challa if (!msg->rc) 54*19d8e8c7SSrujana Challa lfs->are_lfs_attached = 1; 55*19d8e8c7SSrujana Challa break; 56*19d8e8c7SSrujana Challa case MBOX_MSG_DETACH_RESOURCES: 57*19d8e8c7SSrujana Challa /* Check if resources were successfully detached */ 58*19d8e8c7SSrujana Challa if (!msg->rc) 59*19d8e8c7SSrujana Challa lfs->are_lfs_attached = 0; 60*19d8e8c7SSrujana Challa break; 61*19d8e8c7SSrujana Challa case MBOX_MSG_MSIX_OFFSET: 62*19d8e8c7SSrujana Challa rsp_msix = (struct msix_offset_rsp *) msg; 63*19d8e8c7SSrujana Challa for (i = 0; i < rsp_msix->cptlfs; i++) 64*19d8e8c7SSrujana Challa lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i]; 65*19d8e8c7SSrujana Challa break; 66*19d8e8c7SSrujana Challa case MBOX_MSG_CPT_RD_WR_REGISTER: 67*19d8e8c7SSrujana Challa rsp_reg = (struct cpt_rd_wr_reg_msg *) msg; 68*19d8e8c7SSrujana Challa if (msg->rc) { 69*19d8e8c7SSrujana Challa dev_err(&cptvf->pdev->dev, 70*19d8e8c7SSrujana Challa "Reg %llx rd/wr(%d) failed %d\n", 71*19d8e8c7SSrujana Challa rsp_reg->reg_offset, rsp_reg->is_write, 72*19d8e8c7SSrujana Challa msg->rc); 73*19d8e8c7SSrujana Challa return; 74*19d8e8c7SSrujana Challa } 75*19d8e8c7SSrujana Challa if (!rsp_reg->is_write) 76*19d8e8c7SSrujana Challa *rsp_reg->ret_val = rsp_reg->val; 77*19d8e8c7SSrujana Challa break; 78*19d8e8c7SSrujana Challa default: 79*19d8e8c7SSrujana Challa dev_err(&cptvf->pdev->dev, "Unsupported msg %d received.\n", 80*19d8e8c7SSrujana Challa msg->id); 81*19d8e8c7SSrujana Challa break; 82*19d8e8c7SSrujana Challa } 83*19d8e8c7SSrujana Challa } 84*19d8e8c7SSrujana Challa 85*19d8e8c7SSrujana Challa void otx2_cptvf_pfvf_mbox_handler(struct work_struct *work) 86*19d8e8c7SSrujana Challa { 87*19d8e8c7SSrujana Challa struct otx2_cptvf_dev *cptvf; 88*19d8e8c7SSrujana Challa struct otx2_mbox *pfvf_mbox; 89*19d8e8c7SSrujana Challa struct otx2_mbox_dev *mdev; 90*19d8e8c7SSrujana Challa struct mbox_hdr *rsp_hdr; 91*19d8e8c7SSrujana Challa struct mbox_msghdr *msg; 92*19d8e8c7SSrujana Challa int offset, i; 93*19d8e8c7SSrujana Challa 94*19d8e8c7SSrujana Challa /* sync with mbox memory region */ 95*19d8e8c7SSrujana Challa smp_rmb(); 96*19d8e8c7SSrujana Challa 97*19d8e8c7SSrujana Challa cptvf = container_of(work, struct otx2_cptvf_dev, pfvf_mbox_work); 98*19d8e8c7SSrujana Challa pfvf_mbox = &cptvf->pfvf_mbox; 99*19d8e8c7SSrujana Challa mdev = &pfvf_mbox->dev[0]; 100*19d8e8c7SSrujana Challa rsp_hdr = (struct mbox_hdr *)(mdev->mbase + pfvf_mbox->rx_start); 101*19d8e8c7SSrujana Challa if (rsp_hdr->num_msgs == 0) 102*19d8e8c7SSrujana Challa return; 103*19d8e8c7SSrujana Challa offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN); 104*19d8e8c7SSrujana Challa 105*19d8e8c7SSrujana Challa for (i = 0; i < rsp_hdr->num_msgs; i++) { 106*19d8e8c7SSrujana Challa msg = (struct mbox_msghdr *)(mdev->mbase + pfvf_mbox->rx_start + 107*19d8e8c7SSrujana Challa offset); 108*19d8e8c7SSrujana Challa process_pfvf_mbox_mbox_msg(cptvf, msg); 109*19d8e8c7SSrujana Challa offset = msg->next_msgoff; 110*19d8e8c7SSrujana Challa mdev->msgs_acked++; 111*19d8e8c7SSrujana Challa } 112*19d8e8c7SSrujana Challa otx2_mbox_reset(pfvf_mbox, 0); 113*19d8e8c7SSrujana Challa } 114