Commit fd9d7859 authored by Hariprasad Kelam's avatar Hariprasad Kelam Committed by Jakub Kicinski
Browse files

octeontx2-pf: Implement ingress/egress VLAN offload



This patch implements egress VLAN offload by appending NIX_SEND_EXT_S
header to NIX_SEND_HDR_S. The VLAN TCI information is specified
in the NIX_SEND_EXT_S. The VLAN offload in the ingress path is
implemented by configuring the NIX_RX_VTAG_ACTION_S to strip and
capture the outer vlan fields. The NIX PF allocates one MCAM entry
for Rx VLAN offload.

Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarNaveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 9a946def
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -479,6 +479,19 @@ enum nix_af_status {
	NIX_AF_INVAL_NPA_PF_FUNC    = -419,
	NIX_AF_INVAL_SSO_PF_FUNC    = -420,
	NIX_AF_ERR_TX_VTAG_NOSPC    = -421,
	NIX_AF_ERR_RX_VTAG_INUSE    = -422,
};

/* For NIX RX vtag action  */
enum nix_rx_vtag0_type {
	NIX_AF_LFX_RX_VTAG_TYPE0, /* reserved for rx vlan offload */
	NIX_AF_LFX_RX_VTAG_TYPE1,
	NIX_AF_LFX_RX_VTAG_TYPE2,
	NIX_AF_LFX_RX_VTAG_TYPE3,
	NIX_AF_LFX_RX_VTAG_TYPE4,
	NIX_AF_LFX_RX_VTAG_TYPE5,
	NIX_AF_LFX_RX_VTAG_TYPE6,
	NIX_AF_LFX_RX_VTAG_TYPE7,
};

/* For NIX LF context alloc and init */
+2 −1
Original line number Diff line number Diff line
@@ -1984,7 +1984,8 @@ static int nix_rx_vtag_cfg(struct rvu *rvu, int nixlf, int blkaddr,
{
	u64 regval = req->vtag_size;

	if (req->rx.vtag_type > 7 || req->vtag_size > VTAGSIZE_T8)
	if (req->rx.vtag_type > NIX_AF_LFX_RX_VTAG_TYPE7 ||
	    req->vtag_size > VTAGSIZE_T8)
		return -EINVAL;

	if (req->rx.capture_vtag)
+6 −2
Original line number Diff line number Diff line
@@ -191,10 +191,14 @@ int otx2_set_mac_address(struct net_device *netdev, void *p)
	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

	if (!otx2_hw_set_mac_addr(pfvf, addr->sa_data))
	if (!otx2_hw_set_mac_addr(pfvf, addr->sa_data)) {
		memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
	else
		/* update dmac field in vlan offload rule */
		if (pfvf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
			otx2_install_rxvlan_offload_flow(pfvf);
	} else {
		return -EPERM;
	}

	return 0;
}
+7 −1
Original line number Diff line number Diff line
@@ -240,10 +240,13 @@ struct otx2_flow_config {
	u32			nr_flows;
#define OTX2_MAX_NTUPLE_FLOWS	32
#define OTX2_MAX_UNICAST_FLOWS	8
#define OTX2_MAX_VLAN_FLOWS	1
#define OTX2_MCAM_COUNT		(OTX2_MAX_NTUPLE_FLOWS + \
				 OTX2_MAX_UNICAST_FLOWS)
				 OTX2_MAX_UNICAST_FLOWS + \
				 OTX2_MAX_VLAN_FLOWS)
	u32			ntuple_offset;
	u32			unicast_offset;
	u32			rx_vlan_offset;
	u32                     ntuple_max_flows;
	struct list_head	flow_list;
};
@@ -261,6 +264,7 @@ struct otx2_nic {
#define OTX2_FLAG_MCAM_ENTRIES_ALLOC		BIT_ULL(3)
#define OTX2_FLAG_NTUPLE_SUPPORT		BIT_ULL(4)
#define OTX2_FLAG_UCAST_FLTR_SUPPORT		BIT_ULL(5)
#define OTX2_FLAG_RX_VLAN_SUPPORT		BIT_ULL(6)
#define OTX2_FLAG_RX_PAUSE_ENABLED		BIT_ULL(9)
#define OTX2_FLAG_TX_PAUSE_ENABLED		BIT_ULL(10)
	u64			flags;
@@ -687,5 +691,7 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
			      struct npc_install_flow_req *req);
int otx2_del_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);
int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable);
int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf);

#endif /* OTX2_COMMON_H */
+102 −0
Original line number Diff line number Diff line
@@ -58,8 +58,11 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
		flow_cfg->ntuple_offset = 0;
		flow_cfg->unicast_offset = flow_cfg->ntuple_offset +
						OTX2_MAX_NTUPLE_FLOWS;
		flow_cfg->rx_vlan_offset = flow_cfg->unicast_offset +
						OTX2_MAX_UNICAST_FLOWS;
		pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
		pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
		pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
	}

	for (i = 0; i < rsp->count; i++)
@@ -711,3 +714,102 @@ int otx2_destroy_mcam_flows(struct otx2_nic *pfvf)

	return 0;
}

int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf)
{
	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
	struct npc_install_flow_req *req;
	int err;

	mutex_lock(&pfvf->mbox.lock);
	req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
	if (!req) {
		mutex_unlock(&pfvf->mbox.lock);
		return -ENOMEM;
	}

	req->entry = flow_cfg->entry[flow_cfg->rx_vlan_offset];
	req->intf = NIX_INTF_RX;
	ether_addr_copy(req->packet.dmac, pfvf->netdev->dev_addr);
	eth_broadcast_addr((u8 *)&req->mask.dmac);
	req->channel = pfvf->hw.rx_chan_base;
	req->op = NIX_RX_ACTION_DEFAULT;
	req->features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_DMAC);
	req->vtag0_valid = true;
	req->vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0;

	/* Send message to AF */
	err = otx2_sync_mbox_msg(&pfvf->mbox);
	mutex_unlock(&pfvf->mbox.lock);
	return err;
}

static int otx2_delete_rxvlan_offload_flow(struct otx2_nic *pfvf)
{
	struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
	struct npc_delete_flow_req *req;
	int err;

	mutex_lock(&pfvf->mbox.lock);
	req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
	if (!req) {
		mutex_unlock(&pfvf->mbox.lock);
		return -ENOMEM;
	}

	req->entry = flow_cfg->entry[flow_cfg->rx_vlan_offset];
	/* Send message to AF */
	err = otx2_sync_mbox_msg(&pfvf->mbox);
	mutex_unlock(&pfvf->mbox.lock);
	return err;
}

int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable)
{
	struct nix_vtag_config *req;
	struct mbox_msghdr *rsp_hdr;
	int err;

	/* Dont have enough mcam entries */
	if (!(pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT))
		return -ENOMEM;

	if (enable) {
		err = otx2_install_rxvlan_offload_flow(pf);
		if (err)
			return err;
	} else {
		err = otx2_delete_rxvlan_offload_flow(pf);
		if (err)
			return err;
	}

	mutex_lock(&pf->mbox.lock);
	req = otx2_mbox_alloc_msg_nix_vtag_cfg(&pf->mbox);
	if (!req) {
		mutex_unlock(&pf->mbox.lock);
		return -ENOMEM;
	}

	/* config strip, capture and size */
	req->vtag_size = VTAGSIZE_T4;
	req->cfg_type = 1; /* rx vlan cfg */
	req->rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0;
	req->rx.strip_vtag = enable;
	req->rx.capture_vtag = enable;

	err = otx2_sync_mbox_msg(&pf->mbox);
	if (err) {
		mutex_unlock(&pf->mbox.lock);
		return err;
	}

	rsp_hdr = otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
	if (IS_ERR(rsp_hdr)) {
		mutex_unlock(&pf->mbox.lock);
		return PTR_ERR(rsp_hdr);
	}

	mutex_unlock(&pf->mbox.lock);
	return rsp_hdr->rc;
}
Loading