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