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_cptpf.h" 662306a36Sopenharmony_ci#include "rvu_reg.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* Fastpath ipsec opcode with inplace processing */ 962306a36Sopenharmony_ci#define CPT_INLINE_RX_OPCODE (0x26 | (1 << 6)) 1062306a36Sopenharmony_ci#define CN10K_CPT_INLINE_RX_OPCODE (0x29 | (1 << 6)) 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define cpt_inline_rx_opcode(pdev) \ 1362306a36Sopenharmony_ci({ \ 1462306a36Sopenharmony_ci u8 opcode; \ 1562306a36Sopenharmony_ci if (is_dev_otx2(pdev)) \ 1662306a36Sopenharmony_ci opcode = CPT_INLINE_RX_OPCODE; \ 1762306a36Sopenharmony_ci else \ 1862306a36Sopenharmony_ci opcode = CN10K_CPT_INLINE_RX_OPCODE; \ 1962306a36Sopenharmony_ci (opcode); \ 2062306a36Sopenharmony_ci}) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * CPT PF driver version, It will be incremented by 1 for every feature 2462306a36Sopenharmony_ci * addition in CPT mailbox messages. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#define OTX2_CPT_PF_DRV_VERSION 0x1 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic int forward_to_af(struct otx2_cptpf_dev *cptpf, 2962306a36Sopenharmony_ci struct otx2_cptvf_info *vf, 3062306a36Sopenharmony_ci struct mbox_msghdr *req, int size) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct mbox_msghdr *msg; 3362306a36Sopenharmony_ci int ret; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci mutex_lock(&cptpf->lock); 3662306a36Sopenharmony_ci msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size); 3762306a36Sopenharmony_ci if (msg == NULL) { 3862306a36Sopenharmony_ci mutex_unlock(&cptpf->lock); 3962306a36Sopenharmony_ci return -ENOMEM; 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr), 4362306a36Sopenharmony_ci (uint8_t *)req + sizeof(struct mbox_msghdr), size); 4462306a36Sopenharmony_ci msg->id = req->id; 4562306a36Sopenharmony_ci msg->pcifunc = req->pcifunc; 4662306a36Sopenharmony_ci msg->sig = req->sig; 4762306a36Sopenharmony_ci msg->ver = req->ver; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox); 5062306a36Sopenharmony_ci /* Error code -EIO indicate there is a communication failure 5162306a36Sopenharmony_ci * to the AF. Rest of the error codes indicate that AF processed 5262306a36Sopenharmony_ci * VF messages and set the error codes in response messages 5362306a36Sopenharmony_ci * (if any) so simply forward responses to VF. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci if (ret == -EIO) { 5662306a36Sopenharmony_ci dev_warn(&cptpf->pdev->dev, 5762306a36Sopenharmony_ci "AF not responding to VF%d messages\n", vf->vf_id); 5862306a36Sopenharmony_ci mutex_unlock(&cptpf->lock); 5962306a36Sopenharmony_ci return ret; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci mutex_unlock(&cptpf->lock); 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf, 6662306a36Sopenharmony_ci struct otx2_cptvf_info *vf, 6762306a36Sopenharmony_ci struct mbox_msghdr *req) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct otx2_cpt_caps_rsp *rsp; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci rsp = (struct otx2_cpt_caps_rsp *) 7262306a36Sopenharmony_ci otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, 7362306a36Sopenharmony_ci sizeof(*rsp)); 7462306a36Sopenharmony_ci if (!rsp) 7562306a36Sopenharmony_ci return -ENOMEM; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci rsp->hdr.id = MBOX_MSG_GET_CAPS; 7862306a36Sopenharmony_ci rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 7962306a36Sopenharmony_ci rsp->hdr.pcifunc = req->pcifunc; 8062306a36Sopenharmony_ci rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION; 8162306a36Sopenharmony_ci rsp->cpt_revision = cptpf->pdev->revision; 8262306a36Sopenharmony_ci memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps)); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf, 8862306a36Sopenharmony_ci struct otx2_cptvf_info *vf, 8962306a36Sopenharmony_ci struct mbox_msghdr *req) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct otx2_cpt_egrp_num_msg *grp_req; 9262306a36Sopenharmony_ci struct otx2_cpt_egrp_num_rsp *rsp; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci grp_req = (struct otx2_cpt_egrp_num_msg *)req; 9562306a36Sopenharmony_ci rsp = (struct otx2_cpt_egrp_num_rsp *) 9662306a36Sopenharmony_ci otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp)); 9762306a36Sopenharmony_ci if (!rsp) 9862306a36Sopenharmony_ci return -ENOMEM; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM; 10162306a36Sopenharmony_ci rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 10262306a36Sopenharmony_ci rsp->hdr.pcifunc = req->pcifunc; 10362306a36Sopenharmony_ci rsp->eng_type = grp_req->eng_type; 10462306a36Sopenharmony_ci rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps, 10562306a36Sopenharmony_ci grp_req->eng_type); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf, 11162306a36Sopenharmony_ci struct otx2_cptvf_info *vf, 11262306a36Sopenharmony_ci struct mbox_msghdr *req) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct otx2_cpt_kvf_limits_rsp *rsp; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci rsp = (struct otx2_cpt_kvf_limits_rsp *) 11762306a36Sopenharmony_ci otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp)); 11862306a36Sopenharmony_ci if (!rsp) 11962306a36Sopenharmony_ci return -ENOMEM; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS; 12262306a36Sopenharmony_ci rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 12362306a36Sopenharmony_ci rsp->hdr.pcifunc = req->pcifunc; 12462306a36Sopenharmony_ci rsp->kvf_limits = cptpf->kvf_limits; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic int send_inline_ipsec_inbound_msg(struct otx2_cptpf_dev *cptpf, 13062306a36Sopenharmony_ci int sso_pf_func, u8 slot) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct cpt_inline_ipsec_cfg_msg *req; 13362306a36Sopenharmony_ci struct pci_dev *pdev = cptpf->pdev; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci req = (struct cpt_inline_ipsec_cfg_msg *) 13662306a36Sopenharmony_ci otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0, 13762306a36Sopenharmony_ci sizeof(*req), sizeof(struct msg_rsp)); 13862306a36Sopenharmony_ci if (req == NULL) { 13962306a36Sopenharmony_ci dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); 14062306a36Sopenharmony_ci return -EFAULT; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci memset(req, 0, sizeof(*req)); 14362306a36Sopenharmony_ci req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG; 14462306a36Sopenharmony_ci req->hdr.sig = OTX2_MBOX_REQ_SIG; 14562306a36Sopenharmony_ci req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); 14662306a36Sopenharmony_ci req->dir = CPT_INLINE_INBOUND; 14762306a36Sopenharmony_ci req->slot = slot; 14862306a36Sopenharmony_ci req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd; 14962306a36Sopenharmony_ci req->sso_pf_func = sso_pf_func; 15062306a36Sopenharmony_ci req->enable = 1; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic int rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, u8 egrp, 15662306a36Sopenharmony_ci struct otx2_cpt_rx_inline_lf_cfg *req) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct nix_inline_ipsec_cfg *nix_req; 15962306a36Sopenharmony_ci struct pci_dev *pdev = cptpf->pdev; 16062306a36Sopenharmony_ci int ret; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci nix_req = (struct nix_inline_ipsec_cfg *) 16362306a36Sopenharmony_ci otx2_mbox_alloc_msg_rsp(&cptpf->afpf_mbox, 0, 16462306a36Sopenharmony_ci sizeof(*nix_req), 16562306a36Sopenharmony_ci sizeof(struct msg_rsp)); 16662306a36Sopenharmony_ci if (nix_req == NULL) { 16762306a36Sopenharmony_ci dev_err(&pdev->dev, "RVU MBOX failed to get message.\n"); 16862306a36Sopenharmony_ci return -EFAULT; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci memset(nix_req, 0, sizeof(*nix_req)); 17162306a36Sopenharmony_ci nix_req->hdr.id = MBOX_MSG_NIX_INLINE_IPSEC_CFG; 17262306a36Sopenharmony_ci nix_req->hdr.sig = OTX2_MBOX_REQ_SIG; 17362306a36Sopenharmony_ci nix_req->enable = 1; 17462306a36Sopenharmony_ci if (!req->credit || req->credit > OTX2_CPT_INST_QLEN_MSGS) 17562306a36Sopenharmony_ci nix_req->cpt_credit = OTX2_CPT_INST_QLEN_MSGS - 1; 17662306a36Sopenharmony_ci else 17762306a36Sopenharmony_ci nix_req->cpt_credit = req->credit - 1; 17862306a36Sopenharmony_ci nix_req->gen_cfg.egrp = egrp; 17962306a36Sopenharmony_ci if (req->opcode) 18062306a36Sopenharmony_ci nix_req->gen_cfg.opcode = req->opcode; 18162306a36Sopenharmony_ci else 18262306a36Sopenharmony_ci nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev); 18362306a36Sopenharmony_ci nix_req->gen_cfg.param1 = req->param1; 18462306a36Sopenharmony_ci nix_req->gen_cfg.param2 = req->param2; 18562306a36Sopenharmony_ci nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); 18662306a36Sopenharmony_ci nix_req->inst_qsel.cpt_slot = 0; 18762306a36Sopenharmony_ci ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); 18862306a36Sopenharmony_ci if (ret) 18962306a36Sopenharmony_ci return ret; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (cptpf->has_cpt1) { 19262306a36Sopenharmony_ci ret = send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 1); 19362306a36Sopenharmony_ci if (ret) 19462306a36Sopenharmony_ci return ret; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return send_inline_ipsec_inbound_msg(cptpf, req->sso_pf_func, 0); 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int handle_msg_rx_inline_ipsec_lf_cfg(struct otx2_cptpf_dev *cptpf, 20162306a36Sopenharmony_ci struct mbox_msghdr *req) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct otx2_cpt_rx_inline_lf_cfg *cfg_req; 20462306a36Sopenharmony_ci u8 egrp; 20562306a36Sopenharmony_ci int ret; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci cfg_req = (struct otx2_cpt_rx_inline_lf_cfg *)req; 20862306a36Sopenharmony_ci if (cptpf->lfs.lfs_num) { 20962306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 21062306a36Sopenharmony_ci "LF is already configured for RX inline ipsec.\n"); 21162306a36Sopenharmony_ci return -EEXIST; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci /* 21462306a36Sopenharmony_ci * Allow LFs to execute requests destined to only grp IE_TYPES and 21562306a36Sopenharmony_ci * set queue priority of each LF to high 21662306a36Sopenharmony_ci */ 21762306a36Sopenharmony_ci egrp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, OTX2_CPT_IE_TYPES); 21862306a36Sopenharmony_ci if (egrp == OTX2_CPT_INVALID_CRYPTO_ENG_GRP) { 21962306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 22062306a36Sopenharmony_ci "Engine group for inline ipsec is not available\n"); 22162306a36Sopenharmony_ci return -ENOENT; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci otx2_cptlf_set_dev_info(&cptpf->lfs, cptpf->pdev, cptpf->reg_base, 22562306a36Sopenharmony_ci &cptpf->afpf_mbox, BLKADDR_CPT0); 22662306a36Sopenharmony_ci ret = otx2_cptlf_init(&cptpf->lfs, 1 << egrp, OTX2_CPT_QUEUE_HI_PRIO, 22762306a36Sopenharmony_ci 1); 22862306a36Sopenharmony_ci if (ret) { 22962306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 23062306a36Sopenharmony_ci "LF configuration failed for RX inline ipsec.\n"); 23162306a36Sopenharmony_ci return ret; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (cptpf->has_cpt1) { 23562306a36Sopenharmony_ci cptpf->rsrc_req_blkaddr = BLKADDR_CPT1; 23662306a36Sopenharmony_ci otx2_cptlf_set_dev_info(&cptpf->cpt1_lfs, cptpf->pdev, 23762306a36Sopenharmony_ci cptpf->reg_base, &cptpf->afpf_mbox, 23862306a36Sopenharmony_ci BLKADDR_CPT1); 23962306a36Sopenharmony_ci ret = otx2_cptlf_init(&cptpf->cpt1_lfs, 1 << egrp, 24062306a36Sopenharmony_ci OTX2_CPT_QUEUE_HI_PRIO, 1); 24162306a36Sopenharmony_ci if (ret) { 24262306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 24362306a36Sopenharmony_ci "LF configuration failed for RX inline ipsec.\n"); 24462306a36Sopenharmony_ci goto lf_cleanup; 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci cptpf->rsrc_req_blkaddr = 0; 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci ret = rx_inline_ipsec_lf_cfg(cptpf, egrp, cfg_req); 25062306a36Sopenharmony_ci if (ret) 25162306a36Sopenharmony_ci goto lf1_cleanup; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci return 0; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cilf1_cleanup: 25662306a36Sopenharmony_ci otx2_cptlf_shutdown(&cptpf->cpt1_lfs); 25762306a36Sopenharmony_cilf_cleanup: 25862306a36Sopenharmony_ci otx2_cptlf_shutdown(&cptpf->lfs); 25962306a36Sopenharmony_ci return ret; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf, 26362306a36Sopenharmony_ci struct otx2_cptvf_info *vf, 26462306a36Sopenharmony_ci struct mbox_msghdr *req, int size) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci int err = 0; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* Check if msg is valid, if not reply with an invalid msg */ 26962306a36Sopenharmony_ci if (req->sig != OTX2_MBOX_REQ_SIG) 27062306a36Sopenharmony_ci goto inval_msg; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci switch (req->id) { 27362306a36Sopenharmony_ci case MBOX_MSG_GET_ENG_GRP_NUM: 27462306a36Sopenharmony_ci err = handle_msg_get_eng_grp_num(cptpf, vf, req); 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci case MBOX_MSG_GET_CAPS: 27762306a36Sopenharmony_ci err = handle_msg_get_caps(cptpf, vf, req); 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci case MBOX_MSG_GET_KVF_LIMITS: 28062306a36Sopenharmony_ci err = handle_msg_kvf_limits(cptpf, vf, req); 28162306a36Sopenharmony_ci break; 28262306a36Sopenharmony_ci case MBOX_MSG_RX_INLINE_IPSEC_LF_CFG: 28362306a36Sopenharmony_ci err = handle_msg_rx_inline_ipsec_lf_cfg(cptpf, req); 28462306a36Sopenharmony_ci break; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci default: 28762306a36Sopenharmony_ci err = forward_to_af(cptpf, vf, req, size); 28862306a36Sopenharmony_ci break; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci return err; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciinval_msg: 29362306a36Sopenharmony_ci otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id); 29462306a36Sopenharmony_ci otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id); 29562306a36Sopenharmony_ci return err; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ciirqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = arg; 30162306a36Sopenharmony_ci struct otx2_cptvf_info *vf; 30262306a36Sopenharmony_ci int i, vf_idx; 30362306a36Sopenharmony_ci u64 intr; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* 30662306a36Sopenharmony_ci * Check which VF has raised an interrupt and schedule 30762306a36Sopenharmony_ci * corresponding work queue to process the messages 30862306a36Sopenharmony_ci */ 30962306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 31062306a36Sopenharmony_ci /* Read the interrupt bits */ 31162306a36Sopenharmony_ci intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, 31262306a36Sopenharmony_ci RVU_PF_VFPF_MBOX_INTX(i)); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) { 31562306a36Sopenharmony_ci vf = &cptpf->vf[vf_idx]; 31662306a36Sopenharmony_ci if (intr & (1ULL << vf->intr_idx)) { 31762306a36Sopenharmony_ci queue_work(cptpf->vfpf_mbox_wq, 31862306a36Sopenharmony_ci &vf->vfpf_mbox_work); 31962306a36Sopenharmony_ci /* Clear the interrupt */ 32062306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 32162306a36Sopenharmony_ci 0, RVU_PF_VFPF_MBOX_INTX(i), 32262306a36Sopenharmony_ci BIT_ULL(vf->intr_idx)); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci return IRQ_HANDLED; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_civoid otx2_cptpf_vfpf_mbox_handler(struct work_struct *work) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf; 33262306a36Sopenharmony_ci struct otx2_cptvf_info *vf; 33362306a36Sopenharmony_ci struct otx2_mbox_dev *mdev; 33462306a36Sopenharmony_ci struct mbox_hdr *req_hdr; 33562306a36Sopenharmony_ci struct mbox_msghdr *msg; 33662306a36Sopenharmony_ci struct otx2_mbox *mbox; 33762306a36Sopenharmony_ci int offset, i, err; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work); 34062306a36Sopenharmony_ci cptpf = vf->cptpf; 34162306a36Sopenharmony_ci mbox = &cptpf->vfpf_mbox; 34262306a36Sopenharmony_ci /* sync with mbox memory region */ 34362306a36Sopenharmony_ci smp_rmb(); 34462306a36Sopenharmony_ci mdev = &mbox->dev[vf->vf_id]; 34562306a36Sopenharmony_ci /* Process received mbox messages */ 34662306a36Sopenharmony_ci req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); 34762306a36Sopenharmony_ci offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci for (i = 0; i < req_hdr->num_msgs; i++) { 35062306a36Sopenharmony_ci msg = (struct mbox_msghdr *)(mdev->mbase + offset); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* Set which VF sent this message based on mbox IRQ */ 35362306a36Sopenharmony_ci msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) | 35462306a36Sopenharmony_ci ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci err = cptpf_handle_vf_req(cptpf, vf, msg, 35762306a36Sopenharmony_ci msg->next_msgoff - offset); 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * Behave as the AF, drop the msg if there is 36062306a36Sopenharmony_ci * no memory, timeout handling also goes here 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci if (err == -ENOMEM || err == -EIO) 36362306a36Sopenharmony_ci break; 36462306a36Sopenharmony_ci offset = msg->next_msgoff; 36562306a36Sopenharmony_ci /* Write barrier required for VF responses which are handled by 36662306a36Sopenharmony_ci * PF driver and not forwarded to AF. 36762306a36Sopenharmony_ci */ 36862306a36Sopenharmony_ci smp_wmb(); 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci /* Send mbox responses to VF */ 37162306a36Sopenharmony_ci if (mdev->num_msgs) 37262306a36Sopenharmony_ci otx2_mbox_msg_send(mbox, vf->vf_id); 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ciirqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf = arg; 37862306a36Sopenharmony_ci struct otx2_mbox_dev *mdev; 37962306a36Sopenharmony_ci struct otx2_mbox *mbox; 38062306a36Sopenharmony_ci struct mbox_hdr *hdr; 38162306a36Sopenharmony_ci u64 intr; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* Read the interrupt bits */ 38462306a36Sopenharmony_ci intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (intr & 0x1ULL) { 38762306a36Sopenharmony_ci mbox = &cptpf->afpf_mbox; 38862306a36Sopenharmony_ci mdev = &mbox->dev[0]; 38962306a36Sopenharmony_ci hdr = mdev->mbase + mbox->rx_start; 39062306a36Sopenharmony_ci if (hdr->num_msgs) 39162306a36Sopenharmony_ci /* Schedule work queue function to process the MBOX request */ 39262306a36Sopenharmony_ci queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci mbox = &cptpf->afpf_mbox_up; 39562306a36Sopenharmony_ci mdev = &mbox->dev[0]; 39662306a36Sopenharmony_ci hdr = mdev->mbase + mbox->rx_start; 39762306a36Sopenharmony_ci if (hdr->num_msgs) 39862306a36Sopenharmony_ci /* Schedule work queue function to process the MBOX request */ 39962306a36Sopenharmony_ci queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_up_work); 40062306a36Sopenharmony_ci /* Clear and ack the interrupt */ 40162306a36Sopenharmony_ci otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT, 40262306a36Sopenharmony_ci 0x1ULL); 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci return IRQ_HANDLED; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf, 40862306a36Sopenharmony_ci struct mbox_msghdr *msg) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci struct otx2_cptlfs_info *lfs = &cptpf->lfs; 41162306a36Sopenharmony_ci struct device *dev = &cptpf->pdev->dev; 41262306a36Sopenharmony_ci struct cpt_rd_wr_reg_msg *rsp_rd_wr; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci if (msg->id >= MBOX_MSG_MAX) { 41562306a36Sopenharmony_ci dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id); 41662306a36Sopenharmony_ci return; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci if (msg->sig != OTX2_MBOX_RSP_SIG) { 41962306a36Sopenharmony_ci dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n", 42062306a36Sopenharmony_ci msg->sig, msg->id); 42162306a36Sopenharmony_ci return; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci if (cptpf->rsrc_req_blkaddr == BLKADDR_CPT1) 42462306a36Sopenharmony_ci lfs = &cptpf->cpt1_lfs; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci switch (msg->id) { 42762306a36Sopenharmony_ci case MBOX_MSG_READY: 42862306a36Sopenharmony_ci cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) & 42962306a36Sopenharmony_ci RVU_PFVF_PF_MASK; 43062306a36Sopenharmony_ci break; 43162306a36Sopenharmony_ci case MBOX_MSG_CPT_RD_WR_REGISTER: 43262306a36Sopenharmony_ci rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg; 43362306a36Sopenharmony_ci if (msg->rc) { 43462306a36Sopenharmony_ci dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n", 43562306a36Sopenharmony_ci rsp_rd_wr->reg_offset, rsp_rd_wr->is_write, 43662306a36Sopenharmony_ci msg->rc); 43762306a36Sopenharmony_ci return; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci if (!rsp_rd_wr->is_write) 44062306a36Sopenharmony_ci *rsp_rd_wr->ret_val = rsp_rd_wr->val; 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci case MBOX_MSG_ATTACH_RESOURCES: 44362306a36Sopenharmony_ci if (!msg->rc) 44462306a36Sopenharmony_ci lfs->are_lfs_attached = 1; 44562306a36Sopenharmony_ci break; 44662306a36Sopenharmony_ci case MBOX_MSG_DETACH_RESOURCES: 44762306a36Sopenharmony_ci if (!msg->rc) 44862306a36Sopenharmony_ci lfs->are_lfs_attached = 0; 44962306a36Sopenharmony_ci break; 45062306a36Sopenharmony_ci case MBOX_MSG_CPT_INLINE_IPSEC_CFG: 45162306a36Sopenharmony_ci case MBOX_MSG_NIX_INLINE_IPSEC_CFG: 45262306a36Sopenharmony_ci break; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci default: 45562306a36Sopenharmony_ci dev_err(dev, 45662306a36Sopenharmony_ci "Unsupported msg %d received.\n", msg->id); 45762306a36Sopenharmony_ci break; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg, 46262306a36Sopenharmony_ci int vf_id, int size) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci struct otx2_mbox *vfpf_mbox; 46562306a36Sopenharmony_ci struct mbox_msghdr *fwd; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (msg->id >= MBOX_MSG_MAX) { 46862306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 46962306a36Sopenharmony_ci "MBOX msg with unknown ID %d\n", msg->id); 47062306a36Sopenharmony_ci return; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci if (msg->sig != OTX2_MBOX_RSP_SIG) { 47362306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 47462306a36Sopenharmony_ci "MBOX msg with wrong signature %x, ID %d\n", 47562306a36Sopenharmony_ci msg->sig, msg->id); 47662306a36Sopenharmony_ci return; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci vfpf_mbox = &cptpf->vfpf_mbox; 47962306a36Sopenharmony_ci vf_id--; 48062306a36Sopenharmony_ci if (vf_id >= cptpf->enabled_vfs) { 48162306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 48262306a36Sopenharmony_ci "MBOX msg to unknown VF: %d >= %d\n", 48362306a36Sopenharmony_ci vf_id, cptpf->enabled_vfs); 48462306a36Sopenharmony_ci return; 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci if (msg->id == MBOX_MSG_VF_FLR) 48762306a36Sopenharmony_ci return; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size); 49062306a36Sopenharmony_ci if (!fwd) { 49162306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 49262306a36Sopenharmony_ci "Forwarding to VF%d failed.\n", vf_id); 49362306a36Sopenharmony_ci return; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr), 49662306a36Sopenharmony_ci (uint8_t *)msg + sizeof(struct mbox_msghdr), size); 49762306a36Sopenharmony_ci fwd->id = msg->id; 49862306a36Sopenharmony_ci fwd->pcifunc = msg->pcifunc; 49962306a36Sopenharmony_ci fwd->sig = msg->sig; 50062306a36Sopenharmony_ci fwd->ver = msg->ver; 50162306a36Sopenharmony_ci fwd->rc = msg->rc; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci/* Handle mailbox messages received from AF */ 50562306a36Sopenharmony_civoid otx2_cptpf_afpf_mbox_handler(struct work_struct *work) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf; 50862306a36Sopenharmony_ci struct otx2_mbox *afpf_mbox; 50962306a36Sopenharmony_ci struct otx2_mbox_dev *mdev; 51062306a36Sopenharmony_ci struct mbox_hdr *rsp_hdr; 51162306a36Sopenharmony_ci struct mbox_msghdr *msg; 51262306a36Sopenharmony_ci int offset, vf_id, i; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work); 51562306a36Sopenharmony_ci afpf_mbox = &cptpf->afpf_mbox; 51662306a36Sopenharmony_ci mdev = &afpf_mbox->dev[0]; 51762306a36Sopenharmony_ci /* Sync mbox data into memory */ 51862306a36Sopenharmony_ci smp_wmb(); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start); 52162306a36Sopenharmony_ci offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci for (i = 0; i < rsp_hdr->num_msgs; i++) { 52462306a36Sopenharmony_ci msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start + 52562306a36Sopenharmony_ci offset); 52662306a36Sopenharmony_ci vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) & 52762306a36Sopenharmony_ci RVU_PFVF_FUNC_MASK; 52862306a36Sopenharmony_ci if (vf_id > 0) 52962306a36Sopenharmony_ci forward_to_vf(cptpf, msg, vf_id, 53062306a36Sopenharmony_ci msg->next_msgoff - offset); 53162306a36Sopenharmony_ci else 53262306a36Sopenharmony_ci process_afpf_mbox_msg(cptpf, msg); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci offset = msg->next_msgoff; 53562306a36Sopenharmony_ci /* Sync VF response ready to be sent */ 53662306a36Sopenharmony_ci smp_wmb(); 53762306a36Sopenharmony_ci mdev->msgs_acked++; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci otx2_mbox_reset(afpf_mbox, 0); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic void handle_msg_cpt_inst_lmtst(struct otx2_cptpf_dev *cptpf, 54362306a36Sopenharmony_ci struct mbox_msghdr *msg) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci struct cpt_inst_lmtst_req *req = (struct cpt_inst_lmtst_req *)msg; 54662306a36Sopenharmony_ci struct otx2_cptlfs_info *lfs = &cptpf->lfs; 54762306a36Sopenharmony_ci struct msg_rsp *rsp; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci if (cptpf->lfs.lfs_num) 55062306a36Sopenharmony_ci lfs->ops->send_cmd((union otx2_cpt_inst_s *)req->inst, 1, 55162306a36Sopenharmony_ci &lfs->lf[0]); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci rsp = (struct msg_rsp *)otx2_mbox_alloc_msg(&cptpf->afpf_mbox_up, 0, 55462306a36Sopenharmony_ci sizeof(*rsp)); 55562306a36Sopenharmony_ci if (!rsp) 55662306a36Sopenharmony_ci return; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci rsp->hdr.id = msg->id; 55962306a36Sopenharmony_ci rsp->hdr.sig = OTX2_MBOX_RSP_SIG; 56062306a36Sopenharmony_ci rsp->hdr.pcifunc = 0; 56162306a36Sopenharmony_ci rsp->hdr.rc = 0; 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cistatic void process_afpf_mbox_up_msg(struct otx2_cptpf_dev *cptpf, 56562306a36Sopenharmony_ci struct mbox_msghdr *msg) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci if (msg->id >= MBOX_MSG_MAX) { 56862306a36Sopenharmony_ci dev_err(&cptpf->pdev->dev, 56962306a36Sopenharmony_ci "MBOX msg with unknown ID %d\n", msg->id); 57062306a36Sopenharmony_ci return; 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci switch (msg->id) { 57462306a36Sopenharmony_ci case MBOX_MSG_CPT_INST_LMTST: 57562306a36Sopenharmony_ci handle_msg_cpt_inst_lmtst(cptpf, msg); 57662306a36Sopenharmony_ci break; 57762306a36Sopenharmony_ci default: 57862306a36Sopenharmony_ci otx2_reply_invalid_msg(&cptpf->afpf_mbox_up, 0, 0, msg->id); 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_civoid otx2_cptpf_afpf_mbox_up_handler(struct work_struct *work) 58362306a36Sopenharmony_ci{ 58462306a36Sopenharmony_ci struct otx2_cptpf_dev *cptpf; 58562306a36Sopenharmony_ci struct otx2_mbox_dev *mdev; 58662306a36Sopenharmony_ci struct mbox_hdr *rsp_hdr; 58762306a36Sopenharmony_ci struct mbox_msghdr *msg; 58862306a36Sopenharmony_ci struct otx2_mbox *mbox; 58962306a36Sopenharmony_ci int offset, i; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_up_work); 59262306a36Sopenharmony_ci mbox = &cptpf->afpf_mbox_up; 59362306a36Sopenharmony_ci mdev = &mbox->dev[0]; 59462306a36Sopenharmony_ci /* Sync mbox data into memory */ 59562306a36Sopenharmony_ci smp_wmb(); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start); 59862306a36Sopenharmony_ci offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci for (i = 0; i < rsp_hdr->num_msgs; i++) { 60162306a36Sopenharmony_ci msg = (struct mbox_msghdr *)(mdev->mbase + offset); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci process_afpf_mbox_up_msg(cptpf, msg); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci offset = mbox->rx_start + msg->next_msgoff; 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci otx2_mbox_msg_send(mbox, 0); 60862306a36Sopenharmony_ci} 609