Commit 11c730bf authored by Harman Kalra's avatar Harman Kalra Committed by Jakub Kicinski
Browse files

octeontx2-af: support for coalescing KPU profiles



Adding support to load a new type of KPU image, known as coalesced/
consolidated KPU image via firmware database. This image is a
consolidation of multiple KPU profiles into a single image.

During kernel bootup this coalesced image will be read via
firmware database and only the relevant KPU profile will be loaded.
Existing functionality of loading single KPU/MKEX profile
is intact as the images are differentiated based on the image signature.

Signed-off-by: default avatarHarman Kalra <hkalra@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <Sunil.Goutham@marvell.com>
Signed-off-by: default avatarGeorge Cherian <george.cherian@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c87e6b13
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -427,6 +427,17 @@ struct nix_tx_action {
#define NIXLF_BCAST_ENTRY	1
#define NIXLF_PROMISC_ENTRY	2

struct npc_coalesced_kpu_prfl {
#define NPC_SIGN	0x00666f727063706e
#define NPC_PRFL_NAME   "npc_prfls_array"
#define NPC_NAME_LEN	32
	__le64 signature; /* "npcprof\0" (8 bytes/ASCII characters) */
	u8 name[NPC_NAME_LEN]; /* KPU Profile name */
	u64 version; /* KPU firmware/profile version */
	u8 num_prfl; /* No of NPC profiles. */
	u16 prfl_sz[0];
};

struct npc_mcam_kex {
	/* MKEX Profle Header */
	u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */
+68 −15
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#define NPC_KEX_CHAN_MASK		0xFFFULL
#define NPC_KEX_PF_FUNC_MASK		0xFFFFULL

#define ALIGN_8B_CEIL(__a)	(((__a) + 7) & (-8))

static const char def_pfl_name[] = "default";

static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
@@ -1417,28 +1419,78 @@ static int npc_apply_custom_kpu(struct rvu *rvu,
	return 0;
}

static int npc_load_kpu_prfl_img(struct rvu *rvu, void __iomem *prfl_addr,
				 u64 prfl_sz, const char *kpu_profile)
{
	struct npc_kpu_profile_fwdata *kpu_data = NULL;
	int rc = -EINVAL;

	kpu_data = (struct npc_kpu_profile_fwdata __force *)prfl_addr;
	if (le64_to_cpu(kpu_data->signature) == KPU_SIGN &&
	    !strncmp(kpu_data->name, kpu_profile, KPU_NAME_LEN)) {
		dev_info(rvu->dev, "Loading KPU profile from firmware db: %s\n",
			 kpu_profile);
		rvu->kpu_fwdata = kpu_data;
		rvu->kpu_fwdata_sz = prfl_sz;
		rvu->kpu_prfl_addr = prfl_addr;
		rc = 0;
	}

	return rc;
}

static int npc_fwdb_detect_load_prfl_img(struct rvu *rvu, uint64_t prfl_sz,
					 const char *kpu_profile)
{
	struct npc_coalesced_kpu_prfl *img_data = NULL;
	int i = 0, rc = -EINVAL;
	void __iomem *kpu_prfl_addr;
	u16 offset;

	img_data = (struct npc_coalesced_kpu_prfl __force *)rvu->kpu_prfl_addr;
	if (le64_to_cpu(img_data->signature) == KPU_SIGN &&
	    !strncmp(img_data->name, kpu_profile, KPU_NAME_LEN)) {
		/* Loaded profile is a single KPU profile. */
		rc = npc_load_kpu_prfl_img(rvu, rvu->kpu_prfl_addr,
					   prfl_sz, kpu_profile);
		goto done;
	}

	/* Loaded profile is coalesced image, offset of first KPU profile.*/
	offset = offsetof(struct npc_coalesced_kpu_prfl, prfl_sz) +
		(img_data->num_prfl * sizeof(uint16_t));
	/* Check if mapped image is coalesced image. */
	while (i < img_data->num_prfl) {
		/* Profile image offsets are rounded up to next 8 multiple.*/
		offset = ALIGN_8B_CEIL(offset);
		kpu_prfl_addr = (void __iomem *)((uintptr_t)rvu->kpu_prfl_addr +
					 offset);
		rc = npc_load_kpu_prfl_img(rvu, kpu_prfl_addr,
					   img_data->prfl_sz[i], kpu_profile);
		if (!rc)
			break;
		/* Calculating offset of profile image based on profile size.*/
		offset += img_data->prfl_sz[i];
		i++;
	}
done:
	return rc;
}

static int npc_load_kpu_profile_fwdb(struct rvu *rvu, const char *kpu_profile)
{
	struct npc_kpu_profile_fwdata *kpu_fw = NULL;
	int ret = -EINVAL;
	u64 prfl_sz;
	int ret;

	/* Setting up the mapping for NPC profile image */
	ret = npc_fwdb_prfl_img_map(rvu, &rvu->kpu_prfl_addr, &prfl_sz);
	if (ret < 0)
		return ret;
		goto done;

	rvu->kpu_fwdata =
		(struct npc_kpu_profile_fwdata __force *)rvu->kpu_prfl_addr;
	rvu->kpu_fwdata_sz = prfl_sz;

	kpu_fw = rvu->kpu_fwdata;
	if (le64_to_cpu(kpu_fw->signature) == KPU_SIGN &&
	    !strncmp(kpu_fw->name, kpu_profile, KPU_NAME_LEN)) {
		dev_info(rvu->dev, "Loading KPU profile from firmware db: %s\n",
			 kpu_profile);
		return 0;
	}
	/* Detect if profile is coalesced or single KPU profile and load */
	ret = npc_fwdb_detect_load_prfl_img(rvu, prfl_sz, kpu_profile);
	if (ret == 0)
		goto done;

	/* Cleaning up if KPU profile image from fwdata is not valid. */
	if (rvu->kpu_prfl_addr) {
@@ -1448,7 +1500,8 @@ static int npc_load_kpu_profile_fwdb(struct rvu *rvu, const char *kpu_profile)
		rvu->kpu_fwdata = NULL;
	}

	return -EINVAL;
done:
	return ret;
}

static void npc_load_kpu_profile(struct rvu *rvu)