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

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
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -995,13 +995,11 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
	struct npc_mcam *mcam = &rvu->hw->mcam;
	struct rvu_npc_mcam_rule dummy = { 0 };
	struct rvu_npc_mcam_rule *rule;
	bool new = false, msg_from_vf;
	u16 owner = req->hdr.pcifunc;
	struct msg_rsp write_rsp;
	struct mcam_entry *entry;
	int entry_index, err;

	msg_from_vf = !!(owner & RVU_PFVF_FUNC_MASK);
	bool new = false;

	installed_features = req->features;
	features = req->features;
@@ -1027,7 +1025,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
	}

	/* 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) &
					def_ucast_rule->features;
		if (missing_features)
@@ -1130,6 +1128,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
				      struct npc_install_flow_rsp *rsp)
{
	bool from_vf = !!(req->hdr.pcifunc & RVU_PFVF_FUNC_MASK);
	struct rvu_switch *rswitch = &rvu->rswitch;
	int blkaddr, nixlf, err;
	struct rvu_pfvf *pfvf;
	bool pf_set_vfs_mac = false;
@@ -1221,15 +1220,12 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
		return 0;
	}

	/* If message is from VF then its flow should not overlap with
	 * reserved unicast flow.
	 */
	if (from_vf && pfvf->def_ucast_rule && is_npc_intf_rx(req->intf) &&
	    pfvf->def_ucast_rule->features & req->features)
		return NPC_FLOW_VF_OVERLAP;
	mutex_lock(&rswitch->switch_lock);
	err = npc_install_flow(rvu, blkaddr, target, nixlf, pfvf,
			       req, rsp, enable, pf_set_vfs_mac);
	mutex_unlock(&rswitch->switch_lock);

	return npc_install_flow(rvu, blkaddr, target, nixlf, pfvf, req, rsp,
				enable, pf_set_vfs_mac);
	return err;
}

static int npc_delete_flow(struct rvu *rvu, struct rvu_npc_mcam_rule *rule,
+7 −0
Original line number Diff line number Diff line
@@ -710,6 +710,11 @@ MBOX_UP_CGX_MESSAGES
#define	RVU_PFVF_FUNC_SHIFT	0
#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)
{
	return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK;
@@ -815,6 +820,7 @@ int otx2_set_real_num_queues(struct net_device *netdev,
			     int tx_queues, int rx_queues);
/* MCAM filter related APIs */
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);
void otx2_mcam_flow_del(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,
int otx2_remove_flow(struct otx2_nic *pfvf, u32 location);
int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
			      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);
int otx2_del_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);
+11 −41
Original line number Diff line number Diff line
@@ -645,6 +645,7 @@ static int otx2_set_rss_hash_opts(struct otx2_nic *pfvf,
static int otx2_get_rxnfc(struct net_device *dev,
			  struct ethtool_rxnfc *nfc, u32 *rules)
{
	bool ntuple = !!(dev->features & NETIF_F_NTUPLE);
	struct otx2_nic *pfvf = netdev_priv(dev);
	int ret = -EOPNOTSUPP;

@@ -654,13 +655,17 @@ static int otx2_get_rxnfc(struct net_device *dev,
		ret = 0;
		break;
	case ETHTOOL_GRXCLSRLCNT:
		if (netif_running(dev) && ntuple) {
			nfc->rule_cnt = pfvf->flow_cfg->nr_flows;
			ret = 0;
		}
		break;
	case ETHTOOL_GRXCLSRULE:
		if (netif_running(dev) && ntuple)
			ret = otx2_get_flow(pfvf, nfc,  nfc->fs.location);
		break;
	case ETHTOOL_GRXCLSRLALL:
		if (netif_running(dev) && ntuple)
			ret = otx2_get_all_flows(pfvf, nfc, rules);
		break;
	case ETHTOOL_GRXFH:
@@ -696,41 +701,6 @@ static int otx2_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *nfc)
	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)
{
	struct otx2_nic *pfvf = netdev_priv(netdev);
@@ -1357,8 +1327,8 @@ static const struct ethtool_ops otx2vf_ethtool_ops = {
	.get_sset_count		= otx2vf_get_sset_count,
	.set_channels		= otx2_set_channels,
	.get_channels		= otx2_get_channels,
	.get_rxnfc		= otx2vf_get_rxnfc,
	.set_rxnfc              = otx2vf_set_rxnfc,
	.get_rxnfc		= otx2_get_rxnfc,
	.set_rxnfc              = otx2_set_rxnfc,
	.get_rxfh_key_size	= otx2_get_rxfh_key_size,
	.get_rxfh_indir_size	= otx2_get_rxfh_indir_size,
	.get_rxfh		= otx2_get_rxfh,
+44 −7
Original line number Diff line number Diff line
@@ -92,8 +92,14 @@ static int otx2_alloc_ntuple_mcam_entries(struct otx2_nic *pfvf, u16 count)
		req->contig = false;
		req->count = (count - allocated) > NPC_MAX_NONCONTIG_ENTRIES ?
				NPC_MAX_NONCONTIG_ENTRIES : count - allocated;

		/* 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 */
		if (otx2_sync_mbox_msg(&pfvf->mbox))
@@ -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->tc_max_flows = allocated;

	pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
	pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;

	if (allocated != count)
		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);

	return allocated;
}

@@ -195,12 +203,34 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
		return 0;
	}

	pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
	pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;

	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 err;
@@ -248,6 +278,7 @@ void otx2_mcam_flow_del(struct otx2_nic *pf)
{
	otx2_destroy_mcam_flows(pf);
}
EXPORT_SYMBOL(otx2_mcam_flow_del);

/*  On success adds mcam entry
 *  On failure enable promisous mode
@@ -379,8 +410,11 @@ static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow)
	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 ||
	    bitmap_weight(&flow_cfg->dmacflt_bmap,
			  flow_cfg->dmacflt_max_flows))
@@ -388,6 +422,7 @@ static int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
	else
		return flow_cfg->ntuple_max_flows;
}
EXPORT_SYMBOL(otx2_get_maxflows);

int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
		  u32 location)
@@ -732,7 +767,7 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
			ether_addr_copy(pmask->dmac, eth_mask->h_dest);
			req->features |= BIT_ULL(NPC_DMAC);
		}
		if (eth_mask->h_proto) {
		if (eth_hdr->h_proto) {
			memcpy(&pkt->etype, &eth_hdr->h_proto,
			       sizeof(pkt->etype));
			memcpy(&pmask->etype, &eth_mask->h_proto,
@@ -996,6 +1031,8 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
	}

	if (err) {
		if (err == MBOX_MSG_INVALID)
			err = -EINVAL;
		if (new)
			kfree(flow);
		return err;
+28 −0
Original line number Diff line number Diff line
@@ -464,6 +464,28 @@ static void otx2vf_reset_task(struct work_struct *work)
	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 = {
	.ndo_open = otx2vf_open,
	.ndo_stop = otx2vf_stop,
@@ -471,6 +493,7 @@ static const struct net_device_ops otx2vf_netdev_ops = {
	.ndo_set_rx_mode = otx2vf_set_rx_mode,
	.ndo_set_mac_address = otx2_set_mac_address,
	.ndo_change_mtu = otx2vf_change_mtu,
	.ndo_set_features = otx2vf_set_features,
	.ndo_get_stats64 = otx2_get_stats64,
	.ndo_tx_timeout = otx2_tx_timeout,
};
@@ -627,6 +650,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
				NETIF_F_HW_VLAN_STAG_TX;
	netdev->features |= netdev->hw_features;

	netdev->hw_features |= NETIF_F_NTUPLE;
	netdev->hw_features |= NETIF_F_RXALL;

	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)

	otx2vf_set_ethtool_ops(netdev);

	err = otx2vf_mcam_flow_init(vf);
	if (err)
		goto err_unreg_netdev;

	/* Enable pause frames by default */
	vf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED;
	vf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED;