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 */
20d1e1de10SSrujana Challa #define CPT_CTX_ILEN 1ULL
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
cpt_af_flt_intr_handler(int vec,void * ptr)40e625dad8SSrujana Challa static irqreturn_t cpt_af_flt_intr_handler(int vec, void *ptr)
4148260907SSrujana Challa {
4248260907SSrujana Challa struct rvu_block *block = ptr;
4348260907SSrujana Challa struct rvu *rvu = block->rvu;
4448260907SSrujana Challa int blkaddr = block->addr;
45e625dad8SSrujana Challa u64 reg, val;
46e625dad8SSrujana Challa int i, eng;
47e625dad8SSrujana Challa u8 grp;
4848260907SSrujana Challa
49e625dad8SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_FLTX_INT(vec));
50e625dad8SSrujana Challa dev_err_ratelimited(rvu->dev, "Received CPTAF FLT%d irq : 0x%llx", vec, reg);
51e625dad8SSrujana Challa
52e625dad8SSrujana Challa i = -1;
53e625dad8SSrujana Challa while ((i = find_next_bit((unsigned long *)®, 64, i + 1)) < 64) {
54e625dad8SSrujana Challa switch (vec) {
55e625dad8SSrujana Challa case 0:
56e625dad8SSrujana Challa eng = i;
57e625dad8SSrujana Challa break;
58e625dad8SSrujana Challa case 1:
59e625dad8SSrujana Challa eng = i + 64;
60e625dad8SSrujana Challa break;
61e625dad8SSrujana Challa case 2:
62e625dad8SSrujana Challa eng = i + 128;
63e625dad8SSrujana Challa break;
6448260907SSrujana Challa }
65e625dad8SSrujana Challa grp = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng)) & 0xFF;
66e625dad8SSrujana Challa /* Disable and enable the engine which triggers fault */
67e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng), 0x0);
68e625dad8SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng));
69e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng), val & ~1ULL);
7048260907SSrujana Challa
71e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL2(eng), grp);
72e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_EXEX_CTL(eng), val | 1ULL);
73b814cc90SSrujana Challa
74b814cc90SSrujana Challa spin_lock(&rvu->cpt_intr_lock);
75b814cc90SSrujana Challa block->cpt_flt_eng_map[vec] |= BIT_ULL(i);
76b814cc90SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_STS(eng));
77b814cc90SSrujana Challa val = val & 0x3;
78b814cc90SSrujana Challa if (val == 0x1 || val == 0x2)
79b814cc90SSrujana Challa block->cpt_rcvrd_eng_map[vec] |= BIT_ULL(i);
80b814cc90SSrujana Challa spin_unlock(&rvu->cpt_intr_lock);
81e625dad8SSrujana Challa }
82e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT(vec), reg);
8348260907SSrujana Challa
8448260907SSrujana Challa return IRQ_HANDLED;
8548260907SSrujana Challa }
8648260907SSrujana Challa
rvu_cpt_af_flt0_intr_handler(int irq,void * ptr)87e625dad8SSrujana Challa static irqreturn_t rvu_cpt_af_flt0_intr_handler(int irq, void *ptr)
88e625dad8SSrujana Challa {
89e625dad8SSrujana Challa return cpt_af_flt_intr_handler(CPT_AF_INT_VEC_FLT0, ptr);
90e625dad8SSrujana Challa }
91e625dad8SSrujana Challa
rvu_cpt_af_flt1_intr_handler(int irq,void * ptr)92e625dad8SSrujana Challa static irqreturn_t rvu_cpt_af_flt1_intr_handler(int irq, void *ptr)
93e625dad8SSrujana Challa {
94e625dad8SSrujana Challa return cpt_af_flt_intr_handler(CPT_AF_INT_VEC_FLT1, ptr);
95e625dad8SSrujana Challa }
96e625dad8SSrujana Challa
rvu_cpt_af_flt2_intr_handler(int irq,void * ptr)97e625dad8SSrujana Challa static irqreturn_t rvu_cpt_af_flt2_intr_handler(int irq, void *ptr)
98e625dad8SSrujana Challa {
99e625dad8SSrujana Challa return cpt_af_flt_intr_handler(CPT_10K_AF_INT_VEC_FLT2, ptr);
100e625dad8SSrujana Challa }
101e625dad8SSrujana Challa
rvu_cpt_af_rvu_intr_handler(int irq,void * ptr)10248260907SSrujana Challa static irqreturn_t rvu_cpt_af_rvu_intr_handler(int irq, void *ptr)
10348260907SSrujana Challa {
10448260907SSrujana Challa struct rvu_block *block = ptr;
10548260907SSrujana Challa struct rvu *rvu = block->rvu;
10648260907SSrujana Challa int blkaddr = block->addr;
10748260907SSrujana Challa u64 reg;
10848260907SSrujana Challa
10948260907SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RVU_INT);
11048260907SSrujana Challa dev_err_ratelimited(rvu->dev, "Received CPTAF RVU irq : 0x%llx", reg);
11148260907SSrujana Challa
11248260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT, reg);
11348260907SSrujana Challa return IRQ_HANDLED;
11448260907SSrujana Challa }
11548260907SSrujana Challa
rvu_cpt_af_ras_intr_handler(int irq,void * ptr)11648260907SSrujana Challa static irqreturn_t rvu_cpt_af_ras_intr_handler(int irq, void *ptr)
11748260907SSrujana Challa {
11848260907SSrujana Challa struct rvu_block *block = ptr;
11948260907SSrujana Challa struct rvu *rvu = block->rvu;
12048260907SSrujana Challa int blkaddr = block->addr;
12148260907SSrujana Challa u64 reg;
12248260907SSrujana Challa
12348260907SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RAS_INT);
12448260907SSrujana Challa dev_err_ratelimited(rvu->dev, "Received CPTAF RAS irq : 0x%llx", reg);
12548260907SSrujana Challa
12648260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT, reg);
12748260907SSrujana Challa return IRQ_HANDLED;
12848260907SSrujana Challa }
12948260907SSrujana Challa
rvu_cpt_do_register_interrupt(struct rvu_block * block,int irq_offs,irq_handler_t handler,const char * name)13048260907SSrujana Challa static int rvu_cpt_do_register_interrupt(struct rvu_block *block, int irq_offs,
13148260907SSrujana Challa irq_handler_t handler,
13248260907SSrujana Challa const char *name)
13348260907SSrujana Challa {
13448260907SSrujana Challa struct rvu *rvu = block->rvu;
13548260907SSrujana Challa int ret;
13648260907SSrujana Challa
13748260907SSrujana Challa ret = request_irq(pci_irq_vector(rvu->pdev, irq_offs), handler, 0,
13848260907SSrujana Challa name, block);
13948260907SSrujana Challa if (ret) {
14048260907SSrujana Challa dev_err(rvu->dev, "RVUAF: %s irq registration failed", name);
14148260907SSrujana Challa return ret;
14248260907SSrujana Challa }
14348260907SSrujana Challa
14448260907SSrujana Challa WARN_ON(rvu->irq_allocated[irq_offs]);
14548260907SSrujana Challa rvu->irq_allocated[irq_offs] = true;
14648260907SSrujana Challa return 0;
14748260907SSrujana Challa }
14848260907SSrujana Challa
cpt_10k_unregister_interrupts(struct rvu_block * block,int off)14948260907SSrujana Challa static void cpt_10k_unregister_interrupts(struct rvu_block *block, int off)
15048260907SSrujana Challa {
15148260907SSrujana Challa struct rvu *rvu = block->rvu;
15248260907SSrujana Challa int blkaddr = block->addr;
15348260907SSrujana Challa int i;
15448260907SSrujana Challa
15548260907SSrujana Challa /* Disable all CPT AF interrupts */
156e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(0), ~0ULL);
157e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(1), ~0ULL);
158e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(2), 0xFFFF);
159e625dad8SSrujana Challa
16048260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
16148260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);
16248260907SSrujana Challa
16348260907SSrujana Challa for (i = 0; i < CPT_10K_AF_INT_VEC_CNT; i++)
16448260907SSrujana Challa if (rvu->irq_allocated[off + i]) {
16548260907SSrujana Challa free_irq(pci_irq_vector(rvu->pdev, off + i), block);
16648260907SSrujana Challa rvu->irq_allocated[off + i] = false;
16748260907SSrujana Challa }
16848260907SSrujana Challa }
16948260907SSrujana Challa
cpt_unregister_interrupts(struct rvu * rvu,int blkaddr)17048260907SSrujana Challa static void cpt_unregister_interrupts(struct rvu *rvu, int blkaddr)
17148260907SSrujana Challa {
17248260907SSrujana Challa struct rvu_hwinfo *hw = rvu->hw;
17348260907SSrujana Challa struct rvu_block *block;
17448260907SSrujana Challa int i, offs;
17548260907SSrujana Challa
17648260907SSrujana Challa if (!is_block_implemented(rvu->hw, blkaddr))
17748260907SSrujana Challa return;
17848260907SSrujana Challa offs = rvu_read64(rvu, blkaddr, CPT_PRIV_AF_INT_CFG) & 0x7FF;
17948260907SSrujana Challa if (!offs) {
18048260907SSrujana Challa dev_warn(rvu->dev,
18148260907SSrujana Challa "Failed to get CPT_AF_INT vector offsets\n");
18248260907SSrujana Challa return;
18348260907SSrujana Challa }
18448260907SSrujana Challa block = &hw->block[blkaddr];
18548260907SSrujana Challa if (!is_rvu_otx2(rvu))
18648260907SSrujana Challa return cpt_10k_unregister_interrupts(block, offs);
18748260907SSrujana Challa
18848260907SSrujana Challa /* Disable all CPT AF interrupts */
18948260907SSrujana Challa for (i = 0; i < CPT_AF_INT_VEC_RVU; i++)
190e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1C(i), ~0ULL);
19148260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1C, 0x1);
19248260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1C, 0x1);
19348260907SSrujana Challa
19448260907SSrujana Challa for (i = 0; i < CPT_AF_INT_VEC_CNT; i++)
19548260907SSrujana Challa if (rvu->irq_allocated[offs + i]) {
19648260907SSrujana Challa free_irq(pci_irq_vector(rvu->pdev, offs + i), block);
19748260907SSrujana Challa rvu->irq_allocated[offs + i] = false;
19848260907SSrujana Challa }
19948260907SSrujana Challa }
20048260907SSrujana Challa
rvu_cpt_unregister_interrupts(struct rvu * rvu)20148260907SSrujana Challa void rvu_cpt_unregister_interrupts(struct rvu *rvu)
20248260907SSrujana Challa {
20348260907SSrujana Challa cpt_unregister_interrupts(rvu, BLKADDR_CPT0);
20448260907SSrujana Challa cpt_unregister_interrupts(rvu, BLKADDR_CPT1);
20548260907SSrujana Challa }
20648260907SSrujana Challa
cpt_10k_register_interrupts(struct rvu_block * block,int off)20748260907SSrujana Challa static int cpt_10k_register_interrupts(struct rvu_block *block, int off)
20848260907SSrujana Challa {
20948260907SSrujana Challa struct rvu *rvu = block->rvu;
21048260907SSrujana Challa int blkaddr = block->addr;
211e625dad8SSrujana Challa irq_handler_t flt_fn;
21248260907SSrujana Challa int i, ret;
21348260907SSrujana Challa
21448260907SSrujana Challa for (i = CPT_10K_AF_INT_VEC_FLT0; i < CPT_10K_AF_INT_VEC_RVU; i++) {
2156dc9a23eSSunil Goutham sprintf(&rvu->irq_name[(off + i) * NAME_SIZE], "CPTAF FLT%d", i);
216e625dad8SSrujana Challa
217e625dad8SSrujana Challa switch (i) {
218e625dad8SSrujana Challa case CPT_10K_AF_INT_VEC_FLT0:
219e625dad8SSrujana Challa flt_fn = rvu_cpt_af_flt0_intr_handler;
220e625dad8SSrujana Challa break;
221e625dad8SSrujana Challa case CPT_10K_AF_INT_VEC_FLT1:
222e625dad8SSrujana Challa flt_fn = rvu_cpt_af_flt1_intr_handler;
223e625dad8SSrujana Challa break;
224e625dad8SSrujana Challa case CPT_10K_AF_INT_VEC_FLT2:
225e625dad8SSrujana Challa flt_fn = rvu_cpt_af_flt2_intr_handler;
226e625dad8SSrujana Challa break;
227e625dad8SSrujana Challa }
22848260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, off + i,
229e625dad8SSrujana Challa flt_fn, &rvu->irq_name[(off + i) * NAME_SIZE]);
23048260907SSrujana Challa if (ret)
23148260907SSrujana Challa goto err;
232e625dad8SSrujana Challa if (i == CPT_10K_AF_INT_VEC_FLT2)
233e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), 0xFFFF);
234e625dad8SSrujana Challa else
235e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), ~0ULL);
23648260907SSrujana Challa }
23748260907SSrujana Challa
23848260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RVU,
23948260907SSrujana Challa rvu_cpt_af_rvu_intr_handler,
24048260907SSrujana Challa "CPTAF RVU");
24148260907SSrujana Challa if (ret)
24248260907SSrujana Challa goto err;
24348260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1S, 0x1);
24448260907SSrujana Challa
24548260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, off + CPT_10K_AF_INT_VEC_RAS,
24648260907SSrujana Challa rvu_cpt_af_ras_intr_handler,
24748260907SSrujana Challa "CPTAF RAS");
24848260907SSrujana Challa if (ret)
24948260907SSrujana Challa goto err;
25048260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1S, 0x1);
25148260907SSrujana Challa
25248260907SSrujana Challa return 0;
25348260907SSrujana Challa err:
25448260907SSrujana Challa rvu_cpt_unregister_interrupts(rvu);
25548260907SSrujana Challa return ret;
25648260907SSrujana Challa }
25748260907SSrujana Challa
cpt_register_interrupts(struct rvu * rvu,int blkaddr)25848260907SSrujana Challa static int cpt_register_interrupts(struct rvu *rvu, int blkaddr)
25948260907SSrujana Challa {
26048260907SSrujana Challa struct rvu_hwinfo *hw = rvu->hw;
26148260907SSrujana Challa struct rvu_block *block;
262e625dad8SSrujana Challa irq_handler_t flt_fn;
26348260907SSrujana Challa int i, offs, ret = 0;
26448260907SSrujana Challa
26548260907SSrujana Challa if (!is_block_implemented(rvu->hw, blkaddr))
26648260907SSrujana Challa return 0;
26748260907SSrujana Challa
26848260907SSrujana Challa block = &hw->block[blkaddr];
26948260907SSrujana Challa offs = rvu_read64(rvu, blkaddr, CPT_PRIV_AF_INT_CFG) & 0x7FF;
27048260907SSrujana Challa if (!offs) {
27148260907SSrujana Challa dev_warn(rvu->dev,
27248260907SSrujana Challa "Failed to get CPT_AF_INT vector offsets\n");
27348260907SSrujana Challa return 0;
27448260907SSrujana Challa }
27548260907SSrujana Challa
27648260907SSrujana Challa if (!is_rvu_otx2(rvu))
27748260907SSrujana Challa return cpt_10k_register_interrupts(block, offs);
27848260907SSrujana Challa
27948260907SSrujana Challa for (i = CPT_AF_INT_VEC_FLT0; i < CPT_AF_INT_VEC_RVU; i++) {
280e625dad8SSrujana Challa sprintf(&rvu->irq_name[(offs + i) * NAME_SIZE], "CPTAF FLT%d", i);
281e625dad8SSrujana Challa switch (i) {
282e625dad8SSrujana Challa case CPT_AF_INT_VEC_FLT0:
283e625dad8SSrujana Challa flt_fn = rvu_cpt_af_flt0_intr_handler;
284e625dad8SSrujana Challa break;
285e625dad8SSrujana Challa case CPT_AF_INT_VEC_FLT1:
286e625dad8SSrujana Challa flt_fn = rvu_cpt_af_flt1_intr_handler;
287e625dad8SSrujana Challa break;
288e625dad8SSrujana Challa }
28948260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, offs + i,
290e625dad8SSrujana Challa flt_fn, &rvu->irq_name[(offs + i) * NAME_SIZE]);
29148260907SSrujana Challa if (ret)
29248260907SSrujana Challa goto err;
293e625dad8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_FLTX_INT_ENA_W1S(i), ~0ULL);
29448260907SSrujana Challa }
29548260907SSrujana Challa
29648260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RVU,
29748260907SSrujana Challa rvu_cpt_af_rvu_intr_handler,
29848260907SSrujana Challa "CPTAF RVU");
29948260907SSrujana Challa if (ret)
30048260907SSrujana Challa goto err;
30148260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RVU_INT_ENA_W1S, 0x1);
30248260907SSrujana Challa
30348260907SSrujana Challa ret = rvu_cpt_do_register_interrupt(block, offs + CPT_AF_INT_VEC_RAS,
30448260907SSrujana Challa rvu_cpt_af_ras_intr_handler,
30548260907SSrujana Challa "CPTAF RAS");
30648260907SSrujana Challa if (ret)
30748260907SSrujana Challa goto err;
30848260907SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RAS_INT_ENA_W1S, 0x1);
30948260907SSrujana Challa
31048260907SSrujana Challa return 0;
31148260907SSrujana Challa err:
31248260907SSrujana Challa rvu_cpt_unregister_interrupts(rvu);
31348260907SSrujana Challa return ret;
31448260907SSrujana Challa }
31548260907SSrujana Challa
rvu_cpt_register_interrupts(struct rvu * rvu)31648260907SSrujana Challa int rvu_cpt_register_interrupts(struct rvu *rvu)
31748260907SSrujana Challa {
31848260907SSrujana Challa int ret;
31948260907SSrujana Challa
32048260907SSrujana Challa ret = cpt_register_interrupts(rvu, BLKADDR_CPT0);
32148260907SSrujana Challa if (ret)
32248260907SSrujana Challa return ret;
32348260907SSrujana Challa
32448260907SSrujana Challa return cpt_register_interrupts(rvu, BLKADDR_CPT1);
32548260907SSrujana Challa }
32648260907SSrujana Challa
get_cpt_pf_num(struct rvu * rvu)327ae454086SSrujana Challa static int get_cpt_pf_num(struct rvu *rvu)
328ae454086SSrujana Challa {
329ae454086SSrujana Challa int i, domain_nr, cpt_pf_num = -1;
330ae454086SSrujana Challa struct pci_dev *pdev;
331ae454086SSrujana Challa
332ae454086SSrujana Challa domain_nr = pci_domain_nr(rvu->pdev->bus);
333ae454086SSrujana Challa for (i = 0; i < rvu->hw->total_pfs; i++) {
334ae454086SSrujana Challa pdev = pci_get_domain_bus_and_slot(domain_nr, i + 1, 0);
335ae454086SSrujana Challa if (!pdev)
336ae454086SSrujana Challa continue;
337ae454086SSrujana Challa
338e4bbc5c5SSrujana Challa if (pdev->device == PCI_DEVID_OTX2_CPT_PF ||
339e4bbc5c5SSrujana Challa pdev->device == PCI_DEVID_OTX2_CPT10K_PF) {
340ae454086SSrujana Challa cpt_pf_num = i;
341ae454086SSrujana Challa put_device(&pdev->dev);
342ae454086SSrujana Challa break;
343ae454086SSrujana Challa }
344ae454086SSrujana Challa put_device(&pdev->dev);
345ae454086SSrujana Challa }
346ae454086SSrujana Challa return cpt_pf_num;
347ae454086SSrujana Challa }
348ae454086SSrujana Challa
is_cpt_pf(struct rvu * rvu,u16 pcifunc)349ae454086SSrujana Challa static bool is_cpt_pf(struct rvu *rvu, u16 pcifunc)
350ae454086SSrujana Challa {
35141b166e5SSrujana Challa int cpt_pf_num = rvu->cpt_pf_num;
352ae454086SSrujana Challa
353ae454086SSrujana Challa if (rvu_get_pf(pcifunc) != cpt_pf_num)
354ae454086SSrujana Challa return false;
355ae454086SSrujana Challa if (pcifunc & RVU_PFVF_FUNC_MASK)
356ae454086SSrujana Challa return false;
357ae454086SSrujana Challa
358ae454086SSrujana Challa return true;
359ae454086SSrujana Challa }
360ae454086SSrujana Challa
is_cpt_vf(struct rvu * rvu,u16 pcifunc)361ae454086SSrujana Challa static bool is_cpt_vf(struct rvu *rvu, u16 pcifunc)
362ae454086SSrujana Challa {
36341b166e5SSrujana Challa int cpt_pf_num = rvu->cpt_pf_num;
364ae454086SSrujana Challa
365ae454086SSrujana Challa if (rvu_get_pf(pcifunc) != cpt_pf_num)
366ae454086SSrujana Challa return false;
367ae454086SSrujana Challa if (!(pcifunc & RVU_PFVF_FUNC_MASK))
368ae454086SSrujana Challa return false;
369ae454086SSrujana Challa
370ae454086SSrujana Challa return true;
371ae454086SSrujana Challa }
372ae454086SSrujana Challa
validate_and_get_cpt_blkaddr(int req_blkaddr)373ecad2ce8SSrujana Challa static int validate_and_get_cpt_blkaddr(int req_blkaddr)
374ecad2ce8SSrujana Challa {
375ecad2ce8SSrujana Challa int blkaddr;
376ecad2ce8SSrujana Challa
377ecad2ce8SSrujana Challa blkaddr = req_blkaddr ? req_blkaddr : BLKADDR_CPT0;
378ecad2ce8SSrujana Challa if (blkaddr != BLKADDR_CPT0 && blkaddr != BLKADDR_CPT1)
379ecad2ce8SSrujana Challa return -EINVAL;
380ecad2ce8SSrujana Challa
381ecad2ce8SSrujana Challa return blkaddr;
382ecad2ce8SSrujana Challa }
383ecad2ce8SSrujana Challa
rvu_mbox_handler_cpt_lf_alloc(struct rvu * rvu,struct cpt_lf_alloc_req_msg * req,struct msg_rsp * rsp)384ae454086SSrujana Challa int rvu_mbox_handler_cpt_lf_alloc(struct rvu *rvu,
385ae454086SSrujana Challa struct cpt_lf_alloc_req_msg *req,
386ae454086SSrujana Challa struct msg_rsp *rsp)
387ae454086SSrujana Challa {
388ae454086SSrujana Challa u16 pcifunc = req->hdr.pcifunc;
389ae454086SSrujana Challa struct rvu_block *block;
390ae454086SSrujana Challa int cptlf, blkaddr;
391ae454086SSrujana Challa int num_lfs, slot;
392ae454086SSrujana Challa u64 val;
393ae454086SSrujana Challa
394ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
395ecad2ce8SSrujana Challa if (blkaddr < 0)
396ecad2ce8SSrujana Challa return blkaddr;
397de2854c8SSrujana Challa
398ae454086SSrujana Challa if (req->eng_grpmsk == 0x0)
399ae454086SSrujana Challa return CPT_AF_ERR_GRP_INVALID;
400ae454086SSrujana Challa
401ae454086SSrujana Challa block = &rvu->hw->block[blkaddr];
402ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
403ae454086SSrujana Challa block->addr);
404ae454086SSrujana Challa if (!num_lfs)
405ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID;
406ae454086SSrujana Challa
407ae454086SSrujana Challa /* Check if requested 'CPTLF <=> NIXLF' mapping is valid */
408ae454086SSrujana Challa if (req->nix_pf_func) {
409ae454086SSrujana Challa /* If default, use 'this' CPTLF's PFFUNC */
410ae454086SSrujana Challa if (req->nix_pf_func == RVU_DEFAULT_PF_FUNC)
411ae454086SSrujana Challa req->nix_pf_func = pcifunc;
412ae454086SSrujana Challa if (!is_pffunc_map_valid(rvu, req->nix_pf_func, BLKTYPE_NIX))
413ae454086SSrujana Challa return CPT_AF_ERR_NIX_PF_FUNC_INVALID;
414ae454086SSrujana Challa }
415ae454086SSrujana Challa
416ae454086SSrujana Challa /* Check if requested 'CPTLF <=> SSOLF' mapping is valid */
417ae454086SSrujana Challa if (req->sso_pf_func) {
418ae454086SSrujana Challa /* If default, use 'this' CPTLF's PFFUNC */
419ae454086SSrujana Challa if (req->sso_pf_func == RVU_DEFAULT_PF_FUNC)
420ae454086SSrujana Challa req->sso_pf_func = pcifunc;
421ae454086SSrujana Challa if (!is_pffunc_map_valid(rvu, req->sso_pf_func, BLKTYPE_SSO))
422ae454086SSrujana Challa return CPT_AF_ERR_SSO_PF_FUNC_INVALID;
423ae454086SSrujana Challa }
424ae454086SSrujana Challa
425ae454086SSrujana Challa for (slot = 0; slot < num_lfs; slot++) {
426ae454086SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, slot);
427ae454086SSrujana Challa if (cptlf < 0)
428ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID;
429ae454086SSrujana Challa
430ae454086SSrujana Challa /* Set CPT LF group and priority */
431ae454086SSrujana Challa val = (u64)req->eng_grpmsk << 48 | 1;
432d1e1de10SSrujana Challa if (!is_rvu_otx2(rvu)) {
433d1e1de10SSrujana Challa if (req->ctx_ilen_valid)
434d1e1de10SSrujana Challa val |= (req->ctx_ilen << 17);
435d1e1de10SSrujana Challa else
436e4bbc5c5SSrujana Challa val |= (CPT_CTX_ILEN << 17);
437d1e1de10SSrujana Challa }
438e4bbc5c5SSrujana Challa
439ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val);
440ae454086SSrujana Challa
4417054d39cSNithin Dabilpuram /* Set CPT LF NIX_PF_FUNC and SSO_PF_FUNC. EXE_LDWB is set
4427054d39cSNithin Dabilpuram * on reset.
4437054d39cSNithin Dabilpuram */
4447054d39cSNithin Dabilpuram val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
4457054d39cSNithin Dabilpuram val &= ~(GENMASK_ULL(63, 48) | GENMASK_ULL(47, 32));
4467054d39cSNithin Dabilpuram val |= ((u64)req->nix_pf_func << 48 |
4477054d39cSNithin Dabilpuram (u64)req->sso_pf_func << 32);
448ae454086SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val);
449ae454086SSrujana Challa }
450ae454086SSrujana Challa
451ae454086SSrujana Challa return 0;
452ae454086SSrujana Challa }
453ae454086SSrujana Challa
cpt_lf_free(struct rvu * rvu,struct msg_req * req,int blkaddr)454de2854c8SSrujana Challa static int cpt_lf_free(struct rvu *rvu, struct msg_req *req, int blkaddr)
455ae454086SSrujana Challa {
456ae454086SSrujana Challa u16 pcifunc = req->hdr.pcifunc;
4577054d39cSNithin Dabilpuram int num_lfs, cptlf, slot, err;
458ae454086SSrujana Challa struct rvu_block *block;
459ae454086SSrujana Challa
460ae454086SSrujana Challa block = &rvu->hw->block[blkaddr];
461ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
462ae454086SSrujana Challa block->addr);
463ae454086SSrujana Challa if (!num_lfs)
464de2854c8SSrujana Challa return 0;
465ae454086SSrujana Challa
466ae454086SSrujana Challa for (slot = 0; slot < num_lfs; slot++) {
467ae454086SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, slot);
468ae454086SSrujana Challa if (cptlf < 0)
469ae454086SSrujana Challa return CPT_AF_ERR_LF_INVALID;
470ae454086SSrujana Challa
4717054d39cSNithin Dabilpuram /* Perform teardown */
4727054d39cSNithin Dabilpuram rvu_cpt_lf_teardown(rvu, pcifunc, blkaddr, cptlf, slot);
4737054d39cSNithin Dabilpuram
4747054d39cSNithin Dabilpuram /* Reset LF */
4757054d39cSNithin Dabilpuram err = rvu_lf_reset(rvu, block, cptlf);
4767054d39cSNithin Dabilpuram if (err) {
4777054d39cSNithin Dabilpuram dev_err(rvu->dev, "Failed to reset blkaddr %d LF%d\n",
4787054d39cSNithin Dabilpuram block->addr, cptlf);
4797054d39cSNithin Dabilpuram }
480ae454086SSrujana Challa }
481ae454086SSrujana Challa
482ae454086SSrujana Challa return 0;
483ae454086SSrujana Challa }
484ae454086SSrujana Challa
rvu_mbox_handler_cpt_lf_free(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)485de2854c8SSrujana Challa int rvu_mbox_handler_cpt_lf_free(struct rvu *rvu, struct msg_req *req,
486de2854c8SSrujana Challa struct msg_rsp *rsp)
487de2854c8SSrujana Challa {
488de2854c8SSrujana Challa int ret;
489de2854c8SSrujana Challa
490de2854c8SSrujana Challa ret = cpt_lf_free(rvu, req, BLKADDR_CPT0);
491de2854c8SSrujana Challa if (ret)
492de2854c8SSrujana Challa return ret;
493de2854c8SSrujana Challa
494de2854c8SSrujana Challa if (is_block_implemented(rvu->hw, BLKADDR_CPT1))
495de2854c8SSrujana Challa ret = cpt_lf_free(rvu, req, BLKADDR_CPT1);
496de2854c8SSrujana Challa
497de2854c8SSrujana Challa return ret;
498de2854c8SSrujana Challa }
499de2854c8SSrujana Challa
cpt_inline_ipsec_cfg_inbound(struct rvu * rvu,int blkaddr,u8 cptlf,struct cpt_inline_ipsec_cfg_msg * req)5004b5a3ab1SSrujana Challa static int cpt_inline_ipsec_cfg_inbound(struct rvu *rvu, int blkaddr, u8 cptlf,
5014b5a3ab1SSrujana Challa struct cpt_inline_ipsec_cfg_msg *req)
5024b5a3ab1SSrujana Challa {
5034b5a3ab1SSrujana Challa u16 sso_pf_func = req->sso_pf_func;
5044b5a3ab1SSrujana Challa u8 nix_sel;
5054b5a3ab1SSrujana Challa u64 val;
5064b5a3ab1SSrujana Challa
5074b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf));
5084b5a3ab1SSrujana Challa if (req->enable && (val & BIT_ULL(16))) {
5094b5a3ab1SSrujana Challa /* IPSec inline outbound path is already enabled for a given
5104b5a3ab1SSrujana Challa * CPT LF, HRM states that inline inbound & outbound paths
5114b5a3ab1SSrujana Challa * must not be enabled at the same time for a given CPT LF
5124b5a3ab1SSrujana Challa */
5134b5a3ab1SSrujana Challa return CPT_AF_ERR_INLINE_IPSEC_INB_ENA;
5144b5a3ab1SSrujana Challa }
5154b5a3ab1SSrujana Challa /* Check if requested 'CPTLF <=> SSOLF' mapping is valid */
5164b5a3ab1SSrujana Challa if (sso_pf_func && !is_pffunc_map_valid(rvu, sso_pf_func, BLKTYPE_SSO))
5174b5a3ab1SSrujana Challa return CPT_AF_ERR_SSO_PF_FUNC_INVALID;
5184b5a3ab1SSrujana Challa
5194b5a3ab1SSrujana Challa nix_sel = (blkaddr == BLKADDR_CPT1) ? 1 : 0;
5204b5a3ab1SSrujana Challa /* Enable CPT LF for IPsec inline inbound operations */
5214b5a3ab1SSrujana Challa if (req->enable)
5224b5a3ab1SSrujana Challa val |= BIT_ULL(9);
5234b5a3ab1SSrujana Challa else
5244b5a3ab1SSrujana Challa val &= ~BIT_ULL(9);
5254b5a3ab1SSrujana Challa
5264b5a3ab1SSrujana Challa val |= (u64)nix_sel << 8;
5274b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val);
5284b5a3ab1SSrujana Challa
5294b5a3ab1SSrujana Challa if (sso_pf_func) {
5304b5a3ab1SSrujana Challa /* Set SSO_PF_FUNC */
5314b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
5324b5a3ab1SSrujana Challa val |= (u64)sso_pf_func << 32;
5334b5a3ab1SSrujana Challa val |= (u64)req->nix_pf_func << 48;
5344b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val);
5354b5a3ab1SSrujana Challa }
5364b5a3ab1SSrujana Challa if (req->sso_pf_func_ovrd)
5374b5a3ab1SSrujana Challa /* Set SSO_PF_FUNC_OVRD for inline IPSec */
5384b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_ECO, 0x1);
5394b5a3ab1SSrujana Challa
5404b5a3ab1SSrujana Challa /* Configure the X2P Link register with the cpt base channel number and
5414b5a3ab1SSrujana Challa * range of channels it should propagate to X2P
5424b5a3ab1SSrujana Challa */
5434b5a3ab1SSrujana Challa if (!is_rvu_otx2(rvu)) {
5444b5a3ab1SSrujana Challa val = (ilog2(NIX_CHAN_CPT_X2P_MASK + 1) << 16);
545b1405691SShijith Thotton val |= (u64)rvu->hw->cpt_chan_base;
5464b5a3ab1SSrujana Challa
5474b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0), val);
5484b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1), val);
5494b5a3ab1SSrujana Challa }
5504b5a3ab1SSrujana Challa
5514b5a3ab1SSrujana Challa return 0;
5524b5a3ab1SSrujana Challa }
5534b5a3ab1SSrujana Challa
cpt_inline_ipsec_cfg_outbound(struct rvu * rvu,int blkaddr,u8 cptlf,struct cpt_inline_ipsec_cfg_msg * req)5544b5a3ab1SSrujana Challa static int cpt_inline_ipsec_cfg_outbound(struct rvu *rvu, int blkaddr, u8 cptlf,
5554b5a3ab1SSrujana Challa struct cpt_inline_ipsec_cfg_msg *req)
5564b5a3ab1SSrujana Challa {
5574b5a3ab1SSrujana Challa u16 nix_pf_func = req->nix_pf_func;
5584b5a3ab1SSrujana Challa int nix_blkaddr;
5594b5a3ab1SSrujana Challa u8 nix_sel;
5604b5a3ab1SSrujana Challa u64 val;
5614b5a3ab1SSrujana Challa
5624b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf));
5634b5a3ab1SSrujana Challa if (req->enable && (val & BIT_ULL(9))) {
5644b5a3ab1SSrujana Challa /* IPSec inline inbound path is already enabled for a given
5654b5a3ab1SSrujana Challa * CPT LF, HRM states that inline inbound & outbound paths
5664b5a3ab1SSrujana Challa * must not be enabled at the same time for a given CPT LF
5674b5a3ab1SSrujana Challa */
5684b5a3ab1SSrujana Challa return CPT_AF_ERR_INLINE_IPSEC_OUT_ENA;
5694b5a3ab1SSrujana Challa }
5704b5a3ab1SSrujana Challa
5714b5a3ab1SSrujana Challa /* Check if requested 'CPTLF <=> NIXLF' mapping is valid */
5724b5a3ab1SSrujana Challa if (nix_pf_func && !is_pffunc_map_valid(rvu, nix_pf_func, BLKTYPE_NIX))
5734b5a3ab1SSrujana Challa return CPT_AF_ERR_NIX_PF_FUNC_INVALID;
5744b5a3ab1SSrujana Challa
5754b5a3ab1SSrujana Challa /* Enable CPT LF for IPsec inline outbound operations */
5764b5a3ab1SSrujana Challa if (req->enable)
5774b5a3ab1SSrujana Challa val |= BIT_ULL(16);
5784b5a3ab1SSrujana Challa else
5794b5a3ab1SSrujana Challa val &= ~BIT_ULL(16);
5804b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val);
5814b5a3ab1SSrujana Challa
5824b5a3ab1SSrujana Challa if (nix_pf_func) {
5834b5a3ab1SSrujana Challa /* Set NIX_PF_FUNC */
5844b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
5854b5a3ab1SSrujana Challa val |= (u64)nix_pf_func << 48;
5864b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), val);
5874b5a3ab1SSrujana Challa
5884b5a3ab1SSrujana Challa nix_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, nix_pf_func);
5894b5a3ab1SSrujana Challa nix_sel = (nix_blkaddr == BLKADDR_NIX0) ? 0 : 1;
5904b5a3ab1SSrujana Challa
5914b5a3ab1SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf));
5924b5a3ab1SSrujana Challa val |= (u64)nix_sel << 8;
5934b5a3ab1SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), val);
5944b5a3ab1SSrujana Challa }
5954b5a3ab1SSrujana Challa
5964b5a3ab1SSrujana Challa return 0;
5974b5a3ab1SSrujana Challa }
5984b5a3ab1SSrujana Challa
rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu * rvu,struct cpt_inline_ipsec_cfg_msg * req,struct msg_rsp * rsp)5994b5a3ab1SSrujana Challa int rvu_mbox_handler_cpt_inline_ipsec_cfg(struct rvu *rvu,
6004b5a3ab1SSrujana Challa struct cpt_inline_ipsec_cfg_msg *req,
6014b5a3ab1SSrujana Challa struct msg_rsp *rsp)
6024b5a3ab1SSrujana Challa {
6034b5a3ab1SSrujana Challa u16 pcifunc = req->hdr.pcifunc;
6044b5a3ab1SSrujana Challa struct rvu_block *block;
6054b5a3ab1SSrujana Challa int cptlf, blkaddr, ret;
6064b5a3ab1SSrujana Challa u16 actual_slot;
6074b5a3ab1SSrujana Challa
6084b5a3ab1SSrujana Challa blkaddr = rvu_get_blkaddr_from_slot(rvu, BLKTYPE_CPT, pcifunc,
6094b5a3ab1SSrujana Challa req->slot, &actual_slot);
6104b5a3ab1SSrujana Challa if (blkaddr < 0)
6114b5a3ab1SSrujana Challa return CPT_AF_ERR_LF_INVALID;
6124b5a3ab1SSrujana Challa
6134b5a3ab1SSrujana Challa block = &rvu->hw->block[blkaddr];
6144b5a3ab1SSrujana Challa
6154b5a3ab1SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, actual_slot);
6164b5a3ab1SSrujana Challa if (cptlf < 0)
6174b5a3ab1SSrujana Challa return CPT_AF_ERR_LF_INVALID;
6184b5a3ab1SSrujana Challa
6194b5a3ab1SSrujana Challa switch (req->dir) {
6204b5a3ab1SSrujana Challa case CPT_INLINE_INBOUND:
6214b5a3ab1SSrujana Challa ret = cpt_inline_ipsec_cfg_inbound(rvu, blkaddr, cptlf, req);
6224b5a3ab1SSrujana Challa break;
6234b5a3ab1SSrujana Challa
6244b5a3ab1SSrujana Challa case CPT_INLINE_OUTBOUND:
6254b5a3ab1SSrujana Challa ret = cpt_inline_ipsec_cfg_outbound(rvu, blkaddr, cptlf, req);
6264b5a3ab1SSrujana Challa break;
6274b5a3ab1SSrujana Challa
6284b5a3ab1SSrujana Challa default:
6294b5a3ab1SSrujana Challa return CPT_AF_ERR_PARAM;
6304b5a3ab1SSrujana Challa }
6314b5a3ab1SSrujana Challa
6324b5a3ab1SSrujana Challa return ret;
6334b5a3ab1SSrujana Challa }
6344b5a3ab1SSrujana Challa
validate_and_update_reg_offset(struct rvu * rvu,struct cpt_rd_wr_reg_msg * req,u64 * reg_offset)635*7a8c74dfSBharat Bhushan static bool validate_and_update_reg_offset(struct rvu *rvu,
636*7a8c74dfSBharat Bhushan struct cpt_rd_wr_reg_msg *req,
637*7a8c74dfSBharat Bhushan u64 *reg_offset)
638ae454086SSrujana Challa {
639ae454086SSrujana Challa u64 offset = req->reg_offset;
640ae454086SSrujana Challa int blkaddr, num_lfs, lf;
641ae454086SSrujana Challa struct rvu_block *block;
642ae454086SSrujana Challa struct rvu_pfvf *pfvf;
643ae454086SSrujana Challa
644ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
645ecad2ce8SSrujana Challa if (blkaddr < 0)
646f3d671c7SDan Carpenter return false;
647ae454086SSrujana Challa
648ae454086SSrujana Challa /* Registers that can be accessed from PF/VF */
649ae454086SSrujana Challa if ((offset & 0xFF000) == CPT_AF_LFX_CTL(0) ||
650ae454086SSrujana Challa (offset & 0xFF000) == CPT_AF_LFX_CTL2(0)) {
651ae454086SSrujana Challa if (offset & 7)
652ae454086SSrujana Challa return false;
653ae454086SSrujana Challa
654ae454086SSrujana Challa lf = (offset & 0xFFF) >> 3;
655ae454086SSrujana Challa block = &rvu->hw->block[blkaddr];
656ae454086SSrujana Challa pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
657ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
658ae454086SSrujana Challa if (lf >= num_lfs)
659ae454086SSrujana Challa /* Slot is not valid for that PF/VF */
660ae454086SSrujana Challa return false;
661ae454086SSrujana Challa
662ae454086SSrujana Challa /* Translate local LF used by VFs to global CPT LF */
663ae454086SSrujana Challa lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr],
664ae454086SSrujana Challa req->hdr.pcifunc, lf);
665ae454086SSrujana Challa if (lf < 0)
666ae454086SSrujana Challa return false;
667ae454086SSrujana Challa
668*7a8c74dfSBharat Bhushan /* Translate local LF's offset to global CPT LF's offset to
669*7a8c74dfSBharat Bhushan * access LFX register.
670*7a8c74dfSBharat Bhushan */
671*7a8c74dfSBharat Bhushan *reg_offset = (req->reg_offset & 0xFF000) + (lf << 3);
672*7a8c74dfSBharat Bhushan
673ae454086SSrujana Challa return true;
674ae454086SSrujana Challa } else if (!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK)) {
675ae454086SSrujana Challa /* Registers that can be accessed from PF */
676ae454086SSrujana Challa switch (offset) {
6779eef6e97SSrujana Challa case CPT_AF_DIAG:
678ae454086SSrujana Challa case CPT_AF_CTL:
679ae454086SSrujana Challa case CPT_AF_PF_FUNC:
680ae454086SSrujana Challa case CPT_AF_BLK_RST:
681ae454086SSrujana Challa case CPT_AF_CONSTANTS1:
682e4bbc5c5SSrujana Challa case CPT_AF_CTX_FLUSH_TIMER:
683ae454086SSrujana Challa return true;
684ae454086SSrujana Challa }
685ae454086SSrujana Challa
686ae454086SSrujana Challa switch (offset & 0xFF000) {
687ae454086SSrujana Challa case CPT_AF_EXEX_STS(0):
688ae454086SSrujana Challa case CPT_AF_EXEX_CTL(0):
689ae454086SSrujana Challa case CPT_AF_EXEX_CTL2(0):
690ae454086SSrujana Challa case CPT_AF_EXEX_UCODE_BASE(0):
691ae454086SSrujana Challa if (offset & 7)
692ae454086SSrujana Challa return false;
693ae454086SSrujana Challa break;
694ae454086SSrujana Challa default:
695ae454086SSrujana Challa return false;
696ae454086SSrujana Challa }
697ae454086SSrujana Challa return true;
698ae454086SSrujana Challa }
699ae454086SSrujana Challa return false;
700ae454086SSrujana Challa }
701ae454086SSrujana Challa
rvu_mbox_handler_cpt_rd_wr_register(struct rvu * rvu,struct cpt_rd_wr_reg_msg * req,struct cpt_rd_wr_reg_msg * rsp)702ae454086SSrujana Challa int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
703ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *req,
704ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *rsp)
705ae454086SSrujana Challa {
70622b864f7SNithin Dabilpuram u64 offset = req->reg_offset;
707*7a8c74dfSBharat Bhushan int blkaddr;
708ae454086SSrujana Challa
709ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
710ecad2ce8SSrujana Challa if (blkaddr < 0)
711ecad2ce8SSrujana Challa return blkaddr;
712ae454086SSrujana Challa
713ae454086SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */
714ae454086SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) &&
715ae454086SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc))
716ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
717ae454086SSrujana Challa
718*7a8c74dfSBharat Bhushan if (!validate_and_update_reg_offset(rvu, req, &offset))
719ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
720ae454086SSrujana Challa
721*7a8c74dfSBharat Bhushan rsp->reg_offset = req->reg_offset;
72222b864f7SNithin Dabilpuram rsp->ret_val = req->ret_val;
72322b864f7SNithin Dabilpuram rsp->is_write = req->is_write;
72422b864f7SNithin Dabilpuram
725ae454086SSrujana Challa if (req->is_write)
72622b864f7SNithin Dabilpuram rvu_write64(rvu, blkaddr, offset, req->val);
727ae454086SSrujana Challa else
72822b864f7SNithin Dabilpuram rsp->val = rvu_read64(rvu, blkaddr, offset);
729ae454086SSrujana Challa
730ae454086SSrujana Challa return 0;
731ae454086SSrujana Challa }
732c57c58fdSSrujana Challa
get_ctx_pc(struct rvu * rvu,struct cpt_sts_rsp * rsp,int blkaddr)7332e2ee4cdSSrujana Challa static void get_ctx_pc(struct rvu *rvu, struct cpt_sts_rsp *rsp, int blkaddr)
7342e2ee4cdSSrujana Challa {
7352e2ee4cdSSrujana Challa if (is_rvu_otx2(rvu))
7362e2ee4cdSSrujana Challa return;
7372e2ee4cdSSrujana Challa
7382e2ee4cdSSrujana Challa rsp->ctx_mis_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_MIS_PC);
7392e2ee4cdSSrujana Challa rsp->ctx_hit_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_HIT_PC);
7402e2ee4cdSSrujana Challa rsp->ctx_aop_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_AOP_PC);
7412e2ee4cdSSrujana Challa rsp->ctx_aop_lat_pc = rvu_read64(rvu, blkaddr,
7422e2ee4cdSSrujana Challa CPT_AF_CTX_AOP_LATENCY_PC);
7432e2ee4cdSSrujana Challa rsp->ctx_ifetch_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_IFETCH_PC);
7442e2ee4cdSSrujana Challa rsp->ctx_ifetch_lat_pc = rvu_read64(rvu, blkaddr,
7452e2ee4cdSSrujana Challa CPT_AF_CTX_IFETCH_LATENCY_PC);
7462e2ee4cdSSrujana Challa rsp->ctx_ffetch_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC);
7472e2ee4cdSSrujana Challa rsp->ctx_ffetch_lat_pc = rvu_read64(rvu, blkaddr,
7482e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC);
7492e2ee4cdSSrujana Challa rsp->ctx_wback_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC);
7502e2ee4cdSSrujana Challa rsp->ctx_wback_lat_pc = rvu_read64(rvu, blkaddr,
7512e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC);
7522e2ee4cdSSrujana Challa rsp->ctx_psh_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC);
7532e2ee4cdSSrujana Challa rsp->ctx_psh_lat_pc = rvu_read64(rvu, blkaddr,
7542e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC);
7552e2ee4cdSSrujana Challa rsp->ctx_err = rvu_read64(rvu, blkaddr, CPT_AF_CTX_ERR);
7562e2ee4cdSSrujana Challa rsp->ctx_enc_id = rvu_read64(rvu, blkaddr, CPT_AF_CTX_ENC_ID);
7572e2ee4cdSSrujana Challa rsp->ctx_flush_timer = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FLUSH_TIMER);
7582e2ee4cdSSrujana Challa
7592e2ee4cdSSrujana Challa rsp->rxc_time = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME);
7602e2ee4cdSSrujana Challa rsp->rxc_time_cfg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG);
7612e2ee4cdSSrujana Challa rsp->rxc_active_sts = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS);
7622e2ee4cdSSrujana Challa rsp->rxc_zombie_sts = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ZOMBIE_STS);
7632e2ee4cdSSrujana Challa rsp->rxc_dfrg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_DFRG);
7642e2ee4cdSSrujana Challa rsp->x2p_link_cfg0 = rvu_read64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0));
7652e2ee4cdSSrujana Challa rsp->x2p_link_cfg1 = rvu_read64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1));
7662e2ee4cdSSrujana Challa }
7672e2ee4cdSSrujana Challa
get_eng_sts(struct rvu * rvu,struct cpt_sts_rsp * rsp,int blkaddr)7682e2ee4cdSSrujana Challa static void get_eng_sts(struct rvu *rvu, struct cpt_sts_rsp *rsp, int blkaddr)
7692e2ee4cdSSrujana Challa {
7702e2ee4cdSSrujana Challa u16 max_ses, max_ies, max_aes;
7712e2ee4cdSSrujana Challa u32 e_min = 0, e_max = 0;
7722e2ee4cdSSrujana Challa u64 reg;
7732e2ee4cdSSrujana Challa
7742e2ee4cdSSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS1);
7752e2ee4cdSSrujana Challa max_ses = reg & 0xffff;
7762e2ee4cdSSrujana Challa max_ies = (reg >> 16) & 0xffff;
7772e2ee4cdSSrujana Challa max_aes = (reg >> 32) & 0xffff;
7782e2ee4cdSSrujana Challa
7792e2ee4cdSSrujana Challa /* Get AE status */
7802e2ee4cdSSrujana Challa e_min = max_ses + max_ies;
7812e2ee4cdSSrujana Challa e_max = max_ses + max_ies + max_aes;
7822e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, ae);
7832e2ee4cdSSrujana Challa /* Get SE status */
7842e2ee4cdSSrujana Challa e_min = 0;
7852e2ee4cdSSrujana Challa e_max = max_ses;
7862e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, se);
7872e2ee4cdSSrujana Challa /* Get IE status */
7882e2ee4cdSSrujana Challa e_min = max_ses;
7892e2ee4cdSSrujana Challa e_max = max_ses + max_ies;
7902e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, ie);
7912e2ee4cdSSrujana Challa }
7922e2ee4cdSSrujana Challa
rvu_mbox_handler_cpt_sts(struct rvu * rvu,struct cpt_sts_req * req,struct cpt_sts_rsp * rsp)7932e2ee4cdSSrujana Challa int rvu_mbox_handler_cpt_sts(struct rvu *rvu, struct cpt_sts_req *req,
7942e2ee4cdSSrujana Challa struct cpt_sts_rsp *rsp)
7952e2ee4cdSSrujana Challa {
7962e2ee4cdSSrujana Challa int blkaddr;
7972e2ee4cdSSrujana Challa
7982e2ee4cdSSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
7992e2ee4cdSSrujana Challa if (blkaddr < 0)
8002e2ee4cdSSrujana Challa return blkaddr;
8012e2ee4cdSSrujana Challa
8022e2ee4cdSSrujana Challa /* This message is accepted only if sent from CPT PF/VF */
8032e2ee4cdSSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) &&
8042e2ee4cdSSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc))
8052e2ee4cdSSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
8062e2ee4cdSSrujana Challa
8072e2ee4cdSSrujana Challa get_ctx_pc(rvu, rsp, blkaddr);
8082e2ee4cdSSrujana Challa
8092e2ee4cdSSrujana Challa /* Get CPT engines status */
8102e2ee4cdSSrujana Challa get_eng_sts(rvu, rsp, blkaddr);
8112e2ee4cdSSrujana Challa
8122e2ee4cdSSrujana Challa /* Read CPT instruction PC registers */
8132e2ee4cdSSrujana Challa rsp->inst_req_pc = rvu_read64(rvu, blkaddr, CPT_AF_INST_REQ_PC);
8142e2ee4cdSSrujana Challa rsp->inst_lat_pc = rvu_read64(rvu, blkaddr, CPT_AF_INST_LATENCY_PC);
8152e2ee4cdSSrujana Challa rsp->rd_req_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_REQ_PC);
8162e2ee4cdSSrujana Challa rsp->rd_lat_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_LATENCY_PC);
8172e2ee4cdSSrujana Challa rsp->rd_uc_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_UC_PC);
8182e2ee4cdSSrujana Challa rsp->active_cycles_pc = rvu_read64(rvu, blkaddr,
8192e2ee4cdSSrujana Challa CPT_AF_ACTIVE_CYCLES_PC);
8202e2ee4cdSSrujana Challa rsp->exe_err_info = rvu_read64(rvu, blkaddr, CPT_AF_EXE_ERR_INFO);
8212e2ee4cdSSrujana Challa rsp->cptclk_cnt = rvu_read64(rvu, blkaddr, CPT_AF_CPTCLK_CNT);
8222e2ee4cdSSrujana Challa rsp->diag = rvu_read64(rvu, blkaddr, CPT_AF_DIAG);
8232e2ee4cdSSrujana Challa
8242e2ee4cdSSrujana Challa return 0;
8252e2ee4cdSSrujana Challa }
8262e2ee4cdSSrujana Challa
827ecad2ce8SSrujana Challa #define RXC_ZOMBIE_THRES GENMASK_ULL(59, 48)
828ecad2ce8SSrujana Challa #define RXC_ZOMBIE_LIMIT GENMASK_ULL(43, 32)
829ecad2ce8SSrujana Challa #define RXC_ACTIVE_THRES GENMASK_ULL(27, 16)
830ecad2ce8SSrujana Challa #define RXC_ACTIVE_LIMIT GENMASK_ULL(11, 0)
831ecad2ce8SSrujana Challa #define RXC_ACTIVE_COUNT GENMASK_ULL(60, 48)
832ecad2ce8SSrujana Challa #define RXC_ZOMBIE_COUNT GENMASK_ULL(60, 48)
833ecad2ce8SSrujana Challa
cpt_rxc_time_cfg(struct rvu * rvu,struct cpt_rxc_time_cfg_req * req,int blkaddr,struct cpt_rxc_time_cfg_req * save)834ecad2ce8SSrujana Challa static void cpt_rxc_time_cfg(struct rvu *rvu, struct cpt_rxc_time_cfg_req *req,
835e2784acbSNithin Dabilpuram int blkaddr, struct cpt_rxc_time_cfg_req *save)
836ecad2ce8SSrujana Challa {
837ecad2ce8SSrujana Challa u64 dfrg_reg;
838ecad2ce8SSrujana Challa
839e2784acbSNithin Dabilpuram if (save) {
840e2784acbSNithin Dabilpuram /* Save older config */
841e2784acbSNithin Dabilpuram dfrg_reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_DFRG);
842e2784acbSNithin Dabilpuram save->zombie_thres = FIELD_GET(RXC_ZOMBIE_THRES, dfrg_reg);
843e2784acbSNithin Dabilpuram save->zombie_limit = FIELD_GET(RXC_ZOMBIE_LIMIT, dfrg_reg);
844e2784acbSNithin Dabilpuram save->active_thres = FIELD_GET(RXC_ACTIVE_THRES, dfrg_reg);
845e2784acbSNithin Dabilpuram save->active_limit = FIELD_GET(RXC_ACTIVE_LIMIT, dfrg_reg);
846e2784acbSNithin Dabilpuram
847e2784acbSNithin Dabilpuram save->step = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG);
848e2784acbSNithin Dabilpuram }
849e2784acbSNithin Dabilpuram
850ecad2ce8SSrujana Challa dfrg_reg = FIELD_PREP(RXC_ZOMBIE_THRES, req->zombie_thres);
851ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ZOMBIE_LIMIT, req->zombie_limit);
852ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ACTIVE_THRES, req->active_thres);
853ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ACTIVE_LIMIT, req->active_limit);
854ecad2ce8SSrujana Challa
855ecad2ce8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG, req->step);
856ecad2ce8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RXC_DFRG, dfrg_reg);
857ecad2ce8SSrujana Challa }
858ecad2ce8SSrujana Challa
rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu * rvu,struct cpt_rxc_time_cfg_req * req,struct msg_rsp * rsp)859ecad2ce8SSrujana Challa int rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu *rvu,
860ecad2ce8SSrujana Challa struct cpt_rxc_time_cfg_req *req,
861ecad2ce8SSrujana Challa struct msg_rsp *rsp)
862ecad2ce8SSrujana Challa {
863ecad2ce8SSrujana Challa int blkaddr;
864ecad2ce8SSrujana Challa
865ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
866ecad2ce8SSrujana Challa if (blkaddr < 0)
867ecad2ce8SSrujana Challa return blkaddr;
868ecad2ce8SSrujana Challa
869ecad2ce8SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */
870ecad2ce8SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) &&
871ecad2ce8SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc))
872ecad2ce8SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
873ecad2ce8SSrujana Challa
874e2784acbSNithin Dabilpuram cpt_rxc_time_cfg(rvu, req, blkaddr, NULL);
875ecad2ce8SSrujana Challa
876ecad2ce8SSrujana Challa return 0;
877ecad2ce8SSrujana Challa }
878ecad2ce8SSrujana Challa
rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)879149f3b73SSrujana Challa int rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu *rvu, struct msg_req *req,
880149f3b73SSrujana Challa struct msg_rsp *rsp)
881149f3b73SSrujana Challa {
882149f3b73SSrujana Challa return rvu_cpt_ctx_flush(rvu, req->hdr.pcifunc);
883149f3b73SSrujana Challa }
884149f3b73SSrujana Challa
rvu_mbox_handler_cpt_lf_reset(struct rvu * rvu,struct cpt_lf_rst_req * req,struct msg_rsp * rsp)885b7e41527SSrujana Challa int rvu_mbox_handler_cpt_lf_reset(struct rvu *rvu, struct cpt_lf_rst_req *req,
886b7e41527SSrujana Challa struct msg_rsp *rsp)
887b7e41527SSrujana Challa {
888b7e41527SSrujana Challa u16 pcifunc = req->hdr.pcifunc;
889b7e41527SSrujana Challa struct rvu_block *block;
890b7e41527SSrujana Challa int cptlf, blkaddr, ret;
891b7e41527SSrujana Challa u16 actual_slot;
892b7e41527SSrujana Challa u64 ctl, ctl2;
893b7e41527SSrujana Challa
894b7e41527SSrujana Challa blkaddr = rvu_get_blkaddr_from_slot(rvu, BLKTYPE_CPT, pcifunc,
895b7e41527SSrujana Challa req->slot, &actual_slot);
896b7e41527SSrujana Challa if (blkaddr < 0)
897b7e41527SSrujana Challa return CPT_AF_ERR_LF_INVALID;
898b7e41527SSrujana Challa
899b7e41527SSrujana Challa block = &rvu->hw->block[blkaddr];
900b7e41527SSrujana Challa
901b7e41527SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, actual_slot);
902b7e41527SSrujana Challa if (cptlf < 0)
903b7e41527SSrujana Challa return CPT_AF_ERR_LF_INVALID;
904b7e41527SSrujana Challa ctl = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf));
905b7e41527SSrujana Challa ctl2 = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
906b7e41527SSrujana Challa
907b7e41527SSrujana Challa ret = rvu_lf_reset(rvu, block, cptlf);
908b7e41527SSrujana Challa if (ret)
909b7e41527SSrujana Challa dev_err(rvu->dev, "Failed to reset blkaddr %d LF%d\n",
910b7e41527SSrujana Challa block->addr, cptlf);
911b7e41527SSrujana Challa
912b7e41527SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), ctl);
913b7e41527SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), ctl2);
914b7e41527SSrujana Challa
915b7e41527SSrujana Challa return 0;
916b7e41527SSrujana Challa }
917b7e41527SSrujana Challa
rvu_mbox_handler_cpt_flt_eng_info(struct rvu * rvu,struct cpt_flt_eng_info_req * req,struct cpt_flt_eng_info_rsp * rsp)918b814cc90SSrujana Challa int rvu_mbox_handler_cpt_flt_eng_info(struct rvu *rvu, struct cpt_flt_eng_info_req *req,
919b814cc90SSrujana Challa struct cpt_flt_eng_info_rsp *rsp)
920b814cc90SSrujana Challa {
921b814cc90SSrujana Challa struct rvu_block *block;
922b814cc90SSrujana Challa unsigned long flags;
923b814cc90SSrujana Challa int blkaddr, vec;
924b814cc90SSrujana Challa
925b814cc90SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
926b814cc90SSrujana Challa if (blkaddr < 0)
927b814cc90SSrujana Challa return blkaddr;
928b814cc90SSrujana Challa
929b814cc90SSrujana Challa block = &rvu->hw->block[blkaddr];
930b814cc90SSrujana Challa for (vec = 0; vec < CPT_10K_AF_INT_VEC_RVU; vec++) {
931b814cc90SSrujana Challa spin_lock_irqsave(&rvu->cpt_intr_lock, flags);
932b814cc90SSrujana Challa rsp->flt_eng_map[vec] = block->cpt_flt_eng_map[vec];
933b814cc90SSrujana Challa rsp->rcvrd_eng_map[vec] = block->cpt_rcvrd_eng_map[vec];
934b814cc90SSrujana Challa if (req->reset) {
935b814cc90SSrujana Challa block->cpt_flt_eng_map[vec] = 0x0;
936b814cc90SSrujana Challa block->cpt_rcvrd_eng_map[vec] = 0x0;
937b814cc90SSrujana Challa }
938b814cc90SSrujana Challa spin_unlock_irqrestore(&rvu->cpt_intr_lock, flags);
939b814cc90SSrujana Challa }
940b814cc90SSrujana Challa return 0;
941b814cc90SSrujana Challa }
942b814cc90SSrujana Challa
cpt_rxc_teardown(struct rvu * rvu,int blkaddr)943149f3b73SSrujana Challa static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
944149f3b73SSrujana Challa {
945e2784acbSNithin Dabilpuram struct cpt_rxc_time_cfg_req req, prev;
946149f3b73SSrujana Challa int timeout = 2000;
947149f3b73SSrujana Challa u64 reg;
948149f3b73SSrujana Challa
949149f3b73SSrujana Challa if (is_rvu_otx2(rvu))
950149f3b73SSrujana Challa return;
951149f3b73SSrujana Challa
952149f3b73SSrujana Challa /* Set time limit to minimum values, so that rxc entries will be
953149f3b73SSrujana Challa * flushed out quickly.
954149f3b73SSrujana Challa */
955149f3b73SSrujana Challa req.step = 1;
956149f3b73SSrujana Challa req.zombie_thres = 1;
957149f3b73SSrujana Challa req.zombie_limit = 1;
958149f3b73SSrujana Challa req.active_thres = 1;
959149f3b73SSrujana Challa req.active_limit = 1;
960149f3b73SSrujana Challa
961e2784acbSNithin Dabilpuram cpt_rxc_time_cfg(rvu, &req, blkaddr, &prev);
962149f3b73SSrujana Challa
963149f3b73SSrujana Challa do {
964149f3b73SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS);
965149f3b73SSrujana Challa udelay(1);
966149f3b73SSrujana Challa if (FIELD_GET(RXC_ACTIVE_COUNT, reg))
967149f3b73SSrujana Challa timeout--;
968149f3b73SSrujana Challa else
969149f3b73SSrujana Challa break;
970149f3b73SSrujana Challa } while (timeout);
971149f3b73SSrujana Challa
972149f3b73SSrujana Challa if (timeout == 0)
973149f3b73SSrujana Challa dev_warn(rvu->dev, "Poll for RXC active count hits hard loop counter\n");
974149f3b73SSrujana Challa
975149f3b73SSrujana Challa timeout = 2000;
976149f3b73SSrujana Challa do {
977149f3b73SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ZOMBIE_STS);
978149f3b73SSrujana Challa udelay(1);
979149f3b73SSrujana Challa if (FIELD_GET(RXC_ZOMBIE_COUNT, reg))
980149f3b73SSrujana Challa timeout--;
981149f3b73SSrujana Challa else
982149f3b73SSrujana Challa break;
983149f3b73SSrujana Challa } while (timeout);
984149f3b73SSrujana Challa
985149f3b73SSrujana Challa if (timeout == 0)
986149f3b73SSrujana Challa dev_warn(rvu->dev, "Poll for RXC zombie count hits hard loop counter\n");
987e2784acbSNithin Dabilpuram
988e2784acbSNithin Dabilpuram /* Restore config */
989e2784acbSNithin Dabilpuram cpt_rxc_time_cfg(rvu, &prev, blkaddr, NULL);
990149f3b73SSrujana Challa }
991149f3b73SSrujana Challa
9925c22fce6SSrujana Challa #define INFLIGHT GENMASK_ULL(8, 0)
9935c22fce6SSrujana Challa #define GRB_CNT GENMASK_ULL(39, 32)
9945c22fce6SSrujana Challa #define GWB_CNT GENMASK_ULL(47, 40)
9955c22fce6SSrujana Challa #define XQ_XOR GENMASK_ULL(63, 63)
9965c22fce6SSrujana Challa #define DQPTR GENMASK_ULL(19, 0)
9975c22fce6SSrujana Challa #define NQPTR GENMASK_ULL(51, 32)
998c57c58fdSSrujana Challa
cpt_lf_disable_iqueue(struct rvu * rvu,int blkaddr,int slot)999c57c58fdSSrujana Challa static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot)
1000c57c58fdSSrujana Challa {
10015c22fce6SSrujana Challa int timeout = 1000000;
10025c22fce6SSrujana Challa u64 inprog, inst_ptr;
10035c22fce6SSrujana Challa u64 qsize, pending;
10045c22fce6SSrujana Challa int i = 0;
1005c57c58fdSSrujana Challa
1006c57c58fdSSrujana Challa /* Disable instructions enqueuing */
1007c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), 0x0);
1008c57c58fdSSrujana Challa
1009c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr,
1010c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
10115c22fce6SSrujana Challa inprog |= BIT_ULL(16);
1012c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr,
1013c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog);
1014c57c58fdSSrujana Challa
10155c22fce6SSrujana Challa qsize = rvu_read64(rvu, blkaddr,
10165c22fce6SSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_Q_SIZE)) & 0x7FFF;
10175c22fce6SSrujana Challa do {
10185c22fce6SSrujana Challa inst_ptr = rvu_read64(rvu, blkaddr,
10195c22fce6SSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_Q_INST_PTR));
10205c22fce6SSrujana Challa pending = (FIELD_GET(XQ_XOR, inst_ptr) * qsize * 40) +
10215c22fce6SSrujana Challa FIELD_GET(NQPTR, inst_ptr) -
10225c22fce6SSrujana Challa FIELD_GET(DQPTR, inst_ptr);
10235c22fce6SSrujana Challa udelay(1);
10245c22fce6SSrujana Challa timeout--;
10255c22fce6SSrujana Challa } while ((pending != 0) && (timeout != 0));
10265c22fce6SSrujana Challa
10275c22fce6SSrujana Challa if (timeout == 0)
10285c22fce6SSrujana Challa dev_warn(rvu->dev, "TIMEOUT: CPT poll on pending instructions\n");
10295c22fce6SSrujana Challa
10305c22fce6SSrujana Challa timeout = 1000000;
1031c57c58fdSSrujana Challa /* Wait for CPT queue to become execution-quiescent */
1032c57c58fdSSrujana Challa do {
1033c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr,
1034c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
1035c57c58fdSSrujana Challa
10365c22fce6SSrujana Challa if ((FIELD_GET(INFLIGHT, inprog) == 0) &&
10375c22fce6SSrujana Challa (FIELD_GET(GRB_CNT, inprog) == 0)) {
1038c57c58fdSSrujana Challa i++;
1039c57c58fdSSrujana Challa } else {
1040c57c58fdSSrujana Challa i = 0;
10415c22fce6SSrujana Challa timeout--;
1042c57c58fdSSrujana Challa }
10435c22fce6SSrujana Challa } while ((timeout != 0) && (i < 10));
1044c57c58fdSSrujana Challa
10455c22fce6SSrujana Challa if (timeout == 0)
10465c22fce6SSrujana Challa dev_warn(rvu->dev, "TIMEOUT: CPT poll on inflight count\n");
10475c22fce6SSrujana Challa /* Wait for 2 us to flush all queue writes to memory */
10485c22fce6SSrujana Challa udelay(2);
1049c57c58fdSSrujana Challa }
1050c57c58fdSSrujana Challa
rvu_cpt_lf_teardown(struct rvu * rvu,u16 pcifunc,int blkaddr,int lf,int slot)10517054d39cSNithin Dabilpuram int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int slot)
1052c57c58fdSSrujana Challa {
1053c57c58fdSSrujana Challa u64 reg;
1054c57c58fdSSrujana Challa
1055149f3b73SSrujana Challa if (is_cpt_pf(rvu, pcifunc) || is_cpt_vf(rvu, pcifunc))
1056149f3b73SSrujana Challa cpt_rxc_teardown(rvu, blkaddr);
1057149f3b73SSrujana Challa
10585c22fce6SSrujana Challa mutex_lock(&rvu->alias_lock);
1059c57c58fdSSrujana Challa /* Enable BAR2 ALIAS for this pcifunc. */
1060c57c58fdSSrujana Challa reg = BIT_ULL(16) | pcifunc;
10615c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
1062c57c58fdSSrujana Challa
1063c57c58fdSSrujana Challa cpt_lf_disable_iqueue(rvu, blkaddr, slot);
1064c57c58fdSSrujana Challa
10655c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
10665c22fce6SSrujana Challa mutex_unlock(&rvu->alias_lock);
1067c57c58fdSSrujana Challa
1068c57c58fdSSrujana Challa return 0;
1069c57c58fdSSrujana Challa }
1070149f3b73SSrujana Challa
1071149f3b73SSrujana Challa #define CPT_RES_LEN 16
1072149f3b73SSrujana Challa #define CPT_SE_IE_EGRP 1ULL
1073149f3b73SSrujana Challa
cpt_inline_inb_lf_cmd_send(struct rvu * rvu,int blkaddr,int nix_blkaddr)1074149f3b73SSrujana Challa static int cpt_inline_inb_lf_cmd_send(struct rvu *rvu, int blkaddr,
1075149f3b73SSrujana Challa int nix_blkaddr)
1076149f3b73SSrujana Challa {
107741b166e5SSrujana Challa int cpt_pf_num = rvu->cpt_pf_num;
1078149f3b73SSrujana Challa struct cpt_inst_lmtst_req *req;
1079149f3b73SSrujana Challa dma_addr_t res_daddr;
1080149f3b73SSrujana Challa int timeout = 3000;
1081149f3b73SSrujana Challa u8 cpt_idx;
1082149f3b73SSrujana Challa u64 *inst;
1083149f3b73SSrujana Challa u16 *res;
1084149f3b73SSrujana Challa int rc;
1085149f3b73SSrujana Challa
1086149f3b73SSrujana Challa res = kzalloc(CPT_RES_LEN, GFP_KERNEL);
1087149f3b73SSrujana Challa if (!res)
1088149f3b73SSrujana Challa return -ENOMEM;
1089149f3b73SSrujana Challa
1090149f3b73SSrujana Challa res_daddr = dma_map_single(rvu->dev, res, CPT_RES_LEN,
1091149f3b73SSrujana Challa DMA_BIDIRECTIONAL);
1092149f3b73SSrujana Challa if (dma_mapping_error(rvu->dev, res_daddr)) {
1093149f3b73SSrujana Challa dev_err(rvu->dev, "DMA mapping failed for CPT result\n");
1094149f3b73SSrujana Challa rc = -EFAULT;
1095149f3b73SSrujana Challa goto res_free;
1096149f3b73SSrujana Challa }
1097149f3b73SSrujana Challa *res = 0xFFFF;
1098149f3b73SSrujana Challa
1099149f3b73SSrujana Challa /* Send mbox message to CPT PF */
1100149f3b73SSrujana Challa req = (struct cpt_inst_lmtst_req *)
1101149f3b73SSrujana Challa otx2_mbox_alloc_msg_rsp(&rvu->afpf_wq_info.mbox_up,
1102149f3b73SSrujana Challa cpt_pf_num, sizeof(*req),
1103149f3b73SSrujana Challa sizeof(struct msg_rsp));
1104149f3b73SSrujana Challa if (!req) {
1105149f3b73SSrujana Challa rc = -ENOMEM;
1106149f3b73SSrujana Challa goto res_daddr_unmap;
1107149f3b73SSrujana Challa }
1108149f3b73SSrujana Challa req->hdr.sig = OTX2_MBOX_REQ_SIG;
1109149f3b73SSrujana Challa req->hdr.id = MBOX_MSG_CPT_INST_LMTST;
1110149f3b73SSrujana Challa
1111149f3b73SSrujana Challa inst = req->inst;
1112149f3b73SSrujana Challa /* Prepare CPT_INST_S */
1113149f3b73SSrujana Challa inst[0] = 0;
1114149f3b73SSrujana Challa inst[1] = res_daddr;
1115149f3b73SSrujana Challa /* AF PF FUNC */
1116149f3b73SSrujana Challa inst[2] = 0;
1117149f3b73SSrujana Challa /* Set QORD */
1118149f3b73SSrujana Challa inst[3] = 1;
1119149f3b73SSrujana Challa inst[4] = 0;
1120149f3b73SSrujana Challa inst[5] = 0;
1121149f3b73SSrujana Challa inst[6] = 0;
1122149f3b73SSrujana Challa /* Set EGRP */
1123149f3b73SSrujana Challa inst[7] = CPT_SE_IE_EGRP << 61;
1124149f3b73SSrujana Challa
1125149f3b73SSrujana Challa /* Subtract 1 from the NIX-CPT credit count to preserve
1126149f3b73SSrujana Challa * credit counts.
1127149f3b73SSrujana Challa */
1128149f3b73SSrujana Challa cpt_idx = (blkaddr == BLKADDR_CPT0) ? 0 : 1;
1129149f3b73SSrujana Challa rvu_write64(rvu, nix_blkaddr, NIX_AF_RX_CPTX_CREDIT(cpt_idx),
1130149f3b73SSrujana Challa BIT_ULL(22) - 1);
1131149f3b73SSrujana Challa
1132149f3b73SSrujana Challa otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, cpt_pf_num);
1133149f3b73SSrujana Challa rc = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, cpt_pf_num);
1134149f3b73SSrujana Challa if (rc)
1135149f3b73SSrujana Challa dev_warn(rvu->dev, "notification to pf %d failed\n",
1136149f3b73SSrujana Challa cpt_pf_num);
1137149f3b73SSrujana Challa /* Wait for CPT instruction to be completed */
1138149f3b73SSrujana Challa do {
1139149f3b73SSrujana Challa mdelay(1);
1140149f3b73SSrujana Challa if (*res == 0xFFFF)
1141149f3b73SSrujana Challa timeout--;
1142149f3b73SSrujana Challa else
1143149f3b73SSrujana Challa break;
1144149f3b73SSrujana Challa } while (timeout);
1145149f3b73SSrujana Challa
1146149f3b73SSrujana Challa if (timeout == 0)
1147149f3b73SSrujana Challa dev_warn(rvu->dev, "Poll for result hits hard loop counter\n");
1148149f3b73SSrujana Challa
1149149f3b73SSrujana Challa res_daddr_unmap:
1150149f3b73SSrujana Challa dma_unmap_single(rvu->dev, res_daddr, CPT_RES_LEN, DMA_BIDIRECTIONAL);
1151149f3b73SSrujana Challa res_free:
1152149f3b73SSrujana Challa kfree(res);
1153149f3b73SSrujana Challa
1154149f3b73SSrujana Challa return 0;
1155149f3b73SSrujana Challa }
1156149f3b73SSrujana Challa
1157149f3b73SSrujana Challa #define CTX_CAM_PF_FUNC GENMASK_ULL(61, 46)
1158149f3b73SSrujana Challa #define CTX_CAM_CPTR GENMASK_ULL(45, 0)
1159149f3b73SSrujana Challa
rvu_cpt_ctx_flush(struct rvu * rvu,u16 pcifunc)1160149f3b73SSrujana Challa int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc)
1161149f3b73SSrujana Challa {
1162149f3b73SSrujana Challa int nix_blkaddr, blkaddr;
1163149f3b73SSrujana Challa u16 max_ctx_entries, i;
1164149f3b73SSrujana Challa int slot = 0, num_lfs;
1165149f3b73SSrujana Challa u64 reg, cam_data;
1166149f3b73SSrujana Challa int rc;
1167149f3b73SSrujana Challa
1168149f3b73SSrujana Challa nix_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
1169149f3b73SSrujana Challa if (nix_blkaddr < 0)
1170149f3b73SSrujana Challa return -EINVAL;
1171149f3b73SSrujana Challa
1172149f3b73SSrujana Challa if (is_rvu_otx2(rvu))
1173149f3b73SSrujana Challa return 0;
1174149f3b73SSrujana Challa
1175149f3b73SSrujana Challa blkaddr = (nix_blkaddr == BLKADDR_NIX1) ? BLKADDR_CPT1 : BLKADDR_CPT0;
1176149f3b73SSrujana Challa
1177149f3b73SSrujana Challa /* Submit CPT_INST_S to track when all packets have been
1178149f3b73SSrujana Challa * flushed through for the NIX PF FUNC in inline inbound case.
1179149f3b73SSrujana Challa */
1180149f3b73SSrujana Challa rc = cpt_inline_inb_lf_cmd_send(rvu, blkaddr, nix_blkaddr);
1181149f3b73SSrujana Challa if (rc)
1182149f3b73SSrujana Challa return rc;
1183149f3b73SSrujana Challa
1184149f3b73SSrujana Challa /* Wait for rxc entries to be flushed out */
1185149f3b73SSrujana Challa cpt_rxc_teardown(rvu, blkaddr);
1186149f3b73SSrujana Challa
1187149f3b73SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS0);
1188149f3b73SSrujana Challa max_ctx_entries = (reg >> 48) & 0xFFF;
1189149f3b73SSrujana Challa
1190149f3b73SSrujana Challa mutex_lock(&rvu->rsrc_lock);
1191149f3b73SSrujana Challa
1192149f3b73SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
1193149f3b73SSrujana Challa blkaddr);
1194149f3b73SSrujana Challa if (num_lfs == 0) {
1195149f3b73SSrujana Challa dev_warn(rvu->dev, "CPT LF is not configured\n");
1196149f3b73SSrujana Challa goto unlock;
1197149f3b73SSrujana Challa }
1198149f3b73SSrujana Challa
1199149f3b73SSrujana Challa /* Enable BAR2 ALIAS for this pcifunc. */
1200149f3b73SSrujana Challa reg = BIT_ULL(16) | pcifunc;
12015c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
1202149f3b73SSrujana Challa
1203149f3b73SSrujana Challa for (i = 0; i < max_ctx_entries; i++) {
1204149f3b73SSrujana Challa cam_data = rvu_read64(rvu, blkaddr, CPT_AF_CTX_CAM_DATA(i));
1205149f3b73SSrujana Challa
1206149f3b73SSrujana Challa if ((FIELD_GET(CTX_CAM_PF_FUNC, cam_data) == pcifunc) &&
1207149f3b73SSrujana Challa FIELD_GET(CTX_CAM_CPTR, cam_data)) {
1208149f3b73SSrujana Challa reg = BIT_ULL(46) | FIELD_GET(CTX_CAM_CPTR, cam_data);
1209149f3b73SSrujana Challa rvu_write64(rvu, blkaddr,
1210149f3b73SSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTX_FLUSH),
1211149f3b73SSrujana Challa reg);
1212149f3b73SSrujana Challa }
1213149f3b73SSrujana Challa }
12145c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
1215149f3b73SSrujana Challa
1216149f3b73SSrujana Challa unlock:
1217149f3b73SSrujana Challa mutex_unlock(&rvu->rsrc_lock);
1218149f3b73SSrujana Challa
1219149f3b73SSrujana Challa return 0;
1220149f3b73SSrujana Challa }
122141b166e5SSrujana Challa
rvu_cpt_init(struct rvu * rvu)122241b166e5SSrujana Challa int rvu_cpt_init(struct rvu *rvu)
122341b166e5SSrujana Challa {
122441b166e5SSrujana Challa /* Retrieve CPT PF number */
122541b166e5SSrujana Challa rvu->cpt_pf_num = get_cpt_pf_num(rvu);
1226b814cc90SSrujana Challa spin_lock_init(&rvu->cpt_intr_lock);
1227b814cc90SSrujana Challa
122841b166e5SSrujana Challa return 0;
122941b166e5SSrujana Challa }
1230