diff options
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 117 |
2 files changed, 101 insertions, 17 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index fb142520e309..74ed929f101b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -442,6 +442,7 @@ struct rvu { struct rvu_fwdata *fwdata; void *kpu_fwdata; size_t kpu_fwdata_sz; + void __iomem *kpu_prfl_addr; /* NPC KPU data */ struct npc_kpu_profile_adapter kpu; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c index 254b768155cd..91e9467c5f69 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -1134,6 +1134,30 @@ static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr, } } +static int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr, + u64 *size) +{ + u64 prfl_addr, prfl_sz; + + if (!rvu->fwdata) + return -EINVAL; + + prfl_addr = rvu->fwdata->mcam_addr; + prfl_sz = rvu->fwdata->mcam_sz; + + if (!prfl_addr || !prfl_sz) + return -EINVAL; + + *prfl_img_addr = ioremap_wc(prfl_addr, prfl_sz); + if (!(*prfl_img_addr)) + return -ENOMEM; + + *size = prfl_sz; + + return 0; +} + +/* strtoull of "mkexprof" with base:36 */ #define MKEX_END_SIGN 0xdeadbeef static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr, @@ -1141,27 +1165,21 @@ static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr, { struct device *dev = &rvu->pdev->dev; struct npc_mcam_kex *mcam_kex; - void *mkex_prfl_addr = NULL; - u64 prfl_addr, prfl_sz; + void __iomem *mkex_prfl_addr = NULL; + u64 prfl_sz; + int ret; /* If user not selected mkex profile */ if (rvu->kpu_fwdata_sz || !strncmp(mkex_profile, def_pfl_name, MKEX_NAME_LEN)) goto program_mkex; - if (!rvu->fwdata) - goto program_mkex; - prfl_addr = rvu->fwdata->mcam_addr; - prfl_sz = rvu->fwdata->mcam_sz; - - if (!prfl_addr || !prfl_sz) - goto program_mkex; - - mkex_prfl_addr = memremap(prfl_addr, prfl_sz, MEMREMAP_WC); - if (!mkex_prfl_addr) + /* Setting up the mapping for mkex profile image */ + ret = npc_fwdb_prfl_img_map(rvu, &mkex_prfl_addr, &prfl_sz); + if (ret < 0) goto program_mkex; - mcam_kex = (struct npc_mcam_kex *)mkex_prfl_addr; + mcam_kex = (struct npc_mcam_kex __force *)mkex_prfl_addr; while (((s64)prfl_sz > 0) && (mcam_kex->mkex_sign != MKEX_END_SIGN)) { /* Compare with mkex mod_param name string */ @@ -1187,7 +1205,7 @@ program_mkex: /* Program selected mkex profile */ npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mkex); if (mkex_prfl_addr) - memunmap(mkex_prfl_addr); + iounmap(mkex_prfl_addr); } static void npc_config_kpuaction(struct rvu *rvu, int blkaddr, @@ -1386,6 +1404,40 @@ static int npc_apply_custom_kpu(struct rvu *rvu, return 0; } +static int npc_load_kpu_profile_fwdb(struct rvu *rvu, const char *kpu_profile) +{ + struct npc_kpu_profile_fwdata *kpu_fw = NULL; + 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; + + 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; + } + + /* Cleaning up if KPU profile image from fwdata is not valid. */ + if (rvu->kpu_prfl_addr) { + iounmap(rvu->kpu_prfl_addr); + rvu->kpu_prfl_addr = NULL; + rvu->kpu_fwdata_sz = 0; + rvu->kpu_fwdata = NULL; + } + + return -EINVAL; +} + static void npc_load_kpu_profile(struct rvu *rvu) { struct npc_kpu_profile_adapter *profile = &rvu->kpu; @@ -1398,19 +1450,47 @@ static void npc_load_kpu_profile(struct rvu *rvu) /* First prepare default KPU, then we'll customize top entries. */ npc_prepare_default_kpu(profile); - dev_info(rvu->dev, "Loading KPU profile from firmware: %s\n", - kpu_profile); + /* Order of preceedence for load loading NPC profile (high to low) + * Firmware binary in filesystem. + * Firmware database method. + * Default KPU profile. + */ if (!request_firmware(&fw, kpu_profile, rvu->dev)) { + dev_info(rvu->dev, "Loading KPU profile from firmware: %s\n", + kpu_profile); rvu->kpu_fwdata = kzalloc(fw->size, GFP_KERNEL); if (rvu->kpu_fwdata) { memcpy(rvu->kpu_fwdata, fw->data, fw->size); rvu->kpu_fwdata_sz = fw->size; } release_firmware(fw); + goto program_kpu; } +load_image_fwdb: + /* Loading the KPU profile using firmware database */ + if (npc_load_kpu_profile_fwdb(rvu, kpu_profile)) + goto revert_to_default; + +program_kpu: /* Apply profile customization if firmware was loaded. */ if (!rvu->kpu_fwdata_sz || npc_apply_custom_kpu(rvu, profile)) { + /* If image from firmware filesystem fails to load or invalid + * retry with firmware database method. + */ + if (rvu->kpu_fwdata || rvu->kpu_fwdata_sz) { + /* Loading image from firmware database failed. */ + if (rvu->kpu_prfl_addr) { + iounmap(rvu->kpu_prfl_addr); + rvu->kpu_prfl_addr = NULL; + } else { + kfree(rvu->kpu_fwdata); + } + rvu->kpu_fwdata = NULL; + rvu->kpu_fwdata_sz = 0; + goto load_image_fwdb; + } + dev_warn(rvu->dev, "Can't load KPU profile %s. Using default.\n", kpu_profile); @@ -1765,7 +1845,10 @@ void rvu_npc_freemem(struct rvu *rvu) kfree(pkind->rsrc.bmap); kfree(mcam->counters.bmap); - kfree(rvu->kpu_fwdata); + if (rvu->kpu_prfl_addr) + iounmap(rvu->kpu_prfl_addr); + else + kfree(rvu->kpu_fwdata); mutex_destroy(&mcam->lock); } |