Commit 15f52241 authored by David S. Miller's avatar David S. Miller

Merge branch 'octeontx2-updates'

Naveen Mamindlapalli says:

====================
RVU NIX AF driver updates

This patch series includes a few enhancements and other updates to the
RVU NIX AF driver.

The first patch adds devlink option to configure NPC MCAM high priority
zone entries reservation. This is useful when the requester needs more
high priority entries than default reserved entries.

The second patch adds support for RSS hash computation using L3 SRC or
DST only, or L4 SRC or DST only.

The third patch updates DWRR MTU configuration for CN10KB silicon. HW uses
the DWRR MTU to compute DWRR weight.

Patch 4 configures the LBK link in TL3_TL2 configuration only when switch
mode is enabled.

Patch 5 adds an option in the mailbox request to enable/disable DROP_RE bit
which drops packets with L2 errors when set.

Patch 6 updates SMQ flush mechanism to stop other child nodes from
enqueuing any packets while SMQ flush is active. Otherwise SMQ flush may
timeout.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c29e012e e18aab04
...@@ -145,6 +145,13 @@ enum nix_scheduler { ...@@ -145,6 +145,13 @@ enum nix_scheduler {
#define TXSCH_TL1_DFLT_RR_PRIO (0x7ull) #define TXSCH_TL1_DFLT_RR_PRIO (0x7ull)
#define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */ #define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */
/* Don't change the order as on CN10K (except CN10KB)
* SMQX_CFG[SDP] value should be 1 for SDP flows.
*/
#define SMQ_LINK_TYPE_RPM 0
#define SMQ_LINK_TYPE_SDP 1
#define SMQ_LINK_TYPE_LBK 2
/* Min/Max packet sizes, excluding FCS */ /* Min/Max packet sizes, excluding FCS */
#define NIC_HW_MIN_FRS 40 #define NIC_HW_MIN_FRS 40
#define NIC_HW_MAX_FRS 9212 #define NIC_HW_MAX_FRS 9212
......
...@@ -1080,6 +1080,8 @@ struct nix_vtag_config_rsp { ...@@ -1080,6 +1080,8 @@ struct nix_vtag_config_rsp {
*/ */
}; };
#define NIX_FLOW_KEY_TYPE_L3_L4_MASK (~(0xf << 28))
struct nix_rss_flowkey_cfg { struct nix_rss_flowkey_cfg {
struct mbox_msghdr hdr; struct mbox_msghdr hdr;
int mcam_index; /* MCAM entry index to modify */ int mcam_index; /* MCAM entry index to modify */
...@@ -1105,6 +1107,10 @@ struct nix_rss_flowkey_cfg { ...@@ -1105,6 +1107,10 @@ struct nix_rss_flowkey_cfg {
#define NIX_FLOW_KEY_TYPE_IPV4_PROTO BIT(21) #define NIX_FLOW_KEY_TYPE_IPV4_PROTO BIT(21)
#define NIX_FLOW_KEY_TYPE_AH BIT(22) #define NIX_FLOW_KEY_TYPE_AH BIT(22)
#define NIX_FLOW_KEY_TYPE_ESP BIT(23) #define NIX_FLOW_KEY_TYPE_ESP BIT(23)
#define NIX_FLOW_KEY_TYPE_L4_DST_ONLY BIT(28)
#define NIX_FLOW_KEY_TYPE_L4_SRC_ONLY BIT(29)
#define NIX_FLOW_KEY_TYPE_L3_DST_ONLY BIT(30)
#define NIX_FLOW_KEY_TYPE_L3_SRC_ONLY BIT(31)
u32 flowkey_cfg; /* Flowkey types selected */ u32 flowkey_cfg; /* Flowkey types selected */
u8 group; /* RSS context or group */ u8 group; /* RSS context or group */
}; };
...@@ -1151,6 +1157,7 @@ struct nix_rx_cfg { ...@@ -1151,6 +1157,7 @@ struct nix_rx_cfg {
struct mbox_msghdr hdr; struct mbox_msghdr hdr;
#define NIX_RX_OL3_VERIFY BIT(0) #define NIX_RX_OL3_VERIFY BIT(0)
#define NIX_RX_OL4_VERIFY BIT(1) #define NIX_RX_OL4_VERIFY BIT(1)
#define NIX_RX_DROP_RE BIT(2)
u8 len_verify; /* Outer L3/L4 len check */ u8 len_verify; /* Outer L3/L4 len check */
#define NIX_RX_CSUM_OL4_VERIFY BIT(0) #define NIX_RX_CSUM_OL4_VERIFY BIT(0)
u8 csum_verify; /* Outer L4 checksum verification */ u8 csum_verify; /* Outer L4 checksum verification */
...@@ -1239,7 +1246,9 @@ struct nix_hw_info { ...@@ -1239,7 +1246,9 @@ struct nix_hw_info {
u16 min_mtu; u16 min_mtu;
u32 rpm_dwrr_mtu; u32 rpm_dwrr_mtu;
u32 sdp_dwrr_mtu; u32 sdp_dwrr_mtu;
u64 rsvd[16]; /* Add reserved fields for future expansion */ u32 lbk_dwrr_mtu;
u32 rsvd32[1];
u64 rsvd[15]; /* Add reserved fields for future expansion */
}; };
struct nix_bandprof_alloc_req { struct nix_bandprof_alloc_req {
......
...@@ -285,6 +285,22 @@ struct nix_mark_format { ...@@ -285,6 +285,22 @@ struct nix_mark_format {
u32 *cfg; u32 *cfg;
}; };
/* smq(flush) to tl1 cir/pir info */
struct nix_smq_tree_ctx {
u64 cir_off;
u64 cir_val;
u64 pir_off;
u64 pir_val;
};
/* smq flush context */
struct nix_smq_flush_ctx {
int smq;
u16 tl1_schq;
u16 tl2_schq;
struct nix_smq_tree_ctx smq_tree_ctx[NIX_TXSCH_LVL_CNT];
};
struct npc_pkind { struct npc_pkind {
struct rsrc_bmap rsrc; struct rsrc_bmap rsrc;
u32 *pfchan_map; u32 *pfchan_map;
...@@ -346,6 +362,7 @@ struct hw_cap { ...@@ -346,6 +362,7 @@ struct hw_cap {
bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */ bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */
bool programmable_chans; /* Channels programmable ? */ bool programmable_chans; /* Channels programmable ? */
bool ipolicer; bool ipolicer;
bool nix_multiple_dwrr_mtu; /* Multiple DWRR_MTU to choose from */
bool npc_hash_extract; /* Hash extract enabled ? */ bool npc_hash_extract; /* Hash extract enabled ? */
bool npc_exact_match_enabled; /* Exact match supported ? */ bool npc_exact_match_enabled; /* Exact match supported ? */
}; };
...@@ -802,8 +819,11 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw, ...@@ -802,8 +819,11 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw,
struct nix_cn10k_aq_enq_rsp *aq_rsp, struct nix_cn10k_aq_enq_rsp *aq_rsp,
u16 pcifunc, u8 ctype, u32 qidx); u16 pcifunc, u8 ctype, u32 qidx);
int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc); int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc);
int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type);
u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu); u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu);
u32 convert_bytes_to_dwrr_mtu(u32 bytes); u32 convert_bytes_to_dwrr_mtu(u32 bytes);
void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
struct nix_txsch *txsch, bool enable);
/* NPC APIs */ /* NPC APIs */
void rvu_npc_freemem(struct rvu *rvu); void rvu_npc_freemem(struct rvu *rvu);
......
...@@ -1413,7 +1413,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id, ...@@ -1413,7 +1413,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id,
u64 dwrr_mtu; u64 dwrr_mtu;
dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32); dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32);
rvu_write64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU, dwrr_mtu); rvu_write64(rvu, BLKADDR_NIX0,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), dwrr_mtu);
return 0; return 0;
} }
...@@ -1428,7 +1429,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id, ...@@ -1428,7 +1429,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
if (!rvu->hw->cap.nix_common_dwrr_mtu) if (!rvu->hw->cap.nix_common_dwrr_mtu)
return -EOPNOTSUPP; return -EOPNOTSUPP;
dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));
ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu); ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu);
return 0; return 0;
...@@ -1438,6 +1440,7 @@ enum rvu_af_dl_param_id { ...@@ -1438,6 +1440,7 @@ enum rvu_af_dl_param_id {
RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE, RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
}; };
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id, static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
...@@ -1494,6 +1497,67 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id, ...@@ -1494,6 +1497,67 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
return -EFAULT; return -EFAULT;
} }
static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
struct npc_mcam *mcam;
u32 percent;
mcam = &rvu->hw->mcam;
percent = (mcam->hprio_count * 100) / mcam->bmap_entries;
ctx->val.vu8 = (u8)percent;
return 0;
}
static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
struct npc_mcam *mcam;
u32 percent;
percent = ctx->val.vu8;
mcam = &rvu->hw->mcam;
mcam->hprio_count = (mcam->bmap_entries * percent) / 100;
mcam->hprio_end = mcam->hprio_count;
mcam->lprio_count = (mcam->bmap_entries - mcam->hprio_count) / 2;
mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count;
return 0;
}
static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id,
union devlink_param_value val,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
struct npc_mcam *mcam;
/* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */
if (val.vu8 < 12 || val.vu8 > 100) {
NL_SET_ERR_MSG_MOD(extack,
"mcam high zone percent must be between 12% to 100%");
return -EINVAL;
}
/* Do not allow user to modify the high priority zone entries while mcam entries
* have already been assigned.
*/
mcam = &rvu->hw->mcam;
if (mcam->bmap_fcnt < mcam->bmap_entries) {
NL_SET_ERR_MSG_MOD(extack,
"mcam entries have already been assigned, can't resize");
return -EPERM;
}
return 0;
}
static const struct devlink_param rvu_af_dl_params[] = { static const struct devlink_param rvu_af_dl_params[] = {
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
"dwrr_mtu", DEVLINK_PARAM_TYPE_U32, "dwrr_mtu", DEVLINK_PARAM_TYPE_U32,
...@@ -1509,6 +1573,12 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = { ...@@ -1509,6 +1573,12 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = {
rvu_af_npc_exact_feature_get, rvu_af_npc_exact_feature_get,
rvu_af_npc_exact_feature_disable, rvu_af_npc_exact_feature_disable,
rvu_af_npc_exact_feature_validate), rvu_af_npc_exact_feature_validate),
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
"npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
rvu_af_dl_npc_mcam_high_zone_percent_get,
rvu_af_dl_npc_mcam_high_zone_percent_set,
rvu_af_dl_npc_mcam_high_zone_percent_validate),
}; };
/* Devlink switch mode */ /* Devlink switch mode */
......
...@@ -191,6 +191,18 @@ struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr) ...@@ -191,6 +191,18 @@ struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr)
return NULL; return NULL;
} }
int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type)
{
if (hw->cap.nix_multiple_dwrr_mtu)
return NIX_AF_DWRR_MTUX(smq_link_type);
if (smq_link_type == SMQ_LINK_TYPE_SDP)
return NIX_AF_DWRR_SDP_MTU;
/* Here it's same reg for RPM and LBK */
return NIX_AF_DWRR_RPM_MTU;
}
u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu) u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu)
{ {
dwrr_mtu &= 0x1FULL; dwrr_mtu &= 0x1FULL;
...@@ -2102,9 +2114,121 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu, ...@@ -2102,9 +2114,121 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu,
return rc; return rc;
} }
static void nix_smq_flush_fill_ctx(struct rvu *rvu, int blkaddr, int smq,
struct nix_smq_flush_ctx *smq_flush_ctx)
{
struct nix_smq_tree_ctx *smq_tree_ctx;
u64 parent_off, regval;
u16 schq;
int lvl;
smq_flush_ctx->smq = smq;
schq = smq;
for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) {
smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl];
if (lvl == NIX_TXSCH_LVL_TL1) {
smq_flush_ctx->tl1_schq = schq;
smq_tree_ctx->cir_off = NIX_AF_TL1X_CIR(schq);
smq_tree_ctx->pir_off = 0;
smq_tree_ctx->pir_val = 0;
parent_off = 0;
} else if (lvl == NIX_TXSCH_LVL_TL2) {
smq_flush_ctx->tl2_schq = schq;
smq_tree_ctx->cir_off = NIX_AF_TL2X_CIR(schq);
smq_tree_ctx->pir_off = NIX_AF_TL2X_PIR(schq);
parent_off = NIX_AF_TL2X_PARENT(schq);
} else if (lvl == NIX_TXSCH_LVL_TL3) {
smq_tree_ctx->cir_off = NIX_AF_TL3X_CIR(schq);
smq_tree_ctx->pir_off = NIX_AF_TL3X_PIR(schq);
parent_off = NIX_AF_TL3X_PARENT(schq);
} else if (lvl == NIX_TXSCH_LVL_TL4) {
smq_tree_ctx->cir_off = NIX_AF_TL4X_CIR(schq);
smq_tree_ctx->pir_off = NIX_AF_TL4X_PIR(schq);
parent_off = NIX_AF_TL4X_PARENT(schq);
} else if (lvl == NIX_TXSCH_LVL_MDQ) {
smq_tree_ctx->cir_off = NIX_AF_MDQX_CIR(schq);
smq_tree_ctx->pir_off = NIX_AF_MDQX_PIR(schq);
parent_off = NIX_AF_MDQX_PARENT(schq);
}
/* save cir/pir register values */
smq_tree_ctx->cir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->cir_off);
if (smq_tree_ctx->pir_off)
smq_tree_ctx->pir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->pir_off);
/* get parent txsch node */
if (parent_off) {
regval = rvu_read64(rvu, blkaddr, parent_off);
schq = (regval >> 16) & 0x1FF;
}
}
}
static void nix_smq_flush_enadis_xoff(struct rvu *rvu, int blkaddr,
struct nix_smq_flush_ctx *smq_flush_ctx, bool enable)
{
struct nix_txsch *txsch;
struct nix_hw *nix_hw;
u64 regoff;
int tl2;
nix_hw = get_nix_hw(rvu->hw, blkaddr);
if (!nix_hw)
return;
/* loop through all TL2s with matching PF_FUNC */
txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2];
for (tl2 = 0; tl2 < txsch->schq.max; tl2++) {
/* skip the smq(flush) TL2 */
if (tl2 == smq_flush_ctx->tl2_schq)
continue;
/* skip unused TL2s */
if (TXSCH_MAP_FLAGS(txsch->pfvf_map[tl2]) & NIX_TXSCHQ_FREE)
continue;
/* skip if PF_FUNC doesn't match */
if ((TXSCH_MAP_FUNC(txsch->pfvf_map[tl2]) & ~RVU_PFVF_FUNC_MASK) !=
(TXSCH_MAP_FUNC(txsch->pfvf_map[smq_flush_ctx->tl2_schq] &
~RVU_PFVF_FUNC_MASK)))
continue;
/* enable/disable XOFF */
regoff = NIX_AF_TL2X_SW_XOFF(tl2);
if (enable)
rvu_write64(rvu, blkaddr, regoff, 0x1);
else
rvu_write64(rvu, blkaddr, regoff, 0x0);
}
}
static void nix_smq_flush_enadis_rate(struct rvu *rvu, int blkaddr,
struct nix_smq_flush_ctx *smq_flush_ctx, bool enable)
{
u64 cir_off, pir_off, cir_val, pir_val;
struct nix_smq_tree_ctx *smq_tree_ctx;
int lvl;
for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) {
smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl];
cir_off = smq_tree_ctx->cir_off;
cir_val = smq_tree_ctx->cir_val;
pir_off = smq_tree_ctx->pir_off;
pir_val = smq_tree_ctx->pir_val;
if (enable) {
rvu_write64(rvu, blkaddr, cir_off, cir_val);
if (lvl != NIX_TXSCH_LVL_TL1)
rvu_write64(rvu, blkaddr, pir_off, pir_val);
} else {
rvu_write64(rvu, blkaddr, cir_off, 0x0);
if (lvl != NIX_TXSCH_LVL_TL1)
rvu_write64(rvu, blkaddr, pir_off, 0x0);
}
}
}
static int nix_smq_flush(struct rvu *rvu, int blkaddr, static int nix_smq_flush(struct rvu *rvu, int blkaddr,
int smq, u16 pcifunc, int nixlf) int smq, u16 pcifunc, int nixlf)
{ {
struct nix_smq_flush_ctx *smq_flush_ctx;
int pf = rvu_get_pf(pcifunc); int pf = rvu_get_pf(pcifunc);
u8 cgx_id = 0, lmac_id = 0; u8 cgx_id = 0, lmac_id = 0;
int err, restore_tx_en = 0; int err, restore_tx_en = 0;
...@@ -2124,6 +2248,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, ...@@ -2124,6 +2248,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
lmac_id, true); lmac_id, true);
} }
/* XOFF all TL2s whose parent TL1 matches SMQ tree TL1 */
smq_flush_ctx = kzalloc(sizeof(*smq_flush_ctx), GFP_KERNEL);
if (!smq_flush_ctx)
return -ENOMEM;
nix_smq_flush_fill_ctx(rvu, blkaddr, smq, smq_flush_ctx);
nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, true);
nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, false);
cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq)); cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq));
/* Do SMQ flush and set enqueue xoff */ /* Do SMQ flush and set enqueue xoff */
cfg |= BIT_ULL(50) | BIT_ULL(49); cfg |= BIT_ULL(50) | BIT_ULL(49);
...@@ -2138,8 +2270,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, ...@@ -2138,8 +2270,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,
err = rvu_poll_reg(rvu, blkaddr, err = rvu_poll_reg(rvu, blkaddr,
NIX_AF_SMQX_CFG(smq), BIT_ULL(49), true); NIX_AF_SMQX_CFG(smq), BIT_ULL(49), true);
if (err) if (err)
dev_err(rvu->dev, dev_info(rvu->dev,
"NIXLF%d: SMQ%d flush failed\n", nixlf, smq); "NIXLF%d: SMQ%d flush failed, txlink might be busy\n",
nixlf, smq);
/* clear XOFF on TL2s */
nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, true);
nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, false);
kfree(smq_flush_ctx);
rvu_cgx_enadis_rx_bp(rvu, pf, true); rvu_cgx_enadis_rx_bp(rvu, pf, true);
/* restore cgx tx state */ /* restore cgx tx state */
...@@ -2448,17 +2586,19 @@ static int nix_txschq_cfg_read(struct rvu *rvu, struct nix_hw *nix_hw, ...@@ -2448,17 +2586,19 @@ static int nix_txschq_cfg_read(struct rvu *rvu, struct nix_hw *nix_hw,
return 0; return 0;
} }
static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc,
u16 pcifunc, struct nix_txsch *txsch) struct nix_txsch *txsch, bool enable)
{ {
struct rvu_hwinfo *hw = rvu->hw; struct rvu_hwinfo *hw = rvu->hw;
int lbk_link_start, lbk_links; int lbk_link_start, lbk_links;
u8 pf = rvu_get_pf(pcifunc); u8 pf = rvu_get_pf(pcifunc);
int schq; int schq;
u64 cfg;
if (!is_pf_cgxmapped(rvu, pf)) if (!is_pf_cgxmapped(rvu, pf))
return; return;
cfg = enable ? (BIT_ULL(12) | RVU_SWITCH_LBK_CHAN) : 0;
lbk_link_start = hw->cgx_links; lbk_link_start = hw->cgx_links;
for (schq = 0; schq < txsch->schq.max; schq++) { for (schq = 0; schq < txsch->schq.max; schq++) {
...@@ -2472,8 +2612,7 @@ static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, ...@@ -2472,8 +2612,7 @@ static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr,
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
NIX_AF_TL3_TL2X_LINKX_CFG(schq, NIX_AF_TL3_TL2X_LINKX_CFG(schq,
lbk_link_start + lbk_link_start +
lbk_links), lbk_links), cfg);
BIT_ULL(12) | RVU_SWITCH_LBK_CHAN);
} }
} }
...@@ -2579,8 +2718,6 @@ int rvu_mbox_handler_nix_txschq_cfg(struct rvu *rvu, ...@@ -2579,8 +2718,6 @@ int rvu_mbox_handler_nix_txschq_cfg(struct rvu *rvu,
rvu_write64(rvu, blkaddr, reg, regval); rvu_write64(rvu, blkaddr, reg, regval);
} }
rvu_nix_tx_tl2_cfg(rvu, blkaddr, pcifunc,
&nix_hw->txsch[NIX_TXSCH_LVL_TL2]);
return 0; return 0;
} }
...@@ -3191,10 +3328,16 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) ...@@ -3191,10 +3328,16 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr)
} }
/* Setup a default value of 8192 as DWRR MTU */ /* Setup a default value of 8192 as DWRR MTU */
if (rvu->hw->cap.nix_common_dwrr_mtu) { if (rvu->hw->cap.nix_common_dwrr_mtu ||
rvu_write64(rvu, blkaddr, NIX_AF_DWRR_RPM_MTU, rvu->hw->cap.nix_multiple_dwrr_mtu) {
rvu_write64(rvu, blkaddr,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM),
convert_bytes_to_dwrr_mtu(8192)); convert_bytes_to_dwrr_mtu(8192));
rvu_write64(rvu, blkaddr, NIX_AF_DWRR_SDP_MTU, rvu_write64(rvu, blkaddr,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK),
convert_bytes_to_dwrr_mtu(8192));
rvu_write64(rvu, blkaddr,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP),
convert_bytes_to_dwrr_mtu(8192)); convert_bytes_to_dwrr_mtu(8192));
} }
...@@ -3292,19 +3435,28 @@ int rvu_mbox_handler_nix_get_hw_info(struct rvu *rvu, struct msg_req *req, ...@@ -3292,19 +3435,28 @@ int rvu_mbox_handler_nix_get_hw_info(struct rvu *rvu, struct msg_req *req,
rsp->min_mtu = NIC_HW_MIN_FRS; rsp->min_mtu = NIC_HW_MIN_FRS;
if (!rvu->hw->cap.nix_common_dwrr_mtu) { if (!rvu->hw->cap.nix_common_dwrr_mtu &&
!rvu->hw->cap.nix_multiple_dwrr_mtu) {
/* Return '1' on OTx2 */ /* Return '1' on OTx2 */
rsp->rpm_dwrr_mtu = 1; rsp->rpm_dwrr_mtu = 1;
rsp->sdp_dwrr_mtu = 1; rsp->sdp_dwrr_mtu = 1;
rsp->lbk_dwrr_mtu = 1;
return 0; return 0;
} }
dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); /* Return DWRR_MTU for TLx_SCHEDULE[RR_WEIGHT] config */
dwrr_mtu = rvu_read64(rvu, blkaddr,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM));
rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_SDP_MTU); dwrr_mtu = rvu_read64(rvu, blkaddr,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP));
rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
dwrr_mtu = rvu_read64(rvu, blkaddr,
nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK));
rsp->lbk_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu);
return 0; return 0;
} }
...@@ -3353,6 +3505,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) ...@@ -3353,6 +3505,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
struct nix_rx_flowkey_alg *field; struct nix_rx_flowkey_alg *field;
struct nix_rx_flowkey_alg tmp; struct nix_rx_flowkey_alg tmp;
u32 key_type, valid_key; u32 key_type, valid_key;
u32 l3_l4_src_dst;
int l4_key_offset = 0; int l4_key_offset = 0;
if (!alg) if (!alg)
...@@ -3380,6 +3533,15 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) ...@@ -3380,6 +3533,15 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
* group_member - Enabled when protocol is part of a group. * group_member - Enabled when protocol is part of a group.
*/ */
/* Last 4 bits (31:28) are reserved to specify SRC, DST
* selection for L3, L4 i.e IPV[4,6]_SRC, IPV[4,6]_DST,
* [TCP,UDP,SCTP]_SRC, [TCP,UDP,SCTP]_DST
* 31 => L3_SRC, 30 => L3_DST, 29 => L4_SRC, 28 => L4_DST
*/
l3_l4_src_dst = flow_cfg;
/* Reset these 4 bits, so that these won't be part of key */
flow_cfg &= NIX_FLOW_KEY_TYPE_L3_L4_MASK;
keyoff_marker = 0; max_key_off = 0; group_member = 0; keyoff_marker = 0; max_key_off = 0; group_member = 0;
nr_field = 0; key_off = 0; field_marker = 1; nr_field = 0; key_off = 0; field_marker = 1;
field = &tmp; max_bit_pos = fls(flow_cfg); field = &tmp; max_bit_pos = fls(flow_cfg);
...@@ -3417,6 +3579,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) ...@@ -3417,6 +3579,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
} }
field->hdr_offset = 12; /* SIP offset */ field->hdr_offset = 12; /* SIP offset */
field->bytesm1 = 7; /* SIP + DIP, 8 bytes */ field->bytesm1 = 7; /* SIP + DIP, 8 bytes */
/* Only SIP */
if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY)
field->bytesm1 = 3; /* SIP, 4 bytes */
if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) {
/* Both SIP + DIP */
if (field->bytesm1 == 3) {
field->bytesm1 = 7; /* SIP + DIP, 8B */
} else {
/* Only DIP */
field->hdr_offset = 16; /* DIP off */
field->bytesm1 = 3; /* DIP, 4 bytes */
}
}
field->ltype_mask = 0xF; /* Match only IPv4 */ field->ltype_mask = 0xF; /* Match only IPv4 */
keyoff_marker = false; keyoff_marker = false;
break; break;
...@@ -3430,6 +3608,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) ...@@ -3430,6 +3608,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
} }
field->hdr_offset = 8; /* SIP offset */ field->hdr_offset = 8; /* SIP offset */
field->bytesm1 = 31; /* SIP + DIP, 32 bytes */ field->bytesm1 = 31; /* SIP + DIP, 32 bytes */
/* Only SIP */
if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY)
field->bytesm1 = 15; /* SIP, 16 bytes */
if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) {
/* Both SIP + DIP */
if (field->bytesm1 == 15) {
/* SIP + DIP, 32 bytes */
field->bytesm1 = 31;
} else {
/* Only DIP */
field->hdr_offset = 24; /* DIP off */
field->bytesm1 = 15; /* DIP,16 bytes */
}
}
field->ltype_mask = 0xF; /* Match only IPv6 */ field->ltype_mask = 0xF; /* Match only IPv6 */
break; break;
case NIX_FLOW_KEY_TYPE_TCP: case NIX_FLOW_KEY_TYPE_TCP:
...@@ -3445,6 +3639,21 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) ...@@ -3445,6 +3639,21 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
field->lid = NPC_LID_LH; field->lid = NPC_LID_LH;
field->bytesm1 = 3; /* Sport + Dport, 4 bytes */ field->bytesm1 = 3; /* Sport + Dport, 4 bytes */
if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_SRC_ONLY)
field->bytesm1 = 1; /* SRC, 2 bytes */
if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_DST_ONLY) {
/* Both SRC + DST */
if (field->bytesm1 == 1) {
/* SRC + DST, 4 bytes */
field->bytesm1 = 3;
} else {
/* Only DIP */
field->hdr_offset = 2; /* DST off */
field->bytesm1 = 1; /* DST, 2 bytes */
}
}
/* Enum values for NPC_LID_LD and NPC_LID_LG are same, /* Enum values for NPC_LID_LD and NPC_LID_LG are same,
* so no need to change the ltype_match, just change * so no need to change the ltype_match, just change
* the lid for inner protocols * the lid for inner protocols
...@@ -4113,6 +4322,11 @@ int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req, ...@@ -4113,6 +4322,11 @@ int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req,
else else
cfg &= ~BIT_ULL(40); cfg &= ~BIT_ULL(40);
if (req->len_verify & NIX_RX_DROP_RE)
cfg |= BIT_ULL(32);
else
cfg &= ~BIT_ULL(32);
if (req->csum_verify & BIT(0)) if (req->csum_verify & BIT(0))
cfg |= BIT_ULL(37); cfg |= BIT_ULL(37);
else else
...@@ -4314,8 +4528,11 @@ static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr) ...@@ -4314,8 +4528,11 @@ static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr)
* Check if HW uses a common MTU for all DWRR quantum configs. * Check if HW uses a common MTU for all DWRR quantum configs.
* On OcteonTx2 this register field is '0'. * On OcteonTx2 this register field is '0'.
*/ */
if (((hw_const >> 56) & 0x10) == 0x10) if ((((hw_const >> 56) & 0x10) == 0x10) && !(hw_const & BIT_ULL(61)))
hw->cap.nix_common_dwrr_mtu = true; hw->cap.nix_common_dwrr_mtu = true;
if (hw_const & BIT_ULL(61))
hw->cap.nix_multiple_dwrr_mtu = true;
} }
static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
......
...@@ -272,7 +272,8 @@ ...@@ -272,7 +272,8 @@
#define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3) #define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3)
#define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16) #define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16)
#define NIX_AF_SQM_DBG_CTL_STATUS (0x750) #define NIX_AF_SQM_DBG_CTL_STATUS (0x750)
#define NIX_AF_DWRR_SDP_MTU (0x790) #define NIX_AF_DWRR_SDP_MTU (0x790) /* All CN10K except CN10KB */
#define NIX_AF_DWRR_MTUX(a) (0x790 | (a) << 16) /* Only for CN10KB */
#define NIX_AF_DWRR_RPM_MTU (0x7A0) #define NIX_AF_DWRR_RPM_MTU (0x7A0)
#define NIX_AF_PSE_CHANNEL_LEVEL (0x800) #define NIX_AF_PSE_CHANNEL_LEVEL (0x800)
#define NIX_AF_PSE_SHAPER_CFG (0x810) #define NIX_AF_PSE_SHAPER_CFG (0x810)
......
...@@ -8,6 +8,17 @@ ...@@ -8,6 +8,17 @@
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include "rvu.h" #include "rvu.h"
static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct nix_hw *nix_hw;
nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr);
/* Enable LBK links with channel 63 for TX MCAM rule */
rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc,
&nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable);
}
static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc, static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
u16 chan_mask) u16 chan_mask)
{ {
...@@ -52,6 +63,8 @@ static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry) ...@@ -52,6 +63,8 @@ static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags)) if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
return 0; return 0;
rvu_switch_enable_lbk_link(rvu, pcifunc, true);
lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1; lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
ether_addr_copy(req.packet.dmac, pfvf->mac_addr); ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
eth_broadcast_addr((u8 *)&req.mask.dmac); eth_broadcast_addr((u8 *)&req.mask.dmac);
...@@ -218,6 +231,9 @@ void rvu_switch_disable(struct rvu *rvu) ...@@ -218,6 +231,9 @@ void rvu_switch_disable(struct rvu *rvu)
"Reverting RX rule for PF%d failed(%d)\n", "Reverting RX rule for PF%d failed(%d)\n",
pf, err); pf, err);
/* Disable LBK link */
rvu_switch_enable_lbk_link(rvu, pcifunc, false);
rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
for (vf = 0; vf < numvfs; vf++) { for (vf = 0; vf < numvfs; vf++) {
pcifunc = pf << 10 | ((vf + 1) & 0x3FF); pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
...@@ -226,6 +242,8 @@ void rvu_switch_disable(struct rvu *rvu) ...@@ -226,6 +242,8 @@ void rvu_switch_disable(struct rvu *rvu)
dev_err(rvu->dev, dev_err(rvu->dev,
"Reverting RX rule for PF%dVF%d failed(%d)\n", "Reverting RX rule for PF%dVF%d failed(%d)\n",
pf, vf, err); pf, vf, err);
rvu_switch_enable_lbk_link(rvu, pcifunc, false);
} }
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <net/tso.h> #include <net/tso.h>
#include <linux/bitfield.h>
#include "otx2_reg.h" #include "otx2_reg.h"
#include "otx2_common.h" #include "otx2_common.h"
...@@ -642,6 +643,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for ...@@ -642,6 +643,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for
req->regval[0] = ((u64)pfvf->tx_max_pktlen << 8) | OTX2_MIN_MTU; req->regval[0] = ((u64)pfvf->tx_max_pktlen << 8) | OTX2_MIN_MTU;
req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) | req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) |
(0x2ULL << 36); (0x2ULL << 36);
/* Set link type for DWRR MTU selection on CN10K silicons */
if (!is_dev_otx2(pfvf->pdev))
req->regval[0] |= FIELD_PREP(GENMASK_ULL(58, 57),
(u64)hw->smq_link_type);
req->num_regs++; req->num_regs++;
/* MDQ config */ /* MDQ config */
parent = schq_list[NIX_TXSCH_LVL_TL4][prio]; parent = schq_list[NIX_TXSCH_LVL_TL4][prio];
...@@ -1824,6 +1829,17 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf) ...@@ -1824,6 +1829,17 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf)
} }
} }
static u32 get_dwrr_mtu(struct otx2_nic *pfvf, struct nix_hw_info *hw)
{
if (is_otx2_lbkvf(pfvf->pdev)) {
pfvf->hw.smq_link_type = SMQ_LINK_TYPE_LBK;
return hw->lbk_dwrr_mtu;
}
pfvf->hw.smq_link_type = SMQ_LINK_TYPE_RPM;
return hw->rpm_dwrr_mtu;
}
u16 otx2_get_max_mtu(struct otx2_nic *pfvf) u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
{ {
struct nix_hw_info *rsp; struct nix_hw_info *rsp;
...@@ -1853,7 +1869,7 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf) ...@@ -1853,7 +1869,7 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN; max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN;
/* Also save DWRR MTU, needed for DWRR weight calculation */ /* Also save DWRR MTU, needed for DWRR weight calculation */
pfvf->hw.dwrr_mtu = rsp->rpm_dwrr_mtu; pfvf->hw.dwrr_mtu = get_dwrr_mtu(pfvf, rsp);
if (!pfvf->hw.dwrr_mtu) if (!pfvf->hw.dwrr_mtu)
pfvf->hw.dwrr_mtu = 1; pfvf->hw.dwrr_mtu = 1;
} }
......
...@@ -227,6 +227,7 @@ struct otx2_hw { ...@@ -227,6 +227,7 @@ struct otx2_hw {
u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
u16 matchall_ipolicer; u16 matchall_ipolicer;
u32 dwrr_mtu; u32 dwrr_mtu;
u8 smq_link_type;
/* HW settings, coalescing etc */ /* HW settings, coalescing etc */
u16 rx_chan_base; u16 rx_chan_base;
......
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