Commit d3f2c48d authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'npc-kpu-updates'

George Cherian says:

====================
NPC KPU updates

Add support for
 - Loading Custom KPU profile entries
 - Add NPC profile Load from System Firmware DB
 - Add Support fo Coalescing KPU profiles
 - General Updates/Fixes to default KPU profile
====================

Link: https://lore.kernel.org/r/20210527094439.1910013-1-george.cherian@marvell.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 015dbf56 f9c49be9
...@@ -33,6 +33,10 @@ enum npc_kpu_la_ltype { ...@@ -33,6 +33,10 @@ enum npc_kpu_la_ltype {
NPC_LT_LA_IH_2_ETHER, NPC_LT_LA_IH_2_ETHER,
NPC_LT_LA_HIGIG2_ETHER, NPC_LT_LA_HIGIG2_ETHER,
NPC_LT_LA_IH_NIX_HIGIG2_ETHER, NPC_LT_LA_IH_NIX_HIGIG2_ETHER,
NPC_LT_LA_CUSTOM_L2_90B_ETHER,
NPC_LT_LA_CH_LEN_90B_ETHER,
NPC_LT_LA_CPT_HDR,
NPC_LT_LA_CUSTOM_L2_24B_ETHER,
NPC_LT_LA_CUSTOM0 = 0xE, NPC_LT_LA_CUSTOM0 = 0xE,
NPC_LT_LA_CUSTOM1 = 0xF, NPC_LT_LA_CUSTOM1 = 0xF,
}; };
...@@ -42,7 +46,7 @@ enum npc_kpu_lb_ltype { ...@@ -42,7 +46,7 @@ enum npc_kpu_lb_ltype {
NPC_LT_LB_CTAG, NPC_LT_LB_CTAG,
NPC_LT_LB_STAG_QINQ, NPC_LT_LB_STAG_QINQ,
NPC_LT_LB_BTAG, NPC_LT_LB_BTAG,
NPC_LT_LB_ITAG, NPC_LT_LB_PPPOE,
NPC_LT_LB_DSA, NPC_LT_LB_DSA,
NPC_LT_LB_DSA_VLAN, NPC_LT_LB_DSA_VLAN,
NPC_LT_LB_EDSA, NPC_LT_LB_EDSA,
...@@ -50,6 +54,7 @@ enum npc_kpu_lb_ltype { ...@@ -50,6 +54,7 @@ enum npc_kpu_lb_ltype {
NPC_LT_LB_EXDSA, NPC_LT_LB_EXDSA,
NPC_LT_LB_EXDSA_VLAN, NPC_LT_LB_EXDSA_VLAN,
NPC_LT_LB_FDSA, NPC_LT_LB_FDSA,
NPC_LT_LB_VLAN_EXDSA,
NPC_LT_LB_CUSTOM0 = 0xE, NPC_LT_LB_CUSTOM0 = 0xE,
NPC_LT_LB_CUSTOM1 = 0xF, NPC_LT_LB_CUSTOM1 = 0xF,
}; };
...@@ -65,6 +70,7 @@ enum npc_kpu_lc_ltype { ...@@ -65,6 +70,7 @@ enum npc_kpu_lc_ltype {
NPC_LT_LC_NSH, NPC_LT_LC_NSH,
NPC_LT_LC_PTP, NPC_LT_LC_PTP,
NPC_LT_LC_FCOE, NPC_LT_LC_FCOE,
NPC_LT_LC_NGIO,
NPC_LT_LC_CUSTOM0 = 0xE, NPC_LT_LC_CUSTOM0 = 0xE,
NPC_LT_LC_CUSTOM1 = 0xF, NPC_LT_LC_CUSTOM1 = 0xF,
}; };
...@@ -146,7 +152,14 @@ enum npc_kpu_lh_ltype { ...@@ -146,7 +152,14 @@ enum npc_kpu_lh_ltype {
* Ethernet interfaces, LBK interfaces, etc. * Ethernet interfaces, LBK interfaces, etc.
*/ */
enum npc_pkind_type { enum npc_pkind_type {
NPC_TX_DEF_PKIND = 63ULL, /* NIX-TX PKIND */ NPC_RX_VLAN_EXDSA_PKIND = 56ULL,
NPC_RX_CHLEN24B_PKIND = 57ULL,
NPC_RX_CPT_HDR_PKIND,
NPC_RX_CHLEN90B_PKIND,
NPC_TX_HIGIG_PKIND,
NPC_RX_HIGIG_PKIND,
NPC_RX_EDSA_PKIND,
NPC_TX_DEF_PKIND, /* NIX-TX PKIND */
}; };
/* list of known and supported fields in packet header and /* list of known and supported fields in packet header and
...@@ -213,7 +226,7 @@ struct npc_kpu_profile_cam { ...@@ -213,7 +226,7 @@ struct npc_kpu_profile_cam {
u16 dp1_mask; u16 dp1_mask;
u16 dp2; u16 dp2;
u16 dp2_mask; u16 dp2_mask;
}; } __packed;
struct npc_kpu_profile_action { struct npc_kpu_profile_action {
u8 errlev; u8 errlev;
...@@ -233,13 +246,13 @@ struct npc_kpu_profile_action { ...@@ -233,13 +246,13 @@ struct npc_kpu_profile_action {
u8 mask; u8 mask;
u8 right; u8 right;
u8 shift; u8 shift;
}; } __packed;
struct npc_kpu_profile { struct npc_kpu_profile {
int cam_entries; int cam_entries;
int action_entries; int action_entries;
const struct npc_kpu_profile_cam *cam; struct npc_kpu_profile_cam *cam;
const struct npc_kpu_profile_action *action; struct npc_kpu_profile_action *action;
}; };
/* NPC KPU register formats */ /* NPC KPU register formats */
...@@ -427,6 +440,17 @@ struct nix_tx_action { ...@@ -427,6 +440,17 @@ struct nix_tx_action {
#define NIXLF_BCAST_ENTRY 1 #define NIXLF_BCAST_ENTRY 1
#define NIXLF_PROMISC_ENTRY 2 #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 { struct npc_mcam_kex {
/* MKEX Profle Header */ /* MKEX Profle Header */
u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */ u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */
...@@ -445,6 +469,15 @@ struct npc_mcam_kex { ...@@ -445,6 +469,15 @@ struct npc_mcam_kex {
u64 intf_ld_flags[NPC_MAX_INTF][NPC_MAX_LD][NPC_MAX_LFL]; u64 intf_ld_flags[NPC_MAX_INTF][NPC_MAX_LD][NPC_MAX_LFL];
} __packed; } __packed;
struct npc_kpu_fwdata {
int entries;
/* What follows is:
* struct npc_kpu_profile_cam[entries];
* struct npc_kpu_profile_action[entries];
*/
u8 data[0];
} __packed;
struct npc_lt_def { struct npc_lt_def {
u8 ltype_mask; u8 ltype_mask;
u8 ltype_match; u8 ltype_match;
...@@ -459,6 +492,29 @@ struct npc_lt_def_ipsec { ...@@ -459,6 +492,29 @@ struct npc_lt_def_ipsec {
u8 spi_nz; u8 spi_nz;
}; };
struct npc_lt_def_apad {
u8 ltype_mask;
u8 ltype_match;
u8 lid;
u8 valid;
} __packed;
struct npc_lt_def_color {
u8 ltype_mask;
u8 ltype_match;
u8 lid;
u8 noffset;
u8 offset;
} __packed;
struct npc_lt_def_et {
u8 ltype_mask;
u8 ltype_match;
u8 lid;
u8 valid;
u8 offset;
} __packed;
struct npc_lt_def_cfg { struct npc_lt_def_cfg {
struct npc_lt_def rx_ol2; struct npc_lt_def rx_ol2;
struct npc_lt_def rx_oip4; struct npc_lt_def rx_oip4;
...@@ -476,7 +532,41 @@ struct npc_lt_def_cfg { ...@@ -476,7 +532,41 @@ struct npc_lt_def_cfg {
struct npc_lt_def pck_oip4; struct npc_lt_def pck_oip4;
struct npc_lt_def pck_oip6; struct npc_lt_def pck_oip6;
struct npc_lt_def pck_iip4; struct npc_lt_def pck_iip4;
}; struct npc_lt_def_apad rx_apad0;
struct npc_lt_def_apad rx_apad1;
struct npc_lt_def_color ovlan;
struct npc_lt_def_color ivlan;
struct npc_lt_def_color rx_gen0_color;
struct npc_lt_def_color rx_gen1_color;
struct npc_lt_def_et rx_et[2];
} __packed;
/* Loadable KPU profile firmware data */
struct npc_kpu_profile_fwdata {
#define KPU_SIGN 0x00666f727075706b
#define KPU_NAME_LEN 32
/** Maximum number of custom KPU entries supported by the built-in profile. */
#define KPU_MAX_CST_ENT 2
/* KPU Profle Header */
__le64 signature; /* "kpuprof\0" (8 bytes/ASCII characters) */
u8 name[KPU_NAME_LEN]; /* KPU Profile name */
__le64 version; /* KPU profile version */
u8 kpus;
u8 reserved[7];
/* Default MKEX profile to be used with this KPU profile. May be
* overridden with mkex_profile module parameter. Format is same as for
* the MKEX profile to streamline processing.
*/
struct npc_mcam_kex mkex;
/* LTYPE values for specific HW offloaded protocols. */
struct npc_lt_def_cfg lt_def;
/* Dynamically sized data:
* Custom KPU CAM and ACTION configuration entries.
* struct npc_kpu_fwdata kpu[kpus];
*/
u8 data[0];
} __packed;
struct rvu_npc_mcam_rule { struct rvu_npc_mcam_rule {
struct flow_msg packet; struct flow_msg packet;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -57,6 +57,10 @@ static char *mkex_profile; /* MKEX profile name */ ...@@ -57,6 +57,10 @@ static char *mkex_profile; /* MKEX profile name */
module_param(mkex_profile, charp, 0000); module_param(mkex_profile, charp, 0000);
MODULE_PARM_DESC(mkex_profile, "MKEX profile name string"); MODULE_PARM_DESC(mkex_profile, "MKEX profile name string");
static char *kpu_profile; /* KPU profile name */
module_param(kpu_profile, charp, 0000);
MODULE_PARM_DESC(kpu_profile, "KPU profile name string");
static void rvu_setup_hw_capabilities(struct rvu *rvu) static void rvu_setup_hw_capabilities(struct rvu *rvu)
{ {
struct rvu_hwinfo *hw = rvu->hw; struct rvu_hwinfo *hw = rvu->hw;
...@@ -2842,6 +2846,8 @@ static void rvu_update_module_params(struct rvu *rvu) ...@@ -2842,6 +2846,8 @@ static void rvu_update_module_params(struct rvu *rvu)
strscpy(rvu->mkex_pfl_name, strscpy(rvu->mkex_pfl_name,
mkex_profile ? mkex_profile : default_pfl_name, MKEX_NAME_LEN); mkex_profile ? mkex_profile : default_pfl_name, MKEX_NAME_LEN);
strscpy(rvu->kpu_pfl_name,
kpu_profile ? kpu_profile : default_pfl_name, KPU_NAME_LEN);
} }
static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
......
...@@ -386,6 +386,7 @@ struct npc_kpu_profile_adapter { ...@@ -386,6 +386,7 @@ struct npc_kpu_profile_adapter {
const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */ const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */
const struct npc_kpu_profile *kpu; /* array[kpus] */ const struct npc_kpu_profile *kpu; /* array[kpus] */
struct npc_mcam_kex *mkex; struct npc_mcam_kex *mkex;
bool custom;
size_t pkinds; size_t pkinds;
size_t kpus; size_t kpus;
}; };
...@@ -435,9 +436,13 @@ struct rvu { ...@@ -435,9 +436,13 @@ struct rvu {
struct mutex cgx_cfg_lock; /* serialize cgx configuration */ struct mutex cgx_cfg_lock; /* serialize cgx configuration */
char mkex_pfl_name[MKEX_NAME_LEN]; /* Configured MKEX profile name */ char mkex_pfl_name[MKEX_NAME_LEN]; /* Configured MKEX profile name */
char kpu_pfl_name[KPU_NAME_LEN]; /* Configured KPU profile name */
/* Firmware data */ /* Firmware data */
struct rvu_fwdata *fwdata; struct rvu_fwdata *fwdata;
void *kpu_fwdata;
size_t kpu_fwdata_sz;
void __iomem *kpu_prfl_addr;
/* NPC KPU data */ /* NPC KPU data */
struct npc_kpu_profile_adapter kpu; struct npc_kpu_profile_adapter kpu;
......
...@@ -3523,6 +3523,40 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) ...@@ -3523,6 +3523,40 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
(ltdefs->rx_isctp.lid << 8) | (ltdefs->rx_isctp.ltype_match << 4) | (ltdefs->rx_isctp.lid << 8) | (ltdefs->rx_isctp.ltype_match << 4) |
ltdefs->rx_isctp.ltype_mask); ltdefs->rx_isctp.ltype_mask);
if (!is_rvu_otx2(rvu)) {
/* Enable APAD calculation for other protocols
* matching APAD0 and APAD1 lt def registers.
*/
rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_CST_APAD0,
(ltdefs->rx_apad0.valid << 11) |
(ltdefs->rx_apad0.lid << 8) |
(ltdefs->rx_apad0.ltype_match << 4) |
ltdefs->rx_apad0.ltype_mask);
rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_CST_APAD1,
(ltdefs->rx_apad1.valid << 11) |
(ltdefs->rx_apad1.lid << 8) |
(ltdefs->rx_apad1.ltype_match << 4) |
ltdefs->rx_apad1.ltype_mask);
/* Receive ethertype defination register defines layer
* information in NPC_RESULT_S to identify the Ethertype
* location in L2 header. Used for Ethertype overwriting
* in inline IPsec flow.
*/
rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_ET(0),
(ltdefs->rx_et[0].offset << 12) |
(ltdefs->rx_et[0].valid << 11) |
(ltdefs->rx_et[0].lid << 8) |
(ltdefs->rx_et[0].ltype_match << 4) |
ltdefs->rx_et[0].ltype_mask);
rvu_write64(rvu, blkaddr, NIX_AF_RX_DEF_ET(1),
(ltdefs->rx_et[1].offset << 12) |
(ltdefs->rx_et[1].valid << 11) |
(ltdefs->rx_et[1].lid << 8) |
(ltdefs->rx_et[1].ltype_match << 4) |
ltdefs->rx_et[1].ltype_mask);
}
err = nix_rx_flowkey_alg_cfg(rvu, blkaddr); err = nix_rx_flowkey_alg_cfg(rvu, blkaddr);
if (err) if (err)
return err; return err;
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#define NPC_KEX_CHAN_MASK 0xFFFULL #define NPC_KEX_CHAN_MASK 0xFFFULL
#define NPC_KEX_PF_FUNC_MASK 0xFFFFULL #define NPC_KEX_PF_FUNC_MASK 0xFFFFULL
#define ALIGN_8B_CEIL(__a) (((__a) + 7) & (-8))
static const char def_pfl_name[] = "default"; static const char def_pfl_name[] = "default";
static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam, static void npc_mcam_free_all_entries(struct rvu *rvu, struct npc_mcam *mcam,
...@@ -1134,6 +1136,30 @@ static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr, ...@@ -1134,6 +1136,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 #define MKEX_END_SIGN 0xdeadbeef
static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr, static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr,
...@@ -1141,26 +1167,21 @@ static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr, ...@@ -1141,26 +1167,21 @@ static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr,
{ {
struct device *dev = &rvu->pdev->dev; struct device *dev = &rvu->pdev->dev;
struct npc_mcam_kex *mcam_kex; struct npc_mcam_kex *mcam_kex;
void *mkex_prfl_addr = NULL; void __iomem *mkex_prfl_addr = NULL;
u64 prfl_addr, prfl_sz; u64 prfl_sz;
int ret;
/* If user not selected mkex profile */ /* If user not selected mkex profile */
if (!strncmp(mkex_profile, def_pfl_name, MKEX_NAME_LEN)) if (rvu->kpu_fwdata_sz ||
!strncmp(mkex_profile, def_pfl_name, MKEX_NAME_LEN))
goto program_mkex; goto program_mkex;
if (!rvu->fwdata) /* 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; goto program_mkex;
prfl_addr = rvu->fwdata->mcam_addr;
prfl_sz = rvu->fwdata->mcam_sz;
if (!prfl_addr || !prfl_sz) mcam_kex = (struct npc_mcam_kex __force *)mkex_prfl_addr;
goto program_mkex;
mkex_prfl_addr = memremap(prfl_addr, prfl_sz, MEMREMAP_WC);
if (!mkex_prfl_addr)
goto program_mkex;
mcam_kex = (struct npc_mcam_kex *)mkex_prfl_addr;
while (((s64)prfl_sz > 0) && (mcam_kex->mkex_sign != MKEX_END_SIGN)) { while (((s64)prfl_sz > 0) && (mcam_kex->mkex_sign != MKEX_END_SIGN)) {
/* Compare with mkex mod_param name string */ /* Compare with mkex mod_param name string */
...@@ -1186,7 +1207,7 @@ static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr, ...@@ -1186,7 +1207,7 @@ static void npc_load_mkex_profile(struct rvu *rvu, int blkaddr,
/* Program selected mkex profile */ /* Program selected mkex profile */
npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mkex); npc_program_mkex_profile(rvu, blkaddr, rvu->kpu.mkex);
if (mkex_prfl_addr) if (mkex_prfl_addr)
memunmap(mkex_prfl_addr); iounmap(mkex_prfl_addr);
} }
static void npc_config_kpuaction(struct rvu *rvu, int blkaddr, static void npc_config_kpuaction(struct rvu *rvu, int blkaddr,
...@@ -1263,6 +1284,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu, ...@@ -1263,6 +1284,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
const struct npc_kpu_profile *profile) const struct npc_kpu_profile *profile)
{ {
int entry, num_entries, max_entries; int entry, num_entries, max_entries;
u64 entry_mask;
if (profile->cam_entries != profile->action_entries) { if (profile->cam_entries != profile->action_entries) {
dev_err(rvu->dev, dev_err(rvu->dev,
...@@ -1286,8 +1308,12 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu, ...@@ -1286,8 +1308,12 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
/* Enable all programmed entries */ /* Enable all programmed entries */
num_entries = min_t(int, profile->action_entries, profile->cam_entries); num_entries = min_t(int, profile->action_entries, profile->cam_entries);
entry_mask = enable_mask(num_entries);
/* Disable first KPU_MAX_CST_ENT entries for built-in profile */
if (!rvu->kpu.custom)
entry_mask |= GENMASK_ULL(KPU_MAX_CST_ENT - 1, 0);
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
NPC_AF_KPUX_ENTRY_DISX(kpu, 0), enable_mask(num_entries)); NPC_AF_KPUX_ENTRY_DISX(kpu, 0), entry_mask);
if (num_entries > 64) { if (num_entries > 64) {
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
NPC_AF_KPUX_ENTRY_DISX(kpu, 1), NPC_AF_KPUX_ENTRY_DISX(kpu, 1),
...@@ -1300,6 +1326,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu, ...@@ -1300,6 +1326,7 @@ static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile) static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile)
{ {
profile->custom = 0;
profile->name = def_pfl_name; profile->name = def_pfl_name;
profile->version = NPC_KPU_PROFILE_VER; profile->version = NPC_KPU_PROFILE_VER;
profile->ikpu = ikpu_action_entries; profile->ikpu = ikpu_action_entries;
...@@ -1312,10 +1339,245 @@ static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile) ...@@ -1312,10 +1339,245 @@ static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile)
return 0; return 0;
} }
static int npc_apply_custom_kpu(struct rvu *rvu,
struct npc_kpu_profile_adapter *profile)
{
size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0;
struct npc_kpu_profile_fwdata *fw = rvu->kpu_fwdata;
struct npc_kpu_profile_action *action;
struct npc_kpu_profile_cam *cam;
struct npc_kpu_fwdata *fw_kpu;
int entries;
u16 kpu, entry;
if (rvu->kpu_fwdata_sz < hdr_sz) {
dev_warn(rvu->dev, "Invalid KPU profile size\n");
return -EINVAL;
}
if (le64_to_cpu(fw->signature) != KPU_SIGN) {
dev_warn(rvu->dev, "Invalid KPU profile signature %llx\n",
fw->signature);
return -EINVAL;
}
/* Verify if the using known profile structure */
if (NPC_KPU_VER_MAJ(profile->version) >
NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER)) {
dev_warn(rvu->dev, "Not supported Major version: %d > %d\n",
NPC_KPU_VER_MAJ(profile->version),
NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER));
return -EINVAL;
}
/* Verify if profile is aligned with the required kernel changes */
if (NPC_KPU_VER_MIN(profile->version) <
NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER)) {
dev_warn(rvu->dev,
"Invalid KPU profile version: %d.%d.%d expected vesion <= %d.%d.%d\n",
NPC_KPU_VER_MAJ(profile->version),
NPC_KPU_VER_MIN(profile->version),
NPC_KPU_VER_PATCH(profile->version),
NPC_KPU_VER_MAJ(NPC_KPU_PROFILE_VER),
NPC_KPU_VER_MIN(NPC_KPU_PROFILE_VER),
NPC_KPU_VER_PATCH(NPC_KPU_PROFILE_VER));
return -EINVAL;
}
/* Verify if profile fits the HW */
if (fw->kpus > profile->kpus) {
dev_warn(rvu->dev, "Not enough KPUs: %d > %ld\n", fw->kpus,
profile->kpus);
return -EINVAL;
}
profile->custom = 1;
profile->name = fw->name;
profile->version = le64_to_cpu(fw->version);
profile->mkex = &fw->mkex;
profile->lt_def = &fw->lt_def;
for (kpu = 0; kpu < fw->kpus; kpu++) {
fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
if (fw_kpu->entries > KPU_MAX_CST_ENT)
dev_warn(rvu->dev,
"Too many custom entries on KPU%d: %d > %d\n",
kpu, fw_kpu->entries, KPU_MAX_CST_ENT);
entries = min(fw_kpu->entries, KPU_MAX_CST_ENT);
cam = (struct npc_kpu_profile_cam *)fw_kpu->data;
offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam);
action = (struct npc_kpu_profile_action *)(fw->data + offset);
offset += fw_kpu->entries * sizeof(*action);
if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
dev_warn(rvu->dev,
"Profile size mismatch on KPU%i parsing.\n",
kpu + 1);
return -EINVAL;
}
for (entry = 0; entry < entries; entry++) {
profile->kpu[kpu].cam[entry] = cam[entry];
profile->kpu[kpu].action[entry] = action[entry];
}
}
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)
{
int ret = -EINVAL;
u64 prfl_sz;
/* Setting up the mapping for NPC profile image */
ret = npc_fwdb_prfl_img_map(rvu, &rvu->kpu_prfl_addr, &prfl_sz);
if (ret < 0)
goto done;
/* 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) {
iounmap(rvu->kpu_prfl_addr);
rvu->kpu_prfl_addr = NULL;
rvu->kpu_fwdata_sz = 0;
rvu->kpu_fwdata = NULL;
}
done:
return ret;
}
static void npc_load_kpu_profile(struct rvu *rvu) static void npc_load_kpu_profile(struct rvu *rvu)
{ {
struct npc_kpu_profile_adapter *profile = &rvu->kpu; struct npc_kpu_profile_adapter *profile = &rvu->kpu;
const char *kpu_profile = rvu->kpu_pfl_name;
const struct firmware *fw = NULL;
bool retry_fwdb = false;
/* If user not specified profile customization */
if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN))
goto revert_to_default;
/* First prepare default KPU, then we'll customize top entries. */
npc_prepare_default_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);
retry_fwdb = true;
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;
if (retry_fwdb) {
retry_fwdb = false;
goto load_image_fwdb;
}
}
dev_warn(rvu->dev,
"Can't load KPU profile %s. Using default.\n",
kpu_profile);
kfree(rvu->kpu_fwdata);
rvu->kpu_fwdata = NULL;
goto revert_to_default;
}
dev_info(rvu->dev, "Using custom profile '%s', version %d.%d.%d\n",
profile->name, NPC_KPU_VER_MAJ(profile->version),
NPC_KPU_VER_MIN(profile->version),
NPC_KPU_VER_PATCH(profile->version));
return;
revert_to_default:
npc_prepare_default_kpu(profile); npc_prepare_default_kpu(profile);
} }
...@@ -1654,6 +1916,10 @@ void rvu_npc_freemem(struct rvu *rvu) ...@@ -1654,6 +1916,10 @@ void rvu_npc_freemem(struct rvu *rvu)
kfree(pkind->rsrc.bmap); kfree(pkind->rsrc.bmap);
kfree(mcam->counters.bmap); kfree(mcam->counters.bmap);
if (rvu->kpu_prfl_addr)
iounmap(rvu->kpu_prfl_addr);
else
kfree(rvu->kpu_fwdata);
mutex_destroy(&mcam->lock); mutex_destroy(&mcam->lock);
} }
......
...@@ -208,7 +208,7 @@ ...@@ -208,7 +208,7 @@
#define NIX_AF_RVU_INT_ENA_W1S (0x01D0) #define NIX_AF_RVU_INT_ENA_W1S (0x01D0)
#define NIX_AF_RVU_INT_ENA_W1C (0x01D8) #define NIX_AF_RVU_INT_ENA_W1C (0x01D8)
#define NIX_AF_TCP_TIMER (0x01E0) #define NIX_AF_TCP_TIMER (0x01E0)
#define NIX_AF_RX_WQE_TAG_CTL (0x01F0) #define NIX_AF_RX_DEF_ET(a) (0x01F0ull | (uint64_t)(a) << 3)
#define NIX_AF_RX_DEF_OL2 (0x0200) #define NIX_AF_RX_DEF_OL2 (0x0200)
#define NIX_AF_RX_DEF_OIP4 (0x0210) #define NIX_AF_RX_DEF_OIP4 (0x0210)
#define NIX_AF_RX_DEF_IIP4 (0x0220) #define NIX_AF_RX_DEF_IIP4 (0x0220)
...@@ -219,8 +219,10 @@ ...@@ -219,8 +219,10 @@
#define NIX_AF_RX_DEF_OUDP (0x0270) #define NIX_AF_RX_DEF_OUDP (0x0270)
#define NIX_AF_RX_DEF_IUDP (0x0280) #define NIX_AF_RX_DEF_IUDP (0x0280)
#define NIX_AF_RX_DEF_OSCTP (0x0290) #define NIX_AF_RX_DEF_OSCTP (0x0290)
#define NIX_AF_RX_DEF_CST_APAD0 (0x0298)
#define NIX_AF_RX_DEF_ISCTP (0x02A0) #define NIX_AF_RX_DEF_ISCTP (0x02A0)
#define NIX_AF_RX_DEF_IPSECX (0x02B0) #define NIX_AF_RX_DEF_IPSECX (0x02B0)
#define NIX_AF_RX_DEF_CST_APAD1 (0x02A8)
#define NIX_AF_RX_IPSEC_GEN_CFG (0x0300) #define NIX_AF_RX_IPSEC_GEN_CFG (0x0300)
#define NIX_AF_RX_CPTX_INST_ADDR (0x0310) #define NIX_AF_RX_CPTX_INST_ADDR (0x0310)
#define NIX_AF_NDC_TX_SYNC (0x03F0) #define NIX_AF_NDC_TX_SYNC (0x03F0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment