xref: /openbmc/linux/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
143ac0b82SSrujana Challa // SPDX-License-Identifier: GPL-2.0-only
243ac0b82SSrujana Challa /* Copyright (C) 2020 Marvell. */
343ac0b82SSrujana Challa 
443ac0b82SSrujana Challa #include <linux/ctype.h>
543ac0b82SSrujana Challa #include <linux/firmware.h>
643ac0b82SSrujana Challa #include "otx2_cptpf_ucode.h"
743ac0b82SSrujana Challa #include "otx2_cpt_common.h"
843ac0b82SSrujana Challa #include "otx2_cptpf.h"
978506c2aSSrujana Challa #include "otx2_cptlf.h"
1078506c2aSSrujana Challa #include "otx2_cpt_reqmgr.h"
1143ac0b82SSrujana Challa #include "rvu_reg.h"
1243ac0b82SSrujana Challa 
1343ac0b82SSrujana Challa #define CSR_DELAY 30
1443ac0b82SSrujana Challa 
1543ac0b82SSrujana Challa #define LOADFVC_RLEN 8
1643ac0b82SSrujana Challa #define LOADFVC_MAJOR_OP 0x01
1743ac0b82SSrujana Challa #define LOADFVC_MINOR_OP 0x08
1843ac0b82SSrujana Challa 
1940a645f7SSrujana Challa #define CTX_FLUSH_TIMER_CNT 0xFFFFFF
2040a645f7SSrujana Challa 
2143ac0b82SSrujana Challa struct fw_info_t {
2243ac0b82SSrujana Challa 	struct list_head ucodes;
2343ac0b82SSrujana Challa };
2443ac0b82SSrujana Challa 
get_cores_bmap(struct device * dev,struct otx2_cpt_eng_grp_info * eng_grp)2543ac0b82SSrujana Challa static struct otx2_cpt_bitmap get_cores_bmap(struct device *dev,
2643ac0b82SSrujana Challa 					struct otx2_cpt_eng_grp_info *eng_grp)
2743ac0b82SSrujana Challa {
2843ac0b82SSrujana Challa 	struct otx2_cpt_bitmap bmap = { {0} };
2943ac0b82SSrujana Challa 	bool found = false;
3043ac0b82SSrujana Challa 	int i;
3143ac0b82SSrujana Challa 
3210371b62SDan Carpenter 	if (eng_grp->g->engs_num < 0 ||
3310371b62SDan Carpenter 	    eng_grp->g->engs_num > OTX2_CPT_MAX_ENGINES) {
3443ac0b82SSrujana Challa 		dev_err(dev, "unsupported number of engines %d on octeontx2\n",
3543ac0b82SSrujana Challa 			eng_grp->g->engs_num);
3643ac0b82SSrujana Challa 		return bmap;
3743ac0b82SSrujana Challa 	}
3843ac0b82SSrujana Challa 
3943ac0b82SSrujana Challa 	for (i = 0; i  < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
4043ac0b82SSrujana Challa 		if (eng_grp->engs[i].type) {
4143ac0b82SSrujana Challa 			bitmap_or(bmap.bits, bmap.bits,
4243ac0b82SSrujana Challa 				  eng_grp->engs[i].bmap,
4343ac0b82SSrujana Challa 				  eng_grp->g->engs_num);
4443ac0b82SSrujana Challa 			bmap.size = eng_grp->g->engs_num;
4543ac0b82SSrujana Challa 			found = true;
4643ac0b82SSrujana Challa 		}
4743ac0b82SSrujana Challa 	}
4843ac0b82SSrujana Challa 
4943ac0b82SSrujana Challa 	if (!found)
5043ac0b82SSrujana Challa 		dev_err(dev, "No engines reserved for engine group %d\n",
5143ac0b82SSrujana Challa 			eng_grp->idx);
5243ac0b82SSrujana Challa 	return bmap;
5343ac0b82SSrujana Challa }
5443ac0b82SSrujana Challa 
is_eng_type(int val,int eng_type)5543ac0b82SSrujana Challa static int is_eng_type(int val, int eng_type)
5643ac0b82SSrujana Challa {
5743ac0b82SSrujana Challa 	return val & (1 << eng_type);
5843ac0b82SSrujana Challa }
5943ac0b82SSrujana Challa 
is_2nd_ucode_used(struct otx2_cpt_eng_grp_info * eng_grp)6043ac0b82SSrujana Challa static int is_2nd_ucode_used(struct otx2_cpt_eng_grp_info *eng_grp)
6143ac0b82SSrujana Challa {
6243ac0b82SSrujana Challa 	if (eng_grp->ucode[1].type)
6343ac0b82SSrujana Challa 		return true;
6443ac0b82SSrujana Challa 	else
6543ac0b82SSrujana Challa 		return false;
6643ac0b82SSrujana Challa }
6743ac0b82SSrujana Challa 
set_ucode_filename(struct otx2_cpt_ucode * ucode,const char * filename)6843ac0b82SSrujana Challa static void set_ucode_filename(struct otx2_cpt_ucode *ucode,
6943ac0b82SSrujana Challa 			       const char *filename)
7043ac0b82SSrujana Challa {
7128855860SWolfram Sang 	strscpy(ucode->filename, filename, OTX2_CPT_NAME_LENGTH);
7243ac0b82SSrujana Challa }
7343ac0b82SSrujana Challa 
get_eng_type_str(int eng_type)7443ac0b82SSrujana Challa static char *get_eng_type_str(int eng_type)
7543ac0b82SSrujana Challa {
7643ac0b82SSrujana Challa 	char *str = "unknown";
7743ac0b82SSrujana Challa 
7843ac0b82SSrujana Challa 	switch (eng_type) {
7943ac0b82SSrujana Challa 	case OTX2_CPT_SE_TYPES:
8043ac0b82SSrujana Challa 		str = "SE";
8143ac0b82SSrujana Challa 		break;
8243ac0b82SSrujana Challa 
8343ac0b82SSrujana Challa 	case OTX2_CPT_IE_TYPES:
8443ac0b82SSrujana Challa 		str = "IE";
8543ac0b82SSrujana Challa 		break;
8643ac0b82SSrujana Challa 
8743ac0b82SSrujana Challa 	case OTX2_CPT_AE_TYPES:
8843ac0b82SSrujana Challa 		str = "AE";
8943ac0b82SSrujana Challa 		break;
9043ac0b82SSrujana Challa 	}
9143ac0b82SSrujana Challa 	return str;
9243ac0b82SSrujana Challa }
9343ac0b82SSrujana Challa 
get_ucode_type_str(int ucode_type)9443ac0b82SSrujana Challa static char *get_ucode_type_str(int ucode_type)
9543ac0b82SSrujana Challa {
9643ac0b82SSrujana Challa 	char *str = "unknown";
9743ac0b82SSrujana Challa 
9843ac0b82SSrujana Challa 	switch (ucode_type) {
9943ac0b82SSrujana Challa 	case (1 << OTX2_CPT_SE_TYPES):
10043ac0b82SSrujana Challa 		str = "SE";
10143ac0b82SSrujana Challa 		break;
10243ac0b82SSrujana Challa 
10343ac0b82SSrujana Challa 	case (1 << OTX2_CPT_IE_TYPES):
10443ac0b82SSrujana Challa 		str = "IE";
10543ac0b82SSrujana Challa 		break;
10643ac0b82SSrujana Challa 
10743ac0b82SSrujana Challa 	case (1 << OTX2_CPT_AE_TYPES):
10843ac0b82SSrujana Challa 		str = "AE";
10943ac0b82SSrujana Challa 		break;
11043ac0b82SSrujana Challa 
11143ac0b82SSrujana Challa 	case (1 << OTX2_CPT_SE_TYPES | 1 << OTX2_CPT_IE_TYPES):
11243ac0b82SSrujana Challa 		str = "SE+IPSEC";
11343ac0b82SSrujana Challa 		break;
11443ac0b82SSrujana Challa 	}
11543ac0b82SSrujana Challa 	return str;
11643ac0b82SSrujana Challa }
11743ac0b82SSrujana Challa 
get_ucode_type(struct device * dev,struct otx2_cpt_ucode_hdr * ucode_hdr,int * ucode_type)11843ac0b82SSrujana Challa static int get_ucode_type(struct device *dev,
11943ac0b82SSrujana Challa 			  struct otx2_cpt_ucode_hdr *ucode_hdr,
12043ac0b82SSrujana Challa 			  int *ucode_type)
12143ac0b82SSrujana Challa {
12243ac0b82SSrujana Challa 	struct otx2_cptpf_dev *cptpf = dev_get_drvdata(dev);
12343ac0b82SSrujana Challa 	char ver_str_prefix[OTX2_CPT_UCODE_VER_STR_SZ];
12443ac0b82SSrujana Challa 	char tmp_ver_str[OTX2_CPT_UCODE_VER_STR_SZ];
12543ac0b82SSrujana Challa 	struct pci_dev *pdev = cptpf->pdev;
12643ac0b82SSrujana Challa 	int i, val = 0;
12743ac0b82SSrujana Challa 	u8 nn;
12843ac0b82SSrujana Challa 
12928855860SWolfram Sang 	strscpy(tmp_ver_str, ucode_hdr->ver_str, OTX2_CPT_UCODE_VER_STR_SZ);
13043ac0b82SSrujana Challa 	for (i = 0; i < strlen(tmp_ver_str); i++)
13143ac0b82SSrujana Challa 		tmp_ver_str[i] = tolower(tmp_ver_str[i]);
13243ac0b82SSrujana Challa 
13343ac0b82SSrujana Challa 	sprintf(ver_str_prefix, "ocpt-%02d", pdev->revision);
13443ac0b82SSrujana Challa 	if (!strnstr(tmp_ver_str, ver_str_prefix, OTX2_CPT_UCODE_VER_STR_SZ))
13543ac0b82SSrujana Challa 		return -EINVAL;
13643ac0b82SSrujana Challa 
13743ac0b82SSrujana Challa 	nn = ucode_hdr->ver_num.nn;
13843ac0b82SSrujana Challa 	if (strnstr(tmp_ver_str, "se-", OTX2_CPT_UCODE_VER_STR_SZ) &&
13943ac0b82SSrujana Challa 	    (nn == OTX2_CPT_SE_UC_TYPE1 || nn == OTX2_CPT_SE_UC_TYPE2 ||
14043ac0b82SSrujana Challa 	     nn == OTX2_CPT_SE_UC_TYPE3))
14143ac0b82SSrujana Challa 		val |= 1 << OTX2_CPT_SE_TYPES;
14243ac0b82SSrujana Challa 	if (strnstr(tmp_ver_str, "ie-", OTX2_CPT_UCODE_VER_STR_SZ) &&
14343ac0b82SSrujana Challa 	    (nn == OTX2_CPT_IE_UC_TYPE1 || nn == OTX2_CPT_IE_UC_TYPE2 ||
14443ac0b82SSrujana Challa 	     nn == OTX2_CPT_IE_UC_TYPE3))
14543ac0b82SSrujana Challa 		val |= 1 << OTX2_CPT_IE_TYPES;
14643ac0b82SSrujana Challa 	if (strnstr(tmp_ver_str, "ae", OTX2_CPT_UCODE_VER_STR_SZ) &&
14743ac0b82SSrujana Challa 	    nn == OTX2_CPT_AE_UC_TYPE)
14843ac0b82SSrujana Challa 		val |= 1 << OTX2_CPT_AE_TYPES;
14943ac0b82SSrujana Challa 
15043ac0b82SSrujana Challa 	*ucode_type = val;
15143ac0b82SSrujana Challa 
15243ac0b82SSrujana Challa 	if (!val)
15343ac0b82SSrujana Challa 		return -EINVAL;
15443ac0b82SSrujana Challa 
15543ac0b82SSrujana Challa 	return 0;
15643ac0b82SSrujana Challa }
15743ac0b82SSrujana Challa 
__write_ucode_base(struct otx2_cptpf_dev * cptpf,int eng,dma_addr_t dma_addr,int blkaddr)15843ac0b82SSrujana Challa static int __write_ucode_base(struct otx2_cptpf_dev *cptpf, int eng,
159b2d17df3SSrujana Challa 			      dma_addr_t dma_addr, int blkaddr)
16043ac0b82SSrujana Challa {
16143ac0b82SSrujana Challa 	return otx2_cpt_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
16243ac0b82SSrujana Challa 				     CPT_AF_EXEX_UCODE_BASE(eng),
163b2d17df3SSrujana Challa 				     (u64)dma_addr, blkaddr);
16443ac0b82SSrujana Challa }
16543ac0b82SSrujana Challa 
cptx_set_ucode_base(struct otx2_cpt_eng_grp_info * eng_grp,struct otx2_cptpf_dev * cptpf,int blkaddr)166b2d17df3SSrujana Challa static int cptx_set_ucode_base(struct otx2_cpt_eng_grp_info *eng_grp,
167b2d17df3SSrujana Challa 			       struct otx2_cptpf_dev *cptpf, int blkaddr)
16843ac0b82SSrujana Challa {
16943ac0b82SSrujana Challa 	struct otx2_cpt_engs_rsvd *engs;
17043ac0b82SSrujana Challa 	dma_addr_t dma_addr;
17143ac0b82SSrujana Challa 	int i, bit, ret;
17243ac0b82SSrujana Challa 
17343ac0b82SSrujana Challa 	/* Set PF number for microcode fetches */
17443ac0b82SSrujana Challa 	ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
17543ac0b82SSrujana Challa 				    CPT_AF_PF_FUNC,
176b2d17df3SSrujana Challa 				    cptpf->pf_id << RVU_PFVF_PF_SHIFT, blkaddr);
17743ac0b82SSrujana Challa 	if (ret)
17843ac0b82SSrujana Challa 		return ret;
17943ac0b82SSrujana Challa 
18043ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
18143ac0b82SSrujana Challa 		engs = &eng_grp->engs[i];
18243ac0b82SSrujana Challa 		if (!engs->type)
18343ac0b82SSrujana Challa 			continue;
18443ac0b82SSrujana Challa 
18543ac0b82SSrujana Challa 		dma_addr = engs->ucode->dma;
18643ac0b82SSrujana Challa 
18743ac0b82SSrujana Challa 		/*
18843ac0b82SSrujana Challa 		 * Set UCODE_BASE only for the cores which are not used,
18943ac0b82SSrujana Challa 		 * other cores should have already valid UCODE_BASE set
19043ac0b82SSrujana Challa 		 */
19143ac0b82SSrujana Challa 		for_each_set_bit(bit, engs->bmap, eng_grp->g->engs_num)
19243ac0b82SSrujana Challa 			if (!eng_grp->g->eng_ref_cnt[bit]) {
193b2d17df3SSrujana Challa 				ret = __write_ucode_base(cptpf, bit, dma_addr,
194b2d17df3SSrujana Challa 							 blkaddr);
19543ac0b82SSrujana Challa 				if (ret)
19643ac0b82SSrujana Challa 					return ret;
19743ac0b82SSrujana Challa 			}
19843ac0b82SSrujana Challa 	}
19943ac0b82SSrujana Challa 	return 0;
20043ac0b82SSrujana Challa }
20143ac0b82SSrujana Challa 
cpt_set_ucode_base(struct otx2_cpt_eng_grp_info * eng_grp,void * obj)202b2d17df3SSrujana Challa static int cpt_set_ucode_base(struct otx2_cpt_eng_grp_info *eng_grp, void *obj)
20343ac0b82SSrujana Challa {
20443ac0b82SSrujana Challa 	struct otx2_cptpf_dev *cptpf = obj;
205b2d17df3SSrujana Challa 	int ret;
206b2d17df3SSrujana Challa 
207b2d17df3SSrujana Challa 	if (cptpf->has_cpt1) {
208b2d17df3SSrujana Challa 		ret = cptx_set_ucode_base(eng_grp, cptpf, BLKADDR_CPT1);
209b2d17df3SSrujana Challa 		if (ret)
210b2d17df3SSrujana Challa 			return ret;
211b2d17df3SSrujana Challa 	}
212b2d17df3SSrujana Challa 	return cptx_set_ucode_base(eng_grp, cptpf, BLKADDR_CPT0);
213b2d17df3SSrujana Challa }
214b2d17df3SSrujana Challa 
cptx_detach_and_disable_cores(struct otx2_cpt_eng_grp_info * eng_grp,struct otx2_cptpf_dev * cptpf,struct otx2_cpt_bitmap bmap,int blkaddr)215b2d17df3SSrujana Challa static int cptx_detach_and_disable_cores(struct otx2_cpt_eng_grp_info *eng_grp,
216b2d17df3SSrujana Challa 					 struct otx2_cptpf_dev *cptpf,
217b2d17df3SSrujana Challa 					 struct otx2_cpt_bitmap bmap,
218b2d17df3SSrujana Challa 					 int blkaddr)
219b2d17df3SSrujana Challa {
22043ac0b82SSrujana Challa 	int i, timeout = 10;
22143ac0b82SSrujana Challa 	int busy, ret;
22243ac0b82SSrujana Challa 	u64 reg = 0;
22343ac0b82SSrujana Challa 
22443ac0b82SSrujana Challa 	/* Detach the cores from group */
22543ac0b82SSrujana Challa 	for_each_set_bit(i, bmap.bits, bmap.size) {
22643ac0b82SSrujana Challa 		ret = otx2_cpt_read_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
227b2d17df3SSrujana Challa 					   CPT_AF_EXEX_CTL2(i), &reg, blkaddr);
22843ac0b82SSrujana Challa 		if (ret)
22943ac0b82SSrujana Challa 			return ret;
23043ac0b82SSrujana Challa 
23143ac0b82SSrujana Challa 		if (reg & (1ull << eng_grp->idx)) {
23243ac0b82SSrujana Challa 			eng_grp->g->eng_ref_cnt[i]--;
23343ac0b82SSrujana Challa 			reg &= ~(1ull << eng_grp->idx);
23443ac0b82SSrujana Challa 
23543ac0b82SSrujana Challa 			ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox,
23643ac0b82SSrujana Challa 						    cptpf->pdev,
237b2d17df3SSrujana Challa 						    CPT_AF_EXEX_CTL2(i), reg,
238b2d17df3SSrujana Challa 						    blkaddr);
23943ac0b82SSrujana Challa 			if (ret)
24043ac0b82SSrujana Challa 				return ret;
24143ac0b82SSrujana Challa 		}
24243ac0b82SSrujana Challa 	}
24343ac0b82SSrujana Challa 
24443ac0b82SSrujana Challa 	/* Wait for cores to become idle */
24543ac0b82SSrujana Challa 	do {
24643ac0b82SSrujana Challa 		busy = 0;
24743ac0b82SSrujana Challa 		usleep_range(10000, 20000);
24843ac0b82SSrujana Challa 		if (timeout-- < 0)
24943ac0b82SSrujana Challa 			return -EBUSY;
25043ac0b82SSrujana Challa 
25143ac0b82SSrujana Challa 		for_each_set_bit(i, bmap.bits, bmap.size) {
25243ac0b82SSrujana Challa 			ret = otx2_cpt_read_af_reg(&cptpf->afpf_mbox,
25343ac0b82SSrujana Challa 						   cptpf->pdev,
254b2d17df3SSrujana Challa 						   CPT_AF_EXEX_STS(i), &reg,
255b2d17df3SSrujana Challa 						   blkaddr);
25643ac0b82SSrujana Challa 			if (ret)
25743ac0b82SSrujana Challa 				return ret;
25843ac0b82SSrujana Challa 
25943ac0b82SSrujana Challa 			if (reg & 0x1) {
26043ac0b82SSrujana Challa 				busy = 1;
26143ac0b82SSrujana Challa 				break;
26243ac0b82SSrujana Challa 			}
26343ac0b82SSrujana Challa 		}
26443ac0b82SSrujana Challa 	} while (busy);
26543ac0b82SSrujana Challa 
26643ac0b82SSrujana Challa 	/* Disable the cores only if they are not used anymore */
26743ac0b82SSrujana Challa 	for_each_set_bit(i, bmap.bits, bmap.size) {
26843ac0b82SSrujana Challa 		if (!eng_grp->g->eng_ref_cnt[i]) {
26943ac0b82SSrujana Challa 			ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox,
27043ac0b82SSrujana Challa 						    cptpf->pdev,
271b2d17df3SSrujana Challa 						    CPT_AF_EXEX_CTL(i), 0x0,
272b2d17df3SSrujana Challa 						    blkaddr);
27343ac0b82SSrujana Challa 			if (ret)
27443ac0b82SSrujana Challa 				return ret;
27543ac0b82SSrujana Challa 		}
27643ac0b82SSrujana Challa 	}
27743ac0b82SSrujana Challa 
27843ac0b82SSrujana Challa 	return 0;
27943ac0b82SSrujana Challa }
28043ac0b82SSrujana Challa 
cpt_detach_and_disable_cores(struct otx2_cpt_eng_grp_info * eng_grp,void * obj)281b2d17df3SSrujana Challa static int cpt_detach_and_disable_cores(struct otx2_cpt_eng_grp_info *eng_grp,
28243ac0b82SSrujana Challa 					void *obj)
28343ac0b82SSrujana Challa {
28443ac0b82SSrujana Challa 	struct otx2_cptpf_dev *cptpf = obj;
28543ac0b82SSrujana Challa 	struct otx2_cpt_bitmap bmap;
286b2d17df3SSrujana Challa 	int ret;
28743ac0b82SSrujana Challa 
28843ac0b82SSrujana Challa 	bmap = get_cores_bmap(&cptpf->pdev->dev, eng_grp);
28943ac0b82SSrujana Challa 	if (!bmap.size)
29043ac0b82SSrujana Challa 		return -EINVAL;
29143ac0b82SSrujana Challa 
292b2d17df3SSrujana Challa 	if (cptpf->has_cpt1) {
293b2d17df3SSrujana Challa 		ret = cptx_detach_and_disable_cores(eng_grp, cptpf, bmap,
294b2d17df3SSrujana Challa 						    BLKADDR_CPT1);
295b2d17df3SSrujana Challa 		if (ret)
296b2d17df3SSrujana Challa 			return ret;
297b2d17df3SSrujana Challa 	}
298b2d17df3SSrujana Challa 	return cptx_detach_and_disable_cores(eng_grp, cptpf, bmap,
299b2d17df3SSrujana Challa 					     BLKADDR_CPT0);
300b2d17df3SSrujana Challa }
301b2d17df3SSrujana Challa 
cptx_attach_and_enable_cores(struct otx2_cpt_eng_grp_info * eng_grp,struct otx2_cptpf_dev * cptpf,struct otx2_cpt_bitmap bmap,int blkaddr)302b2d17df3SSrujana Challa static int cptx_attach_and_enable_cores(struct otx2_cpt_eng_grp_info *eng_grp,
303b2d17df3SSrujana Challa 					struct otx2_cptpf_dev *cptpf,
304b2d17df3SSrujana Challa 					struct otx2_cpt_bitmap bmap,
305b2d17df3SSrujana Challa 					int blkaddr)
306b2d17df3SSrujana Challa {
307b2d17df3SSrujana Challa 	u64 reg = 0;
308b2d17df3SSrujana Challa 	int i, ret;
309b2d17df3SSrujana Challa 
31043ac0b82SSrujana Challa 	/* Attach the cores to the group */
31143ac0b82SSrujana Challa 	for_each_set_bit(i, bmap.bits, bmap.size) {
31243ac0b82SSrujana Challa 		ret = otx2_cpt_read_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
313b2d17df3SSrujana Challa 					   CPT_AF_EXEX_CTL2(i), &reg, blkaddr);
31443ac0b82SSrujana Challa 		if (ret)
31543ac0b82SSrujana Challa 			return ret;
31643ac0b82SSrujana Challa 
31743ac0b82SSrujana Challa 		if (!(reg & (1ull << eng_grp->idx))) {
31843ac0b82SSrujana Challa 			eng_grp->g->eng_ref_cnt[i]++;
31943ac0b82SSrujana Challa 			reg |= 1ull << eng_grp->idx;
32043ac0b82SSrujana Challa 
32143ac0b82SSrujana Challa 			ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox,
32243ac0b82SSrujana Challa 						    cptpf->pdev,
323b2d17df3SSrujana Challa 						    CPT_AF_EXEX_CTL2(i), reg,
324b2d17df3SSrujana Challa 						    blkaddr);
32543ac0b82SSrujana Challa 			if (ret)
32643ac0b82SSrujana Challa 				return ret;
32743ac0b82SSrujana Challa 		}
32843ac0b82SSrujana Challa 	}
32943ac0b82SSrujana Challa 
33043ac0b82SSrujana Challa 	/* Enable the cores */
33143ac0b82SSrujana Challa 	for_each_set_bit(i, bmap.bits, bmap.size) {
332b2d17df3SSrujana Challa 		ret = otx2_cpt_add_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
333b2d17df3SSrujana Challa 						CPT_AF_EXEX_CTL(i), 0x1,
334b2d17df3SSrujana Challa 						blkaddr);
33543ac0b82SSrujana Challa 		if (ret)
33643ac0b82SSrujana Challa 			return ret;
33743ac0b82SSrujana Challa 	}
338b2d17df3SSrujana Challa 	return otx2_cpt_send_af_reg_requests(&cptpf->afpf_mbox, cptpf->pdev);
339b2d17df3SSrujana Challa }
34043ac0b82SSrujana Challa 
cpt_attach_and_enable_cores(struct otx2_cpt_eng_grp_info * eng_grp,void * obj)341b2d17df3SSrujana Challa static int cpt_attach_and_enable_cores(struct otx2_cpt_eng_grp_info *eng_grp,
342b2d17df3SSrujana Challa 				       void *obj)
343b2d17df3SSrujana Challa {
344b2d17df3SSrujana Challa 	struct otx2_cptpf_dev *cptpf = obj;
345b2d17df3SSrujana Challa 	struct otx2_cpt_bitmap bmap;
346b2d17df3SSrujana Challa 	int ret;
347b2d17df3SSrujana Challa 
348b2d17df3SSrujana Challa 	bmap = get_cores_bmap(&cptpf->pdev->dev, eng_grp);
349b2d17df3SSrujana Challa 	if (!bmap.size)
350b2d17df3SSrujana Challa 		return -EINVAL;
351b2d17df3SSrujana Challa 
352b2d17df3SSrujana Challa 	if (cptpf->has_cpt1) {
353b2d17df3SSrujana Challa 		ret = cptx_attach_and_enable_cores(eng_grp, cptpf, bmap,
354b2d17df3SSrujana Challa 						   BLKADDR_CPT1);
355b2d17df3SSrujana Challa 		if (ret)
35643ac0b82SSrujana Challa 			return ret;
35743ac0b82SSrujana Challa 	}
358b2d17df3SSrujana Challa 	return cptx_attach_and_enable_cores(eng_grp, cptpf, bmap, BLKADDR_CPT0);
359b2d17df3SSrujana Challa }
36043ac0b82SSrujana Challa 
load_fw(struct device * dev,struct fw_info_t * fw_info,char * filename)36143ac0b82SSrujana Challa static int load_fw(struct device *dev, struct fw_info_t *fw_info,
36243ac0b82SSrujana Challa 		   char *filename)
36343ac0b82SSrujana Challa {
36443ac0b82SSrujana Challa 	struct otx2_cpt_ucode_hdr *ucode_hdr;
36543ac0b82SSrujana Challa 	struct otx2_cpt_uc_info_t *uc_info;
36643ac0b82SSrujana Challa 	int ucode_type, ucode_size;
36743ac0b82SSrujana Challa 	int ret;
36843ac0b82SSrujana Challa 
36943ac0b82SSrujana Challa 	uc_info = kzalloc(sizeof(*uc_info), GFP_KERNEL);
37043ac0b82SSrujana Challa 	if (!uc_info)
37143ac0b82SSrujana Challa 		return -ENOMEM;
37243ac0b82SSrujana Challa 
37343ac0b82SSrujana Challa 	ret = request_firmware(&uc_info->fw, filename, dev);
37443ac0b82SSrujana Challa 	if (ret)
37543ac0b82SSrujana Challa 		goto free_uc_info;
37643ac0b82SSrujana Challa 
37743ac0b82SSrujana Challa 	ucode_hdr = (struct otx2_cpt_ucode_hdr *)uc_info->fw->data;
37843ac0b82SSrujana Challa 	ret = get_ucode_type(dev, ucode_hdr, &ucode_type);
37943ac0b82SSrujana Challa 	if (ret)
38043ac0b82SSrujana Challa 		goto release_fw;
38143ac0b82SSrujana Challa 
38243ac0b82SSrujana Challa 	ucode_size = ntohl(ucode_hdr->code_length) * 2;
38343ac0b82SSrujana Challa 	if (!ucode_size) {
38443ac0b82SSrujana Challa 		dev_err(dev, "Ucode %s invalid size\n", filename);
38543ac0b82SSrujana Challa 		ret = -EINVAL;
38643ac0b82SSrujana Challa 		goto release_fw;
38743ac0b82SSrujana Challa 	}
38843ac0b82SSrujana Challa 
38943ac0b82SSrujana Challa 	set_ucode_filename(&uc_info->ucode, filename);
39043ac0b82SSrujana Challa 	memcpy(uc_info->ucode.ver_str, ucode_hdr->ver_str,
39143ac0b82SSrujana Challa 	       OTX2_CPT_UCODE_VER_STR_SZ);
39243ac0b82SSrujana Challa 	uc_info->ucode.ver_num = ucode_hdr->ver_num;
39343ac0b82SSrujana Challa 	uc_info->ucode.type = ucode_type;
39443ac0b82SSrujana Challa 	uc_info->ucode.size = ucode_size;
39543ac0b82SSrujana Challa 	list_add_tail(&uc_info->list, &fw_info->ucodes);
39643ac0b82SSrujana Challa 
39743ac0b82SSrujana Challa 	return 0;
39843ac0b82SSrujana Challa 
39943ac0b82SSrujana Challa release_fw:
40043ac0b82SSrujana Challa 	release_firmware(uc_info->fw);
40143ac0b82SSrujana Challa free_uc_info:
40243ac0b82SSrujana Challa 	kfree(uc_info);
40343ac0b82SSrujana Challa 	return ret;
40443ac0b82SSrujana Challa }
40543ac0b82SSrujana Challa 
cpt_ucode_release_fw(struct fw_info_t * fw_info)40643ac0b82SSrujana Challa static void cpt_ucode_release_fw(struct fw_info_t *fw_info)
40743ac0b82SSrujana Challa {
40843ac0b82SSrujana Challa 	struct otx2_cpt_uc_info_t *curr, *temp;
40943ac0b82SSrujana Challa 
41043ac0b82SSrujana Challa 	if (!fw_info)
41143ac0b82SSrujana Challa 		return;
41243ac0b82SSrujana Challa 
41343ac0b82SSrujana Challa 	list_for_each_entry_safe(curr, temp, &fw_info->ucodes, list) {
41443ac0b82SSrujana Challa 		list_del(&curr->list);
41543ac0b82SSrujana Challa 		release_firmware(curr->fw);
41643ac0b82SSrujana Challa 		kfree(curr);
41743ac0b82SSrujana Challa 	}
41843ac0b82SSrujana Challa }
41943ac0b82SSrujana Challa 
get_ucode(struct fw_info_t * fw_info,int ucode_type)42043ac0b82SSrujana Challa static struct otx2_cpt_uc_info_t *get_ucode(struct fw_info_t *fw_info,
42143ac0b82SSrujana Challa 					    int ucode_type)
42243ac0b82SSrujana Challa {
42343ac0b82SSrujana Challa 	struct otx2_cpt_uc_info_t *curr;
42443ac0b82SSrujana Challa 
42543ac0b82SSrujana Challa 	list_for_each_entry(curr, &fw_info->ucodes, list) {
42643ac0b82SSrujana Challa 		if (!is_eng_type(curr->ucode.type, ucode_type))
42743ac0b82SSrujana Challa 			continue;
42843ac0b82SSrujana Challa 
42943ac0b82SSrujana Challa 		return curr;
43043ac0b82SSrujana Challa 	}
43143ac0b82SSrujana Challa 	return NULL;
43243ac0b82SSrujana Challa }
43343ac0b82SSrujana Challa 
print_uc_info(struct fw_info_t * fw_info)43443ac0b82SSrujana Challa static void print_uc_info(struct fw_info_t *fw_info)
43543ac0b82SSrujana Challa {
43643ac0b82SSrujana Challa 	struct otx2_cpt_uc_info_t *curr;
43743ac0b82SSrujana Challa 
43843ac0b82SSrujana Challa 	list_for_each_entry(curr, &fw_info->ucodes, list) {
43943ac0b82SSrujana Challa 		pr_debug("Ucode filename %s\n", curr->ucode.filename);
44043ac0b82SSrujana Challa 		pr_debug("Ucode version string %s\n", curr->ucode.ver_str);
44143ac0b82SSrujana Challa 		pr_debug("Ucode version %d.%d.%d.%d\n",
44243ac0b82SSrujana Challa 			 curr->ucode.ver_num.nn, curr->ucode.ver_num.xx,
44343ac0b82SSrujana Challa 			 curr->ucode.ver_num.yy, curr->ucode.ver_num.zz);
44443ac0b82SSrujana Challa 		pr_debug("Ucode type (%d) %s\n", curr->ucode.type,
44543ac0b82SSrujana Challa 			 get_ucode_type_str(curr->ucode.type));
44643ac0b82SSrujana Challa 		pr_debug("Ucode size %d\n", curr->ucode.size);
44743ac0b82SSrujana Challa 		pr_debug("Ucode ptr %p\n", curr->fw->data);
44843ac0b82SSrujana Challa 	}
44943ac0b82SSrujana Challa }
45043ac0b82SSrujana Challa 
cpt_ucode_load_fw(struct pci_dev * pdev,struct fw_info_t * fw_info)45143ac0b82SSrujana Challa static int cpt_ucode_load_fw(struct pci_dev *pdev, struct fw_info_t *fw_info)
45243ac0b82SSrujana Challa {
45343ac0b82SSrujana Challa 	char filename[OTX2_CPT_NAME_LENGTH];
45443ac0b82SSrujana Challa 	char eng_type[8] = {0};
45543ac0b82SSrujana Challa 	int ret, e, i;
45643ac0b82SSrujana Challa 
45743ac0b82SSrujana Challa 	INIT_LIST_HEAD(&fw_info->ucodes);
45843ac0b82SSrujana Challa 
45943ac0b82SSrujana Challa 	for (e = 1; e < OTX2_CPT_MAX_ENG_TYPES; e++) {
46043ac0b82SSrujana Challa 		strcpy(eng_type, get_eng_type_str(e));
46143ac0b82SSrujana Challa 		for (i = 0; i < strlen(eng_type); i++)
46243ac0b82SSrujana Challa 			eng_type[i] = tolower(eng_type[i]);
46343ac0b82SSrujana Challa 
46443ac0b82SSrujana Challa 		snprintf(filename, sizeof(filename), "mrvl/cpt%02d/%s.out",
46543ac0b82SSrujana Challa 			 pdev->revision, eng_type);
46643ac0b82SSrujana Challa 		/* Request firmware for each engine type */
46743ac0b82SSrujana Challa 		ret = load_fw(&pdev->dev, fw_info, filename);
46843ac0b82SSrujana Challa 		if (ret)
46943ac0b82SSrujana Challa 			goto release_fw;
47043ac0b82SSrujana Challa 	}
47143ac0b82SSrujana Challa 	print_uc_info(fw_info);
47243ac0b82SSrujana Challa 	return 0;
47343ac0b82SSrujana Challa 
47443ac0b82SSrujana Challa release_fw:
47543ac0b82SSrujana Challa 	cpt_ucode_release_fw(fw_info);
47643ac0b82SSrujana Challa 	return ret;
47743ac0b82SSrujana Challa }
47843ac0b82SSrujana Challa 
find_engines_by_type(struct otx2_cpt_eng_grp_info * eng_grp,int eng_type)4794ad28689SShijith Thotton struct otx2_cpt_engs_rsvd *find_engines_by_type(
48043ac0b82SSrujana Challa 					struct otx2_cpt_eng_grp_info *eng_grp,
48143ac0b82SSrujana Challa 					int eng_type)
48243ac0b82SSrujana Challa {
48343ac0b82SSrujana Challa 	int i;
48443ac0b82SSrujana Challa 
48543ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
48643ac0b82SSrujana Challa 		if (!eng_grp->engs[i].type)
48743ac0b82SSrujana Challa 			continue;
48843ac0b82SSrujana Challa 
48943ac0b82SSrujana Challa 		if (eng_grp->engs[i].type == eng_type)
49043ac0b82SSrujana Challa 			return &eng_grp->engs[i];
49143ac0b82SSrujana Challa 	}
49243ac0b82SSrujana Challa 	return NULL;
49343ac0b82SSrujana Challa }
49443ac0b82SSrujana Challa 
eng_grp_has_eng_type(struct otx2_cpt_eng_grp_info * eng_grp,int eng_type)49543ac0b82SSrujana Challa static int eng_grp_has_eng_type(struct otx2_cpt_eng_grp_info *eng_grp,
49643ac0b82SSrujana Challa 				int eng_type)
49743ac0b82SSrujana Challa {
49843ac0b82SSrujana Challa 	struct otx2_cpt_engs_rsvd *engs;
49943ac0b82SSrujana Challa 
50043ac0b82SSrujana Challa 	engs = find_engines_by_type(eng_grp, eng_type);
50143ac0b82SSrujana Challa 
50243ac0b82SSrujana Challa 	return (engs != NULL ? 1 : 0);
50343ac0b82SSrujana Challa }
50443ac0b82SSrujana Challa 
update_engines_avail_count(struct device * dev,struct otx2_cpt_engs_available * avail,struct otx2_cpt_engs_rsvd * engs,int val)50543ac0b82SSrujana Challa static int update_engines_avail_count(struct device *dev,
50643ac0b82SSrujana Challa 				      struct otx2_cpt_engs_available *avail,
50743ac0b82SSrujana Challa 				      struct otx2_cpt_engs_rsvd *engs, int val)
50843ac0b82SSrujana Challa {
50943ac0b82SSrujana Challa 	switch (engs->type) {
51043ac0b82SSrujana Challa 	case OTX2_CPT_SE_TYPES:
51143ac0b82SSrujana Challa 		avail->se_cnt += val;
51243ac0b82SSrujana Challa 		break;
51343ac0b82SSrujana Challa 
51443ac0b82SSrujana Challa 	case OTX2_CPT_IE_TYPES:
51543ac0b82SSrujana Challa 		avail->ie_cnt += val;
51643ac0b82SSrujana Challa 		break;
51743ac0b82SSrujana Challa 
51843ac0b82SSrujana Challa 	case OTX2_CPT_AE_TYPES:
51943ac0b82SSrujana Challa 		avail->ae_cnt += val;
52043ac0b82SSrujana Challa 		break;
52143ac0b82SSrujana Challa 
52243ac0b82SSrujana Challa 	default:
52343ac0b82SSrujana Challa 		dev_err(dev, "Invalid engine type %d\n", engs->type);
52443ac0b82SSrujana Challa 		return -EINVAL;
52543ac0b82SSrujana Challa 	}
52643ac0b82SSrujana Challa 	return 0;
52743ac0b82SSrujana Challa }
52843ac0b82SSrujana Challa 
update_engines_offset(struct device * dev,struct otx2_cpt_engs_available * avail,struct otx2_cpt_engs_rsvd * engs)52943ac0b82SSrujana Challa static int update_engines_offset(struct device *dev,
53043ac0b82SSrujana Challa 				 struct otx2_cpt_engs_available *avail,
53143ac0b82SSrujana Challa 				 struct otx2_cpt_engs_rsvd *engs)
53243ac0b82SSrujana Challa {
53343ac0b82SSrujana Challa 	switch (engs->type) {
53443ac0b82SSrujana Challa 	case OTX2_CPT_SE_TYPES:
53543ac0b82SSrujana Challa 		engs->offset = 0;
53643ac0b82SSrujana Challa 		break;
53743ac0b82SSrujana Challa 
53843ac0b82SSrujana Challa 	case OTX2_CPT_IE_TYPES:
53943ac0b82SSrujana Challa 		engs->offset = avail->max_se_cnt;
54043ac0b82SSrujana Challa 		break;
54143ac0b82SSrujana Challa 
54243ac0b82SSrujana Challa 	case OTX2_CPT_AE_TYPES:
54343ac0b82SSrujana Challa 		engs->offset = avail->max_se_cnt + avail->max_ie_cnt;
54443ac0b82SSrujana Challa 		break;
54543ac0b82SSrujana Challa 
54643ac0b82SSrujana Challa 	default:
54743ac0b82SSrujana Challa 		dev_err(dev, "Invalid engine type %d\n", engs->type);
54843ac0b82SSrujana Challa 		return -EINVAL;
54943ac0b82SSrujana Challa 	}
55043ac0b82SSrujana Challa 	return 0;
55143ac0b82SSrujana Challa }
55243ac0b82SSrujana Challa 
release_engines(struct device * dev,struct otx2_cpt_eng_grp_info * grp)55343ac0b82SSrujana Challa static int release_engines(struct device *dev,
55443ac0b82SSrujana Challa 			   struct otx2_cpt_eng_grp_info *grp)
55543ac0b82SSrujana Challa {
55643ac0b82SSrujana Challa 	int i, ret = 0;
55743ac0b82SSrujana Challa 
55843ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
55943ac0b82SSrujana Challa 		if (!grp->engs[i].type)
56043ac0b82SSrujana Challa 			continue;
56143ac0b82SSrujana Challa 
56243ac0b82SSrujana Challa 		if (grp->engs[i].count > 0) {
56343ac0b82SSrujana Challa 			ret = update_engines_avail_count(dev, &grp->g->avail,
56443ac0b82SSrujana Challa 							 &grp->engs[i],
56543ac0b82SSrujana Challa 							 grp->engs[i].count);
56643ac0b82SSrujana Challa 			if (ret)
56743ac0b82SSrujana Challa 				return ret;
56843ac0b82SSrujana Challa 		}
56943ac0b82SSrujana Challa 
57043ac0b82SSrujana Challa 		grp->engs[i].type = 0;
57143ac0b82SSrujana Challa 		grp->engs[i].count = 0;
57243ac0b82SSrujana Challa 		grp->engs[i].offset = 0;
57343ac0b82SSrujana Challa 		grp->engs[i].ucode = NULL;
57443ac0b82SSrujana Challa 		bitmap_zero(grp->engs[i].bmap, grp->g->engs_num);
57543ac0b82SSrujana Challa 	}
57643ac0b82SSrujana Challa 	return 0;
57743ac0b82SSrujana Challa }
57843ac0b82SSrujana Challa 
do_reserve_engines(struct device * dev,struct otx2_cpt_eng_grp_info * grp,struct otx2_cpt_engines * req_engs)57943ac0b82SSrujana Challa static int do_reserve_engines(struct device *dev,
58043ac0b82SSrujana Challa 			      struct otx2_cpt_eng_grp_info *grp,
58143ac0b82SSrujana Challa 			      struct otx2_cpt_engines *req_engs)
58243ac0b82SSrujana Challa {
58343ac0b82SSrujana Challa 	struct otx2_cpt_engs_rsvd *engs = NULL;
58443ac0b82SSrujana Challa 	int i, ret;
58543ac0b82SSrujana Challa 
58643ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
58743ac0b82SSrujana Challa 		if (!grp->engs[i].type) {
58843ac0b82SSrujana Challa 			engs = &grp->engs[i];
58943ac0b82SSrujana Challa 			break;
59043ac0b82SSrujana Challa 		}
59143ac0b82SSrujana Challa 	}
59243ac0b82SSrujana Challa 
59343ac0b82SSrujana Challa 	if (!engs)
59443ac0b82SSrujana Challa 		return -ENOMEM;
59543ac0b82SSrujana Challa 
59643ac0b82SSrujana Challa 	engs->type = req_engs->type;
59743ac0b82SSrujana Challa 	engs->count = req_engs->count;
59843ac0b82SSrujana Challa 
59943ac0b82SSrujana Challa 	ret = update_engines_offset(dev, &grp->g->avail, engs);
60043ac0b82SSrujana Challa 	if (ret)
60143ac0b82SSrujana Challa 		return ret;
60243ac0b82SSrujana Challa 
60343ac0b82SSrujana Challa 	if (engs->count > 0) {
60443ac0b82SSrujana Challa 		ret = update_engines_avail_count(dev, &grp->g->avail, engs,
60543ac0b82SSrujana Challa 						 -engs->count);
60643ac0b82SSrujana Challa 		if (ret)
60743ac0b82SSrujana Challa 			return ret;
60843ac0b82SSrujana Challa 	}
60943ac0b82SSrujana Challa 
61043ac0b82SSrujana Challa 	return 0;
61143ac0b82SSrujana Challa }
61243ac0b82SSrujana Challa 
check_engines_availability(struct device * dev,struct otx2_cpt_eng_grp_info * grp,struct otx2_cpt_engines * req_eng)61343ac0b82SSrujana Challa static int check_engines_availability(struct device *dev,
61443ac0b82SSrujana Challa 				      struct otx2_cpt_eng_grp_info *grp,
61543ac0b82SSrujana Challa 				      struct otx2_cpt_engines *req_eng)
61643ac0b82SSrujana Challa {
61743ac0b82SSrujana Challa 	int avail_cnt = 0;
61843ac0b82SSrujana Challa 
61943ac0b82SSrujana Challa 	switch (req_eng->type) {
62043ac0b82SSrujana Challa 	case OTX2_CPT_SE_TYPES:
62143ac0b82SSrujana Challa 		avail_cnt = grp->g->avail.se_cnt;
62243ac0b82SSrujana Challa 		break;
62343ac0b82SSrujana Challa 
62443ac0b82SSrujana Challa 	case OTX2_CPT_IE_TYPES:
62543ac0b82SSrujana Challa 		avail_cnt = grp->g->avail.ie_cnt;
62643ac0b82SSrujana Challa 		break;
62743ac0b82SSrujana Challa 
62843ac0b82SSrujana Challa 	case OTX2_CPT_AE_TYPES:
62943ac0b82SSrujana Challa 		avail_cnt = grp->g->avail.ae_cnt;
63043ac0b82SSrujana Challa 		break;
63143ac0b82SSrujana Challa 
63243ac0b82SSrujana Challa 	default:
63343ac0b82SSrujana Challa 		dev_err(dev, "Invalid engine type %d\n", req_eng->type);
63443ac0b82SSrujana Challa 		return -EINVAL;
63543ac0b82SSrujana Challa 	}
63643ac0b82SSrujana Challa 
63743ac0b82SSrujana Challa 	if (avail_cnt < req_eng->count) {
63843ac0b82SSrujana Challa 		dev_err(dev,
63943ac0b82SSrujana Challa 			"Error available %s engines %d < than requested %d\n",
64043ac0b82SSrujana Challa 			get_eng_type_str(req_eng->type),
64143ac0b82SSrujana Challa 			avail_cnt, req_eng->count);
64243ac0b82SSrujana Challa 		return -EBUSY;
64343ac0b82SSrujana Challa 	}
64443ac0b82SSrujana Challa 	return 0;
64543ac0b82SSrujana Challa }
64643ac0b82SSrujana Challa 
reserve_engines(struct device * dev,struct otx2_cpt_eng_grp_info * grp,struct otx2_cpt_engines * req_engs,int ucodes_cnt)64743ac0b82SSrujana Challa static int reserve_engines(struct device *dev,
64843ac0b82SSrujana Challa 			   struct otx2_cpt_eng_grp_info *grp,
64943ac0b82SSrujana Challa 			   struct otx2_cpt_engines *req_engs, int ucodes_cnt)
65043ac0b82SSrujana Challa {
65143ac0b82SSrujana Challa 	int i, ret = 0;
65243ac0b82SSrujana Challa 
65343ac0b82SSrujana Challa 	/* Validate if a number of requested engines are available */
65443ac0b82SSrujana Challa 	for (i = 0; i < ucodes_cnt; i++) {
65543ac0b82SSrujana Challa 		ret = check_engines_availability(dev, grp, &req_engs[i]);
65643ac0b82SSrujana Challa 		if (ret)
65743ac0b82SSrujana Challa 			return ret;
65843ac0b82SSrujana Challa 	}
65943ac0b82SSrujana Challa 
66043ac0b82SSrujana Challa 	/* Reserve requested engines for this engine group */
66143ac0b82SSrujana Challa 	for (i = 0; i < ucodes_cnt; i++) {
66243ac0b82SSrujana Challa 		ret = do_reserve_engines(dev, grp, &req_engs[i]);
66343ac0b82SSrujana Challa 		if (ret)
66443ac0b82SSrujana Challa 			return ret;
66543ac0b82SSrujana Challa 	}
66643ac0b82SSrujana Challa 	return 0;
66743ac0b82SSrujana Challa }
66843ac0b82SSrujana Challa 
ucode_unload(struct device * dev,struct otx2_cpt_ucode * ucode)66943ac0b82SSrujana Challa static void ucode_unload(struct device *dev, struct otx2_cpt_ucode *ucode)
67043ac0b82SSrujana Challa {
67143ac0b82SSrujana Challa 	if (ucode->va) {
67240a645f7SSrujana Challa 		dma_free_coherent(dev, OTX2_CPT_UCODE_SZ, ucode->va,
67340a645f7SSrujana Challa 				  ucode->dma);
67443ac0b82SSrujana Challa 		ucode->va = NULL;
67543ac0b82SSrujana Challa 		ucode->dma = 0;
67643ac0b82SSrujana Challa 		ucode->size = 0;
67743ac0b82SSrujana Challa 	}
67843ac0b82SSrujana Challa 
67943ac0b82SSrujana Challa 	memset(&ucode->ver_str, 0, OTX2_CPT_UCODE_VER_STR_SZ);
68043ac0b82SSrujana Challa 	memset(&ucode->ver_num, 0, sizeof(struct otx2_cpt_ucode_ver_num));
68143ac0b82SSrujana Challa 	set_ucode_filename(ucode, "");
68243ac0b82SSrujana Challa 	ucode->type = 0;
68343ac0b82SSrujana Challa }
68443ac0b82SSrujana Challa 
copy_ucode_to_dma_mem(struct device * dev,struct otx2_cpt_ucode * ucode,const u8 * ucode_data)68543ac0b82SSrujana Challa static int copy_ucode_to_dma_mem(struct device *dev,
68643ac0b82SSrujana Challa 				 struct otx2_cpt_ucode *ucode,
68743ac0b82SSrujana Challa 				 const u8 *ucode_data)
68843ac0b82SSrujana Challa {
68943ac0b82SSrujana Challa 	u32 i;
69043ac0b82SSrujana Challa 
69143ac0b82SSrujana Challa 	/*  Allocate DMAable space */
69240a645f7SSrujana Challa 	ucode->va = dma_alloc_coherent(dev, OTX2_CPT_UCODE_SZ, &ucode->dma,
69343ac0b82SSrujana Challa 				       GFP_KERNEL);
69443ac0b82SSrujana Challa 	if (!ucode->va)
69543ac0b82SSrujana Challa 		return -ENOMEM;
69643ac0b82SSrujana Challa 
69743ac0b82SSrujana Challa 	memcpy(ucode->va, ucode_data + sizeof(struct otx2_cpt_ucode_hdr),
69843ac0b82SSrujana Challa 	       ucode->size);
69943ac0b82SSrujana Challa 
70043ac0b82SSrujana Challa 	/* Byte swap 64-bit */
70143ac0b82SSrujana Challa 	for (i = 0; i < (ucode->size / 8); i++)
70243ac0b82SSrujana Challa 		cpu_to_be64s(&((u64 *)ucode->va)[i]);
70343ac0b82SSrujana Challa 	/*  Ucode needs 16-bit swap */
70443ac0b82SSrujana Challa 	for (i = 0; i < (ucode->size / 2); i++)
70543ac0b82SSrujana Challa 		cpu_to_be16s(&((u16 *)ucode->va)[i]);
70643ac0b82SSrujana Challa 	return 0;
70743ac0b82SSrujana Challa }
70843ac0b82SSrujana Challa 
enable_eng_grp(struct otx2_cpt_eng_grp_info * eng_grp,void * obj)70943ac0b82SSrujana Challa static int enable_eng_grp(struct otx2_cpt_eng_grp_info *eng_grp,
71043ac0b82SSrujana Challa 			  void *obj)
71143ac0b82SSrujana Challa {
71243ac0b82SSrujana Challa 	int ret;
71343ac0b82SSrujana Challa 
71443ac0b82SSrujana Challa 	/* Point microcode to each core of the group */
71543ac0b82SSrujana Challa 	ret = cpt_set_ucode_base(eng_grp, obj);
71643ac0b82SSrujana Challa 	if (ret)
71743ac0b82SSrujana Challa 		return ret;
71843ac0b82SSrujana Challa 
71943ac0b82SSrujana Challa 	/* Attach the cores to the group and enable them */
72043ac0b82SSrujana Challa 	ret = cpt_attach_and_enable_cores(eng_grp, obj);
72143ac0b82SSrujana Challa 
72243ac0b82SSrujana Challa 	return ret;
72343ac0b82SSrujana Challa }
72443ac0b82SSrujana Challa 
disable_eng_grp(struct device * dev,struct otx2_cpt_eng_grp_info * eng_grp,void * obj)72543ac0b82SSrujana Challa static int disable_eng_grp(struct device *dev,
72643ac0b82SSrujana Challa 			   struct otx2_cpt_eng_grp_info *eng_grp,
72743ac0b82SSrujana Challa 			   void *obj)
72843ac0b82SSrujana Challa {
72943ac0b82SSrujana Challa 	int i, ret;
73043ac0b82SSrujana Challa 
73143ac0b82SSrujana Challa 	/* Disable all engines used by this group */
73243ac0b82SSrujana Challa 	ret = cpt_detach_and_disable_cores(eng_grp, obj);
73343ac0b82SSrujana Challa 	if (ret)
73443ac0b82SSrujana Challa 		return ret;
73543ac0b82SSrujana Challa 
73643ac0b82SSrujana Challa 	/* Unload ucode used by this engine group */
73743ac0b82SSrujana Challa 	ucode_unload(dev, &eng_grp->ucode[0]);
73843ac0b82SSrujana Challa 	ucode_unload(dev, &eng_grp->ucode[1]);
73943ac0b82SSrujana Challa 
74043ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
74143ac0b82SSrujana Challa 		if (!eng_grp->engs[i].type)
74243ac0b82SSrujana Challa 			continue;
74343ac0b82SSrujana Challa 
74443ac0b82SSrujana Challa 		eng_grp->engs[i].ucode = &eng_grp->ucode[0];
74543ac0b82SSrujana Challa 	}
74643ac0b82SSrujana Challa 
74743ac0b82SSrujana Challa 	/* Clear UCODE_BASE register for each engine used by this group */
74843ac0b82SSrujana Challa 	ret = cpt_set_ucode_base(eng_grp, obj);
74943ac0b82SSrujana Challa 
75043ac0b82SSrujana Challa 	return ret;
75143ac0b82SSrujana Challa }
75243ac0b82SSrujana Challa 
setup_eng_grp_mirroring(struct otx2_cpt_eng_grp_info * dst_grp,struct otx2_cpt_eng_grp_info * src_grp)75343ac0b82SSrujana Challa static void setup_eng_grp_mirroring(struct otx2_cpt_eng_grp_info *dst_grp,
75443ac0b82SSrujana Challa 				    struct otx2_cpt_eng_grp_info *src_grp)
75543ac0b82SSrujana Challa {
75643ac0b82SSrujana Challa 	/* Setup fields for engine group which is mirrored */
75743ac0b82SSrujana Challa 	src_grp->mirror.is_ena = false;
75843ac0b82SSrujana Challa 	src_grp->mirror.idx = 0;
75943ac0b82SSrujana Challa 	src_grp->mirror.ref_count++;
76043ac0b82SSrujana Challa 
76143ac0b82SSrujana Challa 	/* Setup fields for mirroring engine group */
76243ac0b82SSrujana Challa 	dst_grp->mirror.is_ena = true;
76343ac0b82SSrujana Challa 	dst_grp->mirror.idx = src_grp->idx;
76443ac0b82SSrujana Challa 	dst_grp->mirror.ref_count = 0;
76543ac0b82SSrujana Challa }
76643ac0b82SSrujana Challa 
remove_eng_grp_mirroring(struct otx2_cpt_eng_grp_info * dst_grp)76743ac0b82SSrujana Challa static void remove_eng_grp_mirroring(struct otx2_cpt_eng_grp_info *dst_grp)
76843ac0b82SSrujana Challa {
76943ac0b82SSrujana Challa 	struct otx2_cpt_eng_grp_info *src_grp;
77043ac0b82SSrujana Challa 
77143ac0b82SSrujana Challa 	if (!dst_grp->mirror.is_ena)
77243ac0b82SSrujana Challa 		return;
77343ac0b82SSrujana Challa 
77443ac0b82SSrujana Challa 	src_grp = &dst_grp->g->grp[dst_grp->mirror.idx];
77543ac0b82SSrujana Challa 
77643ac0b82SSrujana Challa 	src_grp->mirror.ref_count--;
77743ac0b82SSrujana Challa 	dst_grp->mirror.is_ena = false;
77843ac0b82SSrujana Challa 	dst_grp->mirror.idx = 0;
77943ac0b82SSrujana Challa 	dst_grp->mirror.ref_count = 0;
78043ac0b82SSrujana Challa }
78143ac0b82SSrujana Challa 
update_requested_engs(struct otx2_cpt_eng_grp_info * mirror_eng_grp,struct otx2_cpt_engines * engs,int engs_cnt)78243ac0b82SSrujana Challa static void update_requested_engs(struct otx2_cpt_eng_grp_info *mirror_eng_grp,
78343ac0b82SSrujana Challa 				  struct otx2_cpt_engines *engs, int engs_cnt)
78443ac0b82SSrujana Challa {
78543ac0b82SSrujana Challa 	struct otx2_cpt_engs_rsvd *mirrored_engs;
78643ac0b82SSrujana Challa 	int i;
78743ac0b82SSrujana Challa 
78843ac0b82SSrujana Challa 	for (i = 0; i < engs_cnt; i++) {
78943ac0b82SSrujana Challa 		mirrored_engs = find_engines_by_type(mirror_eng_grp,
79043ac0b82SSrujana Challa 						     engs[i].type);
79143ac0b82SSrujana Challa 		if (!mirrored_engs)
79243ac0b82SSrujana Challa 			continue;
79343ac0b82SSrujana Challa 
79443ac0b82SSrujana Challa 		/*
79543ac0b82SSrujana Challa 		 * If mirrored group has this type of engines attached then
79643ac0b82SSrujana Challa 		 * there are 3 scenarios possible:
79743ac0b82SSrujana Challa 		 * 1) mirrored_engs.count == engs[i].count then all engines
79843ac0b82SSrujana Challa 		 * from mirrored engine group will be shared with this engine
79943ac0b82SSrujana Challa 		 * group
80043ac0b82SSrujana Challa 		 * 2) mirrored_engs.count > engs[i].count then only a subset of
80143ac0b82SSrujana Challa 		 * engines from mirrored engine group will be shared with this
80243ac0b82SSrujana Challa 		 * engine group
80343ac0b82SSrujana Challa 		 * 3) mirrored_engs.count < engs[i].count then all engines
80443ac0b82SSrujana Challa 		 * from mirrored engine group will be shared with this group
80543ac0b82SSrujana Challa 		 * and additional engines will be reserved for exclusively use
80643ac0b82SSrujana Challa 		 * by this engine group
80743ac0b82SSrujana Challa 		 */
80843ac0b82SSrujana Challa 		engs[i].count -= mirrored_engs->count;
80943ac0b82SSrujana Challa 	}
81043ac0b82SSrujana Challa }
81143ac0b82SSrujana Challa 
find_mirrored_eng_grp(struct otx2_cpt_eng_grp_info * grp)81243ac0b82SSrujana Challa static struct otx2_cpt_eng_grp_info *find_mirrored_eng_grp(
81343ac0b82SSrujana Challa 					struct otx2_cpt_eng_grp_info *grp)
81443ac0b82SSrujana Challa {
81543ac0b82SSrujana Challa 	struct otx2_cpt_eng_grps *eng_grps = grp->g;
81643ac0b82SSrujana Challa 	int i;
81743ac0b82SSrujana Challa 
81843ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++) {
81943ac0b82SSrujana Challa 		if (!eng_grps->grp[i].is_enabled)
82043ac0b82SSrujana Challa 			continue;
82143ac0b82SSrujana Challa 		if (eng_grps->grp[i].ucode[0].type &&
82243ac0b82SSrujana Challa 		    eng_grps->grp[i].ucode[1].type)
82343ac0b82SSrujana Challa 			continue;
82443ac0b82SSrujana Challa 		if (grp->idx == i)
82543ac0b82SSrujana Challa 			continue;
82643ac0b82SSrujana Challa 		if (!strncasecmp(eng_grps->grp[i].ucode[0].ver_str,
82743ac0b82SSrujana Challa 				 grp->ucode[0].ver_str,
82843ac0b82SSrujana Challa 				 OTX2_CPT_UCODE_VER_STR_SZ))
82943ac0b82SSrujana Challa 			return &eng_grps->grp[i];
83043ac0b82SSrujana Challa 	}
83143ac0b82SSrujana Challa 
83243ac0b82SSrujana Challa 	return NULL;
83343ac0b82SSrujana Challa }
83443ac0b82SSrujana Challa 
find_unused_eng_grp(struct otx2_cpt_eng_grps * eng_grps)83543ac0b82SSrujana Challa static struct otx2_cpt_eng_grp_info *find_unused_eng_grp(
83643ac0b82SSrujana Challa 					struct otx2_cpt_eng_grps *eng_grps)
83743ac0b82SSrujana Challa {
83843ac0b82SSrujana Challa 	int i;
83943ac0b82SSrujana Challa 
84043ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++) {
84143ac0b82SSrujana Challa 		if (!eng_grps->grp[i].is_enabled)
84243ac0b82SSrujana Challa 			return &eng_grps->grp[i];
84343ac0b82SSrujana Challa 	}
84443ac0b82SSrujana Challa 	return NULL;
84543ac0b82SSrujana Challa }
84643ac0b82SSrujana Challa 
eng_grp_update_masks(struct device * dev,struct otx2_cpt_eng_grp_info * eng_grp)84743ac0b82SSrujana Challa static int eng_grp_update_masks(struct device *dev,
84843ac0b82SSrujana Challa 				struct otx2_cpt_eng_grp_info *eng_grp)
84943ac0b82SSrujana Challa {
85043ac0b82SSrujana Challa 	struct otx2_cpt_engs_rsvd *engs, *mirrored_engs;
85143ac0b82SSrujana Challa 	struct otx2_cpt_bitmap tmp_bmap = { {0} };
85243ac0b82SSrujana Challa 	int i, j, cnt, max_cnt;
85343ac0b82SSrujana Challa 	int bit;
85443ac0b82SSrujana Challa 
85543ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
85643ac0b82SSrujana Challa 		engs = &eng_grp->engs[i];
85743ac0b82SSrujana Challa 		if (!engs->type)
85843ac0b82SSrujana Challa 			continue;
85943ac0b82SSrujana Challa 		if (engs->count <= 0)
86043ac0b82SSrujana Challa 			continue;
86143ac0b82SSrujana Challa 
86243ac0b82SSrujana Challa 		switch (engs->type) {
86343ac0b82SSrujana Challa 		case OTX2_CPT_SE_TYPES:
86443ac0b82SSrujana Challa 			max_cnt = eng_grp->g->avail.max_se_cnt;
86543ac0b82SSrujana Challa 			break;
86643ac0b82SSrujana Challa 
86743ac0b82SSrujana Challa 		case OTX2_CPT_IE_TYPES:
86843ac0b82SSrujana Challa 			max_cnt = eng_grp->g->avail.max_ie_cnt;
86943ac0b82SSrujana Challa 			break;
87043ac0b82SSrujana Challa 
87143ac0b82SSrujana Challa 		case OTX2_CPT_AE_TYPES:
87243ac0b82SSrujana Challa 			max_cnt = eng_grp->g->avail.max_ae_cnt;
87343ac0b82SSrujana Challa 			break;
87443ac0b82SSrujana Challa 
87543ac0b82SSrujana Challa 		default:
87643ac0b82SSrujana Challa 			dev_err(dev, "Invalid engine type %d\n", engs->type);
87743ac0b82SSrujana Challa 			return -EINVAL;
87843ac0b82SSrujana Challa 		}
87943ac0b82SSrujana Challa 
88043ac0b82SSrujana Challa 		cnt = engs->count;
88143ac0b82SSrujana Challa 		WARN_ON(engs->offset + max_cnt > OTX2_CPT_MAX_ENGINES);
88243ac0b82SSrujana Challa 		bitmap_zero(tmp_bmap.bits, eng_grp->g->engs_num);
88343ac0b82SSrujana Challa 		for (j = engs->offset; j < engs->offset + max_cnt; j++) {
88443ac0b82SSrujana Challa 			if (!eng_grp->g->eng_ref_cnt[j]) {
88543ac0b82SSrujana Challa 				bitmap_set(tmp_bmap.bits, j, 1);
88643ac0b82SSrujana Challa 				cnt--;
88743ac0b82SSrujana Challa 				if (!cnt)
88843ac0b82SSrujana Challa 					break;
88943ac0b82SSrujana Challa 			}
89043ac0b82SSrujana Challa 		}
89143ac0b82SSrujana Challa 
89243ac0b82SSrujana Challa 		if (cnt)
89343ac0b82SSrujana Challa 			return -ENOSPC;
89443ac0b82SSrujana Challa 
89543ac0b82SSrujana Challa 		bitmap_copy(engs->bmap, tmp_bmap.bits, eng_grp->g->engs_num);
89643ac0b82SSrujana Challa 	}
89743ac0b82SSrujana Challa 
89843ac0b82SSrujana Challa 	if (!eng_grp->mirror.is_ena)
89943ac0b82SSrujana Challa 		return 0;
90043ac0b82SSrujana Challa 
90143ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
90243ac0b82SSrujana Challa 		engs = &eng_grp->engs[i];
90343ac0b82SSrujana Challa 		if (!engs->type)
90443ac0b82SSrujana Challa 			continue;
90543ac0b82SSrujana Challa 
90643ac0b82SSrujana Challa 		mirrored_engs = find_engines_by_type(
90743ac0b82SSrujana Challa 					&eng_grp->g->grp[eng_grp->mirror.idx],
90843ac0b82SSrujana Challa 					engs->type);
90943ac0b82SSrujana Challa 		WARN_ON(!mirrored_engs && engs->count <= 0);
91043ac0b82SSrujana Challa 		if (!mirrored_engs)
91143ac0b82SSrujana Challa 			continue;
91243ac0b82SSrujana Challa 
91343ac0b82SSrujana Challa 		bitmap_copy(tmp_bmap.bits, mirrored_engs->bmap,
91443ac0b82SSrujana Challa 			    eng_grp->g->engs_num);
91543ac0b82SSrujana Challa 		if (engs->count < 0) {
91643ac0b82SSrujana Challa 			bit = find_first_bit(mirrored_engs->bmap,
91743ac0b82SSrujana Challa 					     eng_grp->g->engs_num);
91843ac0b82SSrujana Challa 			bitmap_clear(tmp_bmap.bits, bit, -engs->count);
91943ac0b82SSrujana Challa 		}
92043ac0b82SSrujana Challa 		bitmap_or(engs->bmap, engs->bmap, tmp_bmap.bits,
92143ac0b82SSrujana Challa 			  eng_grp->g->engs_num);
92243ac0b82SSrujana Challa 	}
92343ac0b82SSrujana Challa 	return 0;
92443ac0b82SSrujana Challa }
92543ac0b82SSrujana Challa 
delete_engine_group(struct device * dev,struct otx2_cpt_eng_grp_info * eng_grp)92643ac0b82SSrujana Challa static int delete_engine_group(struct device *dev,
92743ac0b82SSrujana Challa 			       struct otx2_cpt_eng_grp_info *eng_grp)
92843ac0b82SSrujana Challa {
92943ac0b82SSrujana Challa 	int ret;
93043ac0b82SSrujana Challa 
93143ac0b82SSrujana Challa 	if (!eng_grp->is_enabled)
93243ac0b82SSrujana Challa 		return 0;
93343ac0b82SSrujana Challa 
93443ac0b82SSrujana Challa 	if (eng_grp->mirror.ref_count)
93543ac0b82SSrujana Challa 		return -EINVAL;
93643ac0b82SSrujana Challa 
93743ac0b82SSrujana Challa 	/* Removing engine group mirroring if enabled */
93843ac0b82SSrujana Challa 	remove_eng_grp_mirroring(eng_grp);
93943ac0b82SSrujana Challa 
94043ac0b82SSrujana Challa 	/* Disable engine group */
94143ac0b82SSrujana Challa 	ret = disable_eng_grp(dev, eng_grp, eng_grp->g->obj);
94243ac0b82SSrujana Challa 	if (ret)
94343ac0b82SSrujana Challa 		return ret;
94443ac0b82SSrujana Challa 
94543ac0b82SSrujana Challa 	/* Release all engines held by this engine group */
94643ac0b82SSrujana Challa 	ret = release_engines(dev, eng_grp);
94743ac0b82SSrujana Challa 	if (ret)
94843ac0b82SSrujana Challa 		return ret;
94943ac0b82SSrujana Challa 
95043ac0b82SSrujana Challa 	eng_grp->is_enabled = false;
95143ac0b82SSrujana Challa 
95243ac0b82SSrujana Challa 	return 0;
95343ac0b82SSrujana Challa }
95443ac0b82SSrujana Challa 
update_ucode_ptrs(struct otx2_cpt_eng_grp_info * eng_grp)95543ac0b82SSrujana Challa static void update_ucode_ptrs(struct otx2_cpt_eng_grp_info *eng_grp)
95643ac0b82SSrujana Challa {
95743ac0b82SSrujana Challa 	struct otx2_cpt_ucode *ucode;
95843ac0b82SSrujana Challa 
95943ac0b82SSrujana Challa 	if (eng_grp->mirror.is_ena)
96043ac0b82SSrujana Challa 		ucode = &eng_grp->g->grp[eng_grp->mirror.idx].ucode[0];
96143ac0b82SSrujana Challa 	else
96243ac0b82SSrujana Challa 		ucode = &eng_grp->ucode[0];
96343ac0b82SSrujana Challa 	WARN_ON(!eng_grp->engs[0].type);
96443ac0b82SSrujana Challa 	eng_grp->engs[0].ucode = ucode;
96543ac0b82SSrujana Challa 
96643ac0b82SSrujana Challa 	if (eng_grp->engs[1].type) {
96743ac0b82SSrujana Challa 		if (is_2nd_ucode_used(eng_grp))
96843ac0b82SSrujana Challa 			eng_grp->engs[1].ucode = &eng_grp->ucode[1];
96943ac0b82SSrujana Challa 		else
97043ac0b82SSrujana Challa 			eng_grp->engs[1].ucode = ucode;
97143ac0b82SSrujana Challa 	}
97243ac0b82SSrujana Challa }
97343ac0b82SSrujana Challa 
create_engine_group(struct device * dev,struct otx2_cpt_eng_grps * eng_grps,struct otx2_cpt_engines * engs,int ucodes_cnt,void * ucode_data[],int is_print)97443ac0b82SSrujana Challa static int create_engine_group(struct device *dev,
97543ac0b82SSrujana Challa 			       struct otx2_cpt_eng_grps *eng_grps,
97643ac0b82SSrujana Challa 			       struct otx2_cpt_engines *engs, int ucodes_cnt,
97743ac0b82SSrujana Challa 			       void *ucode_data[], int is_print)
97843ac0b82SSrujana Challa {
97943ac0b82SSrujana Challa 	struct otx2_cpt_eng_grp_info *mirrored_eng_grp;
98043ac0b82SSrujana Challa 	struct otx2_cpt_eng_grp_info *eng_grp;
98143ac0b82SSrujana Challa 	struct otx2_cpt_uc_info_t *uc_info;
98243ac0b82SSrujana Challa 	int i, ret = 0;
98343ac0b82SSrujana Challa 
98443ac0b82SSrujana Challa 	/* Find engine group which is not used */
98543ac0b82SSrujana Challa 	eng_grp = find_unused_eng_grp(eng_grps);
98643ac0b82SSrujana Challa 	if (!eng_grp) {
98743ac0b82SSrujana Challa 		dev_err(dev, "Error all engine groups are being used\n");
98843ac0b82SSrujana Challa 		return -ENOSPC;
98943ac0b82SSrujana Challa 	}
99043ac0b82SSrujana Challa 	/* Load ucode */
99143ac0b82SSrujana Challa 	for (i = 0; i < ucodes_cnt; i++) {
99243ac0b82SSrujana Challa 		uc_info = (struct otx2_cpt_uc_info_t *) ucode_data[i];
99343ac0b82SSrujana Challa 		eng_grp->ucode[i] = uc_info->ucode;
99443ac0b82SSrujana Challa 		ret = copy_ucode_to_dma_mem(dev, &eng_grp->ucode[i],
99543ac0b82SSrujana Challa 					    uc_info->fw->data);
99643ac0b82SSrujana Challa 		if (ret)
99743ac0b82SSrujana Challa 			goto unload_ucode;
99843ac0b82SSrujana Challa 	}
99943ac0b82SSrujana Challa 
100043ac0b82SSrujana Challa 	/* Check if this group mirrors another existing engine group */
100143ac0b82SSrujana Challa 	mirrored_eng_grp = find_mirrored_eng_grp(eng_grp);
100243ac0b82SSrujana Challa 	if (mirrored_eng_grp) {
100343ac0b82SSrujana Challa 		/* Setup mirroring */
100443ac0b82SSrujana Challa 		setup_eng_grp_mirroring(eng_grp, mirrored_eng_grp);
100543ac0b82SSrujana Challa 
100643ac0b82SSrujana Challa 		/*
100743ac0b82SSrujana Challa 		 * Update count of requested engines because some
100843ac0b82SSrujana Challa 		 * of them might be shared with mirrored group
100943ac0b82SSrujana Challa 		 */
101043ac0b82SSrujana Challa 		update_requested_engs(mirrored_eng_grp, engs, ucodes_cnt);
101143ac0b82SSrujana Challa 	}
101243ac0b82SSrujana Challa 	ret = reserve_engines(dev, eng_grp, engs, ucodes_cnt);
101343ac0b82SSrujana Challa 	if (ret)
101443ac0b82SSrujana Challa 		goto unload_ucode;
101543ac0b82SSrujana Challa 
101643ac0b82SSrujana Challa 	/* Update ucode pointers used by engines */
101743ac0b82SSrujana Challa 	update_ucode_ptrs(eng_grp);
101843ac0b82SSrujana Challa 
101943ac0b82SSrujana Challa 	/* Update engine masks used by this group */
102043ac0b82SSrujana Challa 	ret = eng_grp_update_masks(dev, eng_grp);
102143ac0b82SSrujana Challa 	if (ret)
102243ac0b82SSrujana Challa 		goto release_engs;
102343ac0b82SSrujana Challa 
102443ac0b82SSrujana Challa 	/* Enable engine group */
102543ac0b82SSrujana Challa 	ret = enable_eng_grp(eng_grp, eng_grps->obj);
102643ac0b82SSrujana Challa 	if (ret)
102743ac0b82SSrujana Challa 		goto release_engs;
102843ac0b82SSrujana Challa 
102943ac0b82SSrujana Challa 	/*
103043ac0b82SSrujana Challa 	 * If this engine group mirrors another engine group
103143ac0b82SSrujana Challa 	 * then we need to unload ucode as we will use ucode
103243ac0b82SSrujana Challa 	 * from mirrored engine group
103343ac0b82SSrujana Challa 	 */
103443ac0b82SSrujana Challa 	if (eng_grp->mirror.is_ena)
103543ac0b82SSrujana Challa 		ucode_unload(dev, &eng_grp->ucode[0]);
103643ac0b82SSrujana Challa 
103743ac0b82SSrujana Challa 	eng_grp->is_enabled = true;
103843ac0b82SSrujana Challa 
103943ac0b82SSrujana Challa 	if (!is_print)
104043ac0b82SSrujana Challa 		return 0;
104143ac0b82SSrujana Challa 
104243ac0b82SSrujana Challa 	if (mirrored_eng_grp)
104343ac0b82SSrujana Challa 		dev_info(dev,
104443ac0b82SSrujana Challa 			 "Engine_group%d: reuse microcode %s from group %d\n",
104543ac0b82SSrujana Challa 			 eng_grp->idx, mirrored_eng_grp->ucode[0].ver_str,
104643ac0b82SSrujana Challa 			 mirrored_eng_grp->idx);
104743ac0b82SSrujana Challa 	else
104843ac0b82SSrujana Challa 		dev_info(dev, "Engine_group%d: microcode loaded %s\n",
104943ac0b82SSrujana Challa 			 eng_grp->idx, eng_grp->ucode[0].ver_str);
105043ac0b82SSrujana Challa 	if (is_2nd_ucode_used(eng_grp))
105143ac0b82SSrujana Challa 		dev_info(dev, "Engine_group%d: microcode loaded %s\n",
105243ac0b82SSrujana Challa 			 eng_grp->idx, eng_grp->ucode[1].ver_str);
105343ac0b82SSrujana Challa 
105443ac0b82SSrujana Challa 	return 0;
105543ac0b82SSrujana Challa 
105643ac0b82SSrujana Challa release_engs:
105743ac0b82SSrujana Challa 	release_engines(dev, eng_grp);
105843ac0b82SSrujana Challa unload_ucode:
105943ac0b82SSrujana Challa 	ucode_unload(dev, &eng_grp->ucode[0]);
106043ac0b82SSrujana Challa 	ucode_unload(dev, &eng_grp->ucode[1]);
106143ac0b82SSrujana Challa 	return ret;
106243ac0b82SSrujana Challa }
106343ac0b82SSrujana Challa 
delete_engine_grps(struct pci_dev * pdev,struct otx2_cpt_eng_grps * eng_grps)106443ac0b82SSrujana Challa static void delete_engine_grps(struct pci_dev *pdev,
106543ac0b82SSrujana Challa 			       struct otx2_cpt_eng_grps *eng_grps)
106643ac0b82SSrujana Challa {
106743ac0b82SSrujana Challa 	int i;
106843ac0b82SSrujana Challa 
106943ac0b82SSrujana Challa 	/* First delete all mirroring engine groups */
107043ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++)
107143ac0b82SSrujana Challa 		if (eng_grps->grp[i].mirror.is_ena)
107243ac0b82SSrujana Challa 			delete_engine_group(&pdev->dev, &eng_grps->grp[i]);
107343ac0b82SSrujana Challa 
107443ac0b82SSrujana Challa 	/* Delete remaining engine groups */
107543ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++)
107643ac0b82SSrujana Challa 		delete_engine_group(&pdev->dev, &eng_grps->grp[i]);
107743ac0b82SSrujana Challa }
107843ac0b82SSrujana Challa 
1079bd9305b0SSrujana Challa #define PCI_DEVID_CN10K_RNM 0xA098
1080bd9305b0SSrujana Challa #define RNM_ENTROPY_STATUS  0x8
1081bd9305b0SSrujana Challa 
rnm_to_cpt_errata_fixup(struct device * dev)1082bd9305b0SSrujana Challa static void rnm_to_cpt_errata_fixup(struct device *dev)
1083bd9305b0SSrujana Challa {
1084bd9305b0SSrujana Challa 	struct pci_dev *pdev;
1085bd9305b0SSrujana Challa 	void __iomem *base;
1086bd9305b0SSrujana Challa 	int timeout = 5000;
1087bd9305b0SSrujana Challa 
1088bd9305b0SSrujana Challa 	pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RNM, NULL);
1089bd9305b0SSrujana Challa 	if (!pdev)
1090bd9305b0SSrujana Challa 		return;
1091bd9305b0SSrujana Challa 
1092bd9305b0SSrujana Challa 	base = pci_ioremap_bar(pdev, 0);
1093bd9305b0SSrujana Challa 	if (!base)
1094bd9305b0SSrujana Challa 		goto put_pdev;
1095bd9305b0SSrujana Challa 
1096bd9305b0SSrujana Challa 	while ((readq(base + RNM_ENTROPY_STATUS) & 0x7F) != 0x40) {
1097bd9305b0SSrujana Challa 		cpu_relax();
1098bd9305b0SSrujana Challa 		udelay(1);
1099bd9305b0SSrujana Challa 		timeout--;
1100bd9305b0SSrujana Challa 		if (!timeout) {
1101bd9305b0SSrujana Challa 			dev_warn(dev, "RNM is not producing entropy\n");
1102bd9305b0SSrujana Challa 			break;
1103bd9305b0SSrujana Challa 		}
1104bd9305b0SSrujana Challa 	}
1105bd9305b0SSrujana Challa 
1106bd9305b0SSrujana Challa 	iounmap(base);
1107bd9305b0SSrujana Challa 
1108bd9305b0SSrujana Challa put_pdev:
1109bd9305b0SSrujana Challa 	pci_dev_put(pdev);
1110bd9305b0SSrujana Challa }
1111bd9305b0SSrujana Challa 
otx2_cpt_get_eng_grp(struct otx2_cpt_eng_grps * eng_grps,int eng_type)111243ac0b82SSrujana Challa int otx2_cpt_get_eng_grp(struct otx2_cpt_eng_grps *eng_grps, int eng_type)
111343ac0b82SSrujana Challa {
111443ac0b82SSrujana Challa 
111543ac0b82SSrujana Challa 	int eng_grp_num = OTX2_CPT_INVALID_CRYPTO_ENG_GRP;
111643ac0b82SSrujana Challa 	struct otx2_cpt_eng_grp_info *grp;
111743ac0b82SSrujana Challa 	int i;
111843ac0b82SSrujana Challa 
111943ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++) {
112043ac0b82SSrujana Challa 		grp = &eng_grps->grp[i];
112143ac0b82SSrujana Challa 		if (!grp->is_enabled)
112243ac0b82SSrujana Challa 			continue;
112343ac0b82SSrujana Challa 
112443ac0b82SSrujana Challa 		if (eng_type == OTX2_CPT_SE_TYPES) {
112543ac0b82SSrujana Challa 			if (eng_grp_has_eng_type(grp, eng_type) &&
112643ac0b82SSrujana Challa 			    !eng_grp_has_eng_type(grp, OTX2_CPT_IE_TYPES)) {
112743ac0b82SSrujana Challa 				eng_grp_num = i;
112843ac0b82SSrujana Challa 				break;
112943ac0b82SSrujana Challa 			}
113043ac0b82SSrujana Challa 		} else {
113143ac0b82SSrujana Challa 			if (eng_grp_has_eng_type(grp, eng_type)) {
113243ac0b82SSrujana Challa 				eng_grp_num = i;
113343ac0b82SSrujana Challa 				break;
113443ac0b82SSrujana Challa 			}
113543ac0b82SSrujana Challa 		}
113643ac0b82SSrujana Challa 	}
113743ac0b82SSrujana Challa 	return eng_grp_num;
113843ac0b82SSrujana Challa }
113943ac0b82SSrujana Challa 
otx2_cpt_create_eng_grps(struct otx2_cptpf_dev * cptpf,struct otx2_cpt_eng_grps * eng_grps)114040a645f7SSrujana Challa int otx2_cpt_create_eng_grps(struct otx2_cptpf_dev *cptpf,
114143ac0b82SSrujana Challa 			     struct otx2_cpt_eng_grps *eng_grps)
114243ac0b82SSrujana Challa {
114343ac0b82SSrujana Challa 	struct otx2_cpt_uc_info_t *uc_info[OTX2_CPT_MAX_ETYPES_PER_GRP] = {  };
114443ac0b82SSrujana Challa 	struct otx2_cpt_engines engs[OTX2_CPT_MAX_ETYPES_PER_GRP] = { {0} };
114540a645f7SSrujana Challa 	struct pci_dev *pdev = cptpf->pdev;
114643ac0b82SSrujana Challa 	struct fw_info_t fw_info;
11479eef6e97SSrujana Challa 	u64 reg_val;
1148d9d77497SSrujana Challa 	int ret = 0;
114943ac0b82SSrujana Challa 
1150d9d77497SSrujana Challa 	mutex_lock(&eng_grps->lock);
115143ac0b82SSrujana Challa 	/*
115243ac0b82SSrujana Challa 	 * We don't create engine groups if it was already
115343ac0b82SSrujana Challa 	 * made (when user enabled VFs for the first time)
115443ac0b82SSrujana Challa 	 */
115543ac0b82SSrujana Challa 	if (eng_grps->is_grps_created)
1156d9d77497SSrujana Challa 		goto unlock;
115743ac0b82SSrujana Challa 
115843ac0b82SSrujana Challa 	ret = cpt_ucode_load_fw(pdev, &fw_info);
115943ac0b82SSrujana Challa 	if (ret)
1160d9d77497SSrujana Challa 		goto unlock;
116143ac0b82SSrujana Challa 
116243ac0b82SSrujana Challa 	/*
116343ac0b82SSrujana Challa 	 * Create engine group with SE engines for kernel
116443ac0b82SSrujana Challa 	 * crypto functionality (symmetric crypto)
116543ac0b82SSrujana Challa 	 */
116643ac0b82SSrujana Challa 	uc_info[0] = get_ucode(&fw_info, OTX2_CPT_SE_TYPES);
116743ac0b82SSrujana Challa 	if (uc_info[0] == NULL) {
116843ac0b82SSrujana Challa 		dev_err(&pdev->dev, "Unable to find firmware for SE\n");
116943ac0b82SSrujana Challa 		ret = -EINVAL;
117043ac0b82SSrujana Challa 		goto release_fw;
117143ac0b82SSrujana Challa 	}
117243ac0b82SSrujana Challa 	engs[0].type = OTX2_CPT_SE_TYPES;
117343ac0b82SSrujana Challa 	engs[0].count = eng_grps->avail.max_se_cnt;
117443ac0b82SSrujana Challa 
117543ac0b82SSrujana Challa 	ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
117643ac0b82SSrujana Challa 				  (void **) uc_info, 1);
117743ac0b82SSrujana Challa 	if (ret)
117843ac0b82SSrujana Challa 		goto release_fw;
117943ac0b82SSrujana Challa 
118043ac0b82SSrujana Challa 	/*
118143ac0b82SSrujana Challa 	 * Create engine group with SE+IE engines for IPSec.
118243ac0b82SSrujana Challa 	 * All SE engines will be shared with engine group 0.
118343ac0b82SSrujana Challa 	 */
118443ac0b82SSrujana Challa 	uc_info[0] = get_ucode(&fw_info, OTX2_CPT_SE_TYPES);
118543ac0b82SSrujana Challa 	uc_info[1] = get_ucode(&fw_info, OTX2_CPT_IE_TYPES);
118643ac0b82SSrujana Challa 
118743ac0b82SSrujana Challa 	if (uc_info[1] == NULL) {
118843ac0b82SSrujana Challa 		dev_err(&pdev->dev, "Unable to find firmware for IE");
118943ac0b82SSrujana Challa 		ret = -EINVAL;
119043ac0b82SSrujana Challa 		goto delete_eng_grp;
119143ac0b82SSrujana Challa 	}
119243ac0b82SSrujana Challa 	engs[0].type = OTX2_CPT_SE_TYPES;
119343ac0b82SSrujana Challa 	engs[0].count = eng_grps->avail.max_se_cnt;
119443ac0b82SSrujana Challa 	engs[1].type = OTX2_CPT_IE_TYPES;
119543ac0b82SSrujana Challa 	engs[1].count = eng_grps->avail.max_ie_cnt;
119643ac0b82SSrujana Challa 
119743ac0b82SSrujana Challa 	ret = create_engine_group(&pdev->dev, eng_grps, engs, 2,
119843ac0b82SSrujana Challa 				  (void **) uc_info, 1);
119943ac0b82SSrujana Challa 	if (ret)
120043ac0b82SSrujana Challa 		goto delete_eng_grp;
120143ac0b82SSrujana Challa 
120243ac0b82SSrujana Challa 	/*
120343ac0b82SSrujana Challa 	 * Create engine group with AE engines for asymmetric
120443ac0b82SSrujana Challa 	 * crypto functionality.
120543ac0b82SSrujana Challa 	 */
120643ac0b82SSrujana Challa 	uc_info[0] = get_ucode(&fw_info, OTX2_CPT_AE_TYPES);
120743ac0b82SSrujana Challa 	if (uc_info[0] == NULL) {
120843ac0b82SSrujana Challa 		dev_err(&pdev->dev, "Unable to find firmware for AE");
120943ac0b82SSrujana Challa 		ret = -EINVAL;
121043ac0b82SSrujana Challa 		goto delete_eng_grp;
121143ac0b82SSrujana Challa 	}
121243ac0b82SSrujana Challa 	engs[0].type = OTX2_CPT_AE_TYPES;
121343ac0b82SSrujana Challa 	engs[0].count = eng_grps->avail.max_ae_cnt;
121443ac0b82SSrujana Challa 
121543ac0b82SSrujana Challa 	ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
121643ac0b82SSrujana Challa 				  (void **) uc_info, 1);
121743ac0b82SSrujana Challa 	if (ret)
121843ac0b82SSrujana Challa 		goto delete_eng_grp;
121943ac0b82SSrujana Challa 
122043ac0b82SSrujana Challa 	eng_grps->is_grps_created = true;
122143ac0b82SSrujana Challa 
122243ac0b82SSrujana Challa 	cpt_ucode_release_fw(&fw_info);
122340a645f7SSrujana Challa 
122440a645f7SSrujana Challa 	if (is_dev_otx2(pdev))
1225d9d77497SSrujana Challa 		goto unlock;
1226bd9305b0SSrujana Challa 
1227bd9305b0SSrujana Challa 	/*
1228bd9305b0SSrujana Challa 	 * Ensure RNM_ENTROPY_STATUS[NORMAL_CNT] = 0x40 before writing
1229bd9305b0SSrujana Challa 	 * CPT_AF_CTL[RNM_REQ_EN] = 1 as a workaround for HW errata.
1230bd9305b0SSrujana Challa 	 */
1231bd9305b0SSrujana Challa 	rnm_to_cpt_errata_fixup(&pdev->dev);
1232bd9305b0SSrujana Challa 
123340a645f7SSrujana Challa 	/*
123440a645f7SSrujana Challa 	 * Configure engine group mask to allow context prefetching
1235bd9305b0SSrujana Challa 	 * for the groups and enable random number request, to enable
1236bd9305b0SSrujana Challa 	 * CPT to request random numbers from RNM.
123740a645f7SSrujana Challa 	 */
123840a645f7SSrujana Challa 	otx2_cpt_write_af_reg(&cptpf->afpf_mbox, pdev, CPT_AF_CTL,
123940a645f7SSrujana Challa 			      OTX2_CPT_ALL_ENG_GRPS_MASK << 3 | BIT_ULL(16),
124040a645f7SSrujana Challa 			      BLKADDR_CPT0);
124140a645f7SSrujana Challa 	/*
124240a645f7SSrujana Challa 	 * Set interval to periodically flush dirty data for the next
124340a645f7SSrujana Challa 	 * CTX cache entry. Set the interval count to maximum supported
124440a645f7SSrujana Challa 	 * value.
124540a645f7SSrujana Challa 	 */
124640a645f7SSrujana Challa 	otx2_cpt_write_af_reg(&cptpf->afpf_mbox, pdev, CPT_AF_CTX_FLUSH_TIMER,
124740a645f7SSrujana Challa 			      CTX_FLUSH_TIMER_CNT, BLKADDR_CPT0);
12489eef6e97SSrujana Challa 
12499eef6e97SSrujana Challa 	/*
12509eef6e97SSrujana Challa 	 * Set CPT_AF_DIAG[FLT_DIS], as a workaround for HW errata, when
12519eef6e97SSrujana Challa 	 * CPT_AF_DIAG[FLT_DIS] = 0 and a CPT engine access to LLC/DRAM
12529eef6e97SSrujana Challa 	 * encounters a fault/poison, a rare case may result in
12539eef6e97SSrujana Challa 	 * unpredictable data being delivered to a CPT engine.
12549eef6e97SSrujana Challa 	 */
12559eef6e97SSrujana Challa 	otx2_cpt_read_af_reg(&cptpf->afpf_mbox, pdev, CPT_AF_DIAG, &reg_val,
12569eef6e97SSrujana Challa 			     BLKADDR_CPT0);
12579eef6e97SSrujana Challa 	otx2_cpt_write_af_reg(&cptpf->afpf_mbox, pdev, CPT_AF_DIAG,
12589eef6e97SSrujana Challa 			      reg_val | BIT_ULL(24), BLKADDR_CPT0);
12599eef6e97SSrujana Challa 
1260d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
126143ac0b82SSrujana Challa 	return 0;
126243ac0b82SSrujana Challa 
126343ac0b82SSrujana Challa delete_eng_grp:
126443ac0b82SSrujana Challa 	delete_engine_grps(pdev, eng_grps);
126543ac0b82SSrujana Challa release_fw:
126643ac0b82SSrujana Challa 	cpt_ucode_release_fw(&fw_info);
1267d9d77497SSrujana Challa unlock:
1268d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
126943ac0b82SSrujana Challa 	return ret;
127043ac0b82SSrujana Challa }
127143ac0b82SSrujana Challa 
cptx_disable_all_cores(struct otx2_cptpf_dev * cptpf,int total_cores,int blkaddr)1272b2d17df3SSrujana Challa static int cptx_disable_all_cores(struct otx2_cptpf_dev *cptpf, int total_cores,
1273b2d17df3SSrujana Challa 				  int blkaddr)
127443ac0b82SSrujana Challa {
1275b2d17df3SSrujana Challa 	int timeout = 10, ret;
1276b2d17df3SSrujana Challa 	int i, busy;
1277b2d17df3SSrujana Challa 	u64 reg;
127843ac0b82SSrujana Challa 
127943ac0b82SSrujana Challa 	/* Disengage the cores from groups */
128043ac0b82SSrujana Challa 	for (i = 0; i < total_cores; i++) {
128143ac0b82SSrujana Challa 		ret = otx2_cpt_add_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
1282b2d17df3SSrujana Challa 						CPT_AF_EXEX_CTL2(i), 0x0,
1283b2d17df3SSrujana Challa 						blkaddr);
128443ac0b82SSrujana Challa 		if (ret)
128543ac0b82SSrujana Challa 			return ret;
128643ac0b82SSrujana Challa 
128743ac0b82SSrujana Challa 		cptpf->eng_grps.eng_ref_cnt[i] = 0;
128843ac0b82SSrujana Challa 	}
128943ac0b82SSrujana Challa 	ret = otx2_cpt_send_af_reg_requests(&cptpf->afpf_mbox, cptpf->pdev);
129043ac0b82SSrujana Challa 	if (ret)
129143ac0b82SSrujana Challa 		return ret;
129243ac0b82SSrujana Challa 
129343ac0b82SSrujana Challa 	/* Wait for cores to become idle */
129443ac0b82SSrujana Challa 	do {
129543ac0b82SSrujana Challa 		busy = 0;
129643ac0b82SSrujana Challa 		usleep_range(10000, 20000);
129743ac0b82SSrujana Challa 		if (timeout-- < 0)
129843ac0b82SSrujana Challa 			return -EBUSY;
129943ac0b82SSrujana Challa 
130043ac0b82SSrujana Challa 		for (i = 0; i < total_cores; i++) {
130143ac0b82SSrujana Challa 			ret = otx2_cpt_read_af_reg(&cptpf->afpf_mbox,
130243ac0b82SSrujana Challa 						   cptpf->pdev,
1303b2d17df3SSrujana Challa 						   CPT_AF_EXEX_STS(i), &reg,
1304b2d17df3SSrujana Challa 						   blkaddr);
130543ac0b82SSrujana Challa 			if (ret)
130643ac0b82SSrujana Challa 				return ret;
130743ac0b82SSrujana Challa 
130843ac0b82SSrujana Challa 			if (reg & 0x1) {
130943ac0b82SSrujana Challa 				busy = 1;
131043ac0b82SSrujana Challa 				break;
131143ac0b82SSrujana Challa 			}
131243ac0b82SSrujana Challa 		}
131343ac0b82SSrujana Challa 	} while (busy);
131443ac0b82SSrujana Challa 
131543ac0b82SSrujana Challa 	/* Disable the cores */
131643ac0b82SSrujana Challa 	for (i = 0; i < total_cores; i++) {
131743ac0b82SSrujana Challa 		ret = otx2_cpt_add_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev,
1318b2d17df3SSrujana Challa 						CPT_AF_EXEX_CTL(i), 0x0,
1319b2d17df3SSrujana Challa 						blkaddr);
132043ac0b82SSrujana Challa 		if (ret)
132143ac0b82SSrujana Challa 			return ret;
132243ac0b82SSrujana Challa 	}
132343ac0b82SSrujana Challa 	return otx2_cpt_send_af_reg_requests(&cptpf->afpf_mbox, cptpf->pdev);
132443ac0b82SSrujana Challa }
132543ac0b82SSrujana Challa 
otx2_cpt_disable_all_cores(struct otx2_cptpf_dev * cptpf)1326b2d17df3SSrujana Challa int otx2_cpt_disable_all_cores(struct otx2_cptpf_dev *cptpf)
1327b2d17df3SSrujana Challa {
1328b2d17df3SSrujana Challa 	int total_cores, ret;
1329b2d17df3SSrujana Challa 
1330b2d17df3SSrujana Challa 	total_cores = cptpf->eng_grps.avail.max_se_cnt +
1331b2d17df3SSrujana Challa 		      cptpf->eng_grps.avail.max_ie_cnt +
1332b2d17df3SSrujana Challa 		      cptpf->eng_grps.avail.max_ae_cnt;
1333b2d17df3SSrujana Challa 
1334b2d17df3SSrujana Challa 	if (cptpf->has_cpt1) {
1335b2d17df3SSrujana Challa 		ret = cptx_disable_all_cores(cptpf, total_cores, BLKADDR_CPT1);
1336b2d17df3SSrujana Challa 		if (ret)
1337b2d17df3SSrujana Challa 			return ret;
1338b2d17df3SSrujana Challa 	}
1339b2d17df3SSrujana Challa 	return cptx_disable_all_cores(cptpf, total_cores, BLKADDR_CPT0);
1340b2d17df3SSrujana Challa }
1341b2d17df3SSrujana Challa 
otx2_cpt_cleanup_eng_grps(struct pci_dev * pdev,struct otx2_cpt_eng_grps * eng_grps)134243ac0b82SSrujana Challa void otx2_cpt_cleanup_eng_grps(struct pci_dev *pdev,
134343ac0b82SSrujana Challa 			       struct otx2_cpt_eng_grps *eng_grps)
134443ac0b82SSrujana Challa {
134543ac0b82SSrujana Challa 	struct otx2_cpt_eng_grp_info *grp;
134643ac0b82SSrujana Challa 	int i, j;
134743ac0b82SSrujana Challa 
1348d9d77497SSrujana Challa 	mutex_lock(&eng_grps->lock);
134943ac0b82SSrujana Challa 	delete_engine_grps(pdev, eng_grps);
135043ac0b82SSrujana Challa 	/* Release memory */
135143ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++) {
135243ac0b82SSrujana Challa 		grp = &eng_grps->grp[i];
135343ac0b82SSrujana Challa 		for (j = 0; j < OTX2_CPT_MAX_ETYPES_PER_GRP; j++) {
135443ac0b82SSrujana Challa 			kfree(grp->engs[j].bmap);
135543ac0b82SSrujana Challa 			grp->engs[j].bmap = NULL;
135643ac0b82SSrujana Challa 		}
135743ac0b82SSrujana Challa 	}
1358d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
135943ac0b82SSrujana Challa }
136043ac0b82SSrujana Challa 
otx2_cpt_init_eng_grps(struct pci_dev * pdev,struct otx2_cpt_eng_grps * eng_grps)136143ac0b82SSrujana Challa int otx2_cpt_init_eng_grps(struct pci_dev *pdev,
136243ac0b82SSrujana Challa 			   struct otx2_cpt_eng_grps *eng_grps)
136343ac0b82SSrujana Challa {
136443ac0b82SSrujana Challa 	struct otx2_cpt_eng_grp_info *grp;
136543ac0b82SSrujana Challa 	int i, j, ret;
136643ac0b82SSrujana Challa 
1367d9d77497SSrujana Challa 	mutex_init(&eng_grps->lock);
136843ac0b82SSrujana Challa 	eng_grps->obj = pci_get_drvdata(pdev);
136943ac0b82SSrujana Challa 	eng_grps->avail.se_cnt = eng_grps->avail.max_se_cnt;
137043ac0b82SSrujana Challa 	eng_grps->avail.ie_cnt = eng_grps->avail.max_ie_cnt;
137143ac0b82SSrujana Challa 	eng_grps->avail.ae_cnt = eng_grps->avail.max_ae_cnt;
137243ac0b82SSrujana Challa 
137343ac0b82SSrujana Challa 	eng_grps->engs_num = eng_grps->avail.max_se_cnt +
137443ac0b82SSrujana Challa 			     eng_grps->avail.max_ie_cnt +
137543ac0b82SSrujana Challa 			     eng_grps->avail.max_ae_cnt;
137643ac0b82SSrujana Challa 	if (eng_grps->engs_num > OTX2_CPT_MAX_ENGINES) {
137743ac0b82SSrujana Challa 		dev_err(&pdev->dev,
137843ac0b82SSrujana Challa 			"Number of engines %d > than max supported %d\n",
137943ac0b82SSrujana Challa 			eng_grps->engs_num, OTX2_CPT_MAX_ENGINES);
138043ac0b82SSrujana Challa 		ret = -EINVAL;
138143ac0b82SSrujana Challa 		goto cleanup_eng_grps;
138243ac0b82SSrujana Challa 	}
138343ac0b82SSrujana Challa 
138443ac0b82SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++) {
138543ac0b82SSrujana Challa 		grp = &eng_grps->grp[i];
138643ac0b82SSrujana Challa 		grp->g = eng_grps;
138743ac0b82SSrujana Challa 		grp->idx = i;
138843ac0b82SSrujana Challa 
138943ac0b82SSrujana Challa 		for (j = 0; j < OTX2_CPT_MAX_ETYPES_PER_GRP; j++) {
139043ac0b82SSrujana Challa 			grp->engs[j].bmap =
139143ac0b82SSrujana Challa 				kcalloc(BITS_TO_LONGS(eng_grps->engs_num),
139243ac0b82SSrujana Challa 					sizeof(long), GFP_KERNEL);
139343ac0b82SSrujana Challa 			if (!grp->engs[j].bmap) {
139443ac0b82SSrujana Challa 				ret = -ENOMEM;
139543ac0b82SSrujana Challa 				goto cleanup_eng_grps;
139643ac0b82SSrujana Challa 			}
139743ac0b82SSrujana Challa 		}
139843ac0b82SSrujana Challa 	}
139943ac0b82SSrujana Challa 	return 0;
140043ac0b82SSrujana Challa 
140143ac0b82SSrujana Challa cleanup_eng_grps:
140243ac0b82SSrujana Challa 	otx2_cpt_cleanup_eng_grps(pdev, eng_grps);
140343ac0b82SSrujana Challa 	return ret;
140443ac0b82SSrujana Challa }
140578506c2aSSrujana Challa 
create_eng_caps_discovery_grps(struct pci_dev * pdev,struct otx2_cpt_eng_grps * eng_grps)140678506c2aSSrujana Challa static int create_eng_caps_discovery_grps(struct pci_dev *pdev,
140778506c2aSSrujana Challa 					  struct otx2_cpt_eng_grps *eng_grps)
140878506c2aSSrujana Challa {
140978506c2aSSrujana Challa 	struct otx2_cpt_uc_info_t *uc_info[OTX2_CPT_MAX_ETYPES_PER_GRP] = {  };
141078506c2aSSrujana Challa 	struct otx2_cpt_engines engs[OTX2_CPT_MAX_ETYPES_PER_GRP] = { {0} };
141178506c2aSSrujana Challa 	struct fw_info_t fw_info;
141278506c2aSSrujana Challa 	int ret;
141378506c2aSSrujana Challa 
1414d9d77497SSrujana Challa 	mutex_lock(&eng_grps->lock);
141578506c2aSSrujana Challa 	ret = cpt_ucode_load_fw(pdev, &fw_info);
1416d9d77497SSrujana Challa 	if (ret) {
1417d9d77497SSrujana Challa 		mutex_unlock(&eng_grps->lock);
141878506c2aSSrujana Challa 		return ret;
1419d9d77497SSrujana Challa 	}
142078506c2aSSrujana Challa 
1421d9d77497SSrujana Challa 	uc_info[0] = get_ucode(&fw_info, OTX2_CPT_AE_TYPES);
142278506c2aSSrujana Challa 	if (uc_info[0] == NULL) {
142378506c2aSSrujana Challa 		dev_err(&pdev->dev, "Unable to find firmware for AE\n");
142478506c2aSSrujana Challa 		ret = -EINVAL;
142578506c2aSSrujana Challa 		goto release_fw;
142678506c2aSSrujana Challa 	}
142778506c2aSSrujana Challa 	engs[0].type = OTX2_CPT_AE_TYPES;
142878506c2aSSrujana Challa 	engs[0].count = 2;
142978506c2aSSrujana Challa 
143078506c2aSSrujana Challa 	ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
143178506c2aSSrujana Challa 				  (void **) uc_info, 0);
143278506c2aSSrujana Challa 	if (ret)
143378506c2aSSrujana Challa 		goto release_fw;
143478506c2aSSrujana Challa 
143578506c2aSSrujana Challa 	uc_info[0] = get_ucode(&fw_info, OTX2_CPT_SE_TYPES);
143678506c2aSSrujana Challa 	if (uc_info[0] == NULL) {
143778506c2aSSrujana Challa 		dev_err(&pdev->dev, "Unable to find firmware for SE\n");
143878506c2aSSrujana Challa 		ret = -EINVAL;
143978506c2aSSrujana Challa 		goto delete_eng_grp;
144078506c2aSSrujana Challa 	}
144178506c2aSSrujana Challa 	engs[0].type = OTX2_CPT_SE_TYPES;
144278506c2aSSrujana Challa 	engs[0].count = 2;
144378506c2aSSrujana Challa 
144478506c2aSSrujana Challa 	ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
144578506c2aSSrujana Challa 				  (void **) uc_info, 0);
144678506c2aSSrujana Challa 	if (ret)
144778506c2aSSrujana Challa 		goto delete_eng_grp;
144878506c2aSSrujana Challa 
144978506c2aSSrujana Challa 	uc_info[0] = get_ucode(&fw_info, OTX2_CPT_IE_TYPES);
145078506c2aSSrujana Challa 	if (uc_info[0] == NULL) {
145178506c2aSSrujana Challa 		dev_err(&pdev->dev, "Unable to find firmware for IE\n");
145278506c2aSSrujana Challa 		ret = -EINVAL;
145378506c2aSSrujana Challa 		goto delete_eng_grp;
145478506c2aSSrujana Challa 	}
145578506c2aSSrujana Challa 	engs[0].type = OTX2_CPT_IE_TYPES;
145678506c2aSSrujana Challa 	engs[0].count = 2;
145778506c2aSSrujana Challa 
145878506c2aSSrujana Challa 	ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
145978506c2aSSrujana Challa 				  (void **) uc_info, 0);
146078506c2aSSrujana Challa 	if (ret)
146178506c2aSSrujana Challa 		goto delete_eng_grp;
146278506c2aSSrujana Challa 
146378506c2aSSrujana Challa 	cpt_ucode_release_fw(&fw_info);
1464d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
146578506c2aSSrujana Challa 	return 0;
146678506c2aSSrujana Challa 
146778506c2aSSrujana Challa delete_eng_grp:
146878506c2aSSrujana Challa 	delete_engine_grps(pdev, eng_grps);
146978506c2aSSrujana Challa release_fw:
147078506c2aSSrujana Challa 	cpt_ucode_release_fw(&fw_info);
1471d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
147278506c2aSSrujana Challa 	return ret;
147378506c2aSSrujana Challa }
147478506c2aSSrujana Challa 
147578506c2aSSrujana Challa /*
147678506c2aSSrujana Challa  * Get CPT HW capabilities using LOAD_FVC operation.
147778506c2aSSrujana Challa  */
otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev * cptpf)147878506c2aSSrujana Challa int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf)
147978506c2aSSrujana Challa {
148078506c2aSSrujana Challa 	struct otx2_cptlfs_info *lfs = &cptpf->lfs;
148178506c2aSSrujana Challa 	struct otx2_cpt_iq_command iq_cmd;
148278506c2aSSrujana Challa 	union otx2_cpt_opcode opcode;
148378506c2aSSrujana Challa 	union otx2_cpt_res_s *result;
148478506c2aSSrujana Challa 	union otx2_cpt_inst_s inst;
148578506c2aSSrujana Challa 	dma_addr_t rptr_baddr;
148678506c2aSSrujana Challa 	struct pci_dev *pdev;
148778506c2aSSrujana Challa 	u32 len, compl_rlen;
148878506c2aSSrujana Challa 	int ret, etype;
148978506c2aSSrujana Challa 	void *rptr;
149078506c2aSSrujana Challa 
149178506c2aSSrujana Challa 	/*
149278506c2aSSrujana Challa 	 * We don't get capabilities if it was already done
149378506c2aSSrujana Challa 	 * (when user enabled VFs for the first time)
149478506c2aSSrujana Challa 	 */
149578506c2aSSrujana Challa 	if (cptpf->is_eng_caps_discovered)
149678506c2aSSrujana Challa 		return 0;
149778506c2aSSrujana Challa 
149878506c2aSSrujana Challa 	pdev = cptpf->pdev;
149978506c2aSSrujana Challa 	/*
150078506c2aSSrujana Challa 	 * Create engine groups for each type to submit LOAD_FVC op and
150178506c2aSSrujana Challa 	 * get engine's capabilities.
150278506c2aSSrujana Challa 	 */
150378506c2aSSrujana Challa 	ret = create_eng_caps_discovery_grps(pdev, &cptpf->eng_grps);
150478506c2aSSrujana Challa 	if (ret)
150578506c2aSSrujana Challa 		goto delete_grps;
150678506c2aSSrujana Challa 
1507*a4855a8cSSrujana Challa 	otx2_cptlf_set_dev_info(lfs, cptpf->pdev, cptpf->reg_base,
1508*a4855a8cSSrujana Challa 				&cptpf->afpf_mbox, BLKADDR_CPT0);
1509*a4855a8cSSrujana Challa 	ret = otx2_cptlf_init(lfs, OTX2_CPT_ALL_ENG_GRPS_MASK,
151078506c2aSSrujana Challa 			      OTX2_CPT_QUEUE_HI_PRIO, 1);
151178506c2aSSrujana Challa 	if (ret)
151278506c2aSSrujana Challa 		goto delete_grps;
151378506c2aSSrujana Challa 
151478506c2aSSrujana Challa 	compl_rlen = ALIGN(sizeof(union otx2_cpt_res_s), OTX2_CPT_DMA_MINALIGN);
151578506c2aSSrujana Challa 	len = compl_rlen + LOADFVC_RLEN;
151678506c2aSSrujana Challa 
151778506c2aSSrujana Challa 	result = kzalloc(len, GFP_KERNEL);
151878506c2aSSrujana Challa 	if (!result) {
151978506c2aSSrujana Challa 		ret = -ENOMEM;
152078506c2aSSrujana Challa 		goto lf_cleanup;
152178506c2aSSrujana Challa 	}
152278506c2aSSrujana Challa 	rptr_baddr = dma_map_single(&pdev->dev, (void *)result, len,
152378506c2aSSrujana Challa 				    DMA_BIDIRECTIONAL);
152478506c2aSSrujana Challa 	if (dma_mapping_error(&pdev->dev, rptr_baddr)) {
152578506c2aSSrujana Challa 		dev_err(&pdev->dev, "DMA mapping failed\n");
152678506c2aSSrujana Challa 		ret = -EFAULT;
152778506c2aSSrujana Challa 		goto free_result;
152878506c2aSSrujana Challa 	}
152978506c2aSSrujana Challa 	rptr = (u8 *)result + compl_rlen;
153078506c2aSSrujana Challa 
153178506c2aSSrujana Challa 	/* Fill in the command */
153278506c2aSSrujana Challa 	opcode.s.major = LOADFVC_MAJOR_OP;
153378506c2aSSrujana Challa 	opcode.s.minor = LOADFVC_MINOR_OP;
153478506c2aSSrujana Challa 
153578506c2aSSrujana Challa 	iq_cmd.cmd.u = 0;
153678506c2aSSrujana Challa 	iq_cmd.cmd.s.opcode = cpu_to_be16(opcode.flags);
153778506c2aSSrujana Challa 
153878506c2aSSrujana Challa 	/* 64-bit swap for microcode data reads, not needed for addresses */
153978506c2aSSrujana Challa 	cpu_to_be64s(&iq_cmd.cmd.u);
154078506c2aSSrujana Challa 	iq_cmd.dptr = 0;
154178506c2aSSrujana Challa 	iq_cmd.rptr = rptr_baddr + compl_rlen;
154278506c2aSSrujana Challa 	iq_cmd.cptr.u = 0;
154378506c2aSSrujana Challa 
154478506c2aSSrujana Challa 	for (etype = 1; etype < OTX2_CPT_MAX_ENG_TYPES; etype++) {
154578506c2aSSrujana Challa 		result->s.compcode = OTX2_CPT_COMPLETION_CODE_INIT;
154678506c2aSSrujana Challa 		iq_cmd.cptr.s.grp = otx2_cpt_get_eng_grp(&cptpf->eng_grps,
154778506c2aSSrujana Challa 							 etype);
154878506c2aSSrujana Challa 		otx2_cpt_fill_inst(&inst, &iq_cmd, rptr_baddr);
154940a645f7SSrujana Challa 		lfs->ops->send_cmd(&inst, 1, &cptpf->lfs.lf[0]);
155078506c2aSSrujana Challa 
155140a645f7SSrujana Challa 		while (lfs->ops->cpt_get_compcode(result) ==
155240a645f7SSrujana Challa 						OTX2_CPT_COMPLETION_CODE_INIT)
155378506c2aSSrujana Challa 			cpu_relax();
155478506c2aSSrujana Challa 
155578506c2aSSrujana Challa 		cptpf->eng_caps[etype].u = be64_to_cpup(rptr);
155678506c2aSSrujana Challa 	}
155778506c2aSSrujana Challa 	dma_unmap_single(&pdev->dev, rptr_baddr, len, DMA_BIDIRECTIONAL);
155878506c2aSSrujana Challa 	cptpf->is_eng_caps_discovered = true;
155978506c2aSSrujana Challa 
156078506c2aSSrujana Challa free_result:
156178506c2aSSrujana Challa 	kfree(result);
156278506c2aSSrujana Challa lf_cleanup:
1563*a4855a8cSSrujana Challa 	otx2_cptlf_shutdown(lfs);
156478506c2aSSrujana Challa delete_grps:
156578506c2aSSrujana Challa 	delete_engine_grps(pdev, &cptpf->eng_grps);
156678506c2aSSrujana Challa 
156778506c2aSSrujana Challa 	return ret;
156878506c2aSSrujana Challa }
1569d9d77497SSrujana Challa 
otx2_cpt_dl_custom_egrp_create(struct otx2_cptpf_dev * cptpf,struct devlink_param_gset_ctx * ctx)1570d9d77497SSrujana Challa int otx2_cpt_dl_custom_egrp_create(struct otx2_cptpf_dev *cptpf,
1571d9d77497SSrujana Challa 				   struct devlink_param_gset_ctx *ctx)
1572d9d77497SSrujana Challa {
1573d9d77497SSrujana Challa 	struct otx2_cpt_engines engs[OTX2_CPT_MAX_ETYPES_PER_GRP] = { { 0 } };
1574d9d77497SSrujana Challa 	struct otx2_cpt_uc_info_t *uc_info[OTX2_CPT_MAX_ETYPES_PER_GRP] = {};
1575d9d77497SSrujana Challa 	struct otx2_cpt_eng_grps *eng_grps = &cptpf->eng_grps;
1576d9d77497SSrujana Challa 	char *ucode_filename[OTX2_CPT_MAX_ETYPES_PER_GRP];
1577d9d77497SSrujana Challa 	char tmp_buf[OTX2_CPT_NAME_LENGTH] = { 0 };
1578d9d77497SSrujana Challa 	struct device *dev = &cptpf->pdev->dev;
1579d9d77497SSrujana Challa 	char *start, *val, *err_msg, *tmp;
1580d9d77497SSrujana Challa 	int grp_idx = 0, ret = -EINVAL;
1581d9d77497SSrujana Challa 	bool has_se, has_ie, has_ae;
1582d9d77497SSrujana Challa 	struct fw_info_t fw_info;
1583d9d77497SSrujana Challa 	int ucode_idx = 0;
1584d9d77497SSrujana Challa 
1585d9d77497SSrujana Challa 	if (!eng_grps->is_grps_created) {
1586d9d77497SSrujana Challa 		dev_err(dev, "Not allowed before creating the default groups\n");
1587d9d77497SSrujana Challa 		return -EINVAL;
1588d9d77497SSrujana Challa 	}
1589d9d77497SSrujana Challa 	err_msg = "Invalid engine group format";
1590d9d77497SSrujana Challa 	strscpy(tmp_buf, ctx->val.vstr, strlen(ctx->val.vstr) + 1);
1591d9d77497SSrujana Challa 	start = tmp_buf;
1592d9d77497SSrujana Challa 
1593d9d77497SSrujana Challa 	has_se = has_ie = has_ae = false;
1594d9d77497SSrujana Challa 
1595d9d77497SSrujana Challa 	for (;;) {
1596d9d77497SSrujana Challa 		val = strsep(&start, ";");
1597d9d77497SSrujana Challa 		if (!val)
1598d9d77497SSrujana Challa 			break;
1599d9d77497SSrujana Challa 		val = strim(val);
1600d9d77497SSrujana Challa 		if (!*val)
1601d9d77497SSrujana Challa 			continue;
1602d9d77497SSrujana Challa 
1603d9d77497SSrujana Challa 		if (!strncasecmp(val, "se", 2) && strchr(val, ':')) {
1604d9d77497SSrujana Challa 			if (has_se || ucode_idx)
1605d9d77497SSrujana Challa 				goto err_print;
1606b03c0dc0SShijith Thotton 			tmp = strsep(&val, ":");
1607b03c0dc0SShijith Thotton 			if (!tmp)
1608b03c0dc0SShijith Thotton 				goto err_print;
1609b03c0dc0SShijith Thotton 			tmp = strim(tmp);
1610d9d77497SSrujana Challa 			if (!val)
1611d9d77497SSrujana Challa 				goto err_print;
1612d9d77497SSrujana Challa 			if (strlen(tmp) != 2)
1613d9d77497SSrujana Challa 				goto err_print;
1614d9d77497SSrujana Challa 			if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
1615d9d77497SSrujana Challa 				goto err_print;
1616d9d77497SSrujana Challa 			engs[grp_idx++].type = OTX2_CPT_SE_TYPES;
1617d9d77497SSrujana Challa 			has_se = true;
1618d9d77497SSrujana Challa 		} else if (!strncasecmp(val, "ae", 2) && strchr(val, ':')) {
1619d9d77497SSrujana Challa 			if (has_ae || ucode_idx)
1620d9d77497SSrujana Challa 				goto err_print;
1621b03c0dc0SShijith Thotton 			tmp = strsep(&val, ":");
1622b03c0dc0SShijith Thotton 			if (!tmp)
1623b03c0dc0SShijith Thotton 				goto err_print;
1624b03c0dc0SShijith Thotton 			tmp = strim(tmp);
1625d9d77497SSrujana Challa 			if (!val)
1626d9d77497SSrujana Challa 				goto err_print;
1627d9d77497SSrujana Challa 			if (strlen(tmp) != 2)
1628d9d77497SSrujana Challa 				goto err_print;
1629d9d77497SSrujana Challa 			if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
1630d9d77497SSrujana Challa 				goto err_print;
1631d9d77497SSrujana Challa 			engs[grp_idx++].type = OTX2_CPT_AE_TYPES;
1632d9d77497SSrujana Challa 			has_ae = true;
1633d9d77497SSrujana Challa 		} else if (!strncasecmp(val, "ie", 2) && strchr(val, ':')) {
1634d9d77497SSrujana Challa 			if (has_ie || ucode_idx)
1635d9d77497SSrujana Challa 				goto err_print;
1636b03c0dc0SShijith Thotton 			tmp = strsep(&val, ":");
1637b03c0dc0SShijith Thotton 			if (!tmp)
1638b03c0dc0SShijith Thotton 				goto err_print;
1639b03c0dc0SShijith Thotton 			tmp = strim(tmp);
1640d9d77497SSrujana Challa 			if (!val)
1641d9d77497SSrujana Challa 				goto err_print;
1642d9d77497SSrujana Challa 			if (strlen(tmp) != 2)
1643d9d77497SSrujana Challa 				goto err_print;
1644d9d77497SSrujana Challa 			if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
1645d9d77497SSrujana Challa 				goto err_print;
1646d9d77497SSrujana Challa 			engs[grp_idx++].type = OTX2_CPT_IE_TYPES;
1647d9d77497SSrujana Challa 			has_ie = true;
1648d9d77497SSrujana Challa 		} else {
1649d9d77497SSrujana Challa 			if (ucode_idx > 1)
1650d9d77497SSrujana Challa 				goto err_print;
1651d9d77497SSrujana Challa 			if (!strlen(val))
1652d9d77497SSrujana Challa 				goto err_print;
1653d9d77497SSrujana Challa 			if (strnstr(val, " ", strlen(val)))
1654d9d77497SSrujana Challa 				goto err_print;
1655d9d77497SSrujana Challa 			ucode_filename[ucode_idx++] = val;
1656d9d77497SSrujana Challa 		}
1657d9d77497SSrujana Challa 	}
1658d9d77497SSrujana Challa 
1659d9d77497SSrujana Challa 	/* Validate input parameters */
1660d9d77497SSrujana Challa 	if (!(grp_idx && ucode_idx))
1661d9d77497SSrujana Challa 		goto err_print;
1662d9d77497SSrujana Challa 
1663d9d77497SSrujana Challa 	if (ucode_idx > 1 && grp_idx < 2)
1664d9d77497SSrujana Challa 		goto err_print;
1665d9d77497SSrujana Challa 
1666d9d77497SSrujana Challa 	if (grp_idx > OTX2_CPT_MAX_ETYPES_PER_GRP) {
1667d9d77497SSrujana Challa 		err_msg = "Error max 2 engine types can be attached";
1668d9d77497SSrujana Challa 		goto err_print;
1669d9d77497SSrujana Challa 	}
1670d9d77497SSrujana Challa 
1671d9d77497SSrujana Challa 	if (grp_idx > 1) {
1672d9d77497SSrujana Challa 		if ((engs[0].type + engs[1].type) !=
1673d9d77497SSrujana Challa 		    (OTX2_CPT_SE_TYPES + OTX2_CPT_IE_TYPES)) {
1674d9d77497SSrujana Challa 			err_msg = "Only combination of SE+IE engines is allowed";
1675d9d77497SSrujana Challa 			goto err_print;
1676d9d77497SSrujana Challa 		}
1677d9d77497SSrujana Challa 		/* Keep SE engines at zero index */
1678d9d77497SSrujana Challa 		if (engs[1].type == OTX2_CPT_SE_TYPES)
16793954ab6dSJiapeng Chong 			swap(engs[0], engs[1]);
1680d9d77497SSrujana Challa 	}
1681d9d77497SSrujana Challa 	mutex_lock(&eng_grps->lock);
1682d9d77497SSrujana Challa 
1683d9d77497SSrujana Challa 	if (cptpf->enabled_vfs) {
1684d9d77497SSrujana Challa 		dev_err(dev, "Disable VFs before modifying engine groups\n");
1685d9d77497SSrujana Challa 		ret = -EACCES;
1686d9d77497SSrujana Challa 		goto err_unlock;
1687d9d77497SSrujana Challa 	}
1688d9d77497SSrujana Challa 	INIT_LIST_HEAD(&fw_info.ucodes);
1689d9d77497SSrujana Challa 	ret = load_fw(dev, &fw_info, ucode_filename[0]);
1690d9d77497SSrujana Challa 	if (ret) {
1691d9d77497SSrujana Challa 		dev_err(dev, "Unable to load firmware %s\n", ucode_filename[0]);
1692d9d77497SSrujana Challa 		goto err_unlock;
1693d9d77497SSrujana Challa 	}
1694d9d77497SSrujana Challa 	if (ucode_idx > 1) {
1695d9d77497SSrujana Challa 		ret = load_fw(dev, &fw_info, ucode_filename[1]);
1696d9d77497SSrujana Challa 		if (ret) {
1697d9d77497SSrujana Challa 			dev_err(dev, "Unable to load firmware %s\n",
1698d9d77497SSrujana Challa 				ucode_filename[1]);
1699d9d77497SSrujana Challa 			goto release_fw;
1700d9d77497SSrujana Challa 		}
1701d9d77497SSrujana Challa 	}
1702d9d77497SSrujana Challa 	uc_info[0] = get_ucode(&fw_info, engs[0].type);
1703d9d77497SSrujana Challa 	if (uc_info[0] == NULL) {
1704d9d77497SSrujana Challa 		dev_err(dev, "Unable to find firmware for %s\n",
1705d9d77497SSrujana Challa 			get_eng_type_str(engs[0].type));
1706d9d77497SSrujana Challa 		ret = -EINVAL;
1707d9d77497SSrujana Challa 		goto release_fw;
1708d9d77497SSrujana Challa 	}
1709d9d77497SSrujana Challa 	if (ucode_idx > 1) {
1710d9d77497SSrujana Challa 		uc_info[1] = get_ucode(&fw_info, engs[1].type);
1711d9d77497SSrujana Challa 		if (uc_info[1] == NULL) {
1712d9d77497SSrujana Challa 			dev_err(dev, "Unable to find firmware for %s\n",
1713d9d77497SSrujana Challa 				get_eng_type_str(engs[1].type));
1714d9d77497SSrujana Challa 			ret = -EINVAL;
1715d9d77497SSrujana Challa 			goto release_fw;
1716d9d77497SSrujana Challa 		}
1717d9d77497SSrujana Challa 	}
1718d9d77497SSrujana Challa 	ret = create_engine_group(dev, eng_grps, engs, grp_idx,
1719d9d77497SSrujana Challa 				  (void **)uc_info, 1);
1720d9d77497SSrujana Challa 
1721d9d77497SSrujana Challa release_fw:
1722d9d77497SSrujana Challa 	cpt_ucode_release_fw(&fw_info);
1723d9d77497SSrujana Challa err_unlock:
1724d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
1725d9d77497SSrujana Challa 	return ret;
1726d9d77497SSrujana Challa err_print:
1727d9d77497SSrujana Challa 	dev_err(dev, "%s\n", err_msg);
1728d9d77497SSrujana Challa 	return ret;
1729d9d77497SSrujana Challa }
1730d9d77497SSrujana Challa 
otx2_cpt_dl_custom_egrp_delete(struct otx2_cptpf_dev * cptpf,struct devlink_param_gset_ctx * ctx)1731d9d77497SSrujana Challa int otx2_cpt_dl_custom_egrp_delete(struct otx2_cptpf_dev *cptpf,
1732d9d77497SSrujana Challa 				   struct devlink_param_gset_ctx *ctx)
1733d9d77497SSrujana Challa {
1734d9d77497SSrujana Challa 	struct otx2_cpt_eng_grps *eng_grps = &cptpf->eng_grps;
1735d9d77497SSrujana Challa 	struct device *dev = &cptpf->pdev->dev;
1736d9d77497SSrujana Challa 	char *tmp, *err_msg;
1737d9d77497SSrujana Challa 	int egrp;
1738d9d77497SSrujana Challa 	int ret;
1739d9d77497SSrujana Challa 
1740d9d77497SSrujana Challa 	err_msg = "Invalid input string format(ex: egrp:0)";
1741d9d77497SSrujana Challa 	if (strncasecmp(ctx->val.vstr, "egrp", 4))
1742d9d77497SSrujana Challa 		goto err_print;
1743d9d77497SSrujana Challa 	tmp = ctx->val.vstr;
1744d9d77497SSrujana Challa 	strsep(&tmp, ":");
1745d9d77497SSrujana Challa 	if (!tmp)
1746d9d77497SSrujana Challa 		goto err_print;
1747d9d77497SSrujana Challa 	if (kstrtoint(tmp, 10, &egrp))
1748d9d77497SSrujana Challa 		goto err_print;
1749d9d77497SSrujana Challa 
17503438e722SDan Carpenter 	if (egrp < 0 || egrp >= OTX2_CPT_MAX_ENGINE_GROUPS) {
1751d9d77497SSrujana Challa 		dev_err(dev, "Invalid engine group %d", egrp);
1752d9d77497SSrujana Challa 		return -EINVAL;
1753d9d77497SSrujana Challa 	}
1754d9d77497SSrujana Challa 	if (!eng_grps->grp[egrp].is_enabled) {
1755d9d77497SSrujana Challa 		dev_err(dev, "Error engine_group%d is not configured", egrp);
1756d9d77497SSrujana Challa 		return -EINVAL;
1757d9d77497SSrujana Challa 	}
1758d9d77497SSrujana Challa 	mutex_lock(&eng_grps->lock);
1759d9d77497SSrujana Challa 	ret = delete_engine_group(dev, &eng_grps->grp[egrp]);
1760d9d77497SSrujana Challa 	mutex_unlock(&eng_grps->lock);
1761d9d77497SSrujana Challa 
1762d9d77497SSrujana Challa 	return ret;
1763d9d77497SSrujana Challa 
1764d9d77497SSrujana Challa err_print:
1765d9d77497SSrujana Challa 	dev_err(dev, "%s\n", err_msg);
1766d9d77497SSrujana Challa 	return -EINVAL;
1767d9d77497SSrujana Challa }
1768d9d77497SSrujana Challa 
get_engs_info(struct otx2_cpt_eng_grp_info * eng_grp,char * buf,int size,int idx)1769d9d77497SSrujana Challa static void get_engs_info(struct otx2_cpt_eng_grp_info *eng_grp, char *buf,
1770d9d77497SSrujana Challa 			  int size, int idx)
1771d9d77497SSrujana Challa {
1772d9d77497SSrujana Challa 	struct otx2_cpt_engs_rsvd *mirrored_engs = NULL;
1773d9d77497SSrujana Challa 	struct otx2_cpt_engs_rsvd *engs;
1774d9d77497SSrujana Challa 	int len, i;
1775d9d77497SSrujana Challa 
1776d9d77497SSrujana Challa 	buf[0] = '\0';
1777d9d77497SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ETYPES_PER_GRP; i++) {
1778d9d77497SSrujana Challa 		engs = &eng_grp->engs[i];
1779d9d77497SSrujana Challa 		if (!engs->type)
1780d9d77497SSrujana Challa 			continue;
1781d9d77497SSrujana Challa 		if (idx != -1 && idx != i)
1782d9d77497SSrujana Challa 			continue;
1783d9d77497SSrujana Challa 
1784d9d77497SSrujana Challa 		if (eng_grp->mirror.is_ena)
1785d9d77497SSrujana Challa 			mirrored_engs = find_engines_by_type(
1786d9d77497SSrujana Challa 				&eng_grp->g->grp[eng_grp->mirror.idx],
1787d9d77497SSrujana Challa 				engs->type);
1788d9d77497SSrujana Challa 		if (i > 0 && idx == -1) {
1789d9d77497SSrujana Challa 			len = strlen(buf);
1790d9d77497SSrujana Challa 			scnprintf(buf + len, size - len, ", ");
1791d9d77497SSrujana Challa 		}
1792d9d77497SSrujana Challa 
1793d9d77497SSrujana Challa 		len = strlen(buf);
1794d9d77497SSrujana Challa 		scnprintf(buf + len, size - len, "%d %s ",
1795d9d77497SSrujana Challa 			  mirrored_engs ? engs->count + mirrored_engs->count :
1796d9d77497SSrujana Challa 					  engs->count,
1797d9d77497SSrujana Challa 			  get_eng_type_str(engs->type));
1798d9d77497SSrujana Challa 		if (mirrored_engs) {
1799d9d77497SSrujana Challa 			len = strlen(buf);
1800d9d77497SSrujana Challa 			scnprintf(buf + len, size - len,
1801d9d77497SSrujana Challa 				  "(%d shared with engine_group%d) ",
1802d9d77497SSrujana Challa 				  engs->count <= 0 ?
1803d9d77497SSrujana Challa 					  engs->count + mirrored_engs->count :
1804d9d77497SSrujana Challa 					  mirrored_engs->count,
1805d9d77497SSrujana Challa 				  eng_grp->mirror.idx);
1806d9d77497SSrujana Challa 		}
1807d9d77497SSrujana Challa 	}
1808d9d77497SSrujana Challa }
1809d9d77497SSrujana Challa 
otx2_cpt_print_uc_dbg_info(struct otx2_cptpf_dev * cptpf)1810d9d77497SSrujana Challa void otx2_cpt_print_uc_dbg_info(struct otx2_cptpf_dev *cptpf)
1811d9d77497SSrujana Challa {
1812d9d77497SSrujana Challa 	struct otx2_cpt_eng_grps *eng_grps = &cptpf->eng_grps;
1813d9d77497SSrujana Challa 	struct otx2_cpt_eng_grp_info *mirrored_grp;
1814d9d77497SSrujana Challa 	char engs_info[2 * OTX2_CPT_NAME_LENGTH];
1815d9d77497SSrujana Challa 	struct otx2_cpt_eng_grp_info *grp;
1816d9d77497SSrujana Challa 	struct otx2_cpt_engs_rsvd *engs;
1817d9d77497SSrujana Challa 	int i, j;
1818d9d77497SSrujana Challa 
1819d9d77497SSrujana Challa 	pr_debug("Engine groups global info");
1820d9d77497SSrujana Challa 	pr_debug("max SE %d, max IE %d, max AE %d", eng_grps->avail.max_se_cnt,
1821d9d77497SSrujana Challa 		 eng_grps->avail.max_ie_cnt, eng_grps->avail.max_ae_cnt);
1822d9d77497SSrujana Challa 	pr_debug("free SE %d", eng_grps->avail.se_cnt);
1823d9d77497SSrujana Challa 	pr_debug("free IE %d", eng_grps->avail.ie_cnt);
1824d9d77497SSrujana Challa 	pr_debug("free AE %d", eng_grps->avail.ae_cnt);
1825d9d77497SSrujana Challa 
1826d9d77497SSrujana Challa 	for (i = 0; i < OTX2_CPT_MAX_ENGINE_GROUPS; i++) {
1827d9d77497SSrujana Challa 		grp = &eng_grps->grp[i];
1828d9d77497SSrujana Challa 		pr_debug("engine_group%d, state %s", i,
1829d9d77497SSrujana Challa 			 grp->is_enabled ? "enabled" : "disabled");
1830d9d77497SSrujana Challa 		if (grp->is_enabled) {
1831d9d77497SSrujana Challa 			mirrored_grp = &eng_grps->grp[grp->mirror.idx];
1832d9d77497SSrujana Challa 			pr_debug("Ucode0 filename %s, version %s",
1833d9d77497SSrujana Challa 				 grp->mirror.is_ena ?
1834d9d77497SSrujana Challa 					 mirrored_grp->ucode[0].filename :
1835d9d77497SSrujana Challa 					 grp->ucode[0].filename,
1836d9d77497SSrujana Challa 				 grp->mirror.is_ena ?
1837d9d77497SSrujana Challa 					 mirrored_grp->ucode[0].ver_str :
1838d9d77497SSrujana Challa 					 grp->ucode[0].ver_str);
1839d9d77497SSrujana Challa 			if (is_2nd_ucode_used(grp))
1840d9d77497SSrujana Challa 				pr_debug("Ucode1 filename %s, version %s",
1841d9d77497SSrujana Challa 					 grp->ucode[1].filename,
1842d9d77497SSrujana Challa 					 grp->ucode[1].ver_str);
1843d9d77497SSrujana Challa 		}
1844d9d77497SSrujana Challa 
1845d9d77497SSrujana Challa 		for (j = 0; j < OTX2_CPT_MAX_ETYPES_PER_GRP; j++) {
1846d9d77497SSrujana Challa 			engs = &grp->engs[j];
1847d9d77497SSrujana Challa 			if (engs->type) {
184847307c31SKees Cook 				u32 mask[5] = { };
184947307c31SKees Cook 
1850d9d77497SSrujana Challa 				get_engs_info(grp, engs_info,
1851d9d77497SSrujana Challa 					      2 * OTX2_CPT_NAME_LENGTH, j);
1852d9d77497SSrujana Challa 				pr_debug("Slot%d: %s", j, engs_info);
1853d9d77497SSrujana Challa 				bitmap_to_arr32(mask, engs->bmap,
1854d9d77497SSrujana Challa 						eng_grps->engs_num);
1855d9d77497SSrujana Challa 				if (is_dev_otx2(cptpf->pdev))
1856d9d77497SSrujana Challa 					pr_debug("Mask: %8.8x %8.8x %8.8x %8.8x",
1857d9d77497SSrujana Challa 						 mask[3], mask[2], mask[1],
1858d9d77497SSrujana Challa 						 mask[0]);
1859d9d77497SSrujana Challa 				else
1860d9d77497SSrujana Challa 					pr_debug("Mask: %8.8x %8.8x %8.8x %8.8x %8.8x",
1861d9d77497SSrujana Challa 						 mask[4], mask[3], mask[2], mask[1],
1862d9d77497SSrujana Challa 						 mask[0]);
1863d9d77497SSrujana Challa 			}
1864d9d77497SSrujana Challa 		}
1865d9d77497SSrujana Challa 	}
1866d9d77497SSrujana Challa }
1867