162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (C) 2020 Marvell. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "otx2_cpt_common.h" 562306a36Sopenharmony_ci#include "otx2_cptvf.h" 662306a36Sopenharmony_ci#include <rvu_reg.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ciint otx2_cpt_mbox_bbuf_init(struct otx2_cptvf_dev *cptvf, struct pci_dev *pdev) 962306a36Sopenharmony_ci{ 1062306a36Sopenharmony_ci struct otx2_mbox_dev *mdev; 1162306a36Sopenharmony_ci struct otx2_mbox *otx2_mbox; 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci cptvf->bbuf_base = devm_kmalloc(&pdev->dev, MBOX_SIZE, GFP_KERNEL); 1462306a36Sopenharmony_ci if (!cptvf->bbuf_base) 1562306a36Sopenharmony_ci return -ENOMEM; 1662306a36Sopenharmony_ci /* 1762306a36Sopenharmony_ci * Overwrite mbox mbase to point to bounce buffer, so that PF/VF 1862306a36Sopenharmony_ci * prepare all mbox messages in bounce buffer instead of directly 1962306a36Sopenharmony_ci * in hw mbox memory. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci otx2_mbox = &cptvf->pfvf_mbox; 2262306a36Sopenharmony_ci mdev = &otx2_mbox->dev[0]; 2362306a36Sopenharmony_ci mdev->mbase = cptvf->bbuf_base; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci return 0; 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic void otx2_cpt_sync_mbox_bbuf(struct otx2_mbox *mbox, int devid) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN); 3162306a36Sopenharmony_ci void *hw_mbase = mbox->hwbase + (devid * MBOX_SIZE); 3262306a36Sopenharmony_ci struct otx2_mbox_dev *mdev = &mbox->dev[devid]; 3362306a36Sopenharmony_ci struct mbox_hdr *hdr; 3462306a36Sopenharmony_ci u64 msg_size; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci if (mdev->mbase == hw_mbase) 3762306a36Sopenharmony_ci return; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci hdr = hw_mbase + mbox->rx_start; 4062306a36Sopenharmony_ci msg_size = hdr->msg_size; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci if (msg_size > mbox->rx_size - msgs_offset) 4362306a36Sopenharmony_ci msg_size = mbox->rx_size - msgs_offset; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Copy mbox messages from mbox memory to bounce buffer */ 4662306a36Sopenharmony_ci memcpy(mdev->mbase + mbox->rx_start, 4762306a36Sopenharmony_ci hw_mbase + mbox->rx_start, msg_size + msgs_offset); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciirqreturn_t otx2_cptvf_pfvf_mbox_intr(int __always_unused irq, void *arg) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct otx2_cptvf_dev *cptvf = arg; 5362306a36Sopenharmony_ci u64 intr; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* Read the interrupt bits */ 5662306a36Sopenharmony_ci intr = otx2_cpt_read64(cptvf->reg_base, BLKADDR_RVUM, 0, 5762306a36Sopenharmony_ci OTX2_RVU_VF_INT); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (intr & 0x1ULL) { 6062306a36Sopenharmony_ci /* Schedule work queue function to process the MBOX request */ 6162306a36Sopenharmony_ci queue_work(cptvf->pfvf_mbox_wq, &cptvf->pfvf_mbox_work); 6262306a36Sopenharmony_ci /* Clear and ack the interrupt */ 6362306a36Sopenharmony_ci otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, 6462306a36Sopenharmony_ci OTX2_RVU_VF_INT, 0x1ULL); 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci return IRQ_HANDLED; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic void process_pfvf_mbox_mbox_msg(struct otx2_cptvf_dev *cptvf, 7062306a36Sopenharmony_ci struct mbox_msghdr *msg) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct otx2_cptlfs_info *lfs = &cptvf->lfs; 7362306a36Sopenharmony_ci struct otx2_cpt_kvf_limits_rsp *rsp_limits; 7462306a36Sopenharmony_ci struct otx2_cpt_egrp_num_rsp *rsp_grp; 7562306a36Sopenharmony_ci struct cpt_rd_wr_reg_msg *rsp_reg; 7662306a36Sopenharmony_ci struct msix_offset_rsp *rsp_msix; 7762306a36Sopenharmony_ci int i; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (msg->id >= MBOX_MSG_MAX) { 8062306a36Sopenharmony_ci dev_err(&cptvf->pdev->dev, 8162306a36Sopenharmony_ci "MBOX msg with unknown ID %d\n", msg->id); 8262306a36Sopenharmony_ci return; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci if (msg->sig != OTX2_MBOX_RSP_SIG) { 8562306a36Sopenharmony_ci dev_err(&cptvf->pdev->dev, 8662306a36Sopenharmony_ci "MBOX msg with wrong signature %x, ID %d\n", 8762306a36Sopenharmony_ci msg->sig, msg->id); 8862306a36Sopenharmony_ci return; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci switch (msg->id) { 9162306a36Sopenharmony_ci case MBOX_MSG_READY: 9262306a36Sopenharmony_ci cptvf->vf_id = ((msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) 9362306a36Sopenharmony_ci & RVU_PFVF_FUNC_MASK) - 1; 9462306a36Sopenharmony_ci break; 9562306a36Sopenharmony_ci case MBOX_MSG_ATTACH_RESOURCES: 9662306a36Sopenharmony_ci /* Check if resources were successfully attached */ 9762306a36Sopenharmony_ci if (!msg->rc) 9862306a36Sopenharmony_ci lfs->are_lfs_attached = 1; 9962306a36Sopenharmony_ci break; 10062306a36Sopenharmony_ci case MBOX_MSG_DETACH_RESOURCES: 10162306a36Sopenharmony_ci /* Check if resources were successfully detached */ 10262306a36Sopenharmony_ci if (!msg->rc) 10362306a36Sopenharmony_ci lfs->are_lfs_attached = 0; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci case MBOX_MSG_MSIX_OFFSET: 10662306a36Sopenharmony_ci rsp_msix = (struct msix_offset_rsp *) msg; 10762306a36Sopenharmony_ci for (i = 0; i < rsp_msix->cptlfs; i++) 10862306a36Sopenharmony_ci lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i]; 10962306a36Sopenharmony_ci break; 11062306a36Sopenharmony_ci case MBOX_MSG_CPT_RD_WR_REGISTER: 11162306a36Sopenharmony_ci rsp_reg = (struct cpt_rd_wr_reg_msg *) msg; 11262306a36Sopenharmony_ci if (msg->rc) { 11362306a36Sopenharmony_ci dev_err(&cptvf->pdev->dev, 11462306a36Sopenharmony_ci "Reg %llx rd/wr(%d) failed %d\n", 11562306a36Sopenharmony_ci rsp_reg->reg_offset, rsp_reg->is_write, 11662306a36Sopenharmony_ci msg->rc); 11762306a36Sopenharmony_ci return; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci if (!rsp_reg->is_write) 12062306a36Sopenharmony_ci *rsp_reg->ret_val = rsp_reg->val; 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci case MBOX_MSG_GET_ENG_GRP_NUM: 12362306a36Sopenharmony_ci rsp_grp = (struct otx2_cpt_egrp_num_rsp *) msg; 12462306a36Sopenharmony_ci cptvf->lfs.kcrypto_eng_grp_num = rsp_grp->eng_grp_num; 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci case MBOX_MSG_GET_KVF_LIMITS: 12762306a36Sopenharmony_ci rsp_limits = (struct otx2_cpt_kvf_limits_rsp *) msg; 12862306a36Sopenharmony_ci cptvf->lfs.kvf_limits = rsp_limits->kvf_limits; 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci default: 13162306a36Sopenharmony_ci dev_err(&cptvf->pdev->dev, "Unsupported msg %d received.\n", 13262306a36Sopenharmony_ci msg->id); 13362306a36Sopenharmony_ci break; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_civoid otx2_cptvf_pfvf_mbox_handler(struct work_struct *work) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct otx2_cptvf_dev *cptvf; 14062306a36Sopenharmony_ci struct otx2_mbox *pfvf_mbox; 14162306a36Sopenharmony_ci struct otx2_mbox_dev *mdev; 14262306a36Sopenharmony_ci struct mbox_hdr *rsp_hdr; 14362306a36Sopenharmony_ci struct mbox_msghdr *msg; 14462306a36Sopenharmony_ci int offset, i; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* sync with mbox memory region */ 14762306a36Sopenharmony_ci smp_rmb(); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci cptvf = container_of(work, struct otx2_cptvf_dev, pfvf_mbox_work); 15062306a36Sopenharmony_ci pfvf_mbox = &cptvf->pfvf_mbox; 15162306a36Sopenharmony_ci otx2_cpt_sync_mbox_bbuf(pfvf_mbox, 0); 15262306a36Sopenharmony_ci mdev = &pfvf_mbox->dev[0]; 15362306a36Sopenharmony_ci rsp_hdr = (struct mbox_hdr *)(mdev->mbase + pfvf_mbox->rx_start); 15462306a36Sopenharmony_ci if (rsp_hdr->num_msgs == 0) 15562306a36Sopenharmony_ci return; 15662306a36Sopenharmony_ci offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci for (i = 0; i < rsp_hdr->num_msgs; i++) { 15962306a36Sopenharmony_ci msg = (struct mbox_msghdr *)(mdev->mbase + pfvf_mbox->rx_start + 16062306a36Sopenharmony_ci offset); 16162306a36Sopenharmony_ci process_pfvf_mbox_mbox_msg(cptvf, msg); 16262306a36Sopenharmony_ci offset = msg->next_msgoff; 16362306a36Sopenharmony_ci mdev->msgs_acked++; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci otx2_mbox_reset(pfvf_mbox, 0); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ciint otx2_cptvf_send_eng_grp_num_msg(struct otx2_cptvf_dev *cptvf, int eng_type) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct otx2_mbox *mbox = &cptvf->pfvf_mbox; 17162306a36Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 17262306a36Sopenharmony_ci struct otx2_cpt_egrp_num_msg *req; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci req = (struct otx2_cpt_egrp_num_msg *) 17562306a36Sopenharmony_ci otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req), 17662306a36Sopenharmony_ci sizeof(struct otx2_cpt_egrp_num_rsp)); 17762306a36Sopenharmony_ci if (req == NULL) { 17862306a36Sopenharmony_ci dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); 17962306a36Sopenharmony_ci return -EFAULT; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci req->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM; 18262306a36Sopenharmony_ci req->hdr.sig = OTX2_MBOX_REQ_SIG; 18362306a36Sopenharmony_ci req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); 18462306a36Sopenharmony_ci req->eng_type = eng_type; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci return otx2_cpt_send_mbox_msg(mbox, pdev); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciint otx2_cptvf_send_kvf_limits_msg(struct otx2_cptvf_dev *cptvf) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct otx2_mbox *mbox = &cptvf->pfvf_mbox; 19262306a36Sopenharmony_ci struct pci_dev *pdev = cptvf->pdev; 19362306a36Sopenharmony_ci struct mbox_msghdr *req; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci req = (struct mbox_msghdr *) 19662306a36Sopenharmony_ci otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req), 19762306a36Sopenharmony_ci sizeof(struct otx2_cpt_kvf_limits_rsp)); 19862306a36Sopenharmony_ci if (req == NULL) { 19962306a36Sopenharmony_ci dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); 20062306a36Sopenharmony_ci return -EFAULT; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci req->id = MBOX_MSG_GET_KVF_LIMITS; 20362306a36Sopenharmony_ci req->sig = OTX2_MBOX_REQ_SIG; 20462306a36Sopenharmony_ci req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci return otx2_cpt_send_mbox_msg(mbox, pdev); 20762306a36Sopenharmony_ci} 208