otx2_cptpf_mbox.c (9753B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* Copyright (C) 2020 Marvell. */ 3 4#include "otx2_cpt_common.h" 5#include "otx2_cptpf.h" 6#include "rvu_reg.h" 7 8/* 9 * CPT PF driver version, It will be incremented by 1 for every feature 10 * addition in CPT mailbox messages. 11 */ 12#define OTX2_CPT_PF_DRV_VERSION 0x1 13 14static int forward_to_af(struct otx2_cptpf_dev *cptpf, 15 struct otx2_cptvf_info *vf, 16 struct mbox_msghdr *req, int size) 17{ 18 struct mbox_msghdr *msg; 19 int ret; 20 21 mutex_lock(&cptpf->lock); 22 msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size); 23 if (msg == NULL) { 24 mutex_unlock(&cptpf->lock); 25 return -ENOMEM; 26 } 27 28 memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr), 29 (uint8_t *)req + sizeof(struct mbox_msghdr), size); 30 msg->id = req->id; 31 msg->pcifunc = req->pcifunc; 32 msg->sig = req->sig; 33 msg->ver = req->ver; 34 35 ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox); 36 /* Error code -EIO indicate there is a communication failure 37 * to the AF. Rest of the error codes indicate that AF processed 38 * VF messages and set the error codes in response messages 39 * (if any) so simply forward responses to VF. 40 */ 41 if (ret == -EIO) { 42 dev_warn(&cptpf->pdev->dev, 43 "AF not responding to VF%d messages\n", vf->vf_id); 44 mutex_unlock(&cptpf->lock); 45 return ret; 46 } 47 mutex_unlock(&cptpf->lock); 48 return 0; 49} 50 51static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf, 52 struct otx2_cptvf_info *vf, 53 struct mbox_msghdr *req) 54{ 55 struct otx2_cpt_caps_rsp *rsp; 56 57 rsp = (struct otx2_cpt_caps_rsp *) 58 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, 59 sizeof(*rsp)); 60 if (!rsp) 61 return -ENOMEM; 62 63 rsp->hdr.id = MBOX_MSG_GET_CAPS; 64 rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 65 rsp->hdr.pcifunc = req->pcifunc; 66 rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION; 67 rsp->cpt_revision = cptpf->pdev->revision; 68 memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps)); 69 70 return 0; 71} 72 73static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf, 74 struct otx2_cptvf_info *vf, 75 struct mbox_msghdr *req) 76{ 77 struct otx2_cpt_egrp_num_msg *grp_req; 78 struct otx2_cpt_egrp_num_rsp *rsp; 79 80 grp_req = (struct otx2_cpt_egrp_num_msg *)req; 81 rsp = (struct otx2_cpt_egrp_num_rsp *) 82 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp)); 83 if (!rsp) 84 return -ENOMEM; 85 86 rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM; 87 rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 88 rsp->hdr.pcifunc = req->pcifunc; 89 rsp->eng_type = grp_req->eng_type; 90 rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps, 91 grp_req->eng_type); 92 93 return 0; 94} 95 96static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf, 97 struct otx2_cptvf_info *vf, 98 struct mbox_msghdr *req) 99{ 100 struct otx2_cpt_kvf_limits_rsp *rsp; 101 102 rsp = (struct otx2_cpt_kvf_limits_rsp *) 103 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp)); 104 if (!rsp) 105 return -ENOMEM; 106 107 rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS; 108 rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 109 rsp->hdr.pcifunc = req->pcifunc; 110 rsp->kvf_limits = cptpf->kvf_limits; 111 112 return 0; 113} 114 115static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf, 116 struct otx2_cptvf_info *vf, 117 struct mbox_msghdr *req, int size) 118{ 119 int err = 0; 120 121 /* Check if msg is valid, if not reply with an invalid msg */ 122 if (req->sig != OTX2_MBOX_REQ_SIG) 123 goto inval_msg; 124 125 switch (req->id) { 126 case MBOX_MSG_GET_ENG_GRP_NUM: 127 err = handle_msg_get_eng_grp_num(cptpf, vf, req); 128 break; 129 case MBOX_MSG_GET_CAPS: 130 err = handle_msg_get_caps(cptpf, vf, req); 131 break; 132 case MBOX_MSG_GET_KVF_LIMITS: 133 err = handle_msg_kvf_limits(cptpf, vf, req); 134 break; 135 default: 136 err = forward_to_af(cptpf, vf, req, size); 137 break; 138 } 139 return err; 140 141inval_msg: 142 otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id); 143 otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id); 144 return err; 145} 146 147irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg) 148{ 149 struct otx2_cptpf_dev *cptpf = arg; 150 struct otx2_cptvf_info *vf; 151 int i, vf_idx; 152 u64 intr; 153 154 /* 155 * Check which VF has raised an interrupt and schedule 156 * corresponding work queue to process the messages 157 */ 158 for (i = 0; i < 2; i++) { 159 /* Read the interrupt bits */ 160 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, 161 RVU_PF_VFPF_MBOX_INTX(i)); 162 163 for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) { 164 vf = &cptpf->vf[vf_idx]; 165 if (intr & (1ULL << vf->intr_idx)) { 166 queue_work(cptpf->vfpf_mbox_wq, 167 &vf->vfpf_mbox_work); 168 /* Clear the interrupt */ 169 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 170 0, RVU_PF_VFPF_MBOX_INTX(i), 171 BIT_ULL(vf->intr_idx)); 172 } 173 } 174 } 175 return IRQ_HANDLED; 176} 177 178void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work) 179{ 180 struct otx2_cptpf_dev *cptpf; 181 struct otx2_cptvf_info *vf; 182 struct otx2_mbox_dev *mdev; 183 struct mbox_hdr *req_hdr; 184 struct mbox_msghdr *msg; 185 struct otx2_mbox *mbox; 186 int offset, i, err; 187 188 vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work); 189 cptpf = vf->cptpf; 190 mbox = &cptpf->vfpf_mbox; 191 /* sync with mbox memory region */ 192 smp_rmb(); 193 mdev = &mbox->dev[vf->vf_id]; 194 /* Process received mbox messages */ 195 req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); 196 offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN); 197 198 for (i = 0; i < req_hdr->num_msgs; i++) { 199 msg = (struct mbox_msghdr *)(mdev->mbase + offset); 200 201 /* Set which VF sent this message based on mbox IRQ */ 202 msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) | 203 ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK); 204 205 err = cptpf_handle_vf_req(cptpf, vf, msg, 206 msg->next_msgoff - offset); 207 /* 208 * Behave as the AF, drop the msg if there is 209 * no memory, timeout handling also goes here 210 */ 211 if (err == -ENOMEM || err == -EIO) 212 break; 213 offset = msg->next_msgoff; 214 /* Write barrier required for VF responses which are handled by 215 * PF driver and not forwarded to AF. 216 */ 217 smp_wmb(); 218 } 219 /* Send mbox responses to VF */ 220 if (mdev->num_msgs) 221 otx2_mbox_msg_send(mbox, vf->vf_id); 222} 223 224irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg) 225{ 226 struct otx2_cptpf_dev *cptpf = arg; 227 u64 intr; 228 229 /* Read the interrupt bits */ 230 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT); 231 232 if (intr & 0x1ULL) { 233 /* Schedule work queue function to process the MBOX request */ 234 queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work); 235 /* Clear and ack the interrupt */ 236 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 237 0x1ULL); 238 } 239 return IRQ_HANDLED; 240} 241 242static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, 243 struct mbox_msghdr *msg) 244{ 245 struct device *dev = &cptpf->pdev->dev; 246 struct cpt_rd_wr_reg_msg *rsp_rd_wr; 247 248 if (msg->id >= MBOX_MSG_MAX) { 249 dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id); 250 return; 251 } 252 if (msg->sig != OTX2_MBOX_RSP_SIG) { 253 dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n", 254 msg->sig, msg->id); 255 return; 256 } 257 258 switch (msg->id) { 259 case MBOX_MSG_READY: 260 cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) & 261 RVU_PFVF_PF_MASK; 262 break; 263 case MBOX_MSG_CPT_RD_WR_REGISTER: 264 rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg; 265 if (msg->rc) { 266 dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n", 267 rsp_rd_wr->reg_offset, rsp_rd_wr->is_write, 268 msg->rc); 269 return; 270 } 271 if (!rsp_rd_wr->is_write) 272 *rsp_rd_wr->ret_val = rsp_rd_wr->val; 273 break; 274 case MBOX_MSG_ATTACH_RESOURCES: 275 if (!msg->rc) 276 cptpf->lfs.are_lfs_attached = 1; 277 break; 278 case MBOX_MSG_DETACH_RESOURCES: 279 if (!msg->rc) 280 cptpf->lfs.are_lfs_attached = 0; 281 break; 282 283 default: 284 dev_err(dev, 285 "Unsupported msg %d received.\n", msg->id); 286 break; 287 } 288} 289 290static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg, 291 int vf_id, int size) 292{ 293 struct otx2_mbox *vfpf_mbox; 294 struct mbox_msghdr *fwd; 295 296 if (msg->id >= MBOX_MSG_MAX) { 297 dev_err(&cptpf->pdev->dev, 298 "MBOX msg with unknown ID %d\n", msg->id); 299 return; 300 } 301 if (msg->sig != OTX2_MBOX_RSP_SIG) { 302 dev_err(&cptpf->pdev->dev, 303 "MBOX msg with wrong signature %x, ID %d\n", 304 msg->sig, msg->id); 305 return; 306 } 307 vfpf_mbox = &cptpf->vfpf_mbox; 308 vf_id--; 309 if (vf_id >= cptpf->enabled_vfs) { 310 dev_err(&cptpf->pdev->dev, 311 "MBOX msg to unknown VF: %d >= %d\n", 312 vf_id, cptpf->enabled_vfs); 313 return; 314 } 315 if (msg->id == MBOX_MSG_VF_FLR) 316 return; 317 318 fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size); 319 if (!fwd) { 320 dev_err(&cptpf->pdev->dev, 321 "Forwarding to VF%d failed.\n", vf_id); 322 return; 323 } 324 memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr), 325 (uint8_t *)msg + sizeof(struct mbox_msghdr), size); 326 fwd->id = msg->id; 327 fwd->pcifunc = msg->pcifunc; 328 fwd->sig = msg->sig; 329 fwd->ver = msg->ver; 330 fwd->rc = msg->rc; 331} 332 333/* Handle mailbox messages received from AF */ 334void otx2_cptpf_afpf_mbox_handler(struct work_struct *work) 335{ 336 struct otx2_cptpf_dev *cptpf; 337 struct otx2_mbox *afpf_mbox; 338 struct otx2_mbox_dev *mdev; 339 struct mbox_hdr *rsp_hdr; 340 struct mbox_msghdr *msg; 341 int offset, vf_id, i; 342 343 cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work); 344 afpf_mbox = &cptpf->afpf_mbox; 345 mdev = &afpf_mbox->dev[0]; 346 /* Sync mbox data into memory */ 347 smp_wmb(); 348 349 rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start); 350 offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); 351 352 for (i = 0; i < rsp_hdr->num_msgs; i++) { 353 msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start + 354 offset); 355 vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) & 356 RVU_PFVF_FUNC_MASK; 357 if (vf_id > 0) 358 forward_to_vf(cptpf, msg, vf_id, 359 msg->next_msgoff - offset); 360 else 361 process_afpf_mbox_msg(cptpf, msg); 362 363 offset = msg->next_msgoff; 364 /* Sync VF response ready to be sent */ 365 smp_wmb(); 366 mdev->msgs_acked++; 367 } 368 otx2_mbox_reset(afpf_mbox, 0); 369}