Path: blob/master/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
26285 views
// SPDX-License-Identifier: GPL-2.0-only1/* Copyright (C) 2020 Marvell. */23#include "otx2_cpt_common.h"4#include "otx2_cptpf.h"5#include "rvu_reg.h"67/* Fastpath ipsec opcode with inplace processing */8#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6))9#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6))1011#define cpt_inline_rx_opcode(pdev) \12({ \13u8 opcode; \14if (is_dev_otx2(pdev)) \15opcode = CPT_INLINE_RX_OPCODE; \16else \17opcode = CN10K_CPT_INLINE_RX_OPCODE; \18(opcode); \19})2021/*22* CPT PF driver version, It will be incremented by 1 for every feature23* addition in CPT mailbox messages.24*/25#define OTX2_CPT_PF_DRV_VERSION 0x12627static int forward_to_af(struct otx2_cptpf_dev *cptpf,28struct otx2_cptvf_info *vf,29struct mbox_msghdr *req, int size)30{31struct mbox_msghdr *msg;32int ret;3334mutex_lock(&cptpf->lock);35msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);36if (msg == NULL) {37mutex_unlock(&cptpf->lock);38return -ENOMEM;39}4041memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),42(uint8_t *)req + sizeof(struct mbox_msghdr), size);43msg->id = req->id;44msg->pcifunc = req->pcifunc;45msg->sig = req->sig;46msg->ver = req->ver;4748ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);49/* Error code -EIO indicate there is a communication failure50* to the AF. Rest of the error codes indicate that AF processed51* VF messages and set the error codes in response messages52* (if any) so simply forward responses to VF.53*/54if (ret == -EIO) {55dev_warn(&cptpf->pdev->dev,56"AF not responding to VF%d messages\n", vf->vf_id);57mutex_unlock(&cptpf->lock);58return ret;59}60mutex_unlock(&cptpf->lock);61return 0;62}6364static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,65struct otx2_cptvf_info *vf,66struct mbox_msghdr *req)67{68struct otx2_cpt_caps_rsp *rsp;6970rsp = (struct otx2_cpt_caps_rsp *)71otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,72sizeof(*rsp));73if (!rsp)74return -ENOMEM;7576rsp->hdr.id = MBOX_MSG_GET_CAPS;77rsp->hdr.sig = OTX2_MBOX_RSP_SIG;78rsp->hdr.pcifunc = req->pcifunc;79rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;80rsp->cpt_revision = cptpf->eng_grps.rid;81memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));8283return 0;84}8586static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,87struct otx2_cptvf_info *vf,88struct mbox_msghdr *req)89{90struct otx2_cpt_egrp_num_msg *grp_req;91struct otx2_cpt_egrp_num_rsp *rsp;9293grp_req = (struct otx2_cpt_egrp_num_msg *)req;94rsp = (struct otx2_cpt_egrp_num_rsp *)95otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));96if (!rsp)97return -ENOMEM;9899rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;100rsp->hdr.sig = OTX2_MBOX_RSP_SIG;101rsp->hdr.pcifunc = req->pcifunc;102rsp->eng_type = grp_req->eng_type;103rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,104grp_req->eng_type);105106return 0;107}108109static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,110struct otx2_cptvf_info *vf,111struct mbox_msghdr *req)112{113struct otx2_cpt_kvf_limits_rsp *rsp;114115rsp = (struct otx2_cpt_kvf_limits_rsp *)116otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));117if (!rsp)118return -ENOMEM;119120rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;121rsp->hdr.sig = OTX2_MBOX_RSP_SIG;122rsp->hdr.pcifunc = req->pcifunc;123rsp->kvf_limits = cptpf->kvf_limits;124125return 0;126}127128static int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf,129int sso_pf_func, u8 slot)130{131struct cpt_inline_ipsec_cfg_msg *req;132struct pci_dev *pdev = cptpf->pdev;133134req = (struct cpt_inline_ipsec_cfg_msg *)135otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,136sizeof(*req), sizeof(struct msg_rsp));137if (req == NULL) {138dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");139return -EFAULT;140}141memset(req, 0, sizeof(*req));142req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG;143req->hdr.sig = OTX2_MBOX_REQ_SIG;144req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pdev, cptpf->pf_id, 0);145req->dir = CPT_INLINE_INBOUND;146req->slot = slot;147req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd;148req->sso_pf_func = sso_pf_func;149req->enable = 1;150151return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);152}153154static int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp,155struct otx2_cpt_rx_inline_lf_cfg *req)156{157struct nix_inline_ipsec_cfg *nix_req;158struct pci_dev *pdev = cptpf->pdev;159int ret;160161nix_req = (struct nix_inline_ipsec_cfg *)162otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0,163sizeof(*nix_req),164sizeof(struct msg_rsp));165if (nix_req == NULL) {166dev_err(&pdev->dev, "RVU MBOX failed to get message.\n");167return -EFAULT;168}169memset(nix_req, 0, sizeof(*nix_req));170nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG;171nix_req->hdr.sig = OTX2_MBOX_REQ_SIG;172nix_req->enable = 1;173nix_req->credit_th = req->credit_th;174nix_req->bpid = req->bpid;175if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS)176nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1;177else178nix_req->cpt_credit = req->credit - 1;179nix_req->gen_cfg.egrp = egrp;180if (req->opcode)181nix_req->gen_cfg.opcode = req->opcode;182else183nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev);184nix_req->gen_cfg.param1 = req->param1;185nix_req->gen_cfg.param2 = req->param2;186nix_req->inst_qsel.cpt_pf_func =187OTX2_CPT_RVU_PFFUNC(cptpf->pdev, cptpf->pf_id, 0);188nix_req->inst_qsel.cpt_slot = 0;189ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev);190if (ret)191return ret;192193if (cptpf->has_cpt1) {194ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1);195if (ret)196return ret;197}198199return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0);200}201202int203otx2_inline_cptlf_setup(struct otx2_cptpf_dev *cptpf,204struct otx2_cptlfs_info *lfs, u8 egrp, int num_lfs)205{206int ret;207208ret = otx2_cptlf_init(lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO, 1);209if (ret) {210dev_err(&cptpf->pdev->dev,211"LF configuration failed for RX inline ipsec.\n");212return ret;213}214215/* Get msix offsets for attached LFs */216ret = otx2_cpt_msix_offset_msg(lfs);217if (ret)218goto cleanup_lf;219220/* Register for CPT LF Misc interrupts */221ret = otx2_cptlf_register_misc_interrupts(lfs);222if (ret)223goto free_irq;224225return 0;226free_irq:227otx2_cptlf_unregister_misc_interrupts(lfs);228cleanup_lf:229otx2_cptlf_shutdown(lfs);230return ret;231}232233void234otx2_inline_cptlf_cleanup(struct otx2_cptlfs_info *lfs)235{236/* Unregister misc interrupt */237otx2_cptlf_unregister_misc_interrupts(lfs);238239/* Cleanup LFs */240otx2_cptlf_shutdown(lfs);241}242243static int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf,244struct mbox_msghdr *req)245{246struct otx2_cpt_rx_inline_lf_cfg *cfg_req;247int num_lfs = 1, ret;248u8 egrp;249250cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req;251if (cptpf->lfs.lfs_num) {252dev_err(&cptpf->pdev->dev,253"LF is already configured for RX inline ipsec.\n");254return -EEXIST;255}256/*257* Allow LFs to execute requests destined to only grp IE_TYPES and258* set queue priority of each LF to high259*/260egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES);261if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) {262dev_err(&cptpf->pdev->dev,263"Engine group for inline ipsec is not available\n");264return -ENOENT;265}266267cptpf->lfs.global_slot = 0;268cptpf->lfs.ctx_ilen_ovrd = cfg_req->ctx_ilen_valid;269cptpf->lfs.ctx_ilen = cfg_req->ctx_ilen;270271ret = otx2_inline_cptlf_setup(cptpf, &cptpf->lfs, egrp, num_lfs);272if (ret) {273dev_err(&cptpf->pdev->dev, "Inline-Ipsec CPT0 LF setup failed.\n");274return ret;275}276277if (cptpf->has_cpt1) {278cptpf->rsrc_req_blkaddr = BLKADDR_CPT1;279cptpf->cpt1_lfs.global_slot = num_lfs;280cptpf->cpt1_lfs.ctx_ilen_ovrd = cfg_req->ctx_ilen_valid;281cptpf->cpt1_lfs.ctx_ilen = cfg_req->ctx_ilen;282ret = otx2_inline_cptlf_setup(cptpf, &cptpf->cpt1_lfs, egrp,283num_lfs);284if (ret) {285dev_err(&cptpf->pdev->dev, "Inline CPT1 LF setup failed.\n");286goto lf_cleanup;287}288cptpf->rsrc_req_blkaddr = 0;289}290291ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req);292if (ret)293goto lf1_cleanup;294295return 0;296297lf1_cleanup:298otx2_inline_cptlf_cleanup(&cptpf->cpt1_lfs);299lf_cleanup:300otx2_inline_cptlf_cleanup(&cptpf->lfs);301return ret;302}303304static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,305struct otx2_cptvf_info *vf,306struct mbox_msghdr *req, int size)307{308int err = 0;309310/* Check if msg is valid, if not reply with an invalid msg */311if (req->sig != OTX2_MBOX_REQ_SIG)312goto inval_msg;313314switch (req->id) {315case MBOX_MSG_GET_ENG_GRP_NUM:316err = handle_msg_get_eng_grp_num(cptpf, vf, req);317break;318case MBOX_MSG_GET_CAPS:319err = handle_msg_get_caps(cptpf, vf, req);320break;321case MBOX_MSG_GET_KVF_LIMITS:322err = handle_msg_kvf_limits(cptpf, vf, req);323break;324case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG:325err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req);326break;327328default:329err = forward_to_af(cptpf, vf, req, size);330break;331}332return err;333334inval_msg:335otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);336otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);337return err;338}339340irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)341{342struct otx2_cptpf_dev *cptpf = arg;343struct otx2_cptvf_info *vf;344int i, vf_idx;345u64 intr;346347/*348* Check which VF has raised an interrupt and schedule349* corresponding work queue to process the messages350*/351for (i = 0; i < 2; i++) {352/* Read the interrupt bits */353intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,354RVU_PF_VFPF_MBOX_INTX(i));355356for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {357vf = &cptpf->vf[vf_idx];358if (intr & (1ULL << vf->intr_idx)) {359queue_work(cptpf->vfpf_mbox_wq,360&vf->vfpf_mbox_work);361/* Clear the interrupt */362otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,3630, RVU_PF_VFPF_MBOX_INTX(i),364BIT_ULL(vf->intr_idx));365}366}367}368return IRQ_HANDLED;369}370371void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)372{373struct otx2_cptpf_dev *cptpf;374struct otx2_cptvf_info *vf;375struct otx2_mbox_dev *mdev;376struct mbox_hdr *req_hdr;377struct mbox_msghdr *msg;378struct otx2_mbox *mbox;379int offset, i, err;380381vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);382cptpf = vf->cptpf;383mbox = &cptpf->vfpf_mbox;384/* sync with mbox memory region */385smp_rmb();386mdev = &mbox->dev[vf->vf_id];387/* Process received mbox messages */388req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);389offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);390391for (i = 0; i < req_hdr->num_msgs; i++) {392msg = (struct mbox_msghdr *)(mdev->mbase + offset);393394/* Set which VF sent this message based on mbox IRQ */395msg->pcifunc = rvu_make_pcifunc(cptpf->pdev, cptpf->pf_id,396(vf->vf_id + 1));397err = cptpf_handle_vf_req(cptpf, vf, msg,398msg->next_msgoff - offset);399/*400* Behave as the AF, drop the msg if there is401* no memory, timeout handling also goes here402*/403if (err == -ENOMEM || err == -EIO)404break;405offset = msg->next_msgoff;406/* Write barrier required for VF responses which are handled by407* PF driver and not forwarded to AF.408*/409smp_wmb();410}411/* Send mbox responses to VF */412if (mdev->num_msgs)413otx2_mbox_msg_send(mbox, vf->vf_id);414}415416irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)417{418struct otx2_cptpf_dev *cptpf = arg;419struct otx2_mbox_dev *mdev;420struct otx2_mbox *mbox;421struct mbox_hdr *hdr;422u64 intr;423424/* Read the interrupt bits */425intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);426427if (intr & 0x1ULL) {428mbox = &cptpf->afpf_mbox;429mdev = &mbox->dev[0];430hdr = mdev->mbase + mbox->rx_start;431if (hdr->num_msgs)432/* Schedule work queue function to process the MBOX request */433queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);434435mbox = &cptpf->afpf_mbox_up;436mdev = &mbox->dev[0];437hdr = mdev->mbase + mbox->rx_start;438if (hdr->num_msgs)439/* Schedule work queue function to process the MBOX request */440queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work);441/* Clear and ack the interrupt */442otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,4430x1ULL);444}445return IRQ_HANDLED;446}447448static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,449struct mbox_msghdr *msg)450{451struct otx2_cptlfs_info *lfs = &cptpf->lfs;452struct device *dev = &cptpf->pdev->dev;453struct cpt_rd_wr_reg_msg *rsp_rd_wr;454struct msix_offset_rsp *rsp_msix;455int i;456457if (msg->id >= MBOX_MSG_MAX) {458dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);459return;460}461if (msg->sig != OTX2_MBOX_RSP_SIG) {462dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",463msg->sig, msg->id);464return;465}466if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1)467lfs = &cptpf->cpt1_lfs;468469switch (msg->id) {470case MBOX_MSG_READY:471cptpf->pf_id = rvu_get_pf(cptpf->pdev, msg->pcifunc);472break;473case MBOX_MSG_MSIX_OFFSET:474rsp_msix = (struct msix_offset_rsp *) msg;475for (i = 0; i < rsp_msix->cptlfs; i++)476lfs->lf[i].msix_offset = rsp_msix->cptlf_msixoff[i];477478for (i = 0; i < rsp_msix->cpt1_lfs; i++)479lfs->lf[i].msix_offset = rsp_msix->cpt1_lf_msixoff[i];480break;481case MBOX_MSG_CPT_RD_WR_REGISTER:482rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;483if (msg->rc) {484dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",485rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,486msg->rc);487return;488}489if (!rsp_rd_wr->is_write)490*rsp_rd_wr->ret_val = rsp_rd_wr->val;491break;492case MBOX_MSG_ATTACH_RESOURCES:493if (!msg->rc)494lfs->are_lfs_attached = 1;495break;496case MBOX_MSG_DETACH_RESOURCES:497if (!msg->rc)498lfs->are_lfs_attached = 0;499break;500case MBOX_MSG_CPT_INLINE_IPSEC_CFG:501case MBOX_MSG_NIX_INLINE_IPSEC_CFG:502case MBOX_MSG_CPT_LF_RESET:503case MBOX_MSG_LMTST_TBL_SETUP:504break;505506default:507dev_err(dev,508"Unsupported msg %d received.\n", msg->id);509break;510}511}512513static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,514int vf_id, int size)515{516struct otx2_mbox *vfpf_mbox;517struct mbox_msghdr *fwd;518519if (msg->id >= MBOX_MSG_MAX) {520dev_err(&cptpf->pdev->dev,521"MBOX msg with unknown ID %d\n", msg->id);522return;523}524if (msg->sig != OTX2_MBOX_RSP_SIG) {525dev_err(&cptpf->pdev->dev,526"MBOX msg with wrong signature %x, ID %d\n",527msg->sig, msg->id);528return;529}530vfpf_mbox = &cptpf->vfpf_mbox;531vf_id--;532if (vf_id >= cptpf->enabled_vfs) {533dev_err(&cptpf->pdev->dev,534"MBOX msg to unknown VF: %d >= %d\n",535vf_id, cptpf->enabled_vfs);536return;537}538if (msg->id == MBOX_MSG_VF_FLR)539return;540541fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);542if (!fwd) {543dev_err(&cptpf->pdev->dev,544"Forwarding to VF%d failed.\n", vf_id);545return;546}547memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),548(uint8_t *)msg + sizeof(struct mbox_msghdr), size);549fwd->id = msg->id;550fwd->pcifunc = msg->pcifunc;551fwd->sig = msg->sig;552fwd->ver = msg->ver;553fwd->rc = msg->rc;554}555556/* Handle mailbox messages received from AF */557void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)558{559struct otx2_cptpf_dev *cptpf;560struct otx2_mbox *afpf_mbox;561struct otx2_mbox_dev *mdev;562struct mbox_hdr *rsp_hdr;563struct mbox_msghdr *msg;564int offset, vf_id, i;565566cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);567afpf_mbox = &cptpf->afpf_mbox;568mdev = &afpf_mbox->dev[0];569/* Sync mbox data into memory */570smp_wmb();571572rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);573offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);574575for (i = 0; i < rsp_hdr->num_msgs; i++) {576msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +577offset);578vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &579RVU_PFVF_FUNC_MASK;580if (vf_id > 0)581forward_to_vf(cptpf, msg, vf_id,582msg->next_msgoff - offset);583else584process_afpf_mbox_msg(cptpf, msg);585586offset = msg->next_msgoff;587/* Sync VF response ready to be sent */588smp_wmb();589mdev->msgs_acked++;590}591otx2_mbox_reset(afpf_mbox, 0);592}593594static void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf,595struct mbox_msghdr *msg)596{597struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg;598struct otx2_cptlfs_info *lfs = &cptpf->lfs;599struct msg_rsp *rsp;600601if (cptpf->lfs.lfs_num)602lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1,603&lfs->lf[0]);604605rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0,606sizeof(*rsp));607if (!rsp)608return;609610rsp->hdr.id = msg->id;611rsp->hdr.sig = OTX2_MBOX_RSP_SIG;612rsp->hdr.pcifunc = 0;613rsp->hdr.rc = 0;614}615616static void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf,617struct mbox_msghdr *msg)618{619if (msg->id >= MBOX_MSG_MAX) {620dev_err(&cptpf->pdev->dev,621"MBOX msg with unknown ID %d\n", msg->id);622return;623}624625switch (msg->id) {626case MBOX_MSG_CPT_INST_LMTST:627handle_msg_cpt_inst_lmtst(cptpf, msg);628break;629default:630otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id);631}632}633634void otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work)635{636struct otx2_cptpf_dev *cptpf;637struct otx2_mbox_dev *mdev;638struct mbox_hdr *rsp_hdr;639struct mbox_msghdr *msg;640struct otx2_mbox *mbox;641int offset, i;642643cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work);644mbox = &cptpf->afpf_mbox_up;645mdev = &mbox->dev[0];646/* Sync mbox data into memory */647smp_wmb();648649rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);650offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);651652for (i = 0; i < rsp_hdr->num_msgs; i++) {653msg = (struct mbox_msghdr *)(mdev->mbase + offset);654655process_afpf_mbox_up_msg(cptpf, msg);656657offset = mbox->rx_start + msg->next_msgoff;658}659otx2_mbox_msg_send(mbox, 0);660}661662663