667 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (C) 2020 Marvell. */3 4#include "otx2_cpt_common.h"5#include "otx2_cptpf.h"6#include "rvu_reg.h"7 8/* Fastpath ipsec opcode with inplace processing */9#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6))10#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6))11 12#define cpt_inline_rx_opcode(pdev) \13({ \14 u8 opcode; \15 if (is_dev_otx2(pdev)) \16 opcode = CPT_INLINE_RX_OPCODE; \17 else \18 opcode = CN10K_CPT_INLINE_RX_OPCODE; \19 (opcode); \20})21 22/*23 * CPT PF driver version, It will be incremented by 1 for every feature24 * addition in CPT mailbox messages.25 */26#define OTX2_CPT_PF_DRV_VERSION 0x127 28static int forward_to_af(struct otx2_cptpf_dev *cptpf,29 struct otx2_cptvf_info *vf,30 struct mbox_msghdr *req, int size)31{32 struct mbox_msghdr *msg;33 int ret;34 35 mutex_lock(&cptpf->lock);36 msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);37 if (msg == NULL) {38 mutex_unlock(&cptpf->lock);39 return -ENOMEM;40 }41 42 memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),43 (uint8_t *)req + sizeof(struct mbox_msghdr), size);44 msg->id = req->id;45 msg->pcifunc = req->pcifunc;46 msg->sig = req->sig;47 msg->ver = req->ver;48 49 ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);50 /* Error code -EIO indicate there is a communication failure51 * to the AF. Rest of the error codes indicate that AF processed52 * VF messages and set the error codes in response messages53 * (if any) so simply forward responses to VF.54 */55 if (ret == -EIO) {56 dev_warn(&cptpf->pdev->dev,57 "AF not responding to VF%d messages\n", vf->vf_id);58 mutex_unlock(&cptpf->lock);59 return ret;60 }61 mutex_unlock(&cptpf->lock);62 return 0;63}64 65static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,66 struct otx2_cptvf_info *vf,67 struct mbox_msghdr *req)68{69 struct otx2_cpt_caps_rsp *rsp;70 71 rsp = (struct otx2_cpt_caps_rsp *)72 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,73 sizeof(*rsp));74 if (!rsp)75 return -ENOMEM;76 77 rsp->hdr.id = MBOX_MSG_GET_CAPS;78 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;79 rsp->hdr.pcifunc = req->pcifunc;80 rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;81 rsp->cpt_revision = cptpf->eng_grps.rid;82 memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));83 84 return 0;85}86 87static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,88 struct otx2_cptvf_info *vf,89 struct mbox_msghdr *req)90{91 struct otx2_cpt_egrp_num_msg *grp_req;92 struct otx2_cpt_egrp_num_rsp *rsp;93 94 grp_req = (struct otx2_cpt_egrp_num_msg *)req;95 rsp = (struct otx2_cpt_egrp_num_rsp *)96 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));97 if (!rsp)98 return -ENOMEM;99 100 rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;101 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;102 rsp->hdr.pcifunc = req->pcifunc;103 rsp->eng_type = grp_req->eng_type;104 rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,105 grp_req->eng_type);106 107 return 0;108}109 110static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,111 struct otx2_cptvf_info *vf,112 struct mbox_msghdr *req)113{114 struct otx2_cpt_kvf_limits_rsp *rsp;115 116 rsp = (struct otx2_cpt_kvf_limits_rsp *)117 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));118 if (!rsp)119 return -ENOMEM;120 121 rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;122 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;123 rsp->hdr.pcifunc = req->pcifunc;124 rsp->kvf_limits = cptpf->kvf_limits;125 126 return 0;127}128 129static int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf,130 int sso_pf_func, u8 slot)131{132 struct cpt_inline_ipsec_cfg_msg *req;133 struct pci_dev *pdev = cptpf->pdev;134 135 req = (struct cpt_inline_ipsec_cfg_msg *)136 otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,137 sizeof(*req), sizeof(struct msg_rsp));138 if (req == NULL) {139 dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");140 return -EFAULT;141 }142 memset(req, 0, sizeof(*req));143 req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG;144 req->hdr.sig = OTX2_MBOX_REQ_SIG;145 req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0);146 req->dir = CPT_INLINE_INBOUND;147 req->slot = slot;148 req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd;149 req->sso_pf_func = sso_pf_func;150 req->enable = 1;151 152 return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);153}154 155static int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp,156 struct otx2_cpt_rx_inline_lf_cfg *req)157{158 struct nix_inline_ipsec_cfg *nix_req;159 struct pci_dev *pdev = cptpf->pdev;160 int ret;161 162 nix_req = (struct nix_inline_ipsec_cfg *)163 otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,164 sizeof(*nix_req),165 sizeof(struct msg_rsp));166 if (nix_req == NULL) {167 dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");168 return -EFAULT;169 }170 memset(nix_req, 0, sizeof(*nix_req));171 nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG;172 nix_req->hdr.sig = OTX2_MBOX_REQ_SIG;173 nix_req->enable = 1;174 nix_req->credit_th = req->credit_th;175 nix_req->bpid = req->bpid;176 if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS)177 nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1;178 else179 nix_req->cpt_credit = req->credit - 1;180 nix_req->gen_cfg.egrp = egrp;181 if (req->opcode)182 nix_req->gen_cfg.opcode = req->opcode;183 else184 nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev);185 nix_req->gen_cfg.param1 = req->param1;186 nix_req->gen_cfg.param2 = req->param2;187 nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0);188 nix_req->inst_qsel.cpt_slot = 0;189 ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);190 if (ret)191 return ret;192 193 if (cptpf->has_cpt1) {194 ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1);195 if (ret)196 return ret;197 }198 199 return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0);200}201 202int203otx2_inline_cptlf_setup(struct otx2_cptpf_dev *cptpf,204 struct otx2_cptlfs_info *lfs, u8 egrp, int num_lfs)205{206 int ret;207 208 ret = otx2_cptlf_init(lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO, 1);209 if (ret) {210 dev_err(&cptpf->pdev->dev,211 "LF configuration failed for RX inline ipsec.\n");212 return ret;213 }214 215 /* Get msix offsets for attached LFs */216 ret = otx2_cpt_msix_offset_msg(lfs);217 if (ret)218 goto cleanup_lf;219 220 /* Register for CPT LF Misc interrupts */221 ret = otx2_cptlf_register_misc_interrupts(lfs);222 if (ret)223 goto free_irq;224 225 return 0;226free_irq:227 otx2_cptlf_unregister_misc_interrupts(lfs);228cleanup_lf:229 otx2_cptlf_shutdown(lfs);230 return ret;231}232 233void234otx2_inline_cptlf_cleanup(struct otx2_cptlfs_info *lfs)235{236 /* Unregister misc interrupt */237 otx2_cptlf_unregister_misc_interrupts(lfs);238 239 /* Cleanup LFs */240 otx2_cptlf_shutdown(lfs);241}242 243static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,244 struct mbox_msghdr *req)245{246 struct otx2_cpt_rx_inline_lf_cfg *cfg_req;247 int num_lfs = 1, ret;248 u8 egrp;249 250 cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req;251 if (cptpf->lfs.lfs_num) {252 dev_err(&cptpf->pdev->dev,253 "LF is already configured for RX inline ipsec.\n");254 return -EEXIST;255 }256 /*257 * Allow LFs to execute requests destined to only grp IE_TYPES and258 * set queue priority of each LF to high259 */260 egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES);261 if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {262 dev_err(&cptpf->pdev->dev,263 "Engine group for inline ipsec is not available\n");264 return -ENOENT;265 }266 267 otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base,268 &cptpf->afpf_mbox, BLKADDR_CPT0);269 cptpf->lfs.global_slot = 0;270 cptpf->lfs.ctx_ilen_ovrd = cfg_req->ctx_ilen_valid;271 cptpf->lfs.ctx_ilen = cfg_req->ctx_ilen;272 273 ret = otx2_inline_cptlf_setup(cptpf, &cptpf->lfs, egrp, num_lfs);274 if (ret) {275 dev_err(&cptpf->pdev->dev, "Inline-Ipsec CPT0 LF setup failed.\n");276 return ret;277 }278 279 if (cptpf->has_cpt1) {280 cptpf->rsrc_req_blkaddr = BLKADDR_CPT1;281 otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev,282 cptpf->reg_base, &cptpf->afpf_mbox,283 BLKADDR_CPT1);284 cptpf->cpt1_lfs.global_slot = num_lfs;285 cptpf->cpt1_lfs.ctx_ilen_ovrd = cfg_req->ctx_ilen_valid;286 cptpf->cpt1_lfs.ctx_ilen = cfg_req->ctx_ilen;287 ret = otx2_inline_cptlf_setup(cptpf, &cptpf->cpt1_lfs, egrp,288 num_lfs);289 if (ret) {290 dev_err(&cptpf->pdev->dev, "Inline CPT1 LF setup failed.\n");291 goto lf_cleanup;292 }293 cptpf->rsrc_req_blkaddr = 0;294 }295 296 ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req);297 if (ret)298 goto lf1_cleanup;299 300 return 0;301 302lf1_cleanup:303 otx2_inline_cptlf_cleanup(&cptpf->cpt1_lfs);304lf_cleanup:305 otx2_inline_cptlf_cleanup(&cptpf->lfs);306 return ret;307}308 309static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,310 struct otx2_cptvf_info *vf,311 struct mbox_msghdr *req, int size)312{313 int err = 0;314 315 /* Check if msg is valid, if not reply with an invalid msg */316 if (req->sig != OTX2_MBOX_REQ_SIG)317 goto inval_msg;318 319 switch (req->id) {320 case MBOX_MSG_GET_ENG_GRP_NUM:321 err = handle_msg_get_eng_grp_num(cptpf, vf, req);322 break;323 case MBOX_MSG_GET_CAPS:324 err = handle_msg_get_caps(cptpf, vf, req);325 break;326 case MBOX_MSG_GET_KVF_LIMITS:327 err = handle_msg_kvf_limits(cptpf, vf, req);328 break;329 case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG:330 err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req);331 break;332 333 default:334 err = forward_to_af(cptpf, vf, req, size);335 break;336 }337 return err;338 339inval_msg:340 otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);341 otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);342 return err;343}344 345irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)346{347 struct otx2_cptpf_dev *cptpf = arg;348 struct otx2_cptvf_info *vf;349 int i, vf_idx;350 u64 intr;351 352 /*353 * Check which VF has raised an interrupt and schedule354 * corresponding work queue to process the messages355 */356 for (i = 0; i < 2; i++) {357 /* Read the interrupt bits */358 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,359 RVU_PF_VFPF_MBOX_INTX(i));360 361 for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {362 vf = &cptpf->vf[vf_idx];363 if (intr & (1ULL << vf->intr_idx)) {364 queue_work(cptpf->vfpf_mbox_wq,365 &vf->vfpf_mbox_work);366 /* Clear the interrupt */367 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,368 0, RVU_PF_VFPF_MBOX_INTX(i),369 BIT_ULL(vf->intr_idx));370 }371 }372 }373 return IRQ_HANDLED;374}375 376void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)377{378 struct otx2_cptpf_dev *cptpf;379 struct otx2_cptvf_info *vf;380 struct otx2_mbox_dev *mdev;381 struct mbox_hdr *req_hdr;382 struct mbox_msghdr *msg;383 struct otx2_mbox *mbox;384 int offset, i, err;385 386 vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);387 cptpf = vf->cptpf;388 mbox = &cptpf->vfpf_mbox;389 /* sync with mbox memory region */390 smp_rmb();391 mdev = &mbox->dev[vf->vf_id];392 /* Process received mbox messages */393 req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);394 offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);395 396 for (i = 0; i < req_hdr->num_msgs; i++) {397 msg = (struct mbox_msghdr *)(mdev->mbase + offset);398 399 /* Set which VF sent this message based on mbox IRQ */400 msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) |401 ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK);402 403 err = cptpf_handle_vf_req(cptpf, vf, msg,404 msg->next_msgoff - offset);405 /*406 * Behave as the AF, drop the msg if there is407 * no memory, timeout handling also goes here408 */409 if (err == -ENOMEM || err == -EIO)410 break;411 offset = msg->next_msgoff;412 /* Write barrier required for VF responses which are handled by413 * PF driver and not forwarded to AF.414 */415 smp_wmb();416 }417 /* Send mbox responses to VF */418 if (mdev->num_msgs)419 otx2_mbox_msg_send(mbox, vf->vf_id);420}421 422irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)423{424 struct otx2_cptpf_dev *cptpf = arg;425 struct otx2_mbox_dev *mdev;426 struct otx2_mbox *mbox;427 struct mbox_hdr *hdr;428 u64 intr;429 430 /* Read the interrupt bits */431 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);432 433 if (intr & 0x1ULL) {434 mbox = &cptpf->afpf_mbox;435 mdev = &mbox->dev[0];436 hdr = mdev->mbase + mbox->rx_start;437 if (hdr->num_msgs)438 /* Schedule work queue function to process the MBOX request */439 queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);440 441 mbox = &cptpf->afpf_mbox_up;442 mdev = &mbox->dev[0];443 hdr = mdev->mbase + mbox->rx_start;444 if (hdr->num_msgs)445 /* Schedule work queue function to process the MBOX request */446 queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work);447 /* Clear and ack the interrupt */448 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,449 0x1ULL);450 }451 return IRQ_HANDLED;452}453 454static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,455 struct mbox_msghdr *msg)456{457 struct otx2_cptlfs_info *lfs = &cptpf->lfs;458 struct device *dev = &cptpf->pdev->dev;459 struct cpt_rd_wr_reg_msg *rsp_rd_wr;460 struct msix_offset_rsp *rsp_msix;461 int i;462 463 if (msg->id >= MBOX_MSG_MAX) {464 dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);465 return;466 }467 if (msg->sig != OTX2_MBOX_RSP_SIG) {468 dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",469 msg->sig, msg->id);470 return;471 }472 if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1)473 lfs = &cptpf->cpt1_lfs;474 475 switch (msg->id) {476 case MBOX_MSG_READY:477 cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) &478 RVU_PFVF_PF_MASK;479 break;480 case MBOX_MSG_MSIX_OFFSET:481 rsp_msix = (struct msix_offset_rsp *) msg;482 for (i = 0; i < rsp_msix->cptlfs; i++)483 lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i];484 485 for (i = 0; i < rsp_msix->cpt1_lfs; i++)486 lfs->lf[i].msix_offset = rsp_msix->cpt1_lf_msixoff[i];487 break;488 case MBOX_MSG_CPT_RD_WR_REGISTER:489 rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;490 if (msg->rc) {491 dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",492 rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,493 msg->rc);494 return;495 }496 if (!rsp_rd_wr->is_write)497 *rsp_rd_wr->ret_val = rsp_rd_wr->val;498 break;499 case MBOX_MSG_ATTACH_RESOURCES:500 if (!msg->rc)501 lfs->are_lfs_attached = 1;502 break;503 case MBOX_MSG_DETACH_RESOURCES:504 if (!msg->rc)505 lfs->are_lfs_attached = 0;506 break;507 case MBOX_MSG_CPT_INLINE_IPSEC_CFG:508 case MBOX_MSG_NIX_INLINE_IPSEC_CFG:509 case MBOX_MSG_CPT_LF_RESET:510 break;511 512 default:513 dev_err(dev,514 "Unsupported msg %d received.\n", msg->id);515 break;516 }517}518 519static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,520 int vf_id, int size)521{522 struct otx2_mbox *vfpf_mbox;523 struct mbox_msghdr *fwd;524 525 if (msg->id >= MBOX_MSG_MAX) {526 dev_err(&cptpf->pdev->dev,527 "MBOX msg with unknown ID %d\n", msg->id);528 return;529 }530 if (msg->sig != OTX2_MBOX_RSP_SIG) {531 dev_err(&cptpf->pdev->dev,532 "MBOX msg with wrong signature %x, ID %d\n",533 msg->sig, msg->id);534 return;535 }536 vfpf_mbox = &cptpf->vfpf_mbox;537 vf_id--;538 if (vf_id >= cptpf->enabled_vfs) {539 dev_err(&cptpf->pdev->dev,540 "MBOX msg to unknown VF: %d >= %d\n",541 vf_id, cptpf->enabled_vfs);542 return;543 }544 if (msg->id == MBOX_MSG_VF_FLR)545 return;546 547 fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);548 if (!fwd) {549 dev_err(&cptpf->pdev->dev,550 "Forwarding to VF%d failed.\n", vf_id);551 return;552 }553 memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),554 (uint8_t *)msg + sizeof(struct mbox_msghdr), size);555 fwd->id = msg->id;556 fwd->pcifunc = msg->pcifunc;557 fwd->sig = msg->sig;558 fwd->ver = msg->ver;559 fwd->rc = msg->rc;560}561 562/* Handle mailbox messages received from AF */563void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)564{565 struct otx2_cptpf_dev *cptpf;566 struct otx2_mbox *afpf_mbox;567 struct otx2_mbox_dev *mdev;568 struct mbox_hdr *rsp_hdr;569 struct mbox_msghdr *msg;570 int offset, vf_id, i;571 572 cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);573 afpf_mbox = &cptpf->afpf_mbox;574 mdev = &afpf_mbox->dev[0];575 /* Sync mbox data into memory */576 smp_wmb();577 578 rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);579 offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);580 581 for (i = 0; i < rsp_hdr->num_msgs; i++) {582 msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +583 offset);584 vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &585 RVU_PFVF_FUNC_MASK;586 if (vf_id > 0)587 forward_to_vf(cptpf, msg, vf_id,588 msg->next_msgoff - offset);589 else590 process_afpf_mbox_msg(cptpf, msg);591 592 offset = msg->next_msgoff;593 /* Sync VF response ready to be sent */594 smp_wmb();595 mdev->msgs_acked++;596 }597 otx2_mbox_reset(afpf_mbox, 0);598}599 600static void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf,601 struct mbox_msghdr *msg)602{603 struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg;604 struct otx2_cptlfs_info *lfs = &cptpf->lfs;605 struct msg_rsp *rsp;606 607 if (cptpf->lfs.lfs_num)608 lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1,609 &lfs->lf[0]);610 611 rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0,612 sizeof(*rsp));613 if (!rsp)614 return;615 616 rsp->hdr.id = msg->id;617 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;618 rsp->hdr.pcifunc = 0;619 rsp->hdr.rc = 0;620}621 622static void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf,623 struct mbox_msghdr *msg)624{625 if (msg->id >= MBOX_MSG_MAX) {626 dev_err(&cptpf->pdev->dev,627 "MBOX msg with unknown ID %d\n", msg->id);628 return;629 }630 631 switch (msg->id) {632 case MBOX_MSG_CPT_INST_LMTST:633 handle_msg_cpt_inst_lmtst(cptpf, msg);634 break;635 default:636 otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id);637 }638}639 640void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work)641{642 struct otx2_cptpf_dev *cptpf;643 struct otx2_mbox_dev *mdev;644 struct mbox_hdr *rsp_hdr;645 struct mbox_msghdr *msg;646 struct otx2_mbox *mbox;647 int offset, i;648 649 cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work);650 mbox = &cptpf->afpf_mbox_up;651 mdev = &mbox->dev[0];652 /* Sync mbox data into memory */653 smp_wmb();654 655 rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);656 offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);657 658 for (i = 0; i < rsp_hdr->num_msgs; i++) {659 msg = (struct mbox_msghdr *)(mdev->mbase + offset);660 661 process_afpf_mbox_up_msg(cptpf, msg);662 663 offset = mbox->rx_start + msg->next_msgoff;664 }665 otx2_mbox_msg_send(mbox, 0);666}667