1ae454086SSrujana Challa // SPDX-License-Identifier: GPL-2.0-only 2ae454086SSrujana Challa /* Copyright (C) 2020 Marvell. */ 3ae454086SSrujana Challa 4ae454086SSrujana Challa #include <linux/pci.h> 5ae454086SSrujana Challa #include "rvu_struct.h" 6ae454086SSrujana Challa #include "rvu_reg.h" 7ae454086SSrujana Challa #include "mbox.h" 8ae454086SSrujana Challa #include "rvu.h" 9ae454086SSrujana Challa 10ae454086SSrujana Challa /* CPT PF device id */ 11ae454086SSrujana Challa #define PCI_DEVID_OTX2_CPT_PF 0xA0FD 12ae454086SSrujana Challa 13ae454086SSrujana Challa static int get_cpt_pf_num(struct rvu *rvu) 14ae454086SSrujana Challa { 15ae454086SSrujana Challa int i, domain_nr, cpt_pf_num = -1; 16ae454086SSrujana Challa struct pci_dev *pdev; 17ae454086SSrujana Challa 18ae454086SSrujana Challa domain_nr = pci_domain_nr(rvu->pdev->bus); 19ae454086SSrujana Challa for (i = 0; i < rvu->hw->total_pfs; i++) { 20ae454086SSrujana Challa pdev = pci_get_domain_bus_and_slot(domain_nr, i + 1, 0); 21ae454086SSrujana Challa if (!pdev) 22ae454086SSrujana Challa continue; 23ae454086SSrujana Challa 24ae454086SSrujana Challa if (pdev->device == PCI_DEVID_OTX2_CPT_PF) { 25ae454086SSrujana Challa cpt_pf_num = i; 26ae454086SSrujana Challa put_device(&pdev->dev); 27ae454086SSrujana Challa break; 28ae454086SSrujana Challa } 29ae454086SSrujana Challa put_device(&pdev->dev); 30ae454086SSrujana Challa } 31ae454086SSrujana Challa return cpt_pf_num; 32ae454086SSrujana Challa } 33ae454086SSrujana Challa 34ae454086SSrujana Challa static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc) 35ae454086SSrujana Challa { 36ae454086SSrujana Challa int cpt_pf_num = get_cpt_pf_num(rvu); 37ae454086SSrujana Challa 38ae454086SSrujana Challa if (rvu_get_pf(pcifunc) != cpt_pf_num) 39ae454086SSrujana Challa return false; 40ae454086SSrujana Challa if (pcifunc & RVU_PFVF_FUNC_MASK) 41ae454086SSrujana Challa return false; 42ae454086SSrujana Challa 43ae454086SSrujana Challa return true; 44ae454086SSrujana Challa } 45ae454086SSrujana Challa 46ae454086SSrujana Challa static bool is_cpt_vf(struct rvu *rvu, u16 pcifunc) 47ae454086SSrujana Challa { 48ae454086SSrujana Challa int cpt_pf_num = get_cpt_pf_num(rvu); 49ae454086SSrujana Challa 50ae454086SSrujana Challa if (rvu_get_pf(pcifunc) != cpt_pf_num) 51ae454086SSrujana Challa return false; 52ae454086SSrujana Challa if (!(pcifunc & RVU_PFVF_FUNC_MASK)) 53ae454086SSrujana Challa return false; 54ae454086SSrujana Challa 55ae454086SSrujana Challa return true; 56ae454086SSrujana Challa } 57ae454086SSrujana Challa 58ae454086SSrujana Challa int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu, 59ae454086SSrujana Challa struct cpt_lf_alloc_req_msg *req, 60ae454086SSrujana Challa struct msg_rsp *rsp) 61ae454086SSrujana Challa { 62ae454086SSrujana Challa u16 pcifunc = req->hdr.pcifunc; 63ae454086SSrujana Challa struct rvu_block *block; 64ae454086SSrujana Challa int cptlf, blkaddr; 65ae454086SSrujana Challa int num_lfs, slot; 66ae454086SSrujana Challa u64 val; 67ae454086SSrujana Challa 68*de2854c8SSrujana Challa blkaddr = req->blkaddr ? req->blkaddr : BLKADDR_CPT0; 69*de2854c8SSrujana Challa if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1) 70*de2854c8SSrujana Challa return -ENODEV; 71*de2854c8SSrujana Challa 72ae454086SSrujana Challa if (req->eng_grpmsk == 0x0) 73ae454086SSrujana Challa return CPT_AF_ERR_GRP_INVALID; 74ae454086SSrujana Challa 75ae454086SSrujana Challa block = &rvu->hw->block[blkaddr]; 76ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc), 77ae454086SSrujana Challa block->addr); 78ae454086SSrujana Challa if (!num_lfs) 79ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID; 80ae454086SSrujana Challa 81ae454086SSrujana Challa /* Check if requested 'CPTLF <=> NIXLF' mapping is valid */ 82ae454086SSrujana Challa if (req->nix_pf_func) { 83ae454086SSrujana Challa /* If default, use 'this' CPTLF's PFFUNC */ 84ae454086SSrujana Challa if (req->nix_pf_func == RVU_DEFAULT_PF_FUNC) 85ae454086SSrujana Challa req->nix_pf_func = pcifunc; 86ae454086SSrujana Challa if (!is_pffunc_map_valid(rvu, req->nix_pf_func, BLKTYPE_NIX)) 87ae454086SSrujana Challa return CPT_AF_ERR_NIX_PF_FUNC_INVALID; 88ae454086SSrujana Challa } 89ae454086SSrujana Challa 90ae454086SSrujana Challa /* Check if requested 'CPTLF <=> SSOLF' mapping is valid */ 91ae454086SSrujana Challa if (req->sso_pf_func) { 92ae454086SSrujana Challa /* If default, use 'this' CPTLF's PFFUNC */ 93ae454086SSrujana Challa if (req->sso_pf_func == RVU_DEFAULT_PF_FUNC) 94ae454086SSrujana Challa req->sso_pf_func = pcifunc; 95ae454086SSrujana Challa if (!is_pffunc_map_valid(rvu, req->sso_pf_func, BLKTYPE_SSO)) 96ae454086SSrujana Challa return CPT_AF_ERR_SSO_PF_FUNC_INVALID; 97ae454086SSrujana Challa } 98ae454086SSrujana Challa 99ae454086SSrujana Challa for (slot = 0; slot < num_lfs; slot++) { 100ae454086SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, slot); 101ae454086SSrujana Challa if (cptlf < 0) 102ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID; 103ae454086SSrujana Challa 104ae454086SSrujana Challa /* Set CPT LF group and priority */ 105ae454086SSrujana Challa val = (u64)req->eng_grpmsk << 48 | 1; 106ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); 107ae454086SSrujana Challa 108ae454086SSrujana Challa /* Set CPT LF NIX_PF_FUNC and SSO_PF_FUNC */ 109ae454086SSrujana Challa val = (u64)req->nix_pf_func << 48 | 110ae454086SSrujana Challa (u64)req->sso_pf_func << 32; 111ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val); 112ae454086SSrujana Challa } 113ae454086SSrujana Challa 114ae454086SSrujana Challa return 0; 115ae454086SSrujana Challa } 116ae454086SSrujana Challa 117*de2854c8SSrujana Challa static int cpt_lf_free(struct rvu *rvu, struct msg_req *req, int blkaddr) 118ae454086SSrujana Challa { 119ae454086SSrujana Challa u16 pcifunc = req->hdr.pcifunc; 120*de2854c8SSrujana Challa int num_lfs, cptlf, slot; 121ae454086SSrujana Challa struct rvu_block *block; 122ae454086SSrujana Challa 123ae454086SSrujana Challa block = &rvu->hw->block[blkaddr]; 124ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc), 125ae454086SSrujana Challa block->addr); 126ae454086SSrujana Challa if (!num_lfs) 127*de2854c8SSrujana Challa return 0; 128ae454086SSrujana Challa 129ae454086SSrujana Challa for (slot = 0; slot < num_lfs; slot++) { 130ae454086SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, slot); 131ae454086SSrujana Challa if (cptlf < 0) 132ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID; 133ae454086SSrujana Challa 134ae454086SSrujana Challa /* Reset CPT LF group and priority */ 135ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), 0x0); 136ae454086SSrujana Challa /* Reset CPT LF NIX_PF_FUNC and SSO_PF_FUNC */ 137ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), 0x0); 138ae454086SSrujana Challa } 139ae454086SSrujana Challa 140ae454086SSrujana Challa return 0; 141ae454086SSrujana Challa } 142ae454086SSrujana Challa 143*de2854c8SSrujana Challa int rvu_mbox_handler_cpt_lf_free(struct rvu *rvu, struct msg_req *req, 144*de2854c8SSrujana Challa struct msg_rsp *rsp) 145*de2854c8SSrujana Challa { 146*de2854c8SSrujana Challa int ret; 147*de2854c8SSrujana Challa 148*de2854c8SSrujana Challa ret = cpt_lf_free(rvu, req, BLKADDR_CPT0); 149*de2854c8SSrujana Challa if (ret) 150*de2854c8SSrujana Challa return ret; 151*de2854c8SSrujana Challa 152*de2854c8SSrujana Challa if (is_block_implemented(rvu->hw, BLKADDR_CPT1)) 153*de2854c8SSrujana Challa ret = cpt_lf_free(rvu, req, BLKADDR_CPT1); 154*de2854c8SSrujana Challa 155*de2854c8SSrujana Challa return ret; 156*de2854c8SSrujana Challa } 157*de2854c8SSrujana Challa 158ae454086SSrujana Challa static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req) 159ae454086SSrujana Challa { 160ae454086SSrujana Challa u64 offset = req->reg_offset; 161ae454086SSrujana Challa int blkaddr, num_lfs, lf; 162ae454086SSrujana Challa struct rvu_block *block; 163ae454086SSrujana Challa struct rvu_pfvf *pfvf; 164ae454086SSrujana Challa 165ae454086SSrujana Challa blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_CPT, 0); 166ae454086SSrujana Challa 167ae454086SSrujana Challa /* Registers that can be accessed from PF/VF */ 168ae454086SSrujana Challa if ((offset & 0xFF000) == CPT_AF_LFX_CTL(0) || 169ae454086SSrujana Challa (offset & 0xFF000) == CPT_AF_LFX_CTL2(0)) { 170ae454086SSrujana Challa if (offset & 7) 171ae454086SSrujana Challa return false; 172ae454086SSrujana Challa 173ae454086SSrujana Challa lf = (offset & 0xFFF) >> 3; 174ae454086SSrujana Challa block = &rvu->hw->block[blkaddr]; 175ae454086SSrujana Challa pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc); 176ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr); 177ae454086SSrujana Challa if (lf >= num_lfs) 178ae454086SSrujana Challa /* Slot is not valid for that PF/VF */ 179ae454086SSrujana Challa return false; 180ae454086SSrujana Challa 181ae454086SSrujana Challa /* Translate local LF used by VFs to global CPT LF */ 182ae454086SSrujana Challa lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr], 183ae454086SSrujana Challa req->hdr.pcifunc, lf); 184ae454086SSrujana Challa if (lf < 0) 185ae454086SSrujana Challa return false; 186ae454086SSrujana Challa 187ae454086SSrujana Challa return true; 188ae454086SSrujana Challa } else if (!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK)) { 189ae454086SSrujana Challa /* Registers that can be accessed from PF */ 190ae454086SSrujana Challa switch (offset) { 191ae454086SSrujana Challa case CPT_AF_CTL: 192ae454086SSrujana Challa case CPT_AF_PF_FUNC: 193ae454086SSrujana Challa case CPT_AF_BLK_RST: 194ae454086SSrujana Challa case CPT_AF_CONSTANTS1: 195ae454086SSrujana Challa return true; 196ae454086SSrujana Challa } 197ae454086SSrujana Challa 198ae454086SSrujana Challa switch (offset & 0xFF000) { 199ae454086SSrujana Challa case CPT_AF_EXEX_STS(0): 200ae454086SSrujana Challa case CPT_AF_EXEX_CTL(0): 201ae454086SSrujana Challa case CPT_AF_EXEX_CTL2(0): 202ae454086SSrujana Challa case CPT_AF_EXEX_UCODE_BASE(0): 203ae454086SSrujana Challa if (offset & 7) 204ae454086SSrujana Challa return false; 205ae454086SSrujana Challa break; 206ae454086SSrujana Challa default: 207ae454086SSrujana Challa return false; 208ae454086SSrujana Challa } 209ae454086SSrujana Challa return true; 210ae454086SSrujana Challa } 211ae454086SSrujana Challa return false; 212ae454086SSrujana Challa } 213ae454086SSrujana Challa 214ae454086SSrujana Challa int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, 215ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *req, 216ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *rsp) 217ae454086SSrujana Challa { 218ae454086SSrujana Challa int blkaddr; 219ae454086SSrujana Challa 220*de2854c8SSrujana Challa blkaddr = req->blkaddr ? req->blkaddr : BLKADDR_CPT0; 221*de2854c8SSrujana Challa if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1) 222*de2854c8SSrujana Challa return -ENODEV; 223ae454086SSrujana Challa 224ae454086SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */ 225ae454086SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) && 226ae454086SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc)) 227ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED; 228ae454086SSrujana Challa 229ae454086SSrujana Challa rsp->reg_offset = req->reg_offset; 230ae454086SSrujana Challa rsp->ret_val = req->ret_val; 231ae454086SSrujana Challa rsp->is_write = req->is_write; 232ae454086SSrujana Challa 233ae454086SSrujana Challa if (!is_valid_offset(rvu, req)) 234ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED; 235ae454086SSrujana Challa 236ae454086SSrujana Challa if (req->is_write) 237ae454086SSrujana Challa rvu_write64(rvu, blkaddr, req->reg_offset, req->val); 238ae454086SSrujana Challa else 239ae454086SSrujana Challa rsp->val = rvu_read64(rvu, blkaddr, req->reg_offset); 240ae454086SSrujana Challa 241ae454086SSrujana Challa return 0; 242ae454086SSrujana Challa } 243