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);
73*b814cc90SSrujana Challa
74*b814cc90SSrujana Challa spin_lock(&rvu->cpt_intr_lock);
75*b814cc90SSrujana Challa block->cpt_flt_eng_map[vec] |= BIT_ULL(i);
76*b814cc90SSrujana Challa val = rvu_read64(rvu, blkaddr, CPT_AF_EXEX_STS(eng));
77*b814cc90SSrujana Challa val = val & 0x3;
78*b814cc90SSrujana Challa if (val == 0x1 || val == 0x2)
79*b814cc90SSrujana Challa block->cpt_rcvrd_eng_map[vec] |= BIT_ULL(i);
80*b814cc90SSrujana 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
is_valid_offset(struct rvu * rvu,struct cpt_rd_wr_reg_msg * req)635ae454086SSrujana Challa static bool is_valid_offset(struct rvu *rvu, struct cpt_rd_wr_reg_msg *req)
636ae454086SSrujana Challa {
637ae454086SSrujana Challa u64 offset = req->reg_offset;
638ae454086SSrujana Challa int blkaddr, num_lfs, lf;
639ae454086SSrujana Challa struct rvu_block *block;
640ae454086SSrujana Challa struct rvu_pfvf *pfvf;
641ae454086SSrujana Challa
642ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
643ecad2ce8SSrujana Challa if (blkaddr < 0)
644f3d671c7SDan Carpenter return false;
645ae454086SSrujana Challa
646ae454086SSrujana Challa /* Registers that can be accessed from PF/VF */
647ae454086SSrujana Challa if ((offset & 0xFF000) == CPT_AF_LFX_CTL(0) ||
648ae454086SSrujana Challa (offset & 0xFF000) == CPT_AF_LFX_CTL2(0)) {
649ae454086SSrujana Challa if (offset & 7)
650ae454086SSrujana Challa return false;
651ae454086SSrujana Challa
652ae454086SSrujana Challa lf = (offset & 0xFFF) >> 3;
653ae454086SSrujana Challa block = &rvu->hw->block[blkaddr];
654ae454086SSrujana Challa pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
655ae454086SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(pfvf, block->addr);
656ae454086SSrujana Challa if (lf >= num_lfs)
657ae454086SSrujana Challa /* Slot is not valid for that PF/VF */
658ae454086SSrujana Challa return false;
659ae454086SSrujana Challa
660ae454086SSrujana Challa /* Translate local LF used by VFs to global CPT LF */
661ae454086SSrujana Challa lf = rvu_get_lf(rvu, &rvu->hw->block[blkaddr],
662ae454086SSrujana Challa req->hdr.pcifunc, lf);
663ae454086SSrujana Challa if (lf < 0)
664ae454086SSrujana Challa return false;
665ae454086SSrujana Challa
666ae454086SSrujana Challa return true;
667ae454086SSrujana Challa } else if (!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK)) {
668ae454086SSrujana Challa /* Registers that can be accessed from PF */
669ae454086SSrujana Challa switch (offset) {
6709eef6e97SSrujana Challa case CPT_AF_DIAG:
671ae454086SSrujana Challa case CPT_AF_CTL:
672ae454086SSrujana Challa case CPT_AF_PF_FUNC:
673ae454086SSrujana Challa case CPT_AF_BLK_RST:
674ae454086SSrujana Challa case CPT_AF_CONSTANTS1:
675e4bbc5c5SSrujana Challa case CPT_AF_CTX_FLUSH_TIMER:
676ae454086SSrujana Challa return true;
677ae454086SSrujana Challa }
678ae454086SSrujana Challa
679ae454086SSrujana Challa switch (offset & 0xFF000) {
680ae454086SSrujana Challa case CPT_AF_EXEX_STS(0):
681ae454086SSrujana Challa case CPT_AF_EXEX_CTL(0):
682ae454086SSrujana Challa case CPT_AF_EXEX_CTL2(0):
683ae454086SSrujana Challa case CPT_AF_EXEX_UCODE_BASE(0):
684ae454086SSrujana Challa if (offset & 7)
685ae454086SSrujana Challa return false;
686ae454086SSrujana Challa break;
687ae454086SSrujana Challa default:
688ae454086SSrujana Challa return false;
689ae454086SSrujana Challa }
690ae454086SSrujana Challa return true;
691ae454086SSrujana Challa }
692ae454086SSrujana Challa return false;
693ae454086SSrujana Challa }
694ae454086SSrujana 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)695ae454086SSrujana Challa int rvu_mbox_handler_cpt_rd_wr_register(struct rvu *rvu,
696ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *req,
697ae454086SSrujana Challa struct cpt_rd_wr_reg_msg *rsp)
698ae454086SSrujana Challa {
699ae454086SSrujana Challa int blkaddr;
700ae454086SSrujana Challa
701ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
702ecad2ce8SSrujana Challa if (blkaddr < 0)
703ecad2ce8SSrujana Challa return blkaddr;
704ae454086SSrujana Challa
705ae454086SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */
706ae454086SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) &&
707ae454086SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc))
708ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
709ae454086SSrujana Challa
710ae454086SSrujana Challa rsp->reg_offset = req->reg_offset;
711ae454086SSrujana Challa rsp->ret_val = req->ret_val;
712ae454086SSrujana Challa rsp->is_write = req->is_write;
713ae454086SSrujana Challa
714ae454086SSrujana Challa if (!is_valid_offset(rvu, req))
715ae454086SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
716ae454086SSrujana Challa
717ae454086SSrujana Challa if (req->is_write)
718ae454086SSrujana Challa rvu_write64(rvu, blkaddr, req->reg_offset, req->val);
719ae454086SSrujana Challa else
720ae454086SSrujana Challa rsp->val = rvu_read64(rvu, blkaddr, req->reg_offset);
721ae454086SSrujana Challa
722ae454086SSrujana Challa return 0;
723ae454086SSrujana Challa }
724c57c58fdSSrujana Challa
get_ctx_pc(struct rvu * rvu,struct cpt_sts_rsp * rsp,int blkaddr)7252e2ee4cdSSrujana Challa static void get_ctx_pc(struct rvu *rvu, struct cpt_sts_rsp *rsp, int blkaddr)
7262e2ee4cdSSrujana Challa {
7272e2ee4cdSSrujana Challa if (is_rvu_otx2(rvu))
7282e2ee4cdSSrujana Challa return;
7292e2ee4cdSSrujana Challa
7302e2ee4cdSSrujana Challa rsp->ctx_mis_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_MIS_PC);
7312e2ee4cdSSrujana Challa rsp->ctx_hit_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_HIT_PC);
7322e2ee4cdSSrujana Challa rsp->ctx_aop_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_AOP_PC);
7332e2ee4cdSSrujana Challa rsp->ctx_aop_lat_pc = rvu_read64(rvu, blkaddr,
7342e2ee4cdSSrujana Challa CPT_AF_CTX_AOP_LATENCY_PC);
7352e2ee4cdSSrujana Challa rsp->ctx_ifetch_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_IFETCH_PC);
7362e2ee4cdSSrujana Challa rsp->ctx_ifetch_lat_pc = rvu_read64(rvu, blkaddr,
7372e2ee4cdSSrujana Challa CPT_AF_CTX_IFETCH_LATENCY_PC);
7382e2ee4cdSSrujana Challa rsp->ctx_ffetch_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC);
7392e2ee4cdSSrujana Challa rsp->ctx_ffetch_lat_pc = rvu_read64(rvu, blkaddr,
7402e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC);
7412e2ee4cdSSrujana Challa rsp->ctx_wback_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC);
7422e2ee4cdSSrujana Challa rsp->ctx_wback_lat_pc = rvu_read64(rvu, blkaddr,
7432e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC);
7442e2ee4cdSSrujana Challa rsp->ctx_psh_pc = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FFETCH_PC);
7452e2ee4cdSSrujana Challa rsp->ctx_psh_lat_pc = rvu_read64(rvu, blkaddr,
7462e2ee4cdSSrujana Challa CPT_AF_CTX_FFETCH_LATENCY_PC);
7472e2ee4cdSSrujana Challa rsp->ctx_err = rvu_read64(rvu, blkaddr, CPT_AF_CTX_ERR);
7482e2ee4cdSSrujana Challa rsp->ctx_enc_id = rvu_read64(rvu, blkaddr, CPT_AF_CTX_ENC_ID);
7492e2ee4cdSSrujana Challa rsp->ctx_flush_timer = rvu_read64(rvu, blkaddr, CPT_AF_CTX_FLUSH_TIMER);
7502e2ee4cdSSrujana Challa
7512e2ee4cdSSrujana Challa rsp->rxc_time = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME);
7522e2ee4cdSSrujana Challa rsp->rxc_time_cfg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG);
7532e2ee4cdSSrujana Challa rsp->rxc_active_sts = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS);
7542e2ee4cdSSrujana Challa rsp->rxc_zombie_sts = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ZOMBIE_STS);
7552e2ee4cdSSrujana Challa rsp->rxc_dfrg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_DFRG);
7562e2ee4cdSSrujana Challa rsp->x2p_link_cfg0 = rvu_read64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(0));
7572e2ee4cdSSrujana Challa rsp->x2p_link_cfg1 = rvu_read64(rvu, blkaddr, CPT_AF_X2PX_LINK_CFG(1));
7582e2ee4cdSSrujana Challa }
7592e2ee4cdSSrujana Challa
get_eng_sts(struct rvu * rvu,struct cpt_sts_rsp * rsp,int blkaddr)7602e2ee4cdSSrujana Challa static void get_eng_sts(struct rvu *rvu, struct cpt_sts_rsp *rsp, int blkaddr)
7612e2ee4cdSSrujana Challa {
7622e2ee4cdSSrujana Challa u16 max_ses, max_ies, max_aes;
7632e2ee4cdSSrujana Challa u32 e_min = 0, e_max = 0;
7642e2ee4cdSSrujana Challa u64 reg;
7652e2ee4cdSSrujana Challa
7662e2ee4cdSSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS1);
7672e2ee4cdSSrujana Challa max_ses = reg & 0xffff;
7682e2ee4cdSSrujana Challa max_ies = (reg >> 16) & 0xffff;
7692e2ee4cdSSrujana Challa max_aes = (reg >> 32) & 0xffff;
7702e2ee4cdSSrujana Challa
7712e2ee4cdSSrujana Challa /* Get AE status */
7722e2ee4cdSSrujana Challa e_min = max_ses + max_ies;
7732e2ee4cdSSrujana Challa e_max = max_ses + max_ies + max_aes;
7742e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, ae);
7752e2ee4cdSSrujana Challa /* Get SE status */
7762e2ee4cdSSrujana Challa e_min = 0;
7772e2ee4cdSSrujana Challa e_max = max_ses;
7782e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, se);
7792e2ee4cdSSrujana Challa /* Get IE status */
7802e2ee4cdSSrujana Challa e_min = max_ses;
7812e2ee4cdSSrujana Challa e_max = max_ses + max_ies;
7822e2ee4cdSSrujana Challa cpt_get_eng_sts(e_min, e_max, rsp, ie);
7832e2ee4cdSSrujana Challa }
7842e2ee4cdSSrujana Challa
rvu_mbox_handler_cpt_sts(struct rvu * rvu,struct cpt_sts_req * req,struct cpt_sts_rsp * rsp)7852e2ee4cdSSrujana Challa int rvu_mbox_handler_cpt_sts(struct rvu *rvu, struct cpt_sts_req *req,
7862e2ee4cdSSrujana Challa struct cpt_sts_rsp *rsp)
7872e2ee4cdSSrujana Challa {
7882e2ee4cdSSrujana Challa int blkaddr;
7892e2ee4cdSSrujana Challa
7902e2ee4cdSSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
7912e2ee4cdSSrujana Challa if (blkaddr < 0)
7922e2ee4cdSSrujana Challa return blkaddr;
7932e2ee4cdSSrujana Challa
7942e2ee4cdSSrujana Challa /* This message is accepted only if sent from CPT PF/VF */
7952e2ee4cdSSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) &&
7962e2ee4cdSSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc))
7972e2ee4cdSSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
7982e2ee4cdSSrujana Challa
7992e2ee4cdSSrujana Challa get_ctx_pc(rvu, rsp, blkaddr);
8002e2ee4cdSSrujana Challa
8012e2ee4cdSSrujana Challa /* Get CPT engines status */
8022e2ee4cdSSrujana Challa get_eng_sts(rvu, rsp, blkaddr);
8032e2ee4cdSSrujana Challa
8042e2ee4cdSSrujana Challa /* Read CPT instruction PC registers */
8052e2ee4cdSSrujana Challa rsp->inst_req_pc = rvu_read64(rvu, blkaddr, CPT_AF_INST_REQ_PC);
8062e2ee4cdSSrujana Challa rsp->inst_lat_pc = rvu_read64(rvu, blkaddr, CPT_AF_INST_LATENCY_PC);
8072e2ee4cdSSrujana Challa rsp->rd_req_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_REQ_PC);
8082e2ee4cdSSrujana Challa rsp->rd_lat_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_LATENCY_PC);
8092e2ee4cdSSrujana Challa rsp->rd_uc_pc = rvu_read64(rvu, blkaddr, CPT_AF_RD_UC_PC);
8102e2ee4cdSSrujana Challa rsp->active_cycles_pc = rvu_read64(rvu, blkaddr,
8112e2ee4cdSSrujana Challa CPT_AF_ACTIVE_CYCLES_PC);
8122e2ee4cdSSrujana Challa rsp->exe_err_info = rvu_read64(rvu, blkaddr, CPT_AF_EXE_ERR_INFO);
8132e2ee4cdSSrujana Challa rsp->cptclk_cnt = rvu_read64(rvu, blkaddr, CPT_AF_CPTCLK_CNT);
8142e2ee4cdSSrujana Challa rsp->diag = rvu_read64(rvu, blkaddr, CPT_AF_DIAG);
8152e2ee4cdSSrujana Challa
8162e2ee4cdSSrujana Challa return 0;
8172e2ee4cdSSrujana Challa }
8182e2ee4cdSSrujana Challa
819ecad2ce8SSrujana Challa #define RXC_ZOMBIE_THRES GENMASK_ULL(59, 48)
820ecad2ce8SSrujana Challa #define RXC_ZOMBIE_LIMIT GENMASK_ULL(43, 32)
821ecad2ce8SSrujana Challa #define RXC_ACTIVE_THRES GENMASK_ULL(27, 16)
822ecad2ce8SSrujana Challa #define RXC_ACTIVE_LIMIT GENMASK_ULL(11, 0)
823ecad2ce8SSrujana Challa #define RXC_ACTIVE_COUNT GENMASK_ULL(60, 48)
824ecad2ce8SSrujana Challa #define RXC_ZOMBIE_COUNT GENMASK_ULL(60, 48)
825ecad2ce8SSrujana Challa
cpt_rxc_time_cfg(struct rvu * rvu,struct cpt_rxc_time_cfg_req * req,int blkaddr,struct cpt_rxc_time_cfg_req * save)826ecad2ce8SSrujana Challa static void cpt_rxc_time_cfg(struct rvu *rvu, struct cpt_rxc_time_cfg_req *req,
827e2784acbSNithin Dabilpuram int blkaddr, struct cpt_rxc_time_cfg_req *save)
828ecad2ce8SSrujana Challa {
829ecad2ce8SSrujana Challa u64 dfrg_reg;
830ecad2ce8SSrujana Challa
831e2784acbSNithin Dabilpuram if (save) {
832e2784acbSNithin Dabilpuram /* Save older config */
833e2784acbSNithin Dabilpuram dfrg_reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_DFRG);
834e2784acbSNithin Dabilpuram save->zombie_thres = FIELD_GET(RXC_ZOMBIE_THRES, dfrg_reg);
835e2784acbSNithin Dabilpuram save->zombie_limit = FIELD_GET(RXC_ZOMBIE_LIMIT, dfrg_reg);
836e2784acbSNithin Dabilpuram save->active_thres = FIELD_GET(RXC_ACTIVE_THRES, dfrg_reg);
837e2784acbSNithin Dabilpuram save->active_limit = FIELD_GET(RXC_ACTIVE_LIMIT, dfrg_reg);
838e2784acbSNithin Dabilpuram
839e2784acbSNithin Dabilpuram save->step = rvu_read64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG);
840e2784acbSNithin Dabilpuram }
841e2784acbSNithin Dabilpuram
842ecad2ce8SSrujana Challa dfrg_reg = FIELD_PREP(RXC_ZOMBIE_THRES, req->zombie_thres);
843ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ZOMBIE_LIMIT, req->zombie_limit);
844ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ACTIVE_THRES, req->active_thres);
845ecad2ce8SSrujana Challa dfrg_reg |= FIELD_PREP(RXC_ACTIVE_LIMIT, req->active_limit);
846ecad2ce8SSrujana Challa
847ecad2ce8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RXC_TIME_CFG, req->step);
848ecad2ce8SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_RXC_DFRG, dfrg_reg);
849ecad2ce8SSrujana Challa }
850ecad2ce8SSrujana Challa
rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu * rvu,struct cpt_rxc_time_cfg_req * req,struct msg_rsp * rsp)851ecad2ce8SSrujana Challa int rvu_mbox_handler_cpt_rxc_time_cfg(struct rvu *rvu,
852ecad2ce8SSrujana Challa struct cpt_rxc_time_cfg_req *req,
853ecad2ce8SSrujana Challa struct msg_rsp *rsp)
854ecad2ce8SSrujana Challa {
855ecad2ce8SSrujana Challa int blkaddr;
856ecad2ce8SSrujana Challa
857ecad2ce8SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
858ecad2ce8SSrujana Challa if (blkaddr < 0)
859ecad2ce8SSrujana Challa return blkaddr;
860ecad2ce8SSrujana Challa
861ecad2ce8SSrujana Challa /* This message is accepted only if sent from CPT PF/VF */
862ecad2ce8SSrujana Challa if (!is_cpt_pf(rvu, req->hdr.pcifunc) &&
863ecad2ce8SSrujana Challa !is_cpt_vf(rvu, req->hdr.pcifunc))
864ecad2ce8SSrujana Challa return CPT_AF_ERR_ACCESS_DENIED;
865ecad2ce8SSrujana Challa
866e2784acbSNithin Dabilpuram cpt_rxc_time_cfg(rvu, req, blkaddr, NULL);
867ecad2ce8SSrujana Challa
868ecad2ce8SSrujana Challa return 0;
869ecad2ce8SSrujana Challa }
870ecad2ce8SSrujana Challa
rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu * rvu,struct msg_req * req,struct msg_rsp * rsp)871149f3b73SSrujana Challa int rvu_mbox_handler_cpt_ctx_cache_sync(struct rvu *rvu, struct msg_req *req,
872149f3b73SSrujana Challa struct msg_rsp *rsp)
873149f3b73SSrujana Challa {
874149f3b73SSrujana Challa return rvu_cpt_ctx_flush(rvu, req->hdr.pcifunc);
875149f3b73SSrujana Challa }
876149f3b73SSrujana Challa
rvu_mbox_handler_cpt_lf_reset(struct rvu * rvu,struct cpt_lf_rst_req * req,struct msg_rsp * rsp)877b7e41527SSrujana Challa int rvu_mbox_handler_cpt_lf_reset(struct rvu *rvu, struct cpt_lf_rst_req *req,
878b7e41527SSrujana Challa struct msg_rsp *rsp)
879b7e41527SSrujana Challa {
880b7e41527SSrujana Challa u16 pcifunc = req->hdr.pcifunc;
881b7e41527SSrujana Challa struct rvu_block *block;
882b7e41527SSrujana Challa int cptlf, blkaddr, ret;
883b7e41527SSrujana Challa u16 actual_slot;
884b7e41527SSrujana Challa u64 ctl, ctl2;
885b7e41527SSrujana Challa
886b7e41527SSrujana Challa blkaddr = rvu_get_blkaddr_from_slot(rvu, BLKTYPE_CPT, pcifunc,
887b7e41527SSrujana Challa req->slot, &actual_slot);
888b7e41527SSrujana Challa if (blkaddr < 0)
889b7e41527SSrujana Challa return CPT_AF_ERR_LF_INVALID;
890b7e41527SSrujana Challa
891b7e41527SSrujana Challa block = &rvu->hw->block[blkaddr];
892b7e41527SSrujana Challa
893b7e41527SSrujana Challa cptlf = rvu_get_lf(rvu, block, pcifunc, actual_slot);
894b7e41527SSrujana Challa if (cptlf < 0)
895b7e41527SSrujana Challa return CPT_AF_ERR_LF_INVALID;
896b7e41527SSrujana Challa ctl = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf));
897b7e41527SSrujana Challa ctl2 = rvu_read64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf));
898b7e41527SSrujana Challa
899b7e41527SSrujana Challa ret = rvu_lf_reset(rvu, block, cptlf);
900b7e41527SSrujana Challa if (ret)
901b7e41527SSrujana Challa dev_err(rvu->dev, "Failed to reset blkaddr %d LF%d\n",
902b7e41527SSrujana Challa block->addr, cptlf);
903b7e41527SSrujana Challa
904b7e41527SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL(cptlf), ctl);
905b7e41527SSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_LFX_CTL2(cptlf), ctl2);
906b7e41527SSrujana Challa
907b7e41527SSrujana Challa return 0;
908b7e41527SSrujana Challa }
909b7e41527SSrujana 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)910*b814cc90SSrujana Challa int rvu_mbox_handler_cpt_flt_eng_info(struct rvu *rvu, struct cpt_flt_eng_info_req *req,
911*b814cc90SSrujana Challa struct cpt_flt_eng_info_rsp *rsp)
912*b814cc90SSrujana Challa {
913*b814cc90SSrujana Challa struct rvu_block *block;
914*b814cc90SSrujana Challa unsigned long flags;
915*b814cc90SSrujana Challa int blkaddr, vec;
916*b814cc90SSrujana Challa
917*b814cc90SSrujana Challa blkaddr = validate_and_get_cpt_blkaddr(req->blkaddr);
918*b814cc90SSrujana Challa if (blkaddr < 0)
919*b814cc90SSrujana Challa return blkaddr;
920*b814cc90SSrujana Challa
921*b814cc90SSrujana Challa block = &rvu->hw->block[blkaddr];
922*b814cc90SSrujana Challa for (vec = 0; vec < CPT_10K_AF_INT_VEC_RVU; vec++) {
923*b814cc90SSrujana Challa spin_lock_irqsave(&rvu->cpt_intr_lock, flags);
924*b814cc90SSrujana Challa rsp->flt_eng_map[vec] = block->cpt_flt_eng_map[vec];
925*b814cc90SSrujana Challa rsp->rcvrd_eng_map[vec] = block->cpt_rcvrd_eng_map[vec];
926*b814cc90SSrujana Challa if (req->reset) {
927*b814cc90SSrujana Challa block->cpt_flt_eng_map[vec] = 0x0;
928*b814cc90SSrujana Challa block->cpt_rcvrd_eng_map[vec] = 0x0;
929*b814cc90SSrujana Challa }
930*b814cc90SSrujana Challa spin_unlock_irqrestore(&rvu->cpt_intr_lock, flags);
931*b814cc90SSrujana Challa }
932*b814cc90SSrujana Challa return 0;
933*b814cc90SSrujana Challa }
934*b814cc90SSrujana Challa
cpt_rxc_teardown(struct rvu * rvu,int blkaddr)935149f3b73SSrujana Challa static void cpt_rxc_teardown(struct rvu *rvu, int blkaddr)
936149f3b73SSrujana Challa {
937e2784acbSNithin Dabilpuram struct cpt_rxc_time_cfg_req req, prev;
938149f3b73SSrujana Challa int timeout = 2000;
939149f3b73SSrujana Challa u64 reg;
940149f3b73SSrujana Challa
941149f3b73SSrujana Challa if (is_rvu_otx2(rvu))
942149f3b73SSrujana Challa return;
943149f3b73SSrujana Challa
944149f3b73SSrujana Challa /* Set time limit to minimum values, so that rxc entries will be
945149f3b73SSrujana Challa * flushed out quickly.
946149f3b73SSrujana Challa */
947149f3b73SSrujana Challa req.step = 1;
948149f3b73SSrujana Challa req.zombie_thres = 1;
949149f3b73SSrujana Challa req.zombie_limit = 1;
950149f3b73SSrujana Challa req.active_thres = 1;
951149f3b73SSrujana Challa req.active_limit = 1;
952149f3b73SSrujana Challa
953e2784acbSNithin Dabilpuram cpt_rxc_time_cfg(rvu, &req, blkaddr, &prev);
954149f3b73SSrujana Challa
955149f3b73SSrujana Challa do {
956149f3b73SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ACTIVE_STS);
957149f3b73SSrujana Challa udelay(1);
958149f3b73SSrujana Challa if (FIELD_GET(RXC_ACTIVE_COUNT, reg))
959149f3b73SSrujana Challa timeout--;
960149f3b73SSrujana Challa else
961149f3b73SSrujana Challa break;
962149f3b73SSrujana Challa } while (timeout);
963149f3b73SSrujana Challa
964149f3b73SSrujana Challa if (timeout == 0)
965149f3b73SSrujana Challa dev_warn(rvu->dev, "Poll for RXC active count hits hard loop counter\n");
966149f3b73SSrujana Challa
967149f3b73SSrujana Challa timeout = 2000;
968149f3b73SSrujana Challa do {
969149f3b73SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_RXC_ZOMBIE_STS);
970149f3b73SSrujana Challa udelay(1);
971149f3b73SSrujana Challa if (FIELD_GET(RXC_ZOMBIE_COUNT, reg))
972149f3b73SSrujana Challa timeout--;
973149f3b73SSrujana Challa else
974149f3b73SSrujana Challa break;
975149f3b73SSrujana Challa } while (timeout);
976149f3b73SSrujana Challa
977149f3b73SSrujana Challa if (timeout == 0)
978149f3b73SSrujana Challa dev_warn(rvu->dev, "Poll for RXC zombie count hits hard loop counter\n");
979e2784acbSNithin Dabilpuram
980e2784acbSNithin Dabilpuram /* Restore config */
981e2784acbSNithin Dabilpuram cpt_rxc_time_cfg(rvu, &prev, blkaddr, NULL);
982149f3b73SSrujana Challa }
983149f3b73SSrujana Challa
9845c22fce6SSrujana Challa #define INFLIGHT GENMASK_ULL(8, 0)
9855c22fce6SSrujana Challa #define GRB_CNT GENMASK_ULL(39, 32)
9865c22fce6SSrujana Challa #define GWB_CNT GENMASK_ULL(47, 40)
9875c22fce6SSrujana Challa #define XQ_XOR GENMASK_ULL(63, 63)
9885c22fce6SSrujana Challa #define DQPTR GENMASK_ULL(19, 0)
9895c22fce6SSrujana Challa #define NQPTR GENMASK_ULL(51, 32)
990c57c58fdSSrujana Challa
cpt_lf_disable_iqueue(struct rvu * rvu,int blkaddr,int slot)991c57c58fdSSrujana Challa static void cpt_lf_disable_iqueue(struct rvu *rvu, int blkaddr, int slot)
992c57c58fdSSrujana Challa {
9935c22fce6SSrujana Challa int timeout = 1000000;
9945c22fce6SSrujana Challa u64 inprog, inst_ptr;
9955c22fce6SSrujana Challa u64 qsize, pending;
9965c22fce6SSrujana Challa int i = 0;
997c57c58fdSSrujana Challa
998c57c58fdSSrujana Challa /* Disable instructions enqueuing */
999c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr, CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTL), 0x0);
1000c57c58fdSSrujana Challa
1001c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr,
1002c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
10035c22fce6SSrujana Challa inprog |= BIT_ULL(16);
1004c57c58fdSSrujana Challa rvu_write64(rvu, blkaddr,
1005c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG), inprog);
1006c57c58fdSSrujana Challa
10075c22fce6SSrujana Challa qsize = rvu_read64(rvu, blkaddr,
10085c22fce6SSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_Q_SIZE)) & 0x7FFF;
10095c22fce6SSrujana Challa do {
10105c22fce6SSrujana Challa inst_ptr = rvu_read64(rvu, blkaddr,
10115c22fce6SSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_Q_INST_PTR));
10125c22fce6SSrujana Challa pending = (FIELD_GET(XQ_XOR, inst_ptr) * qsize * 40) +
10135c22fce6SSrujana Challa FIELD_GET(NQPTR, inst_ptr) -
10145c22fce6SSrujana Challa FIELD_GET(DQPTR, inst_ptr);
10155c22fce6SSrujana Challa udelay(1);
10165c22fce6SSrujana Challa timeout--;
10175c22fce6SSrujana Challa } while ((pending != 0) && (timeout != 0));
10185c22fce6SSrujana Challa
10195c22fce6SSrujana Challa if (timeout == 0)
10205c22fce6SSrujana Challa dev_warn(rvu->dev, "TIMEOUT: CPT poll on pending instructions\n");
10215c22fce6SSrujana Challa
10225c22fce6SSrujana Challa timeout = 1000000;
1023c57c58fdSSrujana Challa /* Wait for CPT queue to become execution-quiescent */
1024c57c58fdSSrujana Challa do {
1025c57c58fdSSrujana Challa inprog = rvu_read64(rvu, blkaddr,
1026c57c58fdSSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_INPROG));
1027c57c58fdSSrujana Challa
10285c22fce6SSrujana Challa if ((FIELD_GET(INFLIGHT, inprog) == 0) &&
10295c22fce6SSrujana Challa (FIELD_GET(GRB_CNT, inprog) == 0)) {
1030c57c58fdSSrujana Challa i++;
1031c57c58fdSSrujana Challa } else {
1032c57c58fdSSrujana Challa i = 0;
10335c22fce6SSrujana Challa timeout--;
1034c57c58fdSSrujana Challa }
10355c22fce6SSrujana Challa } while ((timeout != 0) && (i < 10));
1036c57c58fdSSrujana Challa
10375c22fce6SSrujana Challa if (timeout == 0)
10385c22fce6SSrujana Challa dev_warn(rvu->dev, "TIMEOUT: CPT poll on inflight count\n");
10395c22fce6SSrujana Challa /* Wait for 2 us to flush all queue writes to memory */
10405c22fce6SSrujana Challa udelay(2);
1041c57c58fdSSrujana Challa }
1042c57c58fdSSrujana Challa
rvu_cpt_lf_teardown(struct rvu * rvu,u16 pcifunc,int blkaddr,int lf,int slot)10437054d39cSNithin Dabilpuram int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int lf, int slot)
1044c57c58fdSSrujana Challa {
1045c57c58fdSSrujana Challa u64 reg;
1046c57c58fdSSrujana Challa
1047149f3b73SSrujana Challa if (is_cpt_pf(rvu, pcifunc) || is_cpt_vf(rvu, pcifunc))
1048149f3b73SSrujana Challa cpt_rxc_teardown(rvu, blkaddr);
1049149f3b73SSrujana Challa
10505c22fce6SSrujana Challa mutex_lock(&rvu->alias_lock);
1051c57c58fdSSrujana Challa /* Enable BAR2 ALIAS for this pcifunc. */
1052c57c58fdSSrujana Challa reg = BIT_ULL(16) | pcifunc;
10535c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
1054c57c58fdSSrujana Challa
1055c57c58fdSSrujana Challa cpt_lf_disable_iqueue(rvu, blkaddr, slot);
1056c57c58fdSSrujana Challa
10575c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
10585c22fce6SSrujana Challa mutex_unlock(&rvu->alias_lock);
1059c57c58fdSSrujana Challa
1060c57c58fdSSrujana Challa return 0;
1061c57c58fdSSrujana Challa }
1062149f3b73SSrujana Challa
1063149f3b73SSrujana Challa #define CPT_RES_LEN 16
1064149f3b73SSrujana Challa #define CPT_SE_IE_EGRP 1ULL
1065149f3b73SSrujana Challa
cpt_inline_inb_lf_cmd_send(struct rvu * rvu,int blkaddr,int nix_blkaddr)1066149f3b73SSrujana Challa static int cpt_inline_inb_lf_cmd_send(struct rvu *rvu, int blkaddr,
1067149f3b73SSrujana Challa int nix_blkaddr)
1068149f3b73SSrujana Challa {
106941b166e5SSrujana Challa int cpt_pf_num = rvu->cpt_pf_num;
1070149f3b73SSrujana Challa struct cpt_inst_lmtst_req *req;
1071149f3b73SSrujana Challa dma_addr_t res_daddr;
1072149f3b73SSrujana Challa int timeout = 3000;
1073149f3b73SSrujana Challa u8 cpt_idx;
1074149f3b73SSrujana Challa u64 *inst;
1075149f3b73SSrujana Challa u16 *res;
1076149f3b73SSrujana Challa int rc;
1077149f3b73SSrujana Challa
1078149f3b73SSrujana Challa res = kzalloc(CPT_RES_LEN, GFP_KERNEL);
1079149f3b73SSrujana Challa if (!res)
1080149f3b73SSrujana Challa return -ENOMEM;
1081149f3b73SSrujana Challa
1082149f3b73SSrujana Challa res_daddr = dma_map_single(rvu->dev, res, CPT_RES_LEN,
1083149f3b73SSrujana Challa DMA_BIDIRECTIONAL);
1084149f3b73SSrujana Challa if (dma_mapping_error(rvu->dev, res_daddr)) {
1085149f3b73SSrujana Challa dev_err(rvu->dev, "DMA mapping failed for CPT result\n");
1086149f3b73SSrujana Challa rc = -EFAULT;
1087149f3b73SSrujana Challa goto res_free;
1088149f3b73SSrujana Challa }
1089149f3b73SSrujana Challa *res = 0xFFFF;
1090149f3b73SSrujana Challa
1091149f3b73SSrujana Challa /* Send mbox message to CPT PF */
1092149f3b73SSrujana Challa req = (struct cpt_inst_lmtst_req *)
1093149f3b73SSrujana Challa otx2_mbox_alloc_msg_rsp(&rvu->afpf_wq_info.mbox_up,
1094149f3b73SSrujana Challa cpt_pf_num, sizeof(*req),
1095149f3b73SSrujana Challa sizeof(struct msg_rsp));
1096149f3b73SSrujana Challa if (!req) {
1097149f3b73SSrujana Challa rc = -ENOMEM;
1098149f3b73SSrujana Challa goto res_daddr_unmap;
1099149f3b73SSrujana Challa }
1100149f3b73SSrujana Challa req->hdr.sig = OTX2_MBOX_REQ_SIG;
1101149f3b73SSrujana Challa req->hdr.id = MBOX_MSG_CPT_INST_LMTST;
1102149f3b73SSrujana Challa
1103149f3b73SSrujana Challa inst = req->inst;
1104149f3b73SSrujana Challa /* Prepare CPT_INST_S */
1105149f3b73SSrujana Challa inst[0] = 0;
1106149f3b73SSrujana Challa inst[1] = res_daddr;
1107149f3b73SSrujana Challa /* AF PF FUNC */
1108149f3b73SSrujana Challa inst[2] = 0;
1109149f3b73SSrujana Challa /* Set QORD */
1110149f3b73SSrujana Challa inst[3] = 1;
1111149f3b73SSrujana Challa inst[4] = 0;
1112149f3b73SSrujana Challa inst[5] = 0;
1113149f3b73SSrujana Challa inst[6] = 0;
1114149f3b73SSrujana Challa /* Set EGRP */
1115149f3b73SSrujana Challa inst[7] = CPT_SE_IE_EGRP << 61;
1116149f3b73SSrujana Challa
1117149f3b73SSrujana Challa /* Subtract 1 from the NIX-CPT credit count to preserve
1118149f3b73SSrujana Challa * credit counts.
1119149f3b73SSrujana Challa */
1120149f3b73SSrujana Challa cpt_idx = (blkaddr == BLKADDR_CPT0) ? 0 : 1;
1121149f3b73SSrujana Challa rvu_write64(rvu, nix_blkaddr, NIX_AF_RX_CPTX_CREDIT(cpt_idx),
1122149f3b73SSrujana Challa BIT_ULL(22) - 1);
1123149f3b73SSrujana Challa
1124149f3b73SSrujana Challa otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, cpt_pf_num);
1125149f3b73SSrujana Challa rc = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, cpt_pf_num);
1126149f3b73SSrujana Challa if (rc)
1127149f3b73SSrujana Challa dev_warn(rvu->dev, "notification to pf %d failed\n",
1128149f3b73SSrujana Challa cpt_pf_num);
1129149f3b73SSrujana Challa /* Wait for CPT instruction to be completed */
1130149f3b73SSrujana Challa do {
1131149f3b73SSrujana Challa mdelay(1);
1132149f3b73SSrujana Challa if (*res == 0xFFFF)
1133149f3b73SSrujana Challa timeout--;
1134149f3b73SSrujana Challa else
1135149f3b73SSrujana Challa break;
1136149f3b73SSrujana Challa } while (timeout);
1137149f3b73SSrujana Challa
1138149f3b73SSrujana Challa if (timeout == 0)
1139149f3b73SSrujana Challa dev_warn(rvu->dev, "Poll for result hits hard loop counter\n");
1140149f3b73SSrujana Challa
1141149f3b73SSrujana Challa res_daddr_unmap:
1142149f3b73SSrujana Challa dma_unmap_single(rvu->dev, res_daddr, CPT_RES_LEN, DMA_BIDIRECTIONAL);
1143149f3b73SSrujana Challa res_free:
1144149f3b73SSrujana Challa kfree(res);
1145149f3b73SSrujana Challa
1146149f3b73SSrujana Challa return 0;
1147149f3b73SSrujana Challa }
1148149f3b73SSrujana Challa
1149149f3b73SSrujana Challa #define CTX_CAM_PF_FUNC GENMASK_ULL(61, 46)
1150149f3b73SSrujana Challa #define CTX_CAM_CPTR GENMASK_ULL(45, 0)
1151149f3b73SSrujana Challa
rvu_cpt_ctx_flush(struct rvu * rvu,u16 pcifunc)1152149f3b73SSrujana Challa int rvu_cpt_ctx_flush(struct rvu *rvu, u16 pcifunc)
1153149f3b73SSrujana Challa {
1154149f3b73SSrujana Challa int nix_blkaddr, blkaddr;
1155149f3b73SSrujana Challa u16 max_ctx_entries, i;
1156149f3b73SSrujana Challa int slot = 0, num_lfs;
1157149f3b73SSrujana Challa u64 reg, cam_data;
1158149f3b73SSrujana Challa int rc;
1159149f3b73SSrujana Challa
1160149f3b73SSrujana Challa nix_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
1161149f3b73SSrujana Challa if (nix_blkaddr < 0)
1162149f3b73SSrujana Challa return -EINVAL;
1163149f3b73SSrujana Challa
1164149f3b73SSrujana Challa if (is_rvu_otx2(rvu))
1165149f3b73SSrujana Challa return 0;
1166149f3b73SSrujana Challa
1167149f3b73SSrujana Challa blkaddr = (nix_blkaddr == BLKADDR_NIX1) ? BLKADDR_CPT1 : BLKADDR_CPT0;
1168149f3b73SSrujana Challa
1169149f3b73SSrujana Challa /* Submit CPT_INST_S to track when all packets have been
1170149f3b73SSrujana Challa * flushed through for the NIX PF FUNC in inline inbound case.
1171149f3b73SSrujana Challa */
1172149f3b73SSrujana Challa rc = cpt_inline_inb_lf_cmd_send(rvu, blkaddr, nix_blkaddr);
1173149f3b73SSrujana Challa if (rc)
1174149f3b73SSrujana Challa return rc;
1175149f3b73SSrujana Challa
1176149f3b73SSrujana Challa /* Wait for rxc entries to be flushed out */
1177149f3b73SSrujana Challa cpt_rxc_teardown(rvu, blkaddr);
1178149f3b73SSrujana Challa
1179149f3b73SSrujana Challa reg = rvu_read64(rvu, blkaddr, CPT_AF_CONSTANTS0);
1180149f3b73SSrujana Challa max_ctx_entries = (reg >> 48) & 0xFFF;
1181149f3b73SSrujana Challa
1182149f3b73SSrujana Challa mutex_lock(&rvu->rsrc_lock);
1183149f3b73SSrujana Challa
1184149f3b73SSrujana Challa num_lfs = rvu_get_rsrc_mapcount(rvu_get_pfvf(rvu, pcifunc),
1185149f3b73SSrujana Challa blkaddr);
1186149f3b73SSrujana Challa if (num_lfs == 0) {
1187149f3b73SSrujana Challa dev_warn(rvu->dev, "CPT LF is not configured\n");
1188149f3b73SSrujana Challa goto unlock;
1189149f3b73SSrujana Challa }
1190149f3b73SSrujana Challa
1191149f3b73SSrujana Challa /* Enable BAR2 ALIAS for this pcifunc. */
1192149f3b73SSrujana Challa reg = BIT_ULL(16) | pcifunc;
11935c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, reg);
1194149f3b73SSrujana Challa
1195149f3b73SSrujana Challa for (i = 0; i < max_ctx_entries; i++) {
1196149f3b73SSrujana Challa cam_data = rvu_read64(rvu, blkaddr, CPT_AF_CTX_CAM_DATA(i));
1197149f3b73SSrujana Challa
1198149f3b73SSrujana Challa if ((FIELD_GET(CTX_CAM_PF_FUNC, cam_data) == pcifunc) &&
1199149f3b73SSrujana Challa FIELD_GET(CTX_CAM_CPTR, cam_data)) {
1200149f3b73SSrujana Challa reg = BIT_ULL(46) | FIELD_GET(CTX_CAM_CPTR, cam_data);
1201149f3b73SSrujana Challa rvu_write64(rvu, blkaddr,
1202149f3b73SSrujana Challa CPT_AF_BAR2_ALIASX(slot, CPT_LF_CTX_FLUSH),
1203149f3b73SSrujana Challa reg);
1204149f3b73SSrujana Challa }
1205149f3b73SSrujana Challa }
12065c22fce6SSrujana Challa rvu_bar2_sel_write64(rvu, blkaddr, CPT_AF_BAR2_SEL, 0);
1207149f3b73SSrujana Challa
1208149f3b73SSrujana Challa unlock:
1209149f3b73SSrujana Challa mutex_unlock(&rvu->rsrc_lock);
1210149f3b73SSrujana Challa
1211149f3b73SSrujana Challa return 0;
1212149f3b73SSrujana Challa }
121341b166e5SSrujana Challa
rvu_cpt_init(struct rvu * rvu)121441b166e5SSrujana Challa int rvu_cpt_init(struct rvu *rvu)
121541b166e5SSrujana Challa {
121641b166e5SSrujana Challa /* Retrieve CPT PF number */
121741b166e5SSrujana Challa rvu->cpt_pf_num = get_cpt_pf_num(rvu);
1218*b814cc90SSrujana Challa spin_lock_init(&rvu->cpt_intr_lock);
1219*b814cc90SSrujana Challa
122041b166e5SSrujana Challa return 0;
122141b166e5SSrujana Challa }
1222