OSDN Git Service

octeontx2-af: support for coalescing KPU profiles
authorHarman Kalra <hkalra@marvell.com>
Thu, 27 May 2021 09:44:38 +0000 (15:14 +0530)
committerJakub Kicinski <kuba@kernel.org>
Sat, 29 May 2021 21:16:22 +0000 (14:16 -0700)
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: Harman Kalra <hkalra@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <Sunil.Goutham@marvell.com>
Signed-off-by: George Cherian <george.cherian@marvell.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/npc.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

index 8114c5f..8afa1c6 100644 (file)
@@ -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) */
index 52ee58c..bd63305 100644 (file)
@@ -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)