Commit f1656942 authored by David S. Miller's avatar David S. Miller

Merge branch 'octeontx2-refactor'

Naveen Mamindlapalli says:

====================
refactor code related to npc install flow

This patchset refactors and cleans up the code associated with the
npc install flow API, specifically to eliminate different code paths
while installing MCAM rules by AF and PF. This makes the code easier
to understand and maintain. Also added support for multi channel NIX
promisc entry.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 930a3a62 058fa3d9
......@@ -605,6 +605,7 @@ enum nix_af_status {
NIX_AF_INVAL_SSO_PF_FUNC = -420,
NIX_AF_ERR_TX_VTAG_NOSPC = -421,
NIX_AF_ERR_RX_VTAG_INUSE = -422,
NIX_AF_ERR_NPC_KEY_NOT_SUPP = -423,
};
/* For NIX RX vtag action */
......@@ -1141,6 +1142,7 @@ struct npc_install_flow_req {
u64 features;
u16 entry;
u16 channel;
u16 chan_mask;
u8 intf;
u8 set_cntr; /* If counter is available set counter for this entry ? */
u8 default_rule;
......
......@@ -420,6 +420,11 @@ struct nix_tx_action {
#define TX_VTAG1_LID_MASK GENMASK_ULL(42, 40)
#define TX_VTAG1_RELPTR_MASK GENMASK_ULL(39, 32)
/* NPC MCAM reserved entry index per nixlf */
#define NIXLF_UCAST_ENTRY 0
#define NIXLF_BCAST_ENTRY 1
#define NIXLF_PROMISC_ENTRY 2
struct npc_mcam_kex {
/* MKEX Profle Header */
u64 mkex_sign; /* "mcam-kex-profile" (8 bytes/ASCII characters) */
......
......@@ -548,6 +548,12 @@ static inline int is_afvf(u16 pcifunc)
return !(pcifunc & ~RVU_PFVF_FUNC_MASK);
}
/* check if PF_FUNC is AF */
static inline bool is_pffunc_af(u16 pcifunc)
{
return !pcifunc;
}
static inline bool is_rvu_fwdata_valid(struct rvu *rvu)
{
return (rvu->fwdata->header_magic == RVU_FWDATA_HEADER_MAGIC) &&
......@@ -640,7 +646,8 @@ int npc_config_ts_kpuaction(struct rvu *rvu, int pf, u16 pcifunc, bool en);
void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, u8 *mac_addr);
void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, bool allmulti);
int nixlf, u64 chan, u8 chan_cnt,
bool allmulti);
void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
......@@ -665,9 +672,6 @@ int rvu_npc_get_tx_nibble_cfg(struct rvu *rvu, u64 nibble_ena);
int npc_mcam_verify_channel(struct rvu *rvu, u16 pcifunc, u8 intf, u16 channel);
int npc_flow_steering_init(struct rvu *rvu, int blkaddr);
const char *npc_get_field_name(u8 hdr);
bool rvu_npc_write_default_rule(struct rvu *rvu, int blkaddr, int nixlf,
u16 pcifunc, u8 intf, struct mcam_entry *entry,
int *entry_index);
int npc_get_bank(struct npc_mcam *mcam, int index);
void npc_mcam_enable_flows(struct rvu *rvu, u16 target);
void npc_mcam_disable_flows(struct rvu *rvu, u16 target);
......@@ -679,6 +683,11 @@ void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature);
u32 rvu_cgx_get_fifolen(struct rvu *rvu);
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
int type);
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
int index);
/* CPT APIs */
int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot);
......
......@@ -2145,7 +2145,7 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused)
seq_printf(s, "\tmcam entry: %d\n", iter->entry);
rvu_dbg_npc_mcam_show_flows(s, iter);
if (iter->intf == NIX_INTF_RX) {
if (is_npc_intf_rx(iter->intf)) {
target = iter->rx_action.pf_func;
pf = (target >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK;
seq_printf(s, "\tForward to: PF%d ", pf);
......
......@@ -273,7 +273,8 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
pfvf->rx_chan_cnt = 1;
pfvf->tx_chan_cnt = 1;
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base, false);
pfvf->rx_chan_base,
pfvf->rx_chan_cnt, false);
break;
}
......@@ -3088,7 +3089,8 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
rvu_npc_disable_promisc_entry(rvu, pcifunc, nixlf);
else
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base, allmulti);
pfvf->rx_chan_base,
pfvf->rx_chan_cnt, allmulti);
return 0;
}
......@@ -3635,9 +3637,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
if (err)
return err;
rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
npc_mcam_disable_flows(rvu, pcifunc);
rvu_npc_disable_mcam_entries(rvu, pcifunc, nixlf);
return rvu_cgx_start_stop_io(rvu, pcifunc, false);
}
......
......@@ -22,10 +22,6 @@
#define RSVD_MCAM_ENTRIES_PER_PF 2 /* Bcast & Promisc */
#define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */
#define NIXLF_UCAST_ENTRY 0
#define NIXLF_BCAST_ENTRY 1
#define NIXLF_PROMISC_ENTRY 2
#define NPC_PARSE_RESULT_DMAC_OFFSET 8
#define NPC_HW_TSTAMP_OFFSET 8
#define NPC_KEX_CHAN_MASK 0xFFFULL
......@@ -96,6 +92,10 @@ int npc_mcam_verify_channel(struct rvu *rvu, u16 pcifunc, u8 intf, u16 channel)
if (is_npc_intf_tx(intf))
return 0;
/* return in case of AF installed rules */
if (is_pffunc_af(pcifunc))
return 0;
if (is_afvf(pcifunc)) {
end = rvu_get_num_lbk_chans();
if (end < 0)
......@@ -196,8 +196,8 @@ static int npc_get_ucast_mcam_index(struct npc_mcam *mcam, u16 pcifunc,
return mcam->nixlf_offset + (max + nixlf) * RSVD_MCAM_ENTRIES_PER_NIXLF;
}
static int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
u16 pcifunc, int nixlf, int type)
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
u16 pcifunc, int nixlf, int type)
{
int pf = rvu_get_pf(pcifunc);
int index;
......@@ -230,8 +230,8 @@ int npc_get_bank(struct npc_mcam *mcam, int index)
return bank;
}
static bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, int index)
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, int index)
{
int bank = npc_get_bank(mcam, index);
u64 cfg;
......@@ -647,13 +647,17 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
}
void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, bool allmulti)
int nixlf, u64 chan, u8 chan_cnt,
bool allmulti)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_install_flow_req req = { 0 };
struct npc_install_flow_rsp rsp = { 0 };
struct npc_mcam *mcam = &rvu->hw->mcam;
int blkaddr, ucast_idx, index, kwi;
struct mcam_entry entry = { {0} };
struct nix_rx_action action = { };
int blkaddr, ucast_idx, index;
u8 mac_addr[ETH_ALEN] = { 0 };
struct nix_rx_action action;
u64 relaxed_mask;
/* Only PF or AF VF can add a promiscuous entry */
if ((pcifunc & RVU_PFVF_FUNC_MASK) && !is_afvf(pcifunc))
......@@ -663,24 +667,15 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
if (blkaddr < 0)
return;
*(u64 *)&action = 0x00;
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_PROMISC_ENTRY);
entry.kw[0] = chan;
entry.kw_mask[0] = 0xFFFULL;
if (allmulti) {
kwi = NPC_KEXOF_DMAC / sizeof(u64);
entry.kw[kwi] = BIT_ULL(40); /* LSB bit of 1st byte in DMAC */
entry.kw_mask[kwi] = BIT_ULL(40);
}
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_UCAST_ENTRY);
/* If the corresponding PF's ucast action is RSS,
* use the same action for promisc also
*/
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_UCAST_ENTRY);
if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
blkaddr, ucast_idx);
......@@ -691,9 +686,36 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
action.pf_func = pcifunc;
}
entry.action = *(u64 *)&action;
npc_config_mcam_entry(rvu, mcam, blkaddr, index,
pfvf->nix_rx_intf, &entry, true);
if (allmulti) {
mac_addr[0] = 0x01; /* LSB bit of 1st byte in DMAC */
ether_addr_copy(req.packet.dmac, mac_addr);
ether_addr_copy(req.mask.dmac, mac_addr);
req.features = BIT_ULL(NPC_DMAC);
}
req.chan_mask = 0xFFFU;
if (chan_cnt > 1) {
if (!is_power_of_2(chan_cnt)) {
dev_err(rvu->dev,
"%s: channel count more than 1, must be power of 2\n", __func__);
return;
}
relaxed_mask = GENMASK_ULL(BITS_PER_LONG_LONG - 1,
ilog2(chan_cnt));
req.chan_mask &= relaxed_mask;
}
req.channel = chan;
req.intf = pfvf->nix_rx_intf;
req.entry = index;
req.op = action.op;
req.hdr.pcifunc = 0; /* AF is requester */
req.vf = pcifunc;
req.index = action.index;
req.match_id = action.match_id;
req.flow_key_alg = action.flow_key_alg;
rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
}
static void npc_enadis_promisc_entry(struct rvu *rvu, u16 pcifunc,
......@@ -728,12 +750,14 @@ void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf)
void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_install_flow_req req = { 0 };
struct npc_install_flow_rsp rsp = { 0 };
struct npc_mcam *mcam = &rvu->hw->mcam;
struct mcam_entry entry = { {0} };
struct rvu_hwinfo *hw = rvu->hw;
struct nix_rx_action action;
struct rvu_pfvf *pfvf;
int blkaddr, index;
u32 req_index = 0;
u8 op;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
......@@ -755,32 +779,29 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_BCAST_ENTRY);
/* Match ingress channel */
entry.kw[0] = chan;
entry.kw_mask[0] = 0xfffull;
/* Match broadcast MAC address.
* DMAC is extracted at 0th bit of PARSE_KEX::KW1
*/
entry.kw[1] = 0xffffffffffffull;
entry.kw_mask[1] = 0xffffffffffffull;
*(u64 *)&action = 0x00;
if (!hw->cap.nix_rx_multicast) {
/* Early silicon doesn't support pkt replication,
* so install entry with UCAST action, so that PF
* receives all broadcast packets.
*/
action.op = NIX_RX_ACTIONOP_UCAST;
action.pf_func = pcifunc;
op = NIX_RX_ACTIONOP_UCAST;
} else {
action.index = pfvf->bcast_mce_idx;
action.op = NIX_RX_ACTIONOP_MCAST;
op = NIX_RX_ACTIONOP_MCAST;
req_index = pfvf->bcast_mce_idx;
}
entry.action = *(u64 *)&action;
npc_config_mcam_entry(rvu, mcam, blkaddr, index,
pfvf->nix_rx_intf, &entry, true);
eth_broadcast_addr((u8 *)&req.packet.dmac);
eth_broadcast_addr((u8 *)&req.mask.dmac);
req.features = BIT_ULL(NPC_DMAC);
req.channel = chan;
req.intf = pfvf->nix_rx_intf;
req.entry = index;
req.op = op;
req.hdr.pcifunc = 0; /* AF is requester */
req.vf = pcifunc;
req.index = req_index;
rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
}
void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable)
......@@ -967,7 +988,7 @@ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_npc_mcam_rule *rule;
struct rvu_npc_mcam_rule *rule, *tmp;
int blkaddr;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
......@@ -977,15 +998,18 @@ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
mutex_lock(&mcam->lock);
/* Disable MCAM entries directing traffic to this 'pcifunc' */
list_for_each_entry(rule, &mcam->mcam_rules, list) {
list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
if (is_npc_intf_rx(rule->intf) &&
rule->rx_action.pf_func == pcifunc) {
npc_enable_mcam_entry(rvu, mcam, blkaddr,
rule->entry, false);
rule->enable = false;
/* Indicate that default rule is disabled */
if (rule->default_rule)
if (rule->default_rule) {
pfvf->def_ucast_rule = NULL;
list_del(&rule->list);
kfree(rule);
}
}
}
......@@ -1674,6 +1698,9 @@ void rvu_npc_get_mcam_counter_alloc_info(struct rvu *rvu, u16 pcifunc,
static int npc_mcam_verify_entry(struct npc_mcam *mcam,
u16 pcifunc, int entry)
{
/* verify AF installed entries */
if (is_pffunc_af(pcifunc))
return 0;
/* Verify if entry is valid and if it is indeed
* allocated to the requesting PFFUNC.
*/
......@@ -2268,6 +2295,10 @@ int rvu_mbox_handler_npc_mcam_write_entry(struct rvu *rvu,
goto exit;
}
/* For AF installed rules, the nix_intf should be set to target NIX */
if (is_pffunc_af(req->hdr.pcifunc))
nix_intf = req->intf;
npc_config_mcam_entry(rvu, mcam, blkaddr, req->entry, nix_intf,
&req->entry_data, req->enable_entry);
......@@ -2730,30 +2761,6 @@ int rvu_mbox_handler_npc_get_kex_cfg(struct rvu *rvu, struct msg_req *req,
return 0;
}
bool rvu_npc_write_default_rule(struct rvu *rvu, int blkaddr, int nixlf,
u16 pcifunc, u8 intf, struct mcam_entry *entry,
int *index)
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_mcam *mcam = &rvu->hw->mcam;
bool enable;
u8 nix_intf;
if (is_npc_intf_tx(intf))
nix_intf = pfvf->nix_tx_intf;
else
nix_intf = pfvf->nix_rx_intf;
*index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_UCAST_ENTRY);
/* dont force enable unicast entry */
enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, *index);
npc_config_mcam_entry(rvu, mcam, blkaddr, *index, nix_intf,
entry, enable);
return enable;
}
int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu,
struct msg_req *req,
struct npc_mcam_read_base_rule_rsp *rsp)
......
......@@ -597,7 +597,7 @@ static int npc_check_unsupported_flows(struct rvu *rvu, u64 features, u8 intf)
dev_info(rvu->dev, "Unsupported flow(s):\n");
for_each_set_bit(bit, (unsigned long *)&unsupported, 64)
dev_info(rvu->dev, "%s ", npc_get_field_name(bit));
return -EOPNOTSUPP;
return NIX_AF_ERR_NPC_KEY_NOT_SUPP;
}
return 0;
......@@ -903,9 +903,11 @@ static void npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf,
struct npc_install_flow_req *req, u16 target)
{
struct nix_rx_action action;
u64 chan_mask;
npc_update_entry(rvu, NPC_CHAN, entry, req->channel, 0,
~0ULL, 0, NIX_INTF_RX);
chan_mask = req->chan_mask ? req->chan_mask : ~0ULL;
npc_update_entry(rvu, NPC_CHAN, entry, req->channel, 0, chan_mask, 0,
NIX_INTF_RX);
*(u64 *)&action = 0x00;
action.pf_func = target;
......@@ -998,33 +1000,21 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
if (is_npc_intf_tx(req->intf))
goto find_rule;
if (def_ucast_rule)
if (req->default_rule) {
entry_index = npc_get_nixlf_mcam_index(mcam, target, nixlf,
NIXLF_UCAST_ENTRY);
enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, entry_index);
}
/* update mcam entry with default unicast rule attributes */
if (def_ucast_rule && (msg_from_vf || (req->default_rule && req->append))) {
missing_features = (def_ucast_rule->features ^ features) &
def_ucast_rule->features;
if (req->default_rule && req->append) {
/* add to default rule */
if (missing_features)
npc_update_flow(rvu, entry, missing_features,
&def_ucast_rule->packet,
&def_ucast_rule->mask,
&dummy, req->intf);
enable = rvu_npc_write_default_rule(rvu, blkaddr,
nixlf, target,
pfvf->nix_rx_intf, entry,
&entry_index);
installed_features = req->features | missing_features;
} else if (req->default_rule && !req->append) {
/* overwrite default rule */
enable = rvu_npc_write_default_rule(rvu, blkaddr,
nixlf, target,
pfvf->nix_rx_intf, entry,
&entry_index);
} else if (msg_from_vf) {
/* normal rule - include default rule also to it for VF */
npc_update_flow(rvu, entry, missing_features,
&def_ucast_rule->packet, &def_ucast_rule->mask,
&dummy, req->intf);
installed_features = req->features | missing_features;
}
......@@ -1036,12 +1026,9 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
return -ENOMEM;
new = true;
}
/* no counter for default rule */
if (req->default_rule)
goto update_rule;
/* allocate new counter if rule has no counter */
if (req->set_cntr && !rule->has_cntr)
if (!req->default_rule && req->set_cntr && !rule->has_cntr)
rvu_mcam_add_counter_to_rule(rvu, owner, rule, rsp);
/* if user wants to delete an existing counter for a rule then
......@@ -1051,7 +1038,14 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
rvu_mcam_remove_counter_from_rule(rvu, owner, rule);
write_req.hdr.pcifunc = owner;
write_req.entry = req->entry;
/* AF owns the default rules so change the owner just to relax
* the checks in rvu_mbox_handler_npc_mcam_write_entry
*/
if (req->default_rule)
write_req.hdr.pcifunc = 0;
write_req.entry = entry_index;
write_req.intf = req->intf;
write_req.enable_entry = (u8)enable;
/* if counter is available then clear and use it */
......@@ -1069,7 +1063,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
kfree(rule);
return err;
}
update_rule:
/* update rule */
memcpy(&rule->packet, &dummy.packet, sizeof(rule->packet));
memcpy(&rule->mask, &dummy.mask, sizeof(rule->mask));
rule->entry = entry_index;
......@@ -1145,8 +1139,13 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
else
target = req->hdr.pcifunc;
if (npc_check_unsupported_flows(rvu, req->features, req->intf))
return -EOPNOTSUPP;
/* ignore chan_mask in case pf func is not AF, revisit later */
if (!is_pffunc_af(req->hdr.pcifunc))
req->chan_mask = 0xFFF;
err = npc_check_unsupported_flows(rvu, req->features, req->intf);
if (err)
return err;
if (npc_mcam_verify_channel(rvu, target, req->intf, req->channel))
return -EINVAL;
......@@ -1278,6 +1277,7 @@ static int npc_update_dmac_value(struct rvu *rvu, int npcblkaddr,
write_req.hdr.pcifunc = rule->owner;
write_req.entry = rule->entry;
write_req.intf = pfvf->nix_rx_intf;
mutex_unlock(&mcam->lock);
err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &write_req, &rsp);
......
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