1ae454086SSrujana Challa // SPDX-License-Identifier: GPL-2.0-only 2c7cd6c5aSSunil Goutham /* Marvell RVU Admin Function driver 3c7cd6c5aSSunil Goutham * 4c7cd6c5aSSunil Goutham * Copyright (C) 2020 Marvell. 5c7cd6c5aSSunil Goutham * 6c7cd6c5aSSunil Goutham */ 7ae454086SSrujana Challa 8ecad2ce8SSrujana Challa #include <linux/bitfield.h> 9ae454086SSrujana Challa #include <linux/pci.h> 10ae454086SSrujana Challa #include "rvu_struct.h" 11ae454086SSrujana Challa #include "rvu_reg.h" 12ae454086SSrujana Challa #include "mbox.h" 13ae454086SSrujana Challa #include "rvu.h" 14ae454086SSrujana Challa 15ae454086SSrujana Challa /* CPT PF device id */ 16ae454086SSrujana Challa #define PCI_DEVID_OTX2_CPT_PF 0xA0FD 17e4bbc5c5SSrujana Challa #define PCI_DEVID_OTX2_CPT10K_PF 0xA0F2 18e4bbc5c5SSrujana Challa 19e4bbc5c5SSrujana Challa /* Length of initial context fetch in 128 byte words */ 20e4bbc5c5SSrujana Challa #define CPT_CTX_ILEN 2 21ae454086SSrujana Challa 222e2ee4cdSSrujana Challa #define cpt_get_eng_sts(e_min, e_max, rsp, etype) \ 232e2ee4cdSSrujana Challa ({ \ 242e2ee4cdSSrujana Challa u64 free_sts = 0, busy_sts = 0; \ 252e2ee4cdSSrujana Challa typeof(rsp) _rsp = rsp; \ 262e2ee4cdSSrujana Challa u32 e, i; \ 272e2ee4cdSSrujana Challa \ 282e2ee4cdSSrujana Challa for (e = (e_min), i = 0; e < (e_max); e++, i++) { \ 292e2ee4cdSSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_STS(e)); \ 302e2ee4cdSSrujana Challa if (reg & 0x1) \ 312e2ee4cdSSrujana Challa busy_sts |= 1ULL << i; \ 322e2ee4cdSSrujana Challa \ 332e2ee4cdSSrujana Challa if (reg & 0x2) \ 342e2ee4cdSSrujana Challa free_sts |= 1ULL << i; \ 352e2ee4cdSSrujana Challa } \ 362e2ee4cdSSrujana Challa (_rsp)->busy_sts_##etype = busy_sts; \ 372e2ee4cdSSrujana Challa (_rsp)->free_sts_##etype = free_sts; \ 382e2ee4cdSSrujana Challa }) 392e2ee4cdSSrujana Challa 40*48260907SSrujana Challa static irqreturn_t rvu_cpt_af_flt_intr_handler(int irq, void *ptr) 41*48260907SSrujana Challa { 42*48260907SSrujana Challa struct rvu_block *block = ptr; 43*48260907SSrujana Challa struct rvu *rvu = block->rvu; 44*48260907SSrujana Challa int blkaddr = block->addr; 45*48260907SSrujana Challa u64 reg0, reg1, reg2; 46*48260907SSrujana Challa 47*48260907SSrujana Challa reg0 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(0)); 48*48260907SSrujana Challa reg1 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(1)); 49*48260907SSrujana Challa if (!is_rvu_otx2(rvu)) { 50*48260907SSrujana Challa reg2 = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(2)); 51*48260907SSrujana Challa dev_err_ratelimited(rvu->dev, 52*48260907SSrujana Challa "Received CPTAF FLT irq : 0x%llx, 0x%llx, 0x%llx", 53*48260907SSrujana Challa reg0, reg1, reg2); 54*48260907SSrujana Challa } else { 55*48260907SSrujana Challa dev_err_ratelimited(rvu->dev, 56*48260907SSrujana Challa "Received CPTAF FLT irq : 0x%llx, 0x%llx", 57*48260907SSrujana Challa reg0, reg1); 58*48260907SSrujana Challa } 59*48260907SSrujana Challa 60*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(0), reg0); 61*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(1), reg1); 62*48260907SSrujana Challa if (!is_rvu_otx2(rvu)) 63*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(2), reg2); 64*48260907SSrujana Challa 65*48260907SSrujana Challa return IRQ_HANDLED; 66*48260907SSrujana Challa } 67*48260907SSrujana Challa 68*48260907SSrujana Challa static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr) 69*48260907SSrujana Challa { 70*48260907SSrujana Challa struct rvu_block *block = ptr; 71*48260907SSrujana Challa struct rvu *rvu = block->rvu; 72*48260907SSrujana Challa int blkaddr = block->addr; 73*48260907SSrujana Challa u64 reg; 74*48260907SSrujana Challa 75*48260907SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RVU_INT); 76*48260907SSrujana Challa dev_err_ratelimited(rvu->dev, "Received CPTAF RVU irq : 0x%llx", reg); 77*48260907SSrujana Challa 78*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT, reg); 79*48260907SSrujana Challa return IRQ_HANDLED; 80*48260907SSrujana Challa } 81*48260907SSrujana Challa 82*48260907SSrujana Challa static irqreturn_t rvu_cpt_af_ras_intr_handler(int irq, void *ptr) 83*48260907SSrujana Challa { 84*48260907SSrujana Challa struct rvu_block *block = ptr; 85*48260907SSrujana Challa struct rvu *rvu = block->rvu; 86*48260907SSrujana Challa int blkaddr = block->addr; 87*48260907SSrujana Challa u64 reg; 88*48260907SSrujana Challa 89*48260907SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RAS_INT); 90*48260907SSrujana Challa dev_err_ratelimited(rvu->dev, "Received CPTAF RAS irq : 0x%llx", reg); 91*48260907SSrujana Challa 92*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT, reg); 93*48260907SSrujana Challa return IRQ_HANDLED; 94*48260907SSrujana Challa } 95*48260907SSrujana Challa 96*48260907SSrujana Challa static int rvu_cpt_do_register_interrupt(struct rvu_block *block, int irq_offs, 97*48260907SSrujana Challa irq_handler_t handler, 98*48260907SSrujana Challa const char *name) 99*48260907SSrujana Challa { 100*48260907SSrujana Challa struct rvu *rvu = block->rvu; 101*48260907SSrujana Challa int ret; 102*48260907SSrujana Challa 103*48260907SSrujana Challa ret = request_irq(pci_irq_vector(rvu->pdev, irq_offs), handler, 0, 104*48260907SSrujana Challa name, block); 105*48260907SSrujana Challa if (ret) { 106*48260907SSrujana Challa dev_err(rvu->dev, "RVUAF: %s irq registration failed", name); 107*48260907SSrujana Challa return ret; 108*48260907SSrujana Challa } 109*48260907SSrujana Challa 110*48260907SSrujana Challa WARN_ON(rvu->irq_allocated[irq_offs]); 111*48260907SSrujana Challa rvu->irq_allocated[irq_offs] = true; 112*48260907SSrujana Challa return 0; 113*48260907SSrujana Challa } 114*48260907SSrujana Challa 115*48260907SSrujana Challa static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off) 116*48260907SSrujana Challa { 117*48260907SSrujana Challa struct rvu *rvu = block->rvu; 118*48260907SSrujana Challa int blkaddr = block->addr; 119*48260907SSrujana Challa int i; 120*48260907SSrujana Challa 121*48260907SSrujana Challa /* Disable all CPT AF interrupts */ 122*48260907SSrujana Challa for (i = 0; i < CPT_10K_AF_INT_VEC_RVU; i++) 123*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1); 124*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1); 125*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1); 126*48260907SSrujana Challa 127*48260907SSrujana Challa for (i = 0; i < CPT_10K_AF_INT_VEC_CNT; i++) 128*48260907SSrujana Challa if (rvu->irq_allocated[off + i]) { 129*48260907SSrujana Challa free_irq(pci_irq_vector(rvu->pdev, off + i), block); 130*48260907SSrujana Challa rvu->irq_allocated[off + i] = false; 131*48260907SSrujana Challa } 132*48260907SSrujana Challa } 133*48260907SSrujana Challa 134*48260907SSrujana Challa static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr) 135*48260907SSrujana Challa { 136*48260907SSrujana Challa struct rvu_hwinfo *hw = rvu->hw; 137*48260907SSrujana Challa struct rvu_block *block; 138*48260907SSrujana Challa int i, offs; 139*48260907SSrujana Challa 140*48260907SSrujana Challa if (!is_block_implemented(rvu->hw, blkaddr)) 141*48260907SSrujana Challa return; 142*48260907SSrujana Challa offs = rvu_read64(rvu, blkaddr, CPT_PRIV_AF_INT_CFG) & 0x7FF; 143*48260907SSrujana Challa if (!offs) { 144*48260907SSrujana Challa dev_warn(rvu->dev, 145*48260907SSrujana Challa "Failed to get CPT_AF_INT vector offsets\n"); 146*48260907SSrujana Challa return; 147*48260907SSrujana Challa } 148*48260907SSrujana Challa block = &hw->block[blkaddr]; 149*48260907SSrujana Challa if (!is_rvu_otx2(rvu)) 150*48260907SSrujana Challa return cpt_10k_unregister_interrupts(block, offs); 151*48260907SSrujana Challa 152*48260907SSrujana Challa /* Disable all CPT AF interrupts */ 153*48260907SSrujana Challa for (i = 0; i < CPT_AF_INT_VEC_RVU; i++) 154*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), 0x1); 155*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1); 156*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1); 157*48260907SSrujana Challa 158*48260907SSrujana Challa for (i = 0; i < CPT_AF_INT_VEC_CNT; i++) 159*48260907SSrujana Challa if (rvu->irq_allocated[offs + i]) { 160*48260907SSrujana Challa free_irq(pci_irq_vector(rvu->pdev, offs + i), block); 161*48260907SSrujana Challa rvu->irq_allocated[offs + i] = false; 162*48260907SSrujana Challa } 163*48260907SSrujana Challa } 164*48260907SSrujana Challa 165*48260907SSrujana Challa void rvu_cpt_unregister_interrupts(struct rvu *rvu) 166*48260907SSrujana Challa { 167*48260907SSrujana Challa cpt_unregister_interrupts(rvu, BLKADDR_CPT0); 168*48260907SSrujana Challa cpt_unregister_interrupts(rvu, BLKADDR_CPT1); 169*48260907SSrujana Challa } 170*48260907SSrujana Challa 171*48260907SSrujana Challa static int cpt_10k_register_interrupts(struct rvu_block *block, int off) 172*48260907SSrujana Challa { 173*48260907SSrujana Challa struct rvu *rvu = block->rvu; 174*48260907SSrujana Challa int blkaddr = block->addr; 175*48260907SSrujana Challa char irq_name[16]; 176*48260907SSrujana Challa int i, ret; 177*48260907SSrujana Challa 178*48260907SSrujana Challa for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) { 179*48260907SSrujana Challa snprintf(irq_name, sizeof(irq_name), "CPTAF FLT%d", i); 180*48260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, off + i, 181*48260907SSrujana Challa rvu_cpt_af_flt_intr_handler, 182*48260907SSrujana Challa irq_name); 183*48260907SSrujana Challa if (ret) 184*48260907SSrujana Challa goto err; 185*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1); 186*48260907SSrujana Challa } 187*48260907SSrujana Challa 188*48260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RVU, 189*48260907SSrujana Challa rvu_cpt_af_rvu_intr_handler, 190*48260907SSrujana Challa "CPTAF RVU"); 191*48260907SSrujana Challa if (ret) 192*48260907SSrujana Challa goto err; 193*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1S, 0x1); 194*48260907SSrujana Challa 195*48260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RAS, 196*48260907SSrujana Challa rvu_cpt_af_ras_intr_handler, 197*48260907SSrujana Challa "CPTAF RAS"); 198*48260907SSrujana Challa if (ret) 199*48260907SSrujana Challa goto err; 200*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1S, 0x1); 201*48260907SSrujana Challa 202*48260907SSrujana Challa return 0; 203*48260907SSrujana Challa err: 204*48260907SSrujana Challa rvu_cpt_unregister_interrupts(rvu); 205*48260907SSrujana Challa return ret; 206*48260907SSrujana Challa } 207*48260907SSrujana Challa 208*48260907SSrujana Challa static int cpt_register_interrupts(struct rvu *rvu, int blkaddr) 209*48260907SSrujana Challa { 210*48260907SSrujana Challa struct rvu_hwinfo *hw = rvu->hw; 211*48260907SSrujana Challa struct rvu_block *block; 212*48260907SSrujana Challa int i, offs, ret = 0; 213*48260907SSrujana Challa char irq_name[16]; 214*48260907SSrujana Challa 215*48260907SSrujana Challa if (!is_block_implemented(rvu->hw, blkaddr)) 216*48260907SSrujana Challa return 0; 217*48260907SSrujana Challa 218*48260907SSrujana Challa block = &hw->block[blkaddr]; 219*48260907SSrujana Challa offs = rvu_read64(rvu, blkaddr, CPT_PRIV_AF_INT_CFG) & 0x7FF; 220*48260907SSrujana Challa if (!offs) { 221*48260907SSrujana Challa dev_warn(rvu->dev, 222*48260907SSrujana Challa "Failed to get CPT_AF_INT vector offsets\n"); 223*48260907SSrujana Challa return 0; 224*48260907SSrujana Challa } 225*48260907SSrujana Challa 226*48260907SSrujana Challa if (!is_rvu_otx2(rvu)) 227*48260907SSrujana Challa return cpt_10k_register_interrupts(block, offs); 228*48260907SSrujana Challa 229*48260907SSrujana Challa for (i = CPT_AF_INT_VEC_FLT0; i < CPT_AF_INT_VEC_RVU; i++) { 230*48260907SSrujana Challa snprintf(irq_name, sizeof(irq_name), "CPTAF FLT%d", i); 231*48260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, offs + i, 232*48260907SSrujana Challa rvu_cpt_af_flt_intr_handler, 233*48260907SSrujana Challa irq_name); 234*48260907SSrujana Challa if (ret) 235*48260907SSrujana Challa goto err; 236*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0x1); 237*48260907SSrujana Challa } 238*48260907SSrujana Challa 239*48260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU, 240*48260907SSrujana Challa rvu_cpt_af_rvu_intr_handler, 241*48260907SSrujana Challa "CPTAF RVU"); 242*48260907SSrujana Challa if (ret) 243*48260907SSrujana Challa goto err; 244*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1S, 0x1); 245*48260907SSrujana Challa 246*48260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RAS, 247*48260907SSrujana Challa rvu_cpt_af_ras_intr_handler, 248*48260907SSrujana Challa "CPTAF RAS"); 249*48260907SSrujana Challa if (ret) 250*48260907SSrujana Challa goto err; 251*48260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1S, 0x1); 252*48260907SSrujana Challa 253*48260907SSrujana Challa return 0; 254*48260907SSrujana Challa err: 255*48260907SSrujana Challa rvu_cpt_unregister_interrupts(rvu); 256*48260907SSrujana Challa return ret; 257*48260907SSrujana Challa } 258*48260907SSrujana Challa 259*48260907SSrujana Challa int rvu_cpt_register_interrupts(struct rvu *rvu) 260*48260907SSrujana Challa { 261*48260907SSrujana Challa int ret; 262*48260907SSrujana Challa 263*48260907SSrujana Challa ret = cpt_register_interrupts(rvu, BLKADDR_CPT0); 264*48260907SSrujana Challa if (ret) 265*48260907SSrujana Challa return ret; 266*48260907SSrujana Challa 267*48260907SSrujana Challa return cpt_register_interrupts(rvu, BLKADDR_CPT1); 268*48260907SSrujana Challa } 269*48260907SSrujana Challa 270ae454086SSrujana Challa static int get_cpt_pf_num(struct rvu *rvu) 271ae454086SSrujana Challa { 272ae454086SSrujana Challa int i, domain_nr, cpt_pf_num = -1; 273ae454086SSrujana Challa struct pci_dev *pdev; 274ae454086SSrujana Challa 275ae454086SSrujana Challa domain_nr = pci_domain_nr(rvu->pdev->bus); 276ae454086SSrujana Challa for (i = 0; i < rvu->hw->total_pfs; i++) { 277ae454086SSrujana Challa pdev = pci_get_domain_bus_and_slot(domain_nr, i + 1, 0); 278ae454086SSrujana Challa if (!pdev) 279ae454086SSrujana Challa continue; 280ae454086SSrujana Challa 281e4bbc5c5SSrujana Challa if (pdev->device == PCI_DEVID_OTX2_CPT_PF || 282e4bbc5c5SSrujana Challa pdev->device == PCI_DEVID_OTX2_CPT10K_PF) { 283ae454086SSrujana Challa cpt_pf_num = i; 284ae454086SSrujana Challa put_device(&pdev->dev); 285ae454086SSrujana Challa break; 286ae454086SSrujana Challa } 287ae454086SSrujana Challa put_device(&pdev->dev); 288ae454086SSrujana Challa } 289ae454086SSrujana Challa return cpt_pf_num; 290ae454086SSrujana Challa } 291ae454086SSrujana Challa 292ae454086SSrujana Challa static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc) 293ae454086SSrujana Challa { 294ae454086SSrujana Challa int cpt_pf_num = get_cpt_pf_num(rvu); 295ae454086SSrujana Challa 296ae454086SSrujana Challa if (rvu_get_pf(pcifunc) != cpt_pf_num) 297ae454086SSrujana Challa return false; 298ae454086SSrujana Challa if (pcifunc & RVU_PFVF_FUNC_MASK) 299ae454086SSrujana Challa return false; 300ae454086SSrujana Challa 301ae454086SSrujana Challa return true; 302ae454086SSrujana Challa } 303ae454086SSrujana Challa 304ae454086SSrujana Challa static bool is_cpt_vf(struct rvu *rvu, u16 pcifunc) 305ae454086SSrujana Challa { 306ae454086SSrujana Challa int cpt_pf_num = get_cpt_pf_num(rvu); 307ae454086SSrujana Challa 308ae454086SSrujana Challa if (rvu_get_pf(pcifunc) != cpt_pf_num) 309ae454086SSrujana Challa return false; 310ae454086SSrujana Challa if (!(pcifunc & RVU_PFVF_FUNC_MASK)) 311ae454086SSrujana Challa return false; 312ae454086SSrujana Challa 313ae454086SSrujana Challa return true; 314ae454086SSrujana Challa } 315ae454086SSrujana Challa 316ecad2ce8SSrujana Challa static int validate_and_get_cpt_blkaddr(int req_blkaddr) 317ecad2ce8SSrujana Challa { 318ecad2ce8SSrujana Challa int blkaddr; 319ecad2ce8SSrujana Challa 320ecad2ce8SSrujana Challa blkaddr = req_blkaddr ? req_blkaddr : BLKADDR_CPT0; 321ecad2ce8SSrujana Challa if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1) 322ecad2ce8SSrujana Challa return -EINVAL; 323ecad2ce8SSrujana Challa 324ecad2ce8SSrujana Challa return blkaddr; 325ecad2ce8SSrujana Challa } 326ecad2ce8SSrujana Challa 327ae454086SSrujana Challa int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu, 328ae454086SSrujana Challa struct cpt_lf_alloc_req_msg *req, 329ae454086SSrujana Challa struct msg_rsp *rsp) 330ae454086SSrujana Challa { 331ae454086SSrujana Challa u16 pcifunc = req->hdr.pcifunc; 332ae454086SSrujana Challa struct rvu_block *block; 333ae454086SSrujana Challa int cptlf, blkaddr; 334ae454086SSrujana Challa int num_lfs, slot; 335ae454086SSrujana Challa u64 val; 336ae454086SSrujana Challa 337ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr); 338ecad2ce8SSrujana Challa if (blkaddr < 0) 339ecad2ce8SSrujana Challa return blkaddr; 340de2854c8SSrujana Challa 341ae454086SSrujana Challa if (req->eng_grpmsk == 0x0) 342ae454086SSrujana Challa return CPT_AF_ERR_GRP_INVALID; 343ae454086SSrujana Challa 344ae454086SSrujana Challa block = &rvu->hw->block[blkaddr]; 345ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc), 346ae454086SSrujana Challa block->addr); 347ae454086SSrujana Challa if (!num_lfs) 348ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID; 349ae454086SSrujana Challa 350ae454086SSrujana Challa /* Check if requested 'CPTLF <=> NIXLF' mapping is valid */ 351ae454086SSrujana Challa if (req->nix_pf_func) { 352ae454086SSrujana Challa /* If default, use 'this' CPTLF's PFFUNC */ 353ae454086SSrujana Challa if (req->nix_pf_func == RVU_DEFAULT_PF_FUNC) 354ae454086SSrujana Challa req->nix_pf_func = pcifunc; 355ae454086SSrujana Challa if (!is_pffunc_map_valid(rvu, req->nix_pf_func, BLKTYPE_NIX)) 356ae454086SSrujana Challa return CPT_AF_ERR_NIX_PF_FUNC_INVALID; 357ae454086SSrujana Challa } 358ae454086SSrujana Challa 359ae454086SSrujana Challa /* Check if requested 'CPTLF <=> SSOLF' mapping is valid */ 360ae454086SSrujana Challa if (req->sso_pf_func) { 361ae454086SSrujana Challa /* If default, use 'this' CPTLF's PFFUNC */ 362ae454086SSrujana Challa if (req->sso_pf_func == RVU_DEFAULT_PF_FUNC) 363ae454086SSrujana Challa req->sso_pf_func = pcifunc; 364ae454086SSrujana Challa if (!is_pffunc_map_valid(rvu, req->sso_pf_func, BLKTYPE_SSO)) 365ae454086SSrujana Challa return CPT_AF_ERR_SSO_PF_FUNC_INVALID; 366ae454086SSrujana Challa } 367ae454086SSrujana Challa 368ae454086SSrujana Challa for (slot = 0; slot < num_lfs; slot++) { 369ae454086SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, slot); 370ae454086SSrujana Challa if (cptlf < 0) 371ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID; 372ae454086SSrujana Challa 373ae454086SSrujana Challa /* Set CPT LF group and priority */ 374ae454086SSrujana Challa val = (u64)req->eng_grpmsk << 48 | 1; 375e4bbc5c5SSrujana Challa if (!is_rvu_otx2(rvu)) 376e4bbc5c5SSrujana Challa val |= (CPT_CTX_ILEN << 17); 377e4bbc5c5SSrujana Challa 378ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); 379ae454086SSrujana Challa 380ae454086SSrujana Challa /* Set CPT LF NIX_PF_FUNC and SSO_PF_FUNC */ 381ae454086SSrujana Challa val = (u64)req->nix_pf_func << 48 | 382ae454086SSrujana Challa (u64)req->sso_pf_func << 32; 383ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val); 384ae454086SSrujana Challa } 385ae454086SSrujana Challa 386ae454086SSrujana Challa return 0; 387ae454086SSrujana Challa } 388ae454086SSrujana Challa 389de2854c8SSrujana Challa static int cpt_lf_free(struct rvu *rvu, struct msg_req *req, int blkaddr) 390ae454086SSrujana Challa { 391ae454086SSrujana Challa u16 pcifunc = req->hdr.pcifunc; 392de2854c8SSrujana Challa int num_lfs, cptlf, slot; 393ae454086SSrujana Challa struct rvu_block *block; 394ae454086SSrujana Challa 395ae454086SSrujana Challa block = &rvu->hw->block[blkaddr]; 396ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc), 397ae454086SSrujana Challa block->addr); 398ae454086SSrujana Challa if (!num_lfs) 399de2854c8SSrujana Challa return 0; 400ae454086SSrujana Challa 401ae454086SSrujana Challa for (slot = 0; slot < num_lfs; slot++) { 402ae454086SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, slot); 403ae454086SSrujana Challa if (cptlf < 0) 404ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID; 405ae454086SSrujana Challa 406ae454086SSrujana Challa /* Reset CPT LF group and priority */ 407ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), 0x0); 408ae454086SSrujana Challa /* Reset CPT LF NIX_PF_FUNC and SSO_PF_FUNC */ 409ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), 0x0); 410ae454086SSrujana Challa } 411ae454086SSrujana Challa 412ae454086SSrujana Challa return 0; 413ae454086SSrujana Challa } 414ae454086SSrujana Challa 415de2854c8SSrujana Challa int rvu_mbox_handler_cpt_lf_free(struct rvu *rvu, struct msg_req *req, 416de2854c8SSrujana Challa struct msg_rsp *rsp) 417de2854c8SSrujana Challa { 418de2854c8SSrujana Challa int ret; 419de2854c8SSrujana Challa 420de2854c8SSrujana Challa ret = cpt_lf_free(rvu, req, BLKADDR_CPT0); 421de2854c8SSrujana Challa if (ret) 422de2854c8SSrujana Challa return ret; 423de2854c8SSrujana Challa 424de2854c8SSrujana Challa if (is_block_implemented(rvu->hw, BLKADDR_CPT1)) 425de2854c8SSrujana Challa ret = cpt_lf_free(rvu, req, BLKADDR_CPT1); 426de2854c8SSrujana Challa 427de2854c8SSrujana Challa return ret; 428de2854c8SSrujana Challa } 429de2854c8SSrujana Challa 4304b5a3ab1SSrujana Challa static int cpt_inline_ipsec_cfg_inbound(struct rvu *rvu, int blkaddr, u8 cptlf, 4314b5a3ab1SSrujana Challa struct cpt_inline_ipsec_cfg_msg *req) 4324b5a3ab1SSrujana Challa { 4334b5a3ab1SSrujana Challa u16 sso_pf_func = req->sso_pf_func; 4344b5a3ab1SSrujana Challa u8 nix_sel; 4354b5a3ab1SSrujana Challa u64 val; 4364b5a3ab1SSrujana Challa 4374b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf)); 4384b5a3ab1SSrujana Challa if (req->enable && (val & BIT_ULL(16))) { 4394b5a3ab1SSrujana Challa /* IPSec inline outbound path is already enabled for a given 4404b5a3ab1SSrujana Challa * CPT LF, HRM states that inline inbound & outbound paths 4414b5a3ab1SSrujana Challa * must not be enabled at the same time for a given CPT LF 4424b5a3ab1SSrujana Challa */ 4434b5a3ab1SSrujana Challa return CPT_AF_ERR_INLINE_IPSEC_INB_ENA; 4444b5a3ab1SSrujana Challa } 4454b5a3ab1SSrujana Challa /* Check if requested 'CPTLF <=> SSOLF' mapping is valid */ 4464b5a3ab1SSrujana Challa if (sso_pf_func && !is_pffunc_map_valid(rvu, sso_pf_func, BLKTYPE_SSO)) 4474b5a3ab1SSrujana Challa return CPT_AF_ERR_SSO_PF_FUNC_INVALID; 4484b5a3ab1SSrujana Challa 4494b5a3ab1SSrujana Challa nix_sel = (blkaddr == BLKADDR_CPT1) ? 1 : 0; 4504b5a3ab1SSrujana Challa /* Enable CPT LF for IPsec inline inbound operations */ 4514b5a3ab1SSrujana Challa if (req->enable) 4524b5a3ab1SSrujana Challa val |= BIT_ULL(9); 4534b5a3ab1SSrujana Challa else 4544b5a3ab1SSrujana Challa val &= ~BIT_ULL(9); 4554b5a3ab1SSrujana Challa 4564b5a3ab1SSrujana Challa val |= (u64)nix_sel << 8; 4574b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); 4584b5a3ab1SSrujana Challa 4594b5a3ab1SSrujana Challa if (sso_pf_func) { 4604b5a3ab1SSrujana Challa /* Set SSO_PF_FUNC */ 4614b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf)); 4624b5a3ab1SSrujana Challa val |= (u64)sso_pf_func << 32; 4634b5a3ab1SSrujana Challa val |= (u64)req->nix_pf_func << 48; 4644b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val); 4654b5a3ab1SSrujana Challa } 4664b5a3ab1SSrujana Challa if (req->sso_pf_func_ovrd) 4674b5a3ab1SSrujana Challa /* Set SSO_PF_FUNC_OVRD for inline IPSec */ 4684b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_ECO, 0x1); 4694b5a3ab1SSrujana Challa 4704b5a3ab1SSrujana Challa /* Configure the X2P Link register with the cpt base channel number and 4714b5a3ab1SSrujana Challa * range of channels it should propagate to X2P 4724b5a3ab1SSrujana Challa */ 4734b5a3ab1SSrujana Challa if (!is_rvu_otx2(rvu)) { 4744b5a3ab1SSrujana Challa val = (ilog2(NIX_CHAN_CPT_X2P_MASK + 1) << 16); 4754b5a3ab1SSrujana Challa val |= rvu->hw->cpt_chan_base; 4764b5a3ab1SSrujana Challa 4774b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0), val); 4784b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1), val); 4794b5a3ab1SSrujana Challa } 4804b5a3ab1SSrujana Challa 4814b5a3ab1SSrujana Challa return 0; 4824b5a3ab1SSrujana Challa } 4834b5a3ab1SSrujana Challa 4844b5a3ab1SSrujana Challa static int cpt_inline_ipsec_cfg_outbound(struct rvu *rvu, int blkaddr, u8 cptlf, 4854b5a3ab1SSrujana Challa struct cpt_inline_ipsec_cfg_msg *req) 4864b5a3ab1SSrujana Challa { 4874b5a3ab1SSrujana Challa u16 nix_pf_func = req->nix_pf_func; 4884b5a3ab1SSrujana Challa int nix_blkaddr; 4894b5a3ab1SSrujana Challa u8 nix_sel; 4904b5a3ab1SSrujana Challa u64 val; 4914b5a3ab1SSrujana Challa 4924b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf)); 4934b5a3ab1SSrujana Challa if (req->enable && (val & BIT_ULL(9))) { 4944b5a3ab1SSrujana Challa /* IPSec inline inbound path is already enabled for a given 4954b5a3ab1SSrujana Challa * CPT LF, HRM states that inline inbound & outbound paths 4964b5a3ab1SSrujana Challa * must not be enabled at the same time for a given CPT LF 4974b5a3ab1SSrujana Challa */ 4984b5a3ab1SSrujana Challa return CPT_AF_ERR_INLINE_IPSEC_OUT_ENA; 4994b5a3ab1SSrujana Challa } 5004b5a3ab1SSrujana Challa 5014b5a3ab1SSrujana Challa /* Check if requested 'CPTLF <=> NIXLF' mapping is valid */ 5024b5a3ab1SSrujana Challa if (nix_pf_func && !is_pffunc_map_valid(rvu, nix_pf_func, BLKTYPE_NIX)) 5034b5a3ab1SSrujana Challa return CPT_AF_ERR_NIX_PF_FUNC_INVALID; 5044b5a3ab1SSrujana Challa 5054b5a3ab1SSrujana Challa /* Enable CPT LF for IPsec inline outbound operations */ 5064b5a3ab1SSrujana Challa if (req->enable) 5074b5a3ab1SSrujana Challa val |= BIT_ULL(16); 5084b5a3ab1SSrujana Challa else 5094b5a3ab1SSrujana Challa val &= ~BIT_ULL(16); 5104b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); 5114b5a3ab1SSrujana Challa 5124b5a3ab1SSrujana Challa if (nix_pf_func) { 5134b5a3ab1SSrujana Challa /* Set NIX_PF_FUNC */ 5144b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf)); 5154b5a3ab1SSrujana Challa val |= (u64)nix_pf_func << 48; 5164b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val); 5174b5a3ab1SSrujana Challa 5184b5a3ab1SSrujana Challa nix_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, nix_pf_func); 5194b5a3ab1SSrujana Challa nix_sel = (nix_blkaddr == BLKADDR_NIX0) ? 0 : 1; 5204b5a3ab1SSrujana Challa 5214b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf)); 5224b5a3ab1SSrujana Challa val |= (u64)nix_sel << 8; 5234b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val); 5244b5a3ab1SSrujana Challa } 5254b5a3ab1SSrujana Challa 5264b5a3ab1SSrujana Challa return 0; 5274b5a3ab1SSrujana Challa } 5284b5a3ab1SSrujana Challa 5294b5a3ab1SSrujana Challa int rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu *rvu, 5304b5a3ab1SSrujana Challa struct cpt_inline_ipsec_cfg_msg *req, 5314b5a3ab1SSrujana Challa struct msg_rsp *rsp) 5324b5a3ab1SSrujana Challa { 5334b5a3ab1SSrujana Challa u16 pcifunc = req->hdr.pcifunc; 5344b5a3ab1SSrujana Challa struct rvu_block *block; 5354b5a3ab1SSrujana Challa int cptlf, blkaddr, ret; 5364b5a3ab1SSrujana Challa u16 actual_slot; 5374b5a3ab1SSrujana Challa 5384b5a3ab1SSrujana Challa blkaddr = rvu_get_blkaddr_from_slot(rvu, BLKTYPE_CPT, pcifunc, 5394b5a3ab1SSrujana Challa req->slot, &actual_slot); 5404b5a3ab1SSrujana Challa if (blkaddr < 0) 5414b5a3ab1SSrujana Challa return CPT_AF_ERR_LF_INVALID; 5424b5a3ab1SSrujana Challa 5434b5a3ab1SSrujana Challa block = &rvu->hw->block[blkaddr]; 5444b5a3ab1SSrujana Challa 5454b5a3ab1SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, actual_slot); 5464b5a3ab1SSrujana Challa if (cptlf < 0) 5474b5a3ab1SSrujana Challa return CPT_AF_ERR_LF_INVALID; 5484b5a3ab1SSrujana Challa 5494b5a3ab1SSrujana Challa switch (req->dir) { 5504b5a3ab1SSrujana Challa case CPT_INLINE_INBOUND: 5514b5a3ab1SSrujana Challa ret = cpt_inline_ipsec_cfg_inbound(rvu, blkaddr, cptlf, req); 5524b5a3ab1SSrujana Challa break; 5534b5a3ab1SSrujana Challa 5544b5a3ab1SSrujana Challa case CPT_INLINE_OUTBOUND: 5554b5a3ab1SSrujana Challa ret = cpt_inline_ipsec_cfg_outbound(rvu, blkaddr, cptlf, req); 5564b5a3ab1SSrujana Challa break; 5574b5a3ab1SSrujana Challa 5584b5a3ab1SSrujana Challa default: 5594b5a3ab1SSrujana Challa return CPT_AF_ERR_PARAM; 5604b5a3ab1SSrujana Challa } 5614b5a3ab1SSrujana Challa 5624b5a3ab1SSrujana Challa return ret; 5634b5a3ab1SSrujana Challa } 5644b5a3ab1SSrujana Challa 565ae454086SSrujana Challa static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req) 566ae454086SSrujana Challa { 567ae454086SSrujana Challa u64 offset = req->reg_offset; 568ae454086SSrujana Challa int blkaddr, num_lfs, lf; 569ae454086SSrujana Challa struct rvu_block *block; 570ae454086SSrujana Challa struct rvu_pfvf *pfvf; 571ae454086SSrujana Challa 572ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr); 573ecad2ce8SSrujana Challa if (blkaddr < 0) 574ecad2ce8SSrujana Challa return blkaddr; 575ae454086SSrujana Challa 576ae454086SSrujana Challa /* Registers that can be accessed from PF/VF */ 577ae454086SSrujana Challa if ((offset & 0xFF000) == CPT_AF_LFX_CTL(0) || 578ae454086SSrujana Challa (offset & 0xFF000) == CPT_AF_LFX_CTL2(0)) { 579ae454086SSrujana Challa if (offset & 7) 580ae454086SSrujana Challa return false; 581ae454086SSrujana Challa 582ae454086SSrujana Challa lf = (offset & 0xFFF) >> 3; 583ae454086SSrujana Challa block = &rvu->hw->block[blkaddr]; 584ae454086SSrujana Challa pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc); 585ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr); 586ae454086SSrujana Challa if (lf >= num_lfs) 587ae454086SSrujana Challa /* Slot is not valid for that PF/VF */ 588ae454086SSrujana Challa return false; 589ae454086SSrujana Challa 590ae454086SSrujana Challa /* Translate local LF used by VFs to global CPT LF */ 591ae454086SSrujana Challa lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr], 592ae454086SSrujana Challa req->hdr.pcifunc, lf); 593ae454086SSrujana Challa if (lf < 0) 594ae454086SSrujana Challa return false; 595ae454086SSrujana Challa 596ae454086SSrujana Challa return true; 597ae454086SSrujana Challa } else if (!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK)) { 598ae454086SSrujana Challa /* Registers that can be accessed from PF */ 599ae454086SSrujana Challa switch (offset) { 600ae454086SSrujana Challa case CPT_AF_CTL: 601ae454086SSrujana Challa case CPT_AF_PF_FUNC: 602ae454086SSrujana Challa case CPT_AF_BLK_RST: 603ae454086SSrujana Challa case CPT_AF_CONSTANTS1: 604e4bbc5c5SSrujana Challa case CPT_AF_CTX_FLUSH_TIMER: 605ae454086SSrujana Challa return true; 606ae454086SSrujana Challa } 607ae454086SSrujana Challa 608ae454086SSrujana Challa switch (offset & 0xFF000) { 609ae454086SSrujana Challa case CPT_AF_EXEX_STS(0): 610ae454086SSrujana Challa case CPT_AF_EXEX_CTL(0): 611ae454086SSrujana Challa case CPT_AF_EXEX_CTL2(0): 612ae454086SSrujana Challa case CPT_AF_EXEX_UCODE_BASE(0): 613ae454086SSrujana Challa if (offset & 7) 614ae454086SSrujana Challa return false; 615ae454086SSrujana Challa break; 616ae454086SSrujana Challa default: 617ae454086SSrujana Challa return false; 618ae454086SSrujana Challa } 619ae454086SSrujana Challa return true; 620ae454086SSrujana Challa } 621ae454086SSrujana Challa return false; 622ae454086SSrujana Challa } 623ae454086SSrujana Challa 624ae454086SSrujana Challa int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu, 625ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *req, 626ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *rsp) 627ae454086SSrujana Challa { 628ae454086SSrujana Challa int blkaddr; 629ae454086SSrujana Challa 630ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr); 631ecad2ce8SSrujana Challa if (blkaddr < 0) 632ecad2ce8SSrujana Challa return blkaddr; 633ae454086SSrujana Challa 634ae454086SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */ 635ae454086SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) && 636ae454086SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc)) 637ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED; 638ae454086SSrujana Challa 639ae454086SSrujana Challa rsp->reg_offset = req->reg_offset; 640ae454086SSrujana Challa rsp->ret_val = req->ret_val; 641ae454086SSrujana Challa rsp->is_write = req->is_write; 642ae454086SSrujana Challa 643ae454086SSrujana Challa if (!is_valid_offset(rvu, req)) 644ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED; 645ae454086SSrujana Challa 646ae454086SSrujana Challa if (req->is_write) 647ae454086SSrujana Challa rvu_write64(rvu, blkaddr, req->reg_offset, req->val); 648ae454086SSrujana Challa else 649ae454086SSrujana Challa rsp->val = rvu_read64(rvu, blkaddr, req->reg_offset); 650ae454086SSrujana Challa 651ae454086SSrujana Challa return 0; 652ae454086SSrujana Challa } 653c57c58fdSSrujana Challa 6542e2ee4cdSSrujana Challa static void get_ctx_pc(struct rvu *rvu, struct cpt_sts_rsp *rsp, int blkaddr) 6552e2ee4cdSSrujana Challa { 6562e2ee4cdSSrujana Challa if (is_rvu_otx2(rvu)) 6572e2ee4cdSSrujana Challa return; 6582e2ee4cdSSrujana Challa 6592e2ee4cdSSrujana Challa rsp->ctx_mis_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_MIS_PC); 6602e2ee4cdSSrujana Challa rsp->ctx_hit_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_HIT_PC); 6612e2ee4cdSSrujana Challa rsp->ctx_aop_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_AOP_PC); 6622e2ee4cdSSrujana Challa rsp->ctx_aop_lat_pc = rvu_read64(rvu, blkaddr, 6632e2ee4cdSSrujana Challa CPT_AF_CTX_AOP_LATENCY_PC); 6642e2ee4cdSSrujana Challa rsp->ctx_ifetch_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_IFETCH_PC); 6652e2ee4cdSSrujana Challa rsp->ctx_ifetch_lat_pc = rvu_read64(rvu, blkaddr, 6662e2ee4cdSSrujana Challa CPT_AF_CTX_IFETCH_LATENCY_PC); 6672e2ee4cdSSrujana Challa rsp->ctx_ffetch_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC); 6682e2ee4cdSSrujana Challa rsp->ctx_ffetch_lat_pc = rvu_read64(rvu, blkaddr, 6692e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC); 6702e2ee4cdSSrujana Challa rsp->ctx_wback_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC); 6712e2ee4cdSSrujana Challa rsp->ctx_wback_lat_pc = rvu_read64(rvu, blkaddr, 6722e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC); 6732e2ee4cdSSrujana Challa rsp->ctx_psh_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC); 6742e2ee4cdSSrujana Challa rsp->ctx_psh_lat_pc = rvu_read64(rvu, blkaddr, 6752e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC); 6762e2ee4cdSSrujana Challa rsp->ctx_err = rvu_read64(rvu, blkaddr, CPT_AF_CTX_ERR); 6772e2ee4cdSSrujana Challa rsp->ctx_enc_id = rvu_read64(rvu, blkaddr, CPT_AF_CTX_ENC_ID); 6782e2ee4cdSSrujana Challa rsp->ctx_flush_timer = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FLUSH_TIMER); 6792e2ee4cdSSrujana Challa 6802e2ee4cdSSrujana Challa rsp->rxc_time = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME); 6812e2ee4cdSSrujana Challa rsp->rxc_time_cfg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG); 6822e2ee4cdSSrujana Challa rsp->rxc_active_sts = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS); 6832e2ee4cdSSrujana Challa rsp->rxc_zombie_sts = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ZOMBIE_STS); 6842e2ee4cdSSrujana Challa rsp->rxc_dfrg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_DFRG); 6852e2ee4cdSSrujana Challa rsp->x2p_link_cfg0 = rvu_read64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0)); 6862e2ee4cdSSrujana Challa rsp->x2p_link_cfg1 = rvu_read64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1)); 6872e2ee4cdSSrujana Challa } 6882e2ee4cdSSrujana Challa 6892e2ee4cdSSrujana Challa static void get_eng_sts(struct rvu *rvu, struct cpt_sts_rsp *rsp, int blkaddr) 6902e2ee4cdSSrujana Challa { 6912e2ee4cdSSrujana Challa u16 max_ses, max_ies, max_aes; 6922e2ee4cdSSrujana Challa u32 e_min = 0, e_max = 0; 6932e2ee4cdSSrujana Challa u64 reg; 6942e2ee4cdSSrujana Challa 6952e2ee4cdSSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS1); 6962e2ee4cdSSrujana Challa max_ses = reg & 0xffff; 6972e2ee4cdSSrujana Challa max_ies = (reg >> 16) & 0xffff; 6982e2ee4cdSSrujana Challa max_aes = (reg >> 32) & 0xffff; 6992e2ee4cdSSrujana Challa 7002e2ee4cdSSrujana Challa /* Get AE status */ 7012e2ee4cdSSrujana Challa e_min = max_ses + max_ies; 7022e2ee4cdSSrujana Challa e_max = max_ses + max_ies + max_aes; 7032e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, ae); 7042e2ee4cdSSrujana Challa /* Get SE status */ 7052e2ee4cdSSrujana Challa e_min = 0; 7062e2ee4cdSSrujana Challa e_max = max_ses; 7072e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, se); 7082e2ee4cdSSrujana Challa /* Get IE status */ 7092e2ee4cdSSrujana Challa e_min = max_ses; 7102e2ee4cdSSrujana Challa e_max = max_ses + max_ies; 7112e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, ie); 7122e2ee4cdSSrujana Challa } 7132e2ee4cdSSrujana Challa 7142e2ee4cdSSrujana Challa int rvu_mbox_handler_cpt_sts(struct rvu *rvu, struct cpt_sts_req *req, 7152e2ee4cdSSrujana Challa struct cpt_sts_rsp *rsp) 7162e2ee4cdSSrujana Challa { 7172e2ee4cdSSrujana Challa int blkaddr; 7182e2ee4cdSSrujana Challa 7192e2ee4cdSSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr); 7202e2ee4cdSSrujana Challa if (blkaddr < 0) 7212e2ee4cdSSrujana Challa return blkaddr; 7222e2ee4cdSSrujana Challa 7232e2ee4cdSSrujana Challa /* This message is accepted only if sent from CPT PF/VF */ 7242e2ee4cdSSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) && 7252e2ee4cdSSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc)) 7262e2ee4cdSSrujana Challa return CPT_AF_ERR_ACCESS_DENIED; 7272e2ee4cdSSrujana Challa 7282e2ee4cdSSrujana Challa get_ctx_pc(rvu, rsp, blkaddr); 7292e2ee4cdSSrujana Challa 7302e2ee4cdSSrujana Challa /* Get CPT engines status */ 7312e2ee4cdSSrujana Challa get_eng_sts(rvu, rsp, blkaddr); 7322e2ee4cdSSrujana Challa 7332e2ee4cdSSrujana Challa /* Read CPT instruction PC registers */ 7342e2ee4cdSSrujana Challa rsp->inst_req_pc = rvu_read64(rvu, blkaddr, CPT_AF_INST_REQ_PC); 7352e2ee4cdSSrujana Challa rsp->inst_lat_pc = rvu_read64(rvu, blkaddr, CPT_AF_INST_LATENCY_PC); 7362e2ee4cdSSrujana Challa rsp->rd_req_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_REQ_PC); 7372e2ee4cdSSrujana Challa rsp->rd_lat_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_LATENCY_PC); 7382e2ee4cdSSrujana Challa rsp->rd_uc_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_UC_PC); 7392e2ee4cdSSrujana Challa rsp->active_cycles_pc = rvu_read64(rvu, blkaddr, 7402e2ee4cdSSrujana Challa CPT_AF_ACTIVE_CYCLES_PC); 7412e2ee4cdSSrujana Challa rsp->exe_err_info = rvu_read64(rvu, blkaddr, CPT_AF_EXE_ERR_INFO); 7422e2ee4cdSSrujana Challa rsp->cptclk_cnt = rvu_read64(rvu, blkaddr, CPT_AF_CPTCLK_CNT); 7432e2ee4cdSSrujana Challa rsp->diag = rvu_read64(rvu, blkaddr, CPT_AF_DIAG); 7442e2ee4cdSSrujana Challa 7452e2ee4cdSSrujana Challa return 0; 7462e2ee4cdSSrujana Challa } 7472e2ee4cdSSrujana Challa 748ecad2ce8SSrujana Challa #define RXC_ZOMBIE_THRES GENMASK_ULL(59, 48) 749ecad2ce8SSrujana Challa #define RXC_ZOMBIE_LIMIT GENMASK_ULL(43, 32) 750ecad2ce8SSrujana Challa #define RXC_ACTIVE_THRES GENMASK_ULL(27, 16) 751ecad2ce8SSrujana Challa #define RXC_ACTIVE_LIMIT GENMASK_ULL(11, 0) 752ecad2ce8SSrujana Challa #define RXC_ACTIVE_COUNT GENMASK_ULL(60, 48) 753ecad2ce8SSrujana Challa #define RXC_ZOMBIE_COUNT GENMASK_ULL(60, 48) 754ecad2ce8SSrujana Challa 755ecad2ce8SSrujana Challa static void cpt_rxc_time_cfg(struct rvu *rvu, struct cpt_rxc_time_cfg_req *req, 756ecad2ce8SSrujana Challa int blkaddr) 757ecad2ce8SSrujana Challa { 758ecad2ce8SSrujana Challa u64 dfrg_reg; 759ecad2ce8SSrujana Challa 760ecad2ce8SSrujana Challa dfrg_reg = FIELD_PREP(RXC_ZOMBIE_THRES, req->zombie_thres); 761ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ZOMBIE_LIMIT, req->zombie_limit); 762ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ACTIVE_THRES, req->active_thres); 763ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ACTIVE_LIMIT, req->active_limit); 764ecad2ce8SSrujana Challa 765ecad2ce8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG, req->step); 766ecad2ce8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RXC_DFRG, dfrg_reg); 767ecad2ce8SSrujana Challa } 768ecad2ce8SSrujana Challa 769ecad2ce8SSrujana Challa int rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu *rvu, 770ecad2ce8SSrujana Challa struct cpt_rxc_time_cfg_req *req, 771ecad2ce8SSrujana Challa struct msg_rsp *rsp) 772ecad2ce8SSrujana Challa { 773ecad2ce8SSrujana Challa int blkaddr; 774ecad2ce8SSrujana Challa 775ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr); 776ecad2ce8SSrujana Challa if (blkaddr < 0) 777ecad2ce8SSrujana Challa return blkaddr; 778ecad2ce8SSrujana Challa 779ecad2ce8SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */ 780ecad2ce8SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) && 781ecad2ce8SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc)) 782ecad2ce8SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED; 783ecad2ce8SSrujana Challa 784ecad2ce8SSrujana Challa cpt_rxc_time_cfg(rvu, req, blkaddr); 785ecad2ce8SSrujana Challa 786ecad2ce8SSrujana Challa return 0; 787ecad2ce8SSrujana Challa } 788ecad2ce8SSrujana Challa 789c57c58fdSSrujana Challa #define INPROG_INFLIGHT(reg) ((reg) & 0x1FF) 790c57c58fdSSrujana Challa #define INPROG_GRB_PARTIAL(reg) ((reg) & BIT_ULL(31)) 791c57c58fdSSrujana Challa #define INPROG_GRB(reg) (((reg) >> 32) & 0xFF) 792c57c58fdSSrujana Challa #define INPROG_GWB(reg) (((reg) >> 40) & 0xFF) 793c57c58fdSSrujana Challa 794c57c58fdSSrujana Challa static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot) 795c57c58fdSSrujana Challa { 796c57c58fdSSrujana Challa int i = 0, hard_lp_ctr = 100000; 797c57c58fdSSrujana Challa u64 inprog, grp_ptr; 798c57c58fdSSrujana Challa u16 nq_ptr, dq_ptr; 799c57c58fdSSrujana Challa 800c57c58fdSSrujana Challa /* Disable instructions enqueuing */ 801c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), 0x0); 802c57c58fdSSrujana Challa 803c57c58fdSSrujana Challa /* Disable executions in the LF's queue */ 804c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr, 805c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); 806c57c58fdSSrujana Challa inprog &= ~BIT_ULL(16); 807c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, 808c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog); 809c57c58fdSSrujana Challa 810c57c58fdSSrujana Challa /* Wait for CPT queue to become execution-quiescent */ 811c57c58fdSSrujana Challa do { 812c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr, 813c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); 814c57c58fdSSrujana Challa if (INPROG_GRB_PARTIAL(inprog)) { 815c57c58fdSSrujana Challa i = 0; 816c57c58fdSSrujana Challa hard_lp_ctr--; 817c57c58fdSSrujana Challa } else { 818c57c58fdSSrujana Challa i++; 819c57c58fdSSrujana Challa } 820c57c58fdSSrujana Challa 821c57c58fdSSrujana Challa grp_ptr = rvu_read64(rvu, blkaddr, 822c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, 823c57c58fdSSrujana Challa CPT_LF_Q_GRP_PTR)); 824c57c58fdSSrujana Challa nq_ptr = (grp_ptr >> 32) & 0x7FFF; 825c57c58fdSSrujana Challa dq_ptr = grp_ptr & 0x7FFF; 826c57c58fdSSrujana Challa 827c57c58fdSSrujana Challa } while (hard_lp_ctr && (i < 10) && (nq_ptr != dq_ptr)); 828c57c58fdSSrujana Challa 829c57c58fdSSrujana Challa if (hard_lp_ctr == 0) 830c57c58fdSSrujana Challa dev_warn(rvu->dev, "CPT FLR hits hard loop counter\n"); 831c57c58fdSSrujana Challa 832c57c58fdSSrujana Challa i = 0; 833c57c58fdSSrujana Challa hard_lp_ctr = 100000; 834c57c58fdSSrujana Challa do { 835c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr, 836c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); 837c57c58fdSSrujana Challa 838c57c58fdSSrujana Challa if ((INPROG_INFLIGHT(inprog) == 0) && 839c57c58fdSSrujana Challa (INPROG_GWB(inprog) < 40) && 840c57c58fdSSrujana Challa ((INPROG_GRB(inprog) == 0) || 841c57c58fdSSrujana Challa (INPROG_GRB((inprog)) == 40))) { 842c57c58fdSSrujana Challa i++; 843c57c58fdSSrujana Challa } else { 844c57c58fdSSrujana Challa i = 0; 845c57c58fdSSrujana Challa hard_lp_ctr--; 846c57c58fdSSrujana Challa } 847c57c58fdSSrujana Challa } while (hard_lp_ctr && (i < 10)); 848c57c58fdSSrujana Challa 849c57c58fdSSrujana Challa if (hard_lp_ctr == 0) 850c57c58fdSSrujana Challa dev_warn(rvu->dev, "CPT FLR hits hard loop counter\n"); 851c57c58fdSSrujana Challa } 852c57c58fdSSrujana Challa 853c57c58fdSSrujana Challa int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot) 854c57c58fdSSrujana Challa { 855c57c58fdSSrujana Challa int blkaddr; 856c57c58fdSSrujana Challa u64 reg; 857c57c58fdSSrujana Challa 858c57c58fdSSrujana Challa blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_CPT, pcifunc); 859c57c58fdSSrujana Challa if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1) 860c57c58fdSSrujana Challa return -EINVAL; 861c57c58fdSSrujana Challa 862c57c58fdSSrujana Challa /* Enable BAR2 ALIAS for this pcifunc. */ 863c57c58fdSSrujana Challa reg = BIT_ULL(16) | pcifunc; 864c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg); 865c57c58fdSSrujana Challa 866c57c58fdSSrujana Challa cpt_lf_disable_iqueue(rvu, blkaddr, slot); 867c57c58fdSSrujana Challa 868c57c58fdSSrujana Challa /* Set group drop to help clear out hardware */ 869c57c58fdSSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG)); 870c57c58fdSSrujana Challa reg |= BIT_ULL(17); 871c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), reg); 872c57c58fdSSrujana Challa 873c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0); 874c57c58fdSSrujana Challa 875c57c58fdSSrujana Challa return 0; 876c57c58fdSSrujana Challa } 877