1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (C) 2020 Marvell. */ 3 4 #include "otx2_cpt_common.h" 5 #include "otx2_cptvf.h" 6 #include <rvu_reg.h> 7 8 int otx2_cpt_mbox_bbuf_init(struct otx2_cptvf_dev *cptvf, struct pci_dev *pdev) 9 { 10 struct otx2_mbox_dev *mdev; 11 struct otx2_mbox *otx2_mbox; 12 13 cptvf->bbuf_base = devm_kmalloc(&pdev->dev, MBOX_SIZE, GFP_KERNEL); 14 if (!cptvf->bbuf_base) 15 return -ENOMEM; 16 /* 17 * Overwrite mbox mbase to point to bounce buffer, so that PF/VF 18 * prepare all mbox messages in bounce buffer instead of directly 19 * in hw mbox memory. 20 */ 21 otx2_mbox = &cptvf->pfvf_mbox; 22 mdev = &otx2_mbox->dev[0]; 23 mdev->mbase = cptvf->bbuf_base; 24 25 return 0; 26 } 27 28 static void otx2_cpt_sync_mbox_bbuf(struct otx2_mbox *mbox, int devid) 29 { 30 u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN); 31 void *hw_mbase = mbox->hwbase + (devid * MBOX_SIZE); 32 struct otx2_mbox_dev *mdev = &mbox->dev[devid]; 33 struct mbox_hdr *hdr; 34 u64 msg_size; 35 36 if (mdev->mbase == hw_mbase) 37 return; 38 39 hdr = hw_mbase + mbox->rx_start; 40 msg_size = hdr->msg_size; 41 42 if (msg_size > mbox->rx_size - msgs_offset) 43 msg_size = mbox->rx_size - msgs_offset; 44 45 /* Copy mbox messages from mbox memory to bounce buffer */ 46 memcpy(mdev->mbase + mbox->rx_start, 47 hw_mbase + mbox->rx_start, msg_size + msgs_offset); 48 } 49 50 irqreturn_t otx2_cptvf_pfvf_mbox_intr(int __always_unused irq, void *arg) 51 { 52 struct otx2_cptvf_dev *cptvf = arg; 53 u64 intr; 54 55 /* Read the interrupt bits */ 56 intr = otx2_cpt_read64(cptvf->reg_base, BLKADDR_RVUM, 0, 57 OTX2_RVU_VF_INT); 58 59 if (intr & 0x1ULL) { 60 /* Schedule work queue function to process the MBOX request */ 61 queue_work(cptvf->pfvf_mbox_wq, &cptvf->pfvf_mbox_work); 62 /* Clear and ack the interrupt */ 63 otx2_cpt_write64(cptvf->reg_base, BLKADDR_RVUM, 0, 64 OTX2_RVU_VF_INT, 0x1ULL); 65 } 66 return IRQ_HANDLED; 67 } 68 69 static void process_pfvf_mbox_mbox_msg(struct otx2_cptvf_dev *cptvf, 70 struct mbox_msghdr *msg) 71 { 72 struct otx2_cptlfs_info *lfs = &cptvf->lfs; 73 struct otx2_cpt_kvf_limits_rsp *rsp_limits; 74 struct otx2_cpt_egrp_num_rsp *rsp_grp; 75 struct cpt_rd_wr_reg_msg *rsp_reg; 76 struct msix_offset_rsp *rsp_msix; 77 int i; 78 79 if (msg->id >= MBOX_MSG_MAX) { 80 dev_err(&cptvf->pdev->dev, 81 "MBOX msg with unknown ID %d\n", msg->id); 82 return; 83 } 84 if (msg->sig != OTX2_MBOX_RSP_SIG) { 85 dev_err(&cptvf->pdev->dev, 86 "MBOX msg with wrong signature %x, ID %d\n", 87 msg->sig, msg->id); 88 return; 89 } 90 switch (msg->id) { 91 case MBOX_MSG_READY: 92 cptvf->vf_id = ((msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) 93 & RVU_PFVF_FUNC_MASK) - 1; 94 break; 95 case MBOX_MSG_ATTACH_RESOURCES: 96 /* Check if resources were successfully attached */ 97 if (!msg->rc) 98 lfs->are_lfs_attached = 1; 99 break; 100 case MBOX_MSG_DETACH_RESOURCES: 101 /* Check if resources were successfully detached */ 102 if (!msg->rc) 103 lfs->are_lfs_attached = 0; 104 break; 105 case MBOX_MSG_MSIX_OFFSET: 106 rsp_msix = (struct msix_offset_rsp *) msg; 107 for (i = 0; i < rsp_msix->cptlfs; i++) 108 lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i]; 109 break; 110 case MBOX_MSG_CPT_RD_WR_REGISTER: 111 rsp_reg = (struct cpt_rd_wr_reg_msg *) msg; 112 if (msg->rc) { 113 dev_err(&cptvf->pdev->dev, 114 "Reg %llx rd/wr(%d) failed %d\n", 115 rsp_reg->reg_offset, rsp_reg->is_write, 116 msg->rc); 117 return; 118 } 119 if (!rsp_reg->is_write) 120 *rsp_reg->ret_val = rsp_reg->val; 121 break; 122 case MBOX_MSG_GET_ENG_GRP_NUM: 123 rsp_grp = (struct otx2_cpt_egrp_num_rsp *) msg; 124 cptvf->lfs.kcrypto_eng_grp_num = rsp_grp->eng_grp_num; 125 break; 126 case MBOX_MSG_GET_KVF_LIMITS: 127 rsp_limits = (struct otx2_cpt_kvf_limits_rsp *) msg; 128 cptvf->lfs.kvf_limits = rsp_limits->kvf_limits; 129 break; 130 default: 131 dev_err(&cptvf->pdev->dev, "Unsupported msg %d received.\n", 132 msg->id); 133 break; 134 } 135 } 136 137 void otx2_cptvf_pfvf_mbox_handler(struct work_struct *work) 138 { 139 struct otx2_cptvf_dev *cptvf; 140 struct otx2_mbox *pfvf_mbox; 141 struct otx2_mbox_dev *mdev; 142 struct mbox_hdr *rsp_hdr; 143 struct mbox_msghdr *msg; 144 int offset, i; 145 146 /* sync with mbox memory region */ 147 smp_rmb(); 148 149 cptvf = container_of(work, struct otx2_cptvf_dev, pfvf_mbox_work); 150 pfvf_mbox = &cptvf->pfvf_mbox; 151 otx2_cpt_sync_mbox_bbuf(pfvf_mbox, 0); 152 mdev = &pfvf_mbox->dev[0]; 153 rsp_hdr = (struct mbox_hdr *)(mdev->mbase + pfvf_mbox->rx_start); 154 if (rsp_hdr->num_msgs == 0) 155 return; 156 offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN); 157 158 for (i = 0; i < rsp_hdr->num_msgs; i++) { 159 msg = (struct mbox_msghdr *)(mdev->mbase + pfvf_mbox->rx_start + 160 offset); 161 process_pfvf_mbox_mbox_msg(cptvf, msg); 162 offset = msg->next_msgoff; 163 mdev->msgs_acked++; 164 } 165 otx2_mbox_reset(pfvf_mbox, 0); 166 } 167 168 int otx2_cptvf_send_eng_grp_num_msg(struct otx2_cptvf_dev *cptvf, int eng_type) 169 { 170 struct otx2_mbox *mbox = &cptvf->pfvf_mbox; 171 struct pci_dev *pdev = cptvf->pdev; 172 struct otx2_cpt_egrp_num_msg *req; 173 174 req = (struct otx2_cpt_egrp_num_msg *) 175 otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req), 176 sizeof(struct otx2_cpt_egrp_num_rsp)); 177 if (req == NULL) { 178 dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); 179 return -EFAULT; 180 } 181 req->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM; 182 req->hdr.sig = OTX2_MBOX_REQ_SIG; 183 req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); 184 req->eng_type = eng_type; 185 186 return otx2_cpt_send_mbox_msg(mbox, pdev); 187 } 188 189 int otx2_cptvf_send_kvf_limits_msg(struct otx2_cptvf_dev *cptvf) 190 { 191 struct otx2_mbox *mbox = &cptvf->pfvf_mbox; 192 struct pci_dev *pdev = cptvf->pdev; 193 struct mbox_msghdr *req; 194 195 req = (struct mbox_msghdr *) 196 otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req), 197 sizeof(struct otx2_cpt_kvf_limits_rsp)); 198 if (req == NULL) { 199 dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); 200 return -EFAULT; 201 } 202 req->id = MBOX_MSG_GET_KVF_LIMITS; 203 req->sig = OTX2_MBOX_REQ_SIG; 204 req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); 205 206 return otx2_cpt_send_mbox_msg(mbox, pdev); 207 } 208