File Index
Files and directories
Sign in
FILE

otx_cptpf_ucode.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/* Marvell OcteonTX CPT driver
   3 *
   4 * Copyright (C) 2019 Marvell International Ltd.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/ctype.h>
  12#include <linux/firmware.h>
  13#include <linux/string_choices.h>
  14#include "otx_cpt_common.h"
  15#include "otx_cptpf_ucode.h"
  16#include "otx_cptpf.h"
  17
  18#define CSR_DELAY 30
  19/* Tar archive defines */
  20#define TAR_MAGIC		"ustar"
  21#define TAR_MAGIC_LEN		6
  22#define TAR_BLOCK_LEN		512
  23#define REGTYPE			'0'
  24#define AREGTYPE		'\0'
  25
  26/* tar header as defined in POSIX 1003.1-1990. */
  27struct tar_hdr_t {
  28	char name[100];
  29	char mode[8];
  30	char uid[8];
  31	char gid[8];
  32	char size[12];
  33	char mtime[12];
  34	char chksum[8];
  35	char typeflag;
  36	char linkname[100];
  37	char magic[6];
  38	char version[2];
  39	char uname[32];
  40	char gname[32];
  41	char devmajor[8];
  42	char devminor[8];
  43	char prefix[155];
  44};
  45
  46struct tar_blk_t {
  47	union {
  48		struct tar_hdr_t hdr;
  49		char block[TAR_BLOCK_LEN];
  50	};
  51};
  52
  53struct tar_arch_info_t {
  54	struct list_head ucodes;
  55	const struct firmware *fw;
  56};
  57
  58static struct otx_cpt_bitmap get_cores_bmap(struct device *dev,
  59					   struct otx_cpt_eng_grp_info *eng_grp)
  60{
  61	struct otx_cpt_bitmap bmap = { {0} };
  62	bool found = false;
  63	int i;
  64
  65	if (eng_grp->g->engs_num > OTX_CPT_MAX_ENGINES) {
  66		dev_err(dev, "unsupported number of engines %d on octeontx\n",
  67			eng_grp->g->engs_num);
  68		return bmap;
  69	}
  70
  71	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
  72		if (eng_grp->engs[i].type) {
  73			bitmap_or(bmap.bits, bmap.bits,
  74				  eng_grp->engs[i].bmap,
  75				  eng_grp->g->engs_num);
  76			bmap.size = eng_grp->g->engs_num;
  77			found = true;
  78		}
  79	}
  80
  81	if (!found)
  82		dev_err(dev, "No engines reserved for engine group %d\n",
  83			eng_grp->idx);
  84	return bmap;
  85}
  86
  87static int is_eng_type(int val, int eng_type)
  88{
  89	return val & (1 << eng_type);
  90}
  91
  92static int dev_supports_eng_type(struct otx_cpt_eng_grps *eng_grps,
  93				 int eng_type)
  94{
  95	return is_eng_type(eng_grps->eng_types_supported, eng_type);
  96}
  97
  98static void set_ucode_filename(struct otx_cpt_ucode *ucode,
  99			       const char *filename)
 100{
 101	strscpy(ucode->filename, filename, OTX_CPT_UCODE_NAME_LENGTH);
 102}
 103
 104static char *get_eng_type_str(int eng_type)
 105{
 106	char *str = "unknown";
 107
 108	switch (eng_type) {
 109	case OTX_CPT_SE_TYPES:
 110		str = "SE";
 111		break;
 112
 113	case OTX_CPT_AE_TYPES:
 114		str = "AE";
 115		break;
 116	}
 117	return str;
 118}
 119
 120static char *get_ucode_type_str(int ucode_type)
 121{
 122	char *str = "unknown";
 123
 124	switch (ucode_type) {
 125	case (1 << OTX_CPT_SE_TYPES):
 126		str = "SE";
 127		break;
 128
 129	case (1 << OTX_CPT_AE_TYPES):
 130		str = "AE";
 131		break;
 132	}
 133	return str;
 134}
 135
 136static int get_ucode_type(struct otx_cpt_ucode_hdr *ucode_hdr, int *ucode_type)
 137{
 138	char tmp_ver_str[OTX_CPT_UCODE_VER_STR_SZ];
 139	u32 i, val = 0;
 140	u8 nn;
 141
 142	strscpy(tmp_ver_str, ucode_hdr->ver_str, OTX_CPT_UCODE_VER_STR_SZ);
 143	for (i = 0; i < strlen(tmp_ver_str); i++)
 144		tmp_ver_str[i] = tolower(tmp_ver_str[i]);
 145
 146	nn = ucode_hdr->ver_num.nn;
 147	if (strnstr(tmp_ver_str, "se-", OTX_CPT_UCODE_VER_STR_SZ) &&
 148	    (nn == OTX_CPT_SE_UC_TYPE1 || nn == OTX_CPT_SE_UC_TYPE2 ||
 149	     nn == OTX_CPT_SE_UC_TYPE3))
 150		val |= 1 << OTX_CPT_SE_TYPES;
 151	if (strnstr(tmp_ver_str, "ae", OTX_CPT_UCODE_VER_STR_SZ) &&
 152	    nn == OTX_CPT_AE_UC_TYPE)
 153		val |= 1 << OTX_CPT_AE_TYPES;
 154
 155	*ucode_type = val;
 156
 157	if (!val)
 158		return -EINVAL;
 159	if (is_eng_type(val, OTX_CPT_AE_TYPES) &&
 160	    is_eng_type(val, OTX_CPT_SE_TYPES))
 161		return -EINVAL;
 162	return 0;
 163}
 164
 165static int is_mem_zero(const char *ptr, int size)
 166{
 167	int i;
 168
 169	for (i = 0; i < size; i++) {
 170		if (ptr[i])
 171			return 0;
 172	}
 173	return 1;
 174}
 175
 176static int cpt_set_ucode_base(struct otx_cpt_eng_grp_info *eng_grp, void *obj)
 177{
 178	struct otx_cpt_device *cpt = (struct otx_cpt_device *) obj;
 179	dma_addr_t dma_addr;
 180	struct otx_cpt_bitmap bmap;
 181	int i;
 182
 183	bmap = get_cores_bmap(&cpt->pdev->dev, eng_grp);
 184	if (!bmap.size)
 185		return -EINVAL;
 186
 187	if (eng_grp->mirror.is_ena)
 188		dma_addr =
 189		       eng_grp->g->grp[eng_grp->mirror.idx].ucode[0].align_dma;
 190	else
 191		dma_addr = eng_grp->ucode[0].align_dma;
 192
 193	/*
 194	 * Set UCODE_BASE only for the cores which are not used,
 195	 * other cores should have already valid UCODE_BASE set
 196	 */
 197	for_each_set_bit(i, bmap.bits, bmap.size)
 198		if (!eng_grp->g->eng_ref_cnt[i])
 199			writeq((u64) dma_addr, cpt->reg_base +
 200				OTX_CPT_PF_ENGX_UCODE_BASE(i));
 201	return 0;
 202}
 203
 204static int cpt_detach_and_disable_cores(struct otx_cpt_eng_grp_info *eng_grp,
 205					void *obj)
 206{
 207	struct otx_cpt_device *cpt = (struct otx_cpt_device *) obj;
 208	struct otx_cpt_bitmap bmap = { {0} };
 209	int timeout = 10;
 210	int i, busy;
 211	u64 reg;
 212
 213	bmap = get_cores_bmap(&cpt->pdev->dev, eng_grp);
 214	if (!bmap.size)
 215		return -EINVAL;
 216
 217	/* Detach the cores from group */
 218	reg = readq(cpt->reg_base + OTX_CPT_PF_GX_EN(eng_grp->idx));
 219	for_each_set_bit(i, bmap.bits, bmap.size) {
 220		if (reg & (1ull << i)) {
 221			eng_grp->g->eng_ref_cnt[i]--;
 222			reg &= ~(1ull << i);
 223		}
 224	}
 225	writeq(reg, cpt->reg_base + OTX_CPT_PF_GX_EN(eng_grp->idx));
 226
 227	/* Wait for cores to become idle */
 228	do {
 229		busy = 0;
 230		usleep_range(10000, 20000);
 231		if (timeout-- < 0)
 232			return -EBUSY;
 233
 234		reg = readq(cpt->reg_base + OTX_CPT_PF_EXEC_BUSY);
 235		for_each_set_bit(i, bmap.bits, bmap.size)
 236			if (reg & (1ull << i)) {
 237				busy = 1;
 238				break;
 239			}
 240	} while (busy);
 241
 242	/* Disable the cores only if they are not used anymore */
 243	reg = readq(cpt->reg_base + OTX_CPT_PF_EXE_CTL);
 244	for_each_set_bit(i, bmap.bits, bmap.size)
 245		if (!eng_grp->g->eng_ref_cnt[i])
 246			reg &= ~(1ull << i);
 247	writeq(reg, cpt->reg_base + OTX_CPT_PF_EXE_CTL);
 248
 249	return 0;
 250}
 251
 252static int cpt_attach_and_enable_cores(struct otx_cpt_eng_grp_info *eng_grp,
 253				       void *obj)
 254{
 255	struct otx_cpt_device *cpt = (struct otx_cpt_device *) obj;
 256	struct otx_cpt_bitmap bmap;
 257	u64 reg;
 258	int i;
 259
 260	bmap = get_cores_bmap(&cpt->pdev->dev, eng_grp);
 261	if (!bmap.size)
 262		return -EINVAL;
 263
 264	/* Attach the cores to the group */
 265	reg = readq(cpt->reg_base + OTX_CPT_PF_GX_EN(eng_grp->idx));
 266	for_each_set_bit(i, bmap.bits, bmap.size) {
 267		if (!(reg & (1ull << i))) {
 268			eng_grp->g->eng_ref_cnt[i]++;
 269			reg |= 1ull << i;
 270		}
 271	}
 272	writeq(reg, cpt->reg_base + OTX_CPT_PF_GX_EN(eng_grp->idx));
 273
 274	/* Enable the cores */
 275	reg = readq(cpt->reg_base + OTX_CPT_PF_EXE_CTL);
 276	for_each_set_bit(i, bmap.bits, bmap.size)
 277		reg |= 1ull << i;
 278	writeq(reg, cpt->reg_base + OTX_CPT_PF_EXE_CTL);
 279
 280	return 0;
 281}
 282
 283static int process_tar_file(struct device *dev,
 284			    struct tar_arch_info_t *tar_arch, char *filename,
 285			    const u8 *data, u32 size)
 286{
 287	struct tar_ucode_info_t *tar_info;
 288	struct otx_cpt_ucode_hdr *ucode_hdr;
 289	int ucode_type, ucode_size;
 290	unsigned int code_length;
 291
 292	/*
 293	 * If size is less than microcode header size then don't report
 294	 * an error because it might not be microcode file, just process
 295	 * next file from archive
 296	 */
 297	if (size < sizeof(struct otx_cpt_ucode_hdr))
 298		return 0;
 299
 300	ucode_hdr = (struct otx_cpt_ucode_hdr *) data;
 301	/*
 302	 * If microcode version can't be found don't report an error
 303	 * because it might not be microcode file, just process next file
 304	 */
 305	if (get_ucode_type(ucode_hdr, &ucode_type))
 306		return 0;
 307
 308	code_length = ntohl(ucode_hdr->code_length);
 309	if (code_length >= INT_MAX / 2) {
 310		dev_err(dev, "Invalid code_length %u\n", code_length);
 311		return -EINVAL;
 312	}
 313
 314	ucode_size = code_length * 2;
 315	if (!ucode_size || (size < round_up(ucode_size, 16) +
 316	    sizeof(struct otx_cpt_ucode_hdr) + OTX_CPT_UCODE_SIGN_LEN)) {
 317		dev_err(dev, "Ucode %s invalid size\n", filename);
 318		return -EINVAL;
 319	}
 320
 321	tar_info = kzalloc(sizeof(struct tar_ucode_info_t), GFP_KERNEL);
 322	if (!tar_info)
 323		return -ENOMEM;
 324
 325	tar_info->ucode_ptr = data;
 326	set_ucode_filename(&tar_info->ucode, filename);
 327	memcpy(tar_info->ucode.ver_str, ucode_hdr->ver_str,
 328	       OTX_CPT_UCODE_VER_STR_SZ);
 329	tar_info->ucode.ver_num = ucode_hdr->ver_num;
 330	tar_info->ucode.type = ucode_type;
 331	tar_info->ucode.size = ucode_size;
 332	list_add_tail(&tar_info->list, &tar_arch->ucodes);
 333
 334	return 0;
 335}
 336
 337static void release_tar_archive(struct tar_arch_info_t *tar_arch)
 338{
 339	struct tar_ucode_info_t *curr, *temp;
 340
 341	if (!tar_arch)
 342		return;
 343
 344	list_for_each_entry_safe(curr, temp, &tar_arch->ucodes, list) {
 345		list_del(&curr->list);
 346		kfree(curr);
 347	}
 348
 349	release_firmware(tar_arch->fw);
 350	kfree(tar_arch);
 351}
 352
 353static struct tar_ucode_info_t *get_uc_from_tar_archive(
 354					struct tar_arch_info_t *tar_arch,
 355					int ucode_type)
 356{
 357	struct tar_ucode_info_t *curr, *uc_found = NULL;
 358
 359	list_for_each_entry(curr, &tar_arch->ucodes, list) {
 360		if (!is_eng_type(curr->ucode.type, ucode_type))
 361			continue;
 362
 363		if (!uc_found) {
 364			uc_found = curr;
 365			continue;
 366		}
 367
 368		switch (ucode_type) {
 369		case OTX_CPT_AE_TYPES:
 370			break;
 371
 372		case OTX_CPT_SE_TYPES:
 373			if (uc_found->ucode.ver_num.nn == OTX_CPT_SE_UC_TYPE2 ||
 374			    (uc_found->ucode.ver_num.nn == OTX_CPT_SE_UC_TYPE3
 375			     && curr->ucode.ver_num.nn == OTX_CPT_SE_UC_TYPE1))
 376				uc_found = curr;
 377			break;
 378		}
 379	}
 380
 381	return uc_found;
 382}
 383
 384static void print_tar_dbg_info(struct tar_arch_info_t *tar_arch,
 385			       char *tar_filename)
 386{
 387	struct tar_ucode_info_t *curr;
 388
 389	pr_debug("Tar archive filename %s\n", tar_filename);
 390	pr_debug("Tar archive pointer %p, size %ld\n", tar_arch->fw->data,
 391		 tar_arch->fw->size);
 392	list_for_each_entry(curr, &tar_arch->ucodes, list) {
 393		pr_debug("Ucode filename %s\n", curr->ucode.filename);
 394		pr_debug("Ucode version string %s\n", curr->ucode.ver_str);
 395		pr_debug("Ucode version %d.%d.%d.%d\n",
 396			 curr->ucode.ver_num.nn, curr->ucode.ver_num.xx,
 397			 curr->ucode.ver_num.yy, curr->ucode.ver_num.zz);
 398		pr_debug("Ucode type (%d) %s\n", curr->ucode.type,
 399			 get_ucode_type_str(curr->ucode.type));
 400		pr_debug("Ucode size %d\n", curr->ucode.size);
 401		pr_debug("Ucode ptr %p\n", curr->ucode_ptr);
 402	}
 403}
 404
 405static struct tar_arch_info_t *load_tar_archive(struct device *dev,
 406						char *tar_filename)
 407{
 408	struct tar_arch_info_t *tar_arch = NULL;
 409	struct tar_blk_t *tar_blk;
 410	unsigned int cur_size;
 411	size_t tar_offs = 0;
 412	size_t tar_size;
 413	int ret;
 414
 415	tar_arch = kzalloc(sizeof(struct tar_arch_info_t), GFP_KERNEL);
 416	if (!tar_arch)
 417		return NULL;
 418
 419	INIT_LIST_HEAD(&tar_arch->ucodes);
 420
 421	/* Load tar archive */
 422	ret = request_firmware(&tar_arch->fw, tar_filename, dev);
 423	if (ret)
 424		goto release_tar_arch;
 425
 426	if (tar_arch->fw->size < TAR_BLOCK_LEN) {
 427		dev_err(dev, "Invalid tar archive %s\n", tar_filename);
 428		goto release_tar_arch;
 429	}
 430
 431	tar_size = tar_arch->fw->size;
 432	tar_blk = (struct tar_blk_t *) tar_arch->fw->data;
 433	if (strncmp(tar_blk->hdr.magic, TAR_MAGIC, TAR_MAGIC_LEN - 1)) {
 434		dev_err(dev, "Unsupported format of tar archive %s\n",
 435			tar_filename);
 436		goto release_tar_arch;
 437	}
 438
 439	while (1) {
 440		/* Read current file size */
 441		ret = kstrtouint(tar_blk->hdr.size, 8, &cur_size);
 442		if (ret)
 443			goto release_tar_arch;
 444
 445		if (tar_offs + cur_size > tar_size ||
 446		    tar_offs + 2*TAR_BLOCK_LEN > tar_size) {
 447			dev_err(dev, "Invalid tar archive %s\n", tar_filename);
 448			goto release_tar_arch;
 449		}
 450
 451		tar_offs += TAR_BLOCK_LEN;
 452		if (tar_blk->hdr.typeflag == REGTYPE ||
 453		    tar_blk->hdr.typeflag == AREGTYPE) {
 454			ret = process_tar_file(dev, tar_arch,
 455					       tar_blk->hdr.name,
 456					       &tar_arch->fw->data[tar_offs],
 457					       cur_size);
 458			if (ret)
 459				goto release_tar_arch;
 460		}
 461
 462		tar_offs += (cur_size/TAR_BLOCK_LEN) * TAR_BLOCK_LEN;
 463		if (cur_size % TAR_BLOCK_LEN)
 464			tar_offs += TAR_BLOCK_LEN;
 465
 466		/* Check for the end of the archive */
 467		if (tar_offs + 2*TAR_BLOCK_LEN > tar_size) {
 468			dev_err(dev, "Invalid tar archive %s\n", tar_filename);
 469			goto release_tar_arch;
 470		}
 471
 472		if (is_mem_zero(&tar_arch->fw->data[tar_offs],
 473		    2*TAR_BLOCK_LEN))
 474			break;
 475
 476		/* Read next block from tar archive */
 477		tar_blk = (struct tar_blk_t *) &tar_arch->fw->data[tar_offs];
 478	}
 479
 480	print_tar_dbg_info(tar_arch, tar_filename);
 481	return tar_arch;
 482release_tar_arch:
 483	release_tar_archive(tar_arch);
 484	return NULL;
 485}
 486
 487static struct otx_cpt_engs_rsvd *find_engines_by_type(
 488					struct otx_cpt_eng_grp_info *eng_grp,
 489					int eng_type)
 490{
 491	int i;
 492
 493	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
 494		if (!eng_grp->engs[i].type)
 495			continue;
 496
 497		if (eng_grp->engs[i].type == eng_type)
 498			return &eng_grp->engs[i];
 499	}
 500	return NULL;
 501}
 502
 503int otx_cpt_uc_supports_eng_type(struct otx_cpt_ucode *ucode, int eng_type)
 504{
 505	return is_eng_type(ucode->type, eng_type);
 506}
 507EXPORT_SYMBOL_GPL(otx_cpt_uc_supports_eng_type);
 508
 509static void print_ucode_info(struct otx_cpt_eng_grp_info *eng_grp,
 510			     char *buf, int size)
 511{
 512	if (eng_grp->mirror.is_ena) {
 513		scnprintf(buf, size, "%s (shared with engine_group%d)",
 514			  eng_grp->g->grp[eng_grp->mirror.idx].ucode[0].ver_str,
 515			  eng_grp->mirror.idx);
 516	} else {
 517		scnprintf(buf, size, "%s", eng_grp->ucode[0].ver_str);
 518	}
 519}
 520
 521static void print_engs_info(struct otx_cpt_eng_grp_info *eng_grp,
 522			    char *buf, int size, int idx)
 523{
 524	struct otx_cpt_engs_rsvd *mirrored_engs = NULL;
 525	struct otx_cpt_engs_rsvd *engs;
 526	int len, i;
 527
 528	buf[0] = '\0';
 529	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
 530		engs = &eng_grp->engs[i];
 531		if (!engs->type)
 532			continue;
 533		if (idx != -1 && idx != i)
 534			continue;
 535
 536		if (eng_grp->mirror.is_ena)
 537			mirrored_engs = find_engines_by_type(
 538					&eng_grp->g->grp[eng_grp->mirror.idx],
 539					engs->type);
 540		if (i > 0 && idx == -1) {
 541			len = strlen(buf);
 542			scnprintf(buf+len, size-len, ", ");
 543		}
 544
 545		len = strlen(buf);
 546		scnprintf(buf+len, size-len, "%d %s ", mirrored_engs ?
 547			  engs->count + mirrored_engs->count : engs->count,
 548			  get_eng_type_str(engs->type));
 549		if (mirrored_engs) {
 550			len = strlen(buf);
 551			scnprintf(buf+len, size-len,
 552				  "(%d shared with engine_group%d) ",
 553				  engs->count <= 0 ? engs->count +
 554				  mirrored_engs->count : mirrored_engs->count,
 555				  eng_grp->mirror.idx);
 556		}
 557	}
 558}
 559
 560static void print_ucode_dbg_info(struct otx_cpt_ucode *ucode)
 561{
 562	pr_debug("Ucode info\n");
 563	pr_debug("Ucode version string %s\n", ucode->ver_str);
 564	pr_debug("Ucode version %d.%d.%d.%d\n", ucode->ver_num.nn,
 565		 ucode->ver_num.xx, ucode->ver_num.yy, ucode->ver_num.zz);
 566	pr_debug("Ucode type %s\n", get_ucode_type_str(ucode->type));
 567	pr_debug("Ucode size %d\n", ucode->size);
 568	pr_debug("Ucode virt address %16.16llx\n", (u64)ucode->align_va);
 569	pr_debug("Ucode phys address %16.16llx\n", ucode->align_dma);
 570}
 571
 572static void cpt_print_engines_mask(struct otx_cpt_eng_grp_info *eng_grp,
 573				   struct device *dev, char *buf, int size)
 574{
 575	struct otx_cpt_bitmap bmap;
 576	u32 mask[2];
 577
 578	bmap = get_cores_bmap(dev, eng_grp);
 579	if (!bmap.size) {
 580		scnprintf(buf, size, "unknown");
 581		return;
 582	}
 583	bitmap_to_arr32(mask, bmap.bits, bmap.size);
 584	scnprintf(buf, size, "%8.8x %8.8x", mask[1], mask[0]);
 585}
 586
 587
 588static void print_dbg_info(struct device *dev,
 589			   struct otx_cpt_eng_grps *eng_grps)
 590{
 591	char engs_info[2*OTX_CPT_UCODE_NAME_LENGTH];
 592	struct otx_cpt_eng_grp_info *mirrored_grp;
 593	char engs_mask[OTX_CPT_UCODE_NAME_LENGTH];
 594	struct otx_cpt_eng_grp_info *grp;
 595	struct otx_cpt_engs_rsvd *engs;
 596	u32 mask[4];
 597	int i, j;
 598
 599	pr_debug("Engine groups global info\n");
 600	pr_debug("max SE %d, max AE %d\n",
 601		 eng_grps->avail.max_se_cnt, eng_grps->avail.max_ae_cnt);
 602	pr_debug("free SE %d\n", eng_grps->avail.se_cnt);
 603	pr_debug("free AE %d\n", eng_grps->avail.ae_cnt);
 604
 605	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++) {
 606		grp = &eng_grps->grp[i];
 607		pr_debug("engine_group%d, state %s\n", i,
 608			 str_enabled_disabled(grp->is_enabled));
 609		if (grp->is_enabled) {
 610			mirrored_grp = &eng_grps->grp[grp->mirror.idx];
 611			pr_debug("Ucode0 filename %s, version %s\n",
 612				 grp->mirror.is_ena ?
 613				 mirrored_grp->ucode[0].filename :
 614				 grp->ucode[0].filename,
 615				 grp->mirror.is_ena ?
 616				 mirrored_grp->ucode[0].ver_str :
 617				 grp->ucode[0].ver_str);
 618		}
 619
 620		for (j = 0; j < OTX_CPT_MAX_ETYPES_PER_GRP; j++) {
 621			engs = &grp->engs[j];
 622			if (engs->type) {
 623				print_engs_info(grp, engs_info,
 624						2*OTX_CPT_UCODE_NAME_LENGTH, j);
 625				pr_debug("Slot%d: %s\n", j, engs_info);
 626				bitmap_to_arr32(mask, engs->bmap,
 627						eng_grps->engs_num);
 628				pr_debug("Mask: %8.8x %8.8x %8.8x %8.8x\n",
 629					 mask[3], mask[2], mask[1], mask[0]);
 630			} else
 631				pr_debug("Slot%d not used\n", j);
 632		}
 633		if (grp->is_enabled) {
 634			cpt_print_engines_mask(grp, dev, engs_mask,
 635					       OTX_CPT_UCODE_NAME_LENGTH);
 636			pr_debug("Cmask: %s\n", engs_mask);
 637		}
 638	}
 639}
 640
 641static int update_engines_avail_count(struct device *dev,
 642				      struct otx_cpt_engs_available *avail,
 643				      struct otx_cpt_engs_rsvd *engs, int val)
 644{
 645	switch (engs->type) {
 646	case OTX_CPT_SE_TYPES:
 647		avail->se_cnt += val;
 648		break;
 649
 650	case OTX_CPT_AE_TYPES:
 651		avail->ae_cnt += val;
 652		break;
 653
 654	default:
 655		dev_err(dev, "Invalid engine type %d\n", engs->type);
 656		return -EINVAL;
 657	}
 658
 659	return 0;
 660}
 661
 662static int update_engines_offset(struct device *dev,
 663				 struct otx_cpt_engs_available *avail,
 664				 struct otx_cpt_engs_rsvd *engs)
 665{
 666	switch (engs->type) {
 667	case OTX_CPT_SE_TYPES:
 668		engs->offset = 0;
 669		break;
 670
 671	case OTX_CPT_AE_TYPES:
 672		engs->offset = avail->max_se_cnt;
 673		break;
 674
 675	default:
 676		dev_err(dev, "Invalid engine type %d\n", engs->type);
 677		return -EINVAL;
 678	}
 679
 680	return 0;
 681}
 682
 683static int release_engines(struct device *dev, struct otx_cpt_eng_grp_info *grp)
 684{
 685	int i, ret = 0;
 686
 687	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
 688		if (!grp->engs[i].type)
 689			continue;
 690
 691		if (grp->engs[i].count > 0) {
 692			ret = update_engines_avail_count(dev, &grp->g->avail,
 693							 &grp->engs[i],
 694							 grp->engs[i].count);
 695			if (ret)
 696				return ret;
 697		}
 698
 699		grp->engs[i].type = 0;
 700		grp->engs[i].count = 0;
 701		grp->engs[i].offset = 0;
 702		grp->engs[i].ucode = NULL;
 703		bitmap_zero(grp->engs[i].bmap, grp->g->engs_num);
 704	}
 705
 706	return 0;
 707}
 708
 709static int do_reserve_engines(struct device *dev,
 710			      struct otx_cpt_eng_grp_info *grp,
 711			      struct otx_cpt_engines *req_engs)
 712{
 713	struct otx_cpt_engs_rsvd *engs = NULL;
 714	int i, ret;
 715
 716	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
 717		if (!grp->engs[i].type) {
 718			engs = &grp->engs[i];
 719			break;
 720		}
 721	}
 722
 723	if (!engs)
 724		return -ENOMEM;
 725
 726	engs->type = req_engs->type;
 727	engs->count = req_engs->count;
 728
 729	ret = update_engines_offset(dev, &grp->g->avail, engs);
 730	if (ret)
 731		return ret;
 732
 733	if (engs->count > 0) {
 734		ret = update_engines_avail_count(dev, &grp->g->avail, engs,
 735						 -engs->count);
 736		if (ret)
 737			return ret;
 738	}
 739
 740	return 0;
 741}
 742
 743static int check_engines_availability(struct device *dev,
 744				      struct otx_cpt_eng_grp_info *grp,
 745				      struct otx_cpt_engines *req_eng)
 746{
 747	int avail_cnt = 0;
 748
 749	switch (req_eng->type) {
 750	case OTX_CPT_SE_TYPES:
 751		avail_cnt = grp->g->avail.se_cnt;
 752		break;
 753
 754	case OTX_CPT_AE_TYPES:
 755		avail_cnt = grp->g->avail.ae_cnt;
 756		break;
 757
 758	default:
 759		dev_err(dev, "Invalid engine type %d\n", req_eng->type);
 760		return -EINVAL;
 761	}
 762
 763	if (avail_cnt < req_eng->count) {
 764		dev_err(dev,
 765			"Error available %s engines %d < than requested %d\n",
 766			get_eng_type_str(req_eng->type),
 767			avail_cnt, req_eng->count);
 768		return -EBUSY;
 769	}
 770
 771	return 0;
 772}
 773
 774static int reserve_engines(struct device *dev, struct otx_cpt_eng_grp_info *grp,
 775			   struct otx_cpt_engines *req_engs, int req_cnt)
 776{
 777	int i, ret;
 778
 779	/* Validate if a number of requested engines is available */
 780	for (i = 0; i < req_cnt; i++) {
 781		ret = check_engines_availability(dev, grp, &req_engs[i]);
 782		if (ret)
 783			return ret;
 784	}
 785
 786	/* Reserve requested engines for this engine group */
 787	for (i = 0; i < req_cnt; i++) {
 788		ret = do_reserve_engines(dev, grp, &req_engs[i]);
 789		if (ret)
 790			return ret;
 791	}
 792	return 0;
 793}
 794
 795static ssize_t eng_grp_info_show(struct device *dev,
 796				 struct device_attribute *attr,
 797				 char *buf)
 798{
 799	char ucode_info[2*OTX_CPT_UCODE_NAME_LENGTH];
 800	char engs_info[2*OTX_CPT_UCODE_NAME_LENGTH];
 801	char engs_mask[OTX_CPT_UCODE_NAME_LENGTH];
 802	struct otx_cpt_eng_grp_info *eng_grp;
 803	int ret;
 804
 805	eng_grp = container_of(attr, struct otx_cpt_eng_grp_info, info_attr);
 806	mutex_lock(&eng_grp->g->lock);
 807
 808	print_engs_info(eng_grp, engs_info, 2*OTX_CPT_UCODE_NAME_LENGTH, -1);
 809	print_ucode_info(eng_grp, ucode_info, 2*OTX_CPT_UCODE_NAME_LENGTH);
 810	cpt_print_engines_mask(eng_grp, dev, engs_mask,
 811			       OTX_CPT_UCODE_NAME_LENGTH);
 812	ret = scnprintf(buf, PAGE_SIZE,
 813			"Microcode : %s\nEngines: %s\nEngines mask: %s\n",
 814			ucode_info, engs_info, engs_mask);
 815
 816	mutex_unlock(&eng_grp->g->lock);
 817	return ret;
 818}
 819
 820static int create_sysfs_eng_grps_info(struct device *dev,
 821				      struct otx_cpt_eng_grp_info *eng_grp)
 822{
 823	eng_grp->info_attr.show = eng_grp_info_show;
 824	eng_grp->info_attr.store = NULL;
 825	eng_grp->info_attr.attr.name = eng_grp->sysfs_info_name;
 826	eng_grp->info_attr.attr.mode = 0440;
 827	sysfs_attr_init(&eng_grp->info_attr.attr);
 828	return device_create_file(dev, &eng_grp->info_attr);
 829}
 830
 831static void ucode_unload(struct device *dev, struct otx_cpt_ucode *ucode)
 832{
 833	if (ucode->va) {
 834		dma_free_coherent(dev, ucode->size + OTX_CPT_UCODE_ALIGNMENT,
 835				  ucode->va, ucode->dma);
 836		ucode->va = NULL;
 837		ucode->align_va = NULL;
 838		ucode->dma = 0;
 839		ucode->align_dma = 0;
 840		ucode->size = 0;
 841	}
 842
 843	memset(&ucode->ver_str, 0, OTX_CPT_UCODE_VER_STR_SZ);
 844	memset(&ucode->ver_num, 0, sizeof(struct otx_cpt_ucode_ver_num));
 845	set_ucode_filename(ucode, "");
 846	ucode->type = 0;
 847}
 848
 849static int copy_ucode_to_dma_mem(struct device *dev,
 850				 struct otx_cpt_ucode *ucode,
 851				 const u8 *ucode_data)
 852{
 853	u32 i;
 854
 855	/*  Allocate DMAable space */
 856	ucode->va = dma_alloc_coherent(dev, ucode->size +
 857				       OTX_CPT_UCODE_ALIGNMENT,
 858				       &ucode->dma, GFP_KERNEL);
 859	if (!ucode->va) {
 860		dev_err(dev, "Unable to allocate space for microcode\n");
 861		return -ENOMEM;
 862	}
 863	ucode->align_va = PTR_ALIGN(ucode->va, OTX_CPT_UCODE_ALIGNMENT);
 864	ucode->align_dma = PTR_ALIGN(ucode->dma, OTX_CPT_UCODE_ALIGNMENT);
 865
 866	memcpy((void *) ucode->align_va, (void *) ucode_data +
 867	       sizeof(struct otx_cpt_ucode_hdr), ucode->size);
 868
 869	/* Byte swap 64-bit */
 870	for (i = 0; i < (ucode->size / 8); i++)
 871		((__be64 *)ucode->align_va)[i] =
 872				cpu_to_be64(((u64 *)ucode->align_va)[i]);
 873	/*  Ucode needs 16-bit swap */
 874	for (i = 0; i < (ucode->size / 2); i++)
 875		((__be16 *)ucode->align_va)[i] =
 876				cpu_to_be16(((u16 *)ucode->align_va)[i]);
 877	return 0;
 878}
 879
 880static int ucode_load(struct device *dev, struct otx_cpt_ucode *ucode,
 881		      const char *ucode_filename)
 882{
 883	struct otx_cpt_ucode_hdr *ucode_hdr;
 884	const struct firmware *fw;
 885	unsigned int code_length;
 886	int ret;
 887
 888	set_ucode_filename(ucode, ucode_filename);
 889	ret = request_firmware(&fw, ucode->filename, dev);
 890	if (ret)
 891		return ret;
 892
 893	ucode_hdr = (struct otx_cpt_ucode_hdr *) fw->data;
 894	memcpy(ucode->ver_str, ucode_hdr->ver_str, OTX_CPT_UCODE_VER_STR_SZ);
 895	ucode->ver_num = ucode_hdr->ver_num;
 896	code_length = ntohl(ucode_hdr->code_length);
 897	if (code_length >= INT_MAX / 2) {
 898		dev_err(dev, "Ucode invalid code_length %u\n", code_length);
 899		ret = -EINVAL;
 900		goto release_fw;
 901	}
 902	ucode->size = code_length * 2;
 903	if (!ucode->size || (fw->size < round_up(ucode->size, 16)
 904	    + sizeof(struct otx_cpt_ucode_hdr) + OTX_CPT_UCODE_SIGN_LEN)) {
 905		dev_err(dev, "Ucode %s invalid size\n", ucode_filename);
 906		ret = -EINVAL;
 907		goto release_fw;
 908	}
 909
 910	ret = get_ucode_type(ucode_hdr, &ucode->type);
 911	if (ret) {
 912		dev_err(dev, "Microcode %s unknown type 0x%x\n",
 913			ucode->filename, ucode->type);
 914		goto release_fw;
 915	}
 916
 917	ret = copy_ucode_to_dma_mem(dev, ucode, fw->data);
 918	if (ret)
 919		goto release_fw;
 920
 921	print_ucode_dbg_info(ucode);
 922release_fw:
 923	release_firmware(fw);
 924	return ret;
 925}
 926
 927static int enable_eng_grp(struct otx_cpt_eng_grp_info *eng_grp,
 928			  void *obj)
 929{
 930	int ret;
 931
 932	ret = cpt_set_ucode_base(eng_grp, obj);
 933	if (ret)
 934		return ret;
 935
 936	ret = cpt_attach_and_enable_cores(eng_grp, obj);
 937	return ret;
 938}
 939
 940static int disable_eng_grp(struct device *dev,
 941			   struct otx_cpt_eng_grp_info *eng_grp,
 942			   void *obj)
 943{
 944	int i, ret;
 945
 946	ret = cpt_detach_and_disable_cores(eng_grp, obj);
 947	if (ret)
 948		return ret;
 949
 950	/* Unload ucode used by this engine group */
 951	ucode_unload(dev, &eng_grp->ucode[0]);
 952
 953	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
 954		if (!eng_grp->engs[i].type)
 955			continue;
 956
 957		eng_grp->engs[i].ucode = &eng_grp->ucode[0];
 958	}
 959
 960	ret = cpt_set_ucode_base(eng_grp, obj);
 961
 962	return ret;
 963}
 964
 965static void setup_eng_grp_mirroring(struct otx_cpt_eng_grp_info *dst_grp,
 966				    struct otx_cpt_eng_grp_info *src_grp)
 967{
 968	/* Setup fields for engine group which is mirrored */
 969	src_grp->mirror.is_ena = false;
 970	src_grp->mirror.idx = 0;
 971	src_grp->mirror.ref_count++;
 972
 973	/* Setup fields for mirroring engine group */
 974	dst_grp->mirror.is_ena = true;
 975	dst_grp->mirror.idx = src_grp->idx;
 976	dst_grp->mirror.ref_count = 0;
 977}
 978
 979static void remove_eng_grp_mirroring(struct otx_cpt_eng_grp_info *dst_grp)
 980{
 981	struct otx_cpt_eng_grp_info *src_grp;
 982
 983	if (!dst_grp->mirror.is_ena)
 984		return;
 985
 986	src_grp = &dst_grp->g->grp[dst_grp->mirror.idx];
 987
 988	src_grp->mirror.ref_count--;
 989	dst_grp->mirror.is_ena = false;
 990	dst_grp->mirror.idx = 0;
 991	dst_grp->mirror.ref_count = 0;
 992}
 993
 994static void update_requested_engs(struct otx_cpt_eng_grp_info *mirrored_eng_grp,
 995				  struct otx_cpt_engines *engs, int engs_cnt)
 996{
 997	struct otx_cpt_engs_rsvd *mirrored_engs;
 998	int i;
 999
1000	for (i = 0; i < engs_cnt; i++) {
1001		mirrored_engs = find_engines_by_type(mirrored_eng_grp,
1002						     engs[i].type);
1003		if (!mirrored_engs)
1004			continue;
1005
1006		/*
1007		 * If mirrored group has this type of engines attached then
1008		 * there are 3 scenarios possible:
1009		 * 1) mirrored_engs.count == engs[i].count then all engines
1010		 * from mirrored engine group will be shared with this engine
1011		 * group
1012		 * 2) mirrored_engs.count > engs[i].count then only a subset of
1013		 * engines from mirrored engine group will be shared with this
1014		 * engine group
1015		 * 3) mirrored_engs.count < engs[i].count then all engines
1016		 * from mirrored engine group will be shared with this group
1017		 * and additional engines will be reserved for exclusively use
1018		 * by this engine group
1019		 */
1020		engs[i].count -= mirrored_engs->count;
1021	}
1022}
1023
1024static struct otx_cpt_eng_grp_info *find_mirrored_eng_grp(
1025					struct otx_cpt_eng_grp_info *grp)
1026{
1027	struct otx_cpt_eng_grps *eng_grps = grp->g;
1028	int i;
1029
1030	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++) {
1031		if (!eng_grps->grp[i].is_enabled)
1032			continue;
1033		if (eng_grps->grp[i].ucode[0].type)
1034			continue;
1035		if (grp->idx == i)
1036			continue;
1037		if (!strncasecmp(eng_grps->grp[i].ucode[0].ver_str,
1038				 grp->ucode[0].ver_str,
1039				 OTX_CPT_UCODE_VER_STR_SZ))
1040			return &eng_grps->grp[i];
1041	}
1042
1043	return NULL;
1044}
1045
1046static struct otx_cpt_eng_grp_info *find_unused_eng_grp(
1047					struct otx_cpt_eng_grps *eng_grps)
1048{
1049	int i;
1050
1051	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++) {
1052		if (!eng_grps->grp[i].is_enabled)
1053			return &eng_grps->grp[i];
1054	}
1055	return NULL;
1056}
1057
1058static int eng_grp_update_masks(struct device *dev,
1059				struct otx_cpt_eng_grp_info *eng_grp)
1060{
1061	struct otx_cpt_engs_rsvd *engs, *mirrored_engs;
1062	struct otx_cpt_bitmap tmp_bmap = { {0} };
1063	int i, j, cnt, max_cnt;
1064	int bit;
1065
1066	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
1067		engs = &eng_grp->engs[i];
1068		if (!engs->type)
1069			continue;
1070		if (engs->count <= 0)
1071			continue;
1072
1073		switch (engs->type) {
1074		case OTX_CPT_SE_TYPES:
1075			max_cnt = eng_grp->g->avail.max_se_cnt;
1076			break;
1077
1078		case OTX_CPT_AE_TYPES:
1079			max_cnt = eng_grp->g->avail.max_ae_cnt;
1080			break;
1081
1082		default:
1083			dev_err(dev, "Invalid engine type %d\n", engs->type);
1084			return -EINVAL;
1085		}
1086
1087		cnt = engs->count;
1088		WARN_ON(engs->offset + max_cnt > OTX_CPT_MAX_ENGINES);
1089		bitmap_zero(tmp_bmap.bits, eng_grp->g->engs_num);
1090		for (j = engs->offset; j < engs->offset + max_cnt; j++) {
1091			if (!eng_grp->g->eng_ref_cnt[j]) {
1092				bitmap_set(tmp_bmap.bits, j, 1);
1093				cnt--;
1094				if (!cnt)
1095					break;
1096			}
1097		}
1098
1099		if (cnt)
1100			return -ENOSPC;
1101
1102		bitmap_copy(engs->bmap, tmp_bmap.bits, eng_grp->g->engs_num);
1103	}
1104
1105	if (!eng_grp->mirror.is_ena)
1106		return 0;
1107
1108	for (i = 0; i < OTX_CPT_MAX_ETYPES_PER_GRP; i++) {
1109		engs = &eng_grp->engs[i];
1110		if (!engs->type)
1111			continue;
1112
1113		mirrored_engs = find_engines_by_type(
1114					&eng_grp->g->grp[eng_grp->mirror.idx],
1115					engs->type);
1116		WARN_ON(!mirrored_engs && engs->count <= 0);
1117		if (!mirrored_engs)
1118			continue;
1119
1120		bitmap_copy(tmp_bmap.bits, mirrored_engs->bmap,
1121			    eng_grp->g->engs_num);
1122		if (engs->count < 0) {
1123			bit = find_first_bit(mirrored_engs->bmap,
1124					     eng_grp->g->engs_num);
1125			bitmap_clear(tmp_bmap.bits, bit, -engs->count);
1126		}
1127		bitmap_or(engs->bmap, engs->bmap, tmp_bmap.bits,
1128			  eng_grp->g->engs_num);
1129	}
1130	return 0;
1131}
1132
1133static int delete_engine_group(struct device *dev,
1134			       struct otx_cpt_eng_grp_info *eng_grp)
1135{
1136	int i, ret;
1137
1138	if (!eng_grp->is_enabled)
1139		return -EINVAL;
1140
1141	if (eng_grp->mirror.ref_count) {
1142		dev_err(dev, "Can't delete engine_group%d as it is used by engine_group(s):",
1143			eng_grp->idx);
1144		for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++) {
1145			if (eng_grp->g->grp[i].mirror.is_ena &&
1146			    eng_grp->g->grp[i].mirror.idx == eng_grp->idx)
1147				pr_cont(" %d", i);
1148		}
1149		pr_cont("\n");
1150		return -EINVAL;
1151	}
1152
1153	/* Removing engine group mirroring if enabled */
1154	remove_eng_grp_mirroring(eng_grp);
1155
1156	/* Disable engine group */
1157	ret = disable_eng_grp(dev, eng_grp, eng_grp->g->obj);
1158	if (ret)
1159		return ret;
1160
1161	/* Release all engines held by this engine group */
1162	ret = release_engines(dev, eng_grp);
1163	if (ret)
1164		return ret;
1165
1166	device_remove_file(dev, &eng_grp->info_attr);
1167	eng_grp->is_enabled = false;
1168
1169	return 0;
1170}
1171
1172static int validate_1_ucode_scenario(struct device *dev,
1173				     struct otx_cpt_eng_grp_info *eng_grp,
1174				     struct otx_cpt_engines *engs, int engs_cnt)
1175{
1176	int i;
1177
1178	/* Verify that ucode loaded supports requested engine types */
1179	for (i = 0; i < engs_cnt; i++) {
1180		if (!otx_cpt_uc_supports_eng_type(&eng_grp->ucode[0],
1181						  engs[i].type)) {
1182			dev_err(dev,
1183				"Microcode %s does not support %s engines\n",
1184				eng_grp->ucode[0].filename,
1185				get_eng_type_str(engs[i].type));
1186			return -EINVAL;
1187		}
1188	}
1189	return 0;
1190}
1191
1192static void update_ucode_ptrs(struct otx_cpt_eng_grp_info *eng_grp)
1193{
1194	struct otx_cpt_ucode *ucode;
1195
1196	if (eng_grp->mirror.is_ena)
1197		ucode = &eng_grp->g->grp[eng_grp->mirror.idx].ucode[0];
1198	else
1199		ucode = &eng_grp->ucode[0];
1200	WARN_ON(!eng_grp->engs[0].type);
1201	eng_grp->engs[0].ucode = ucode;
1202}
1203
1204static int create_engine_group(struct device *dev,
1205			       struct otx_cpt_eng_grps *eng_grps,
1206			       struct otx_cpt_engines *engs, int engs_cnt,
1207			       void *ucode_data[], int ucodes_cnt,
1208			       bool use_uc_from_tar_arch)
1209{
1210	struct otx_cpt_eng_grp_info *mirrored_eng_grp;
1211	struct tar_ucode_info_t *tar_info;
1212	struct otx_cpt_eng_grp_info *eng_grp;
1213	int i, ret = 0;
1214
1215	if (ucodes_cnt > OTX_CPT_MAX_ETYPES_PER_GRP)
1216		return -EINVAL;
1217
1218	/* Validate if requested engine types are supported by this device */
1219	for (i = 0; i < engs_cnt; i++)
1220		if (!dev_supports_eng_type(eng_grps, engs[i].type)) {
1221			dev_err(dev, "Device does not support %s engines\n",
1222				get_eng_type_str(engs[i].type));
1223			return -EPERM;
1224		}
1225
1226	/* Find engine group which is not used */
1227	eng_grp = find_unused_eng_grp(eng_grps);
1228	if (!eng_grp) {
1229		dev_err(dev, "Error all engine groups are being used\n");
1230		return -ENOSPC;
1231	}
1232
1233	/* Load ucode */
1234	for (i = 0; i < ucodes_cnt; i++) {
1235		if (use_uc_from_tar_arch) {
1236			tar_info = (struct tar_ucode_info_t *) ucode_data[i];
1237			eng_grp->ucode[i] = tar_info->ucode;
1238			ret = copy_ucode_to_dma_mem(dev, &eng_grp->ucode[i],
1239						    tar_info->ucode_ptr);
1240		} else
1241			ret = ucode_load(dev, &eng_grp->ucode[i],
1242					 (char *) ucode_data[i]);
1243		if (ret)
1244			goto err_ucode_unload;
1245	}
1246
1247	/* Validate scenario where 1 ucode is used */
1248	ret = validate_1_ucode_scenario(dev, eng_grp, engs, engs_cnt);
1249	if (ret)
1250		goto err_ucode_unload;
1251
1252	/* Check if this group mirrors another existing engine group */
1253	mirrored_eng_grp = find_mirrored_eng_grp(eng_grp);
1254	if (mirrored_eng_grp) {
1255		/* Setup mirroring */
1256		setup_eng_grp_mirroring(eng_grp, mirrored_eng_grp);
1257
1258		/*
1259		 * Update count of requested engines because some
1260		 * of them might be shared with mirrored group
1261		 */
1262		update_requested_engs(mirrored_eng_grp, engs, engs_cnt);
1263	}
1264
1265	/* Reserve engines */
1266	ret = reserve_engines(dev, eng_grp, engs, engs_cnt);
1267	if (ret)
1268		goto err_ucode_unload;
1269
1270	/* Update ucode pointers used by engines */
1271	update_ucode_ptrs(eng_grp);
1272
1273	/* Update engine masks used by this group */
1274	ret = eng_grp_update_masks(dev, eng_grp);
1275	if (ret)
1276		goto err_release_engs;
1277
1278	/* Create sysfs entry for engine group info */
1279	ret = create_sysfs_eng_grps_info(dev, eng_grp);
1280	if (ret)
1281		goto err_release_engs;
1282
1283	/* Enable engine group */
1284	ret = enable_eng_grp(eng_grp, eng_grps->obj);
1285	if (ret)
1286		goto err_release_engs;
1287
1288	/*
1289	 * If this engine group mirrors another engine group
1290	 * then we need to unload ucode as we will use ucode
1291	 * from mirrored engine group
1292	 */
1293	if (eng_grp->mirror.is_ena)
1294		ucode_unload(dev, &eng_grp->ucode[0]);
1295
1296	eng_grp->is_enabled = true;
1297	if (eng_grp->mirror.is_ena)
1298		dev_info(dev,
1299			 "Engine_group%d: reuse microcode %s from group %d\n",
1300			 eng_grp->idx, mirrored_eng_grp->ucode[0].ver_str,
1301			 mirrored_eng_grp->idx);
1302	else
1303		dev_info(dev, "Engine_group%d: microcode loaded %s\n",
1304			 eng_grp->idx, eng_grp->ucode[0].ver_str);
1305
1306	return 0;
1307
1308err_release_engs:
1309	release_engines(dev, eng_grp);
1310err_ucode_unload:
1311	ucode_unload(dev, &eng_grp->ucode[0]);
1312	return ret;
1313}
1314
1315static ssize_t ucode_load_store(struct device *dev,
1316				struct device_attribute *attr,
1317				const char *buf, size_t count)
1318{
1319	struct otx_cpt_engines engs[OTX_CPT_MAX_ETYPES_PER_GRP] = { {0} };
1320	char *ucode_filename[OTX_CPT_MAX_ETYPES_PER_GRP];
1321	char tmp_buf[OTX_CPT_UCODE_NAME_LENGTH] = { 0 };
1322	char *start, *val, *err_msg, *tmp;
1323	struct otx_cpt_eng_grps *eng_grps;
1324	int grp_idx = 0, ret = -EINVAL;
1325	bool has_se, has_ie, has_ae;
1326	int del_grp_idx = -1;
1327	int ucode_idx = 0;
1328
1329	if (count >= OTX_CPT_UCODE_NAME_LENGTH)
1330		return -EINVAL;
1331
1332	eng_grps = container_of(attr, struct otx_cpt_eng_grps, ucode_load_attr);
1333	err_msg = "Invalid engine group format";
1334	strscpy(tmp_buf, buf, OTX_CPT_UCODE_NAME_LENGTH);
1335	start = tmp_buf;
1336
1337	has_se = has_ie = has_ae = false;
1338
1339	for (;;) {
1340		val = strsep(&start, ";");
1341		if (!val)
1342			break;
1343		val = strim(val);
1344		if (!*val)
1345			continue;
1346
1347		if (!strncasecmp(val, "engine_group", 12)) {
1348			if (del_grp_idx != -1)
1349				goto err_print;
1350			tmp = strim(strsep(&val, ":"));
1351			if (!val)
1352				goto err_print;
1353			if (strlen(tmp) != 13)
1354				goto err_print;
1355			if (kstrtoint((tmp + 12), 10, &del_grp_idx))
1356				goto err_print;
1357			val = strim(val);
1358			if (strncasecmp(val, "null", 4))
1359				goto err_print;
1360			if (strlen(val) != 4)
1361				goto err_print;
1362		} else if (!strncasecmp(val, "se", 2) && strchr(val, ':')) {
1363			if (has_se || ucode_idx)
1364				goto err_print;
1365			tmp = strim(strsep(&val, ":"));
1366			if (!val)
1367				goto err_print;
1368			if (strlen(tmp) != 2)
1369				goto err_print;
1370			if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
1371				goto err_print;
1372			engs[grp_idx++].type = OTX_CPT_SE_TYPES;
1373			has_se = true;
1374		} else if (!strncasecmp(val, "ae", 2) && strchr(val, ':')) {
1375			if (has_ae || ucode_idx)
1376				goto err_print;
1377			tmp = strim(strsep(&val, ":"));
1378			if (!val)
1379				goto err_print;
1380			if (strlen(tmp) != 2)
1381				goto err_print;
1382			if (kstrtoint(strim(val), 10, &engs[grp_idx].count))
1383				goto err_print;
1384			engs[grp_idx++].type = OTX_CPT_AE_TYPES;
1385			has_ae = true;
1386		} else {
1387			if (ucode_idx > 1)
1388				goto err_print;
1389			if (!strlen(val))
1390				goto err_print;
1391			if (strnstr(val, " ", strlen(val)))
1392				goto err_print;
1393			ucode_filename[ucode_idx++] = val;
1394		}
1395	}
1396
1397	/* Validate input parameters */
1398	if (del_grp_idx == -1) {
1399		if (!(grp_idx && ucode_idx))
1400			goto err_print;
1401
1402		if (ucode_idx > 1 && grp_idx < 2)
1403			goto err_print;
1404
1405		if (grp_idx > OTX_CPT_MAX_ETYPES_PER_GRP) {
1406			err_msg = "Error max 2 engine types can be attached";
1407			goto err_print;
1408		}
1409
1410	} else {
1411		if (del_grp_idx < 0 ||
1412		    del_grp_idx >= OTX_CPT_MAX_ENGINE_GROUPS) {
1413			dev_err(dev, "Invalid engine group index %d\n",
1414				del_grp_idx);
1415			ret = -EINVAL;
1416			return ret;
1417		}
1418
1419		if (!eng_grps->grp[del_grp_idx].is_enabled) {
1420			dev_err(dev, "Error engine_group%d is not configured\n",
1421				del_grp_idx);
1422			ret = -EINVAL;
1423			return ret;
1424		}
1425
1426		if (grp_idx || ucode_idx)
1427			goto err_print;
1428	}
1429
1430	mutex_lock(&eng_grps->lock);
1431
1432	if (eng_grps->is_rdonly) {
1433		dev_err(dev, "Disable VFs before modifying engine groups\n");
1434		ret = -EACCES;
1435		goto err_unlock;
1436	}
1437
1438	if (del_grp_idx == -1)
1439		/* create engine group */
1440		ret = create_engine_group(dev, eng_grps, engs, grp_idx,
1441					  (void **) ucode_filename,
1442					  ucode_idx, false);
1443	else
1444		/* delete engine group */
1445		ret = delete_engine_group(dev, &eng_grps->grp[del_grp_idx]);
1446	if (ret)
1447		goto err_unlock;
1448
1449	print_dbg_info(dev, eng_grps);
1450err_unlock:
1451	mutex_unlock(&eng_grps->lock);
1452	return ret ? ret : count;
1453err_print:
1454	dev_err(dev, "%s\n", err_msg);
1455
1456	return ret;
1457}
1458
1459int otx_cpt_try_create_default_eng_grps(struct pci_dev *pdev,
1460					struct otx_cpt_eng_grps *eng_grps,
1461					int pf_type)
1462{
1463	struct tar_ucode_info_t *tar_info[OTX_CPT_MAX_ETYPES_PER_GRP] = {};
1464	struct otx_cpt_engines engs[OTX_CPT_MAX_ETYPES_PER_GRP] = {};
1465	struct tar_arch_info_t *tar_arch = NULL;
1466	char *tar_filename;
1467	int i, ret = 0;
1468
1469	mutex_lock(&eng_grps->lock);
1470
1471	/*
1472	 * We don't create engine group for kernel crypto if attempt to create
1473	 * it was already made (when user enabled VFs for the first time)
1474	 */
1475	if (eng_grps->is_first_try)
1476		goto unlock_mutex;
1477	eng_grps->is_first_try = true;
1478
1479	/* We create group for kcrypto only if no groups are configured */
1480	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++)
1481		if (eng_grps->grp[i].is_enabled)
1482			goto unlock_mutex;
1483
1484	switch (pf_type) {
1485	case OTX_CPT_AE:
1486	case OTX_CPT_SE:
1487		tar_filename = OTX_CPT_UCODE_TAR_FILE_NAME;
1488		break;
1489
1490	default:
1491		dev_err(&pdev->dev, "Unknown PF type %d\n", pf_type);
1492		ret = -EINVAL;
1493		goto unlock_mutex;
1494	}
1495
1496	tar_arch = load_tar_archive(&pdev->dev, tar_filename);
1497	if (!tar_arch)
1498		goto unlock_mutex;
1499
1500	/*
1501	 * If device supports SE engines and there is SE microcode in tar
1502	 * archive try to create engine group with SE engines for kernel
1503	 * crypto functionality (symmetric crypto)
1504	 */
1505	tar_info[0] = get_uc_from_tar_archive(tar_arch, OTX_CPT_SE_TYPES);
1506	if (tar_info[0] &&
1507	    dev_supports_eng_type(eng_grps, OTX_CPT_SE_TYPES)) {
1508
1509		engs[0].type = OTX_CPT_SE_TYPES;
1510		engs[0].count = eng_grps->avail.max_se_cnt;
1511
1512		ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
1513					  (void **) tar_info, 1, true);
1514		if (ret)
1515			goto release_tar_arch;
1516	}
1517	/*
1518	 * If device supports AE engines and there is AE microcode in tar
1519	 * archive try to create engine group with AE engines for asymmetric
1520	 * crypto functionality.
1521	 */
1522	tar_info[0] = get_uc_from_tar_archive(tar_arch, OTX_CPT_AE_TYPES);
1523	if (tar_info[0] &&
1524	    dev_supports_eng_type(eng_grps, OTX_CPT_AE_TYPES)) {
1525
1526		engs[0].type = OTX_CPT_AE_TYPES;
1527		engs[0].count = eng_grps->avail.max_ae_cnt;
1528
1529		ret = create_engine_group(&pdev->dev, eng_grps, engs, 1,
1530					  (void **) tar_info, 1, true);
1531		if (ret)
1532			goto release_tar_arch;
1533	}
1534
1535	print_dbg_info(&pdev->dev, eng_grps);
1536release_tar_arch:
1537	release_tar_archive(tar_arch);
1538unlock_mutex:
1539	mutex_unlock(&eng_grps->lock);
1540	return ret;
1541}
1542
1543void otx_cpt_set_eng_grps_is_rdonly(struct otx_cpt_eng_grps *eng_grps,
1544				    bool is_rdonly)
1545{
1546	mutex_lock(&eng_grps->lock);
1547
1548	eng_grps->is_rdonly = is_rdonly;
1549
1550	mutex_unlock(&eng_grps->lock);
1551}
1552
1553void otx_cpt_disable_all_cores(struct otx_cpt_device *cpt)
1554{
1555	int grp, timeout = 100;
1556	u64 reg;
1557
1558	/* Disengage the cores from groups */
1559	for (grp = 0; grp < OTX_CPT_MAX_ENGINE_GROUPS; grp++) {
1560		writeq(0, cpt->reg_base + OTX_CPT_PF_GX_EN(grp));
1561		udelay(CSR_DELAY);
1562	}
1563
1564	reg = readq(cpt->reg_base + OTX_CPT_PF_EXEC_BUSY);
1565	while (reg) {
1566		udelay(CSR_DELAY);
1567		reg = readq(cpt->reg_base + OTX_CPT_PF_EXEC_BUSY);
1568		if (timeout--) {
1569			dev_warn(&cpt->pdev->dev, "Cores still busy\n");
1570			break;
1571		}
1572	}
1573
1574	/* Disable the cores */
1575	writeq(0, cpt->reg_base + OTX_CPT_PF_EXE_CTL);
1576}
1577
1578void otx_cpt_cleanup_eng_grps(struct pci_dev *pdev,
1579			      struct otx_cpt_eng_grps *eng_grps)
1580{
1581	struct otx_cpt_eng_grp_info *grp;
1582	int i, j;
1583
1584	mutex_lock(&eng_grps->lock);
1585	if (eng_grps->is_ucode_load_created) {
1586		device_remove_file(&pdev->dev,
1587				   &eng_grps->ucode_load_attr);
1588		eng_grps->is_ucode_load_created = false;
1589	}
1590
1591	/* First delete all mirroring engine groups */
1592	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++)
1593		if (eng_grps->grp[i].mirror.is_ena)
1594			delete_engine_group(&pdev->dev, &eng_grps->grp[i]);
1595
1596	/* Delete remaining engine groups */
1597	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++)
1598		delete_engine_group(&pdev->dev, &eng_grps->grp[i]);
1599
1600	/* Release memory */
1601	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++) {
1602		grp = &eng_grps->grp[i];
1603		for (j = 0; j < OTX_CPT_MAX_ETYPES_PER_GRP; j++) {
1604			kfree(grp->engs[j].bmap);
1605			grp->engs[j].bmap = NULL;
1606		}
1607	}
1608
1609	mutex_unlock(&eng_grps->lock);
1610}
1611
1612int otx_cpt_init_eng_grps(struct pci_dev *pdev,
1613			  struct otx_cpt_eng_grps *eng_grps, int pf_type)
1614{
1615	struct otx_cpt_eng_grp_info *grp;
1616	int i, j, ret = 0;
1617
1618	mutex_init(&eng_grps->lock);
1619	eng_grps->obj = pci_get_drvdata(pdev);
1620	eng_grps->avail.se_cnt = eng_grps->avail.max_se_cnt;
1621	eng_grps->avail.ae_cnt = eng_grps->avail.max_ae_cnt;
1622
1623	eng_grps->engs_num = eng_grps->avail.max_se_cnt +
1624			     eng_grps->avail.max_ae_cnt;
1625	if (eng_grps->engs_num > OTX_CPT_MAX_ENGINES) {
1626		dev_err(&pdev->dev,
1627			"Number of engines %d > than max supported %d\n",
1628			eng_grps->engs_num, OTX_CPT_MAX_ENGINES);
1629		ret = -EINVAL;
1630		goto err;
1631	}
1632
1633	for (i = 0; i < OTX_CPT_MAX_ENGINE_GROUPS; i++) {
1634		grp = &eng_grps->grp[i];
1635		grp->g = eng_grps;
1636		grp->idx = i;
1637
1638		snprintf(grp->sysfs_info_name, OTX_CPT_UCODE_NAME_LENGTH,
1639			 "engine_group%d", i);
1640		for (j = 0; j < OTX_CPT_MAX_ETYPES_PER_GRP; j++) {
1641			grp->engs[j].bmap =
1642				kcalloc(BITS_TO_LONGS(eng_grps->engs_num),
1643					sizeof(long), GFP_KERNEL);
1644			if (!grp->engs[j].bmap) {
1645				ret = -ENOMEM;
1646				goto err;
1647			}
1648		}
1649	}
1650
1651	switch (pf_type) {
1652	case OTX_CPT_SE:
1653		/* OcteonTX 83XX SE CPT PF has only SE engines attached */
1654		eng_grps->eng_types_supported = 1 << OTX_CPT_SE_TYPES;
1655		break;
1656
1657	case OTX_CPT_AE:
1658		/* OcteonTX 83XX AE CPT PF has only AE engines attached */
1659		eng_grps->eng_types_supported = 1 << OTX_CPT_AE_TYPES;
1660		break;
1661
1662	default:
1663		dev_err(&pdev->dev, "Unknown PF type %d\n", pf_type);
1664		ret = -EINVAL;
1665		goto err;
1666	}
1667
1668	eng_grps->ucode_load_attr.show = NULL;
1669	eng_grps->ucode_load_attr.store = ucode_load_store;
1670	eng_grps->ucode_load_attr.attr.name = "ucode_load";
1671	eng_grps->ucode_load_attr.attr.mode = 0220;
1672	sysfs_attr_init(&eng_grps->ucode_load_attr.attr);
1673	ret = device_create_file(&pdev->dev,
1674				 &eng_grps->ucode_load_attr);
1675	if (ret)
1676		goto err;
1677	eng_grps->is_ucode_load_created = true;
1678
1679	print_dbg_info(&pdev->dev, eng_grps);
1680	return ret;
1681err:
1682	otx_cpt_cleanup_eng_grps(pdev, eng_grps);
1683	return ret;
1684}
~/ Read-only file preview.