Commit 3cffaed2 authored by Rakesh Babu's avatar Rakesh Babu Committed by David S. Miller

octeontx2-pf: Ntuple filters support for VF netdev

Add packet flow classification support for both LMAC mapped virtual
functions and loopback VFs. This patch adds supports for ntuple
offload feature.
Signed-off-by: default avatarRakesh Babu <rsaladi2@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0b3834ae
...@@ -995,13 +995,11 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target, ...@@ -995,13 +995,11 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_npc_mcam_rule dummy = { 0 }; struct rvu_npc_mcam_rule dummy = { 0 };
struct rvu_npc_mcam_rule *rule; struct rvu_npc_mcam_rule *rule;
bool new = false, msg_from_vf;
u16 owner = req->hdr.pcifunc; u16 owner = req->hdr.pcifunc;
struct msg_rsp write_rsp; struct msg_rsp write_rsp;
struct mcam_entry *entry; struct mcam_entry *entry;
int entry_index, err; int entry_index, err;
bool new = false;
msg_from_vf = !!(owner & RVU_PFVF_FUNC_MASK);
installed_features = req->features; installed_features = req->features;
features = req->features; features = req->features;
...@@ -1027,7 +1025,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target, ...@@ -1027,7 +1025,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
} }
/* update mcam entry with default unicast rule attributes */ /* update mcam entry with default unicast rule attributes */
if (def_ucast_rule && (msg_from_vf || (req->default_rule && req->append))) { if (def_ucast_rule && (req->default_rule && req->append)) {
missing_features = (def_ucast_rule->features ^ features) & missing_features = (def_ucast_rule->features ^ features) &
def_ucast_rule->features; def_ucast_rule->features;
if (missing_features) if (missing_features)
...@@ -1130,6 +1128,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, ...@@ -1130,6 +1128,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
struct npc_install_flow_rsp *rsp) struct npc_install_flow_rsp *rsp)
{ {
bool from_vf = !!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK); bool from_vf = !!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK);
struct rvu_switch *rswitch = &rvu->rswitch;
int blkaddr, nixlf, err; int blkaddr, nixlf, err;
struct rvu_pfvf *pfvf; struct rvu_pfvf *pfvf;
bool pf_set_vfs_mac = false; bool pf_set_vfs_mac = false;
...@@ -1221,15 +1220,12 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, ...@@ -1221,15 +1220,12 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
return 0; return 0;
} }
/* If message is from VF then its flow should not overlap with mutex_lock(&rswitch->switch_lock);
* reserved unicast flow. err = npc_install_flow(rvu, blkaddr, target, nixlf, pfvf,
*/ req, rsp, enable, pf_set_vfs_mac);
if (from_vf && pfvf->def_ucast_rule && is_npc_intf_rx(req->intf) && mutex_unlock(&rswitch->switch_lock);
pfvf->def_ucast_rule->features & req->features)
return NPC_FLOW_VF_OVERLAP;
return npc_install_flow(rvu, blkaddr, target, nixlf, pfvf, req, rsp, return err;
enable, pf_set_vfs_mac);
} }
static int npc_delete_flow(struct rvu *rvu, struct rvu_npc_mcam_rule *rule, static int npc_delete_flow(struct rvu *rvu, struct rvu_npc_mcam_rule *rule,
......
...@@ -710,6 +710,11 @@ MBOX_UP_CGX_MESSAGES ...@@ -710,6 +710,11 @@ MBOX_UP_CGX_MESSAGES
#define RVU_PFVF_FUNC_SHIFT 0 #define RVU_PFVF_FUNC_SHIFT 0
#define RVU_PFVF_FUNC_MASK 0x3FF #define RVU_PFVF_FUNC_MASK 0x3FF
static inline bool is_otx2_vf(u16 pcifunc)
{
return !!(pcifunc & RVU_PFVF_FUNC_MASK);
}
static inline int rvu_get_pf(u16 pcifunc) static inline int rvu_get_pf(u16 pcifunc)
{ {
return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK;
...@@ -815,6 +820,7 @@ int otx2_set_real_num_queues(struct net_device *netdev, ...@@ -815,6 +820,7 @@ int otx2_set_real_num_queues(struct net_device *netdev,
int tx_queues, int rx_queues); int tx_queues, int rx_queues);
/* MCAM filter related APIs */ /* MCAM filter related APIs */
int otx2_mcam_flow_init(struct otx2_nic *pf); int otx2_mcam_flow_init(struct otx2_nic *pf);
int otx2vf_mcam_flow_init(struct otx2_nic *pfvf);
int otx2_alloc_mcam_entries(struct otx2_nic *pfvf); int otx2_alloc_mcam_entries(struct otx2_nic *pfvf);
void otx2_mcam_flow_del(struct otx2_nic *pf); void otx2_mcam_flow_del(struct otx2_nic *pf);
int otx2_destroy_ntuple_flows(struct otx2_nic *pf); int otx2_destroy_ntuple_flows(struct otx2_nic *pf);
...@@ -828,6 +834,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, ...@@ -828,6 +834,7 @@ int otx2_add_flow(struct otx2_nic *pfvf,
int otx2_remove_flow(struct otx2_nic *pfvf, u32 location); int otx2_remove_flow(struct otx2_nic *pfvf, u32 location);
int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
struct npc_install_flow_req *req); struct npc_install_flow_req *req);
int otx2_get_maxflows(struct otx2_flow_config *flow_cfg);
void otx2_rss_ctx_flow_del(struct otx2_nic *pfvf, int ctx_id); void otx2_rss_ctx_flow_del(struct otx2_nic *pfvf, int ctx_id);
int otx2_del_macfilter(struct net_device *netdev, const u8 *mac); int otx2_del_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_add_macfilter(struct net_device *netdev, const u8 *mac); int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);
......
...@@ -645,6 +645,7 @@ static int otx2_set_rss_hash_opts(struct otx2_nic *pfvf, ...@@ -645,6 +645,7 @@ static int otx2_set_rss_hash_opts(struct otx2_nic *pfvf,
static int otx2_get_rxnfc(struct net_device *dev, static int otx2_get_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *nfc, u32 *rules) struct ethtool_rxnfc *nfc, u32 *rules)
{ {
bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
struct otx2_nic *pfvf = netdev_priv(dev); struct otx2_nic *pfvf = netdev_priv(dev);
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
...@@ -654,14 +655,18 @@ static int otx2_get_rxnfc(struct net_device *dev, ...@@ -654,14 +655,18 @@ static int otx2_get_rxnfc(struct net_device *dev,
ret = 0; ret = 0;
break; break;
case ETHTOOL_GRXCLSRLCNT: case ETHTOOL_GRXCLSRLCNT:
nfc->rule_cnt = pfvf->flow_cfg->nr_flows; if (netif_running(dev) && ntuple) {
ret = 0; nfc->rule_cnt = pfvf->flow_cfg->nr_flows;
ret = 0;
}
break; break;
case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRULE:
ret = otx2_get_flow(pfvf, nfc, nfc->fs.location); if (netif_running(dev) && ntuple)
ret = otx2_get_flow(pfvf, nfc, nfc->fs.location);
break; break;
case ETHTOOL_GRXCLSRLALL: case ETHTOOL_GRXCLSRLALL:
ret = otx2_get_all_flows(pfvf, nfc, rules); if (netif_running(dev) && ntuple)
ret = otx2_get_all_flows(pfvf, nfc, rules);
break; break;
case ETHTOOL_GRXFH: case ETHTOOL_GRXFH:
return otx2_get_rss_hash_opts(pfvf, nfc); return otx2_get_rss_hash_opts(pfvf, nfc);
...@@ -696,41 +701,6 @@ static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc) ...@@ -696,41 +701,6 @@ static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
return ret; return ret;
} }
static int otx2vf_get_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *nfc, u32 *rules)
{
struct otx2_nic *pfvf = netdev_priv(dev);
int ret = -EOPNOTSUPP;
switch (nfc->cmd) {
case ETHTOOL_GRXRINGS:
nfc->data = pfvf->hw.rx_queues;
ret = 0;
break;
case ETHTOOL_GRXFH:
return otx2_get_rss_hash_opts(pfvf, nfc);
default:
break;
}
return ret;
}
static int otx2vf_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
{
struct otx2_nic *pfvf = netdev_priv(dev);
int ret = -EOPNOTSUPP;
switch (nfc->cmd) {
case ETHTOOL_SRXFH:
ret = otx2_set_rss_hash_opts(pfvf, nfc);
break;
default:
break;
}
return ret;
}
static u32 otx2_get_rxfh_key_size(struct net_device *netdev) static u32 otx2_get_rxfh_key_size(struct net_device *netdev)
{ {
struct otx2_nic *pfvf = netdev_priv(netdev); struct otx2_nic *pfvf = netdev_priv(netdev);
...@@ -1357,8 +1327,8 @@ static const struct ethtool_ops otx2vf_ethtool_ops = { ...@@ -1357,8 +1327,8 @@ static const struct ethtool_ops otx2vf_ethtool_ops = {
.get_sset_count = otx2vf_get_sset_count, .get_sset_count = otx2vf_get_sset_count,
.set_channels = otx2_set_channels, .set_channels = otx2_set_channels,
.get_channels = otx2_get_channels, .get_channels = otx2_get_channels,
.get_rxnfc = otx2vf_get_rxnfc, .get_rxnfc = otx2_get_rxnfc,
.set_rxnfc = otx2vf_set_rxnfc, .set_rxnfc = otx2_set_rxnfc,
.get_rxfh_key_size = otx2_get_rxfh_key_size, .get_rxfh_key_size = otx2_get_rxfh_key_size,
.get_rxfh_indir_size = otx2_get_rxfh_indir_size, .get_rxfh_indir_size = otx2_get_rxfh_indir_size,
.get_rxfh = otx2_get_rxfh, .get_rxfh = otx2_get_rxfh,
......
...@@ -92,8 +92,14 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count) ...@@ -92,8 +92,14 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)
req->contig = false; req->contig = false;
req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ? req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ?
NPC_MAX_NONCONTIG_ENTRIES : count - allocated; NPC_MAX_NONCONTIG_ENTRIES : count - allocated;
req->priority = NPC_MCAM_HIGHER_PRIO;
req->ref_entry = flow_cfg->def_ent[0]; /* Allocate higher priority entries for PFs, so that VF's entries
* will be on top of PF.
*/
if (!is_otx2_vf(pfvf->pcifunc)) {
req->priority = NPC_MCAM_HIGHER_PRIO;
req->ref_entry = flow_cfg->def_ent[0];
}
/* Send message to AF */ /* Send message to AF */
if (otx2_sync_mbox_msg(&pfvf->mbox)) if (otx2_sync_mbox_msg(&pfvf->mbox))
...@@ -121,11 +127,13 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count) ...@@ -121,11 +127,13 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)
flow_cfg->ntuple_max_flows = allocated; flow_cfg->ntuple_max_flows = allocated;
flow_cfg->tc_max_flows = allocated; flow_cfg->tc_max_flows = allocated;
pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
if (allocated != count) if (allocated != count)
netdev_info(pfvf->netdev, netdev_info(pfvf->netdev,
"Unable to allocate %d MCAM entries for ntuple, got %d\n", "Unable to allocate %d MCAM entries, got only %d\n",
count, allocated); count, allocated);
return allocated; return allocated;
} }
...@@ -195,12 +203,34 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf) ...@@ -195,12 +203,34 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
return 0; return 0;
} }
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
return 0; return 0;
} }
int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
{
struct otx2_flow_config *flow_cfg;
int count;
pfvf->flow_cfg = devm_kzalloc(pfvf->dev,
sizeof(struct otx2_flow_config),
GFP_KERNEL);
if (!pfvf->flow_cfg)
return -ENOMEM;
flow_cfg = pfvf->flow_cfg;
INIT_LIST_HEAD(&flow_cfg->flow_list);
flow_cfg->ntuple_max_flows = 0;
count = otx2_alloc_ntuple_mcam_entries(pfvf, OTX2_DEFAULT_FLOWCOUNT);
if (count <= 0)
return -ENOMEM;
return 0;
}
EXPORT_SYMBOL(otx2vf_mcam_flow_init);
int otx2_mcam_flow_init(struct otx2_nic *pf) int otx2_mcam_flow_init(struct otx2_nic *pf)
{ {
int err; int err;
...@@ -248,6 +278,7 @@ void otx2_mcam_flow_del(struct otx2_nic *pf) ...@@ -248,6 +278,7 @@ void otx2_mcam_flow_del(struct otx2_nic *pf)
{ {
otx2_destroy_mcam_flows(pf); otx2_destroy_mcam_flows(pf);
} }
EXPORT_SYMBOL(otx2_mcam_flow_del);
/* On success adds mcam entry /* On success adds mcam entry
* On failure enable promisous mode * On failure enable promisous mode
...@@ -379,8 +410,11 @@ static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow) ...@@ -379,8 +410,11 @@ static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow)
list_add(&flow->list, head); list_add(&flow->list, head);
} }
static int otx2_get_maxflows(struct otx2_flow_config *flow_cfg) int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
{ {
if (!flow_cfg)
return 0;
if (flow_cfg->nr_flows == flow_cfg->ntuple_max_flows || if (flow_cfg->nr_flows == flow_cfg->ntuple_max_flows ||
bitmap_weight(&flow_cfg->dmacflt_bmap, bitmap_weight(&flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows)) flow_cfg->dmacflt_max_flows))
...@@ -388,6 +422,7 @@ static int otx2_get_maxflows(struct otx2_flow_config *flow_cfg) ...@@ -388,6 +422,7 @@ static int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
else else
return flow_cfg->ntuple_max_flows; return flow_cfg->ntuple_max_flows;
} }
EXPORT_SYMBOL(otx2_get_maxflows);
int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc, int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
u32 location) u32 location)
...@@ -732,7 +767,7 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, ...@@ -732,7 +767,7 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
ether_addr_copy(pmask->dmac, eth_mask->h_dest); ether_addr_copy(pmask->dmac, eth_mask->h_dest);
req->features |= BIT_ULL(NPC_DMAC); req->features |= BIT_ULL(NPC_DMAC);
} }
if (eth_mask->h_proto) { if (eth_hdr->h_proto) {
memcpy(&pkt->etype, &eth_hdr->h_proto, memcpy(&pkt->etype, &eth_hdr->h_proto,
sizeof(pkt->etype)); sizeof(pkt->etype));
memcpy(&pmask->etype, &eth_mask->h_proto, memcpy(&pmask->etype, &eth_mask->h_proto,
...@@ -996,6 +1031,8 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc) ...@@ -996,6 +1031,8 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
} }
if (err) { if (err) {
if (err == MBOX_MSG_INVALID)
err = -EINVAL;
if (new) if (new)
kfree(flow); kfree(flow);
return err; return err;
......
...@@ -464,6 +464,28 @@ static void otx2vf_reset_task(struct work_struct *work) ...@@ -464,6 +464,28 @@ static void otx2vf_reset_task(struct work_struct *work)
rtnl_unlock(); rtnl_unlock();
} }
static int otx2vf_set_features(struct net_device *netdev,
netdev_features_t features)
{
netdev_features_t changed = features ^ netdev->features;
bool ntuple_enabled = !!(features & NETIF_F_NTUPLE);
struct otx2_nic *vf = netdev_priv(netdev);
if (changed & NETIF_F_NTUPLE) {
if (!ntuple_enabled) {
otx2_mcam_flow_del(vf);
return 0;
}
if (!otx2_get_maxflows(vf->flow_cfg)) {
netdev_err(netdev,
"Can't enable NTUPLE, MCAM entries not allocated\n");
return -EINVAL;
}
}
return 0;
}
static const struct net_device_ops otx2vf_netdev_ops = { static const struct net_device_ops otx2vf_netdev_ops = {
.ndo_open = otx2vf_open, .ndo_open = otx2vf_open,
.ndo_stop = otx2vf_stop, .ndo_stop = otx2vf_stop,
...@@ -471,6 +493,7 @@ static const struct net_device_ops otx2vf_netdev_ops = { ...@@ -471,6 +493,7 @@ static const struct net_device_ops otx2vf_netdev_ops = {
.ndo_set_rx_mode = otx2vf_set_rx_mode, .ndo_set_rx_mode = otx2vf_set_rx_mode,
.ndo_set_mac_address = otx2_set_mac_address, .ndo_set_mac_address = otx2_set_mac_address,
.ndo_change_mtu = otx2vf_change_mtu, .ndo_change_mtu = otx2vf_change_mtu,
.ndo_set_features = otx2vf_set_features,
.ndo_get_stats64 = otx2_get_stats64, .ndo_get_stats64 = otx2_get_stats64,
.ndo_tx_timeout = otx2_tx_timeout, .ndo_tx_timeout = otx2_tx_timeout,
}; };
...@@ -627,6 +650,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -627,6 +650,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
NETIF_F_HW_VLAN_STAG_TX; NETIF_F_HW_VLAN_STAG_TX;
netdev->features |= netdev->hw_features; netdev->features |= netdev->hw_features;
netdev->hw_features |= NETIF_F_NTUPLE;
netdev->hw_features |= NETIF_F_RXALL; netdev->hw_features |= NETIF_F_RXALL;
netdev->gso_max_segs = OTX2_MAX_GSO_SEGS; netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
...@@ -659,6 +683,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -659,6 +683,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
otx2vf_set_ethtool_ops(netdev); otx2vf_set_ethtool_ops(netdev);
err = otx2vf_mcam_flow_init(vf);
if (err)
goto err_unreg_netdev;
/* Enable pause frames by default */ /* Enable pause frames by default */
vf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED; vf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED;
vf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED; vf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED;
......
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