[v1,44/58] net/octeontx2: implement VLAN utility functions

Message ID 20190602152434.23996-45-jerinj@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series OCTEON TX2 Ethdev driver |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Jerin Jacob Kollanukkaran June 2, 2019, 3:24 p.m. UTC
  From: Vivek Sharma <viveksharma@marvell.com>

Implement accessory functions needed for VLAN functionality.
Introduce VLAN related structures as well.

Maximum Vtag insertion size is controlled by SMQ configuration.
This patch also configure SMQ for supporting upto double vtag insertion.

Signed-off-by: Vivek Sharma <viveksharma@marvell.com>
---
 drivers/net/octeontx2/Makefile      |   1 +
 drivers/net/octeontx2/meson.build   |   1 +
 drivers/net/octeontx2/otx2_ethdev.c |  10 ++
 drivers/net/octeontx2/otx2_ethdev.h |  48 +++++++
 drivers/net/octeontx2/otx2_tm.c     |   5 +-
 drivers/net/octeontx2/otx2_vlan.c   | 190 ++++++++++++++++++++++++++++
 6 files changed, 253 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/octeontx2/otx2_vlan.c
  

Patch

diff --git a/drivers/net/octeontx2/Makefile b/drivers/net/octeontx2/Makefile
index d651c8c50..b1cc6d83b 100644
--- a/drivers/net/octeontx2/Makefile
+++ b/drivers/net/octeontx2/Makefile
@@ -36,6 +36,7 @@  SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX2_PMD) += \
 	otx2_ptp.c	\
 	otx2_flow.c	\
 	otx2_link.c	\
+	otx2_vlan.c	\
 	otx2_stats.c	\
 	otx2_lookup.c	\
 	otx2_ethdev.c	\
diff --git a/drivers/net/octeontx2/meson.build b/drivers/net/octeontx2/meson.build
index a2c494bb4..d5f272c8b 100644
--- a/drivers/net/octeontx2/meson.build
+++ b/drivers/net/octeontx2/meson.build
@@ -9,6 +9,7 @@  sources = files(
 		'otx2_ptp.c',
 		'otx2_flow.c',
 		'otx2_link.c',
+		'otx2_vlan.c',
 		'otx2_stats.c',
 		'otx2_lookup.c',
 		'otx2_ethdev.c',
diff --git a/drivers/net/octeontx2/otx2_ethdev.c b/drivers/net/octeontx2/otx2_ethdev.c
index bda5b4aa4..cfc22a2da 100644
--- a/drivers/net/octeontx2/otx2_ethdev.c
+++ b/drivers/net/octeontx2/otx2_ethdev.c
@@ -1079,6 +1079,7 @@  otx2_nix_configure(struct rte_eth_dev *eth_dev)
 	/* Free the resources allocated from the previous configure */
 	if (dev->configured == 1) {
 		otx2_nix_rxchan_bpid_cfg(eth_dev, false);
+		otx2_nix_vlan_fini(eth_dev);
 		otx2_flow_fini(dev);
 		oxt2_nix_unregister_queue_irqs(eth_dev);
 		nix_set_nop_rxtx_function(eth_dev);
@@ -1126,6 +1127,12 @@  otx2_nix_configure(struct rte_eth_dev *eth_dev)
 		goto free_nix_lf;
 	}
 
+	rc = otx2_nix_vlan_offload_init(eth_dev);
+	if (rc) {
+		otx2_err("Failed to init vlan offload rc=%d", rc);
+		goto free_nix_lf;
+	}
+
 	/* Register queue IRQs */
 	rc = oxt2_nix_register_queue_irqs(eth_dev);
 	if (rc) {
@@ -1546,6 +1553,9 @@  otx2_eth_dev_uninit(struct rte_eth_dev *eth_dev, bool mbox_close)
 	/* Disable nix bpid config */
 	otx2_nix_rxchan_bpid_cfg(eth_dev, false);
 
+	/* Disable vlan offloads */
+	otx2_nix_vlan_fini(eth_dev);
+
 	/* Disable other rte_flow entries */
 	otx2_flow_fini(dev);
 
diff --git a/drivers/net/octeontx2/otx2_ethdev.h b/drivers/net/octeontx2/otx2_ethdev.h
index e9123641c..b54018ae0 100644
--- a/drivers/net/octeontx2/otx2_ethdev.h
+++ b/drivers/net/octeontx2/otx2_ethdev.h
@@ -40,6 +40,7 @@ 
 /* Used for struct otx2_eth_dev::flags */
 #define OTX2_LINK_CFG_IN_PROGRESS_F	BIT_ULL(0)
 
+#define NIX_MAX_VTAG_INS		2
 #define VLAN_TAG_SIZE			4
 #define NIX_HW_L2_OVERHEAD		22
 /* ETH_HLEN+2*VLAN_HLEN */
@@ -163,6 +164,47 @@  struct otx2_fc_info {
 	uint16_t bpid[NIX_MAX_CHAN];
 };
 
+struct vlan_mkex_info {
+	struct npc_xtract_info la_xtract;
+	struct npc_xtract_info lb_xtract;
+	uint64_t lb_lt_offset;
+};
+
+struct vlan_entry {
+	uint32_t mcam_idx;
+	uint16_t vlan_id;
+	TAILQ_ENTRY(vlan_entry) next;
+};
+
+TAILQ_HEAD(otx2_vlan_filter_tbl, vlan_entry);
+
+struct otx2_vlan_info {
+	struct otx2_vlan_filter_tbl fltr_tbl;
+	/* MKEX layer info */
+	struct mcam_entry def_tx_mcam_ent;
+	struct mcam_entry def_rx_mcam_ent;
+	struct vlan_mkex_info mkex;
+	/* Default mcam entry that matches vlan packets */
+	uint32_t def_rx_mcam_idx;
+	uint32_t def_tx_mcam_idx;
+	/* MCAM entry that matches double vlan packets */
+	uint32_t qinq_mcam_idx;
+	/* Indices of tx_vtag def registers */
+	uint32_t outer_vlan_idx;
+	uint32_t inner_vlan_idx;
+	uint16_t outer_vlan_tpid;
+	uint16_t inner_vlan_tpid;
+	uint16_t pvid;
+	/* QinQ entry allocated before default one */
+	uint8_t qinq_before_def;
+	uint8_t pvid_insert_on;
+	/* Rx vtag action type */
+	uint8_t vtag_type_idx;
+	uint8_t filter_on;
+	uint8_t strip_on;
+	uint8_t qinq_on;
+};
+
 struct otx2_eth_dev {
 	OTX2_DEV; /* Base class */
 	MARKER otx2_eth_dev_data_start;
@@ -222,6 +264,7 @@  struct otx2_eth_dev {
 	struct rte_timecounter  systime_tc;
 	struct rte_timecounter  rx_tstamp_tc;
 	struct rte_timecounter  tx_tstamp_tc;
+	struct otx2_vlan_info vlan_info;
 } __rte_cache_aligned;
 
 struct otx2_eth_txq {
@@ -422,4 +465,9 @@  int otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev,
 				struct timespec *ts);
 int otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en);
 
+/* VLAN */
+int otx2_nix_vlan_offload_init(struct rte_eth_dev *eth_dev);
+int otx2_nix_vlan_fini(struct rte_eth_dev *eth_dev);
+
+
 #endif /* __OTX2_ETHDEV_H__ */
diff --git a/drivers/net/octeontx2/otx2_tm.c b/drivers/net/octeontx2/otx2_tm.c
index 4439389b8..246920695 100644
--- a/drivers/net/octeontx2/otx2_tm.c
+++ b/drivers/net/octeontx2/otx2_tm.c
@@ -359,7 +359,7 @@  populate_tm_registers(struct otx2_eth_dev *dev,
 
 		/* Set xoff which will be cleared later */
 		*reg++ = NIX_AF_SMQX_CFG(schq);
-		*regval++ = BIT_ULL(50) |
+		*regval++ = BIT_ULL(50) | ((uint64_t)NIX_MAX_VTAG_INS << 36) |
 				(NIX_MAX_HW_FRS << 8) | NIX_MIN_HW_FRS;
 		req->num_regs++;
 		*reg++ = NIX_AF_MDQX_PARENT(schq);
@@ -688,7 +688,8 @@  nix_smq_xoff(struct otx2_eth_dev *dev, uint16_t smq, bool enable)
 
 	req->reg[0] = NIX_AF_SMQX_CFG(smq);
 	/* Unmodified fields */
-	req->regval[0] = (NIX_MAX_HW_FRS << 8) | NIX_MIN_HW_FRS;
+	req->regval[0] = ((uint64_t)NIX_MAX_VTAG_INS << 36) |
+				(NIX_MAX_HW_FRS << 8) | NIX_MIN_HW_FRS;
 
 	if (enable)
 		req->regval[0] |= BIT_ULL(50) | BIT_ULL(49);
diff --git a/drivers/net/octeontx2/otx2_vlan.c b/drivers/net/octeontx2/otx2_vlan.c
new file mode 100644
index 000000000..b3136d2cf
--- /dev/null
+++ b/drivers/net/octeontx2/otx2_vlan.c
@@ -0,0 +1,190 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2019 Marvell International Ltd.
+ */
+
+#include <rte_malloc.h>
+#include <rte_tailq.h>
+
+#include "otx2_ethdev.h"
+#include "otx2_flow.h"
+
+
+#define VLAN_ID_MATCH	0x1
+#define VTAG_F_MATCH	0x2
+#define MAC_ADDR_MATCH	0x4
+#define QINQ_F_MATCH	0x8
+#define VLAN_DROP	0x10
+
+enum vtag_cfg_dir {
+	VTAG_TX,
+	VTAG_RX
+};
+
+static int
+__rte_unused nix_vlan_mcam_enb_dis(struct otx2_eth_dev *dev,
+				   uint32_t entry, const int enable)
+{
+	struct npc_mcam_ena_dis_entry_req *req;
+	struct otx2_mbox *mbox = dev->mbox;
+	int rc = -EINVAL;
+
+	if (enable)
+		req = otx2_mbox_alloc_msg_npc_mcam_ena_entry(mbox);
+	else
+		req = otx2_mbox_alloc_msg_npc_mcam_dis_entry(mbox);
+
+	req->entry = entry;
+
+	rc = otx2_mbox_process_msg(mbox, NULL);
+	return rc;
+}
+
+static int
+__rte_unused nix_vlan_mcam_free(struct otx2_eth_dev *dev, uint32_t entry)
+{
+	struct npc_mcam_free_entry_req *req;
+	struct otx2_mbox *mbox = dev->mbox;
+	int rc = -EINVAL;
+
+	req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox);
+	req->entry = entry;
+
+	rc = otx2_mbox_process_msg(mbox, NULL);
+	return rc;
+}
+
+static int
+__rte_unused nix_vlan_mcam_write(struct rte_eth_dev *eth_dev, uint16_t ent_idx,
+				 struct mcam_entry *entry, uint8_t intf)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	struct npc_mcam_write_entry_req *req;
+	struct otx2_mbox *mbox = dev->mbox;
+	struct msghdr *rsp;
+	int rc = -EINVAL;
+
+	req = otx2_mbox_alloc_msg_npc_mcam_write_entry(mbox);
+
+	req->entry = ent_idx;
+	req->intf = intf;
+	req->enable_entry = 1;
+	memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+
+	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	return rc;
+}
+
+static int
+__rte_unused nix_vlan_mcam_alloc_and_write(struct rte_eth_dev *eth_dev,
+					   struct mcam_entry *entry,
+					   uint8_t intf, bool drop)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	struct npc_mcam_alloc_and_write_entry_req *req;
+	struct npc_mcam_alloc_and_write_entry_rsp *rsp;
+	struct otx2_mbox *mbox = dev->mbox;
+	int rc = -EINVAL;
+
+	req = otx2_mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
+
+	if (intf == NPC_MCAM_RX) {
+		if (!drop && dev->vlan_info.def_rx_mcam_idx) {
+			req->priority = NPC_MCAM_HIGHER_PRIO;
+			req->ref_entry = dev->vlan_info.def_rx_mcam_idx;
+		} else if (drop && dev->vlan_info.qinq_mcam_idx) {
+			req->priority = NPC_MCAM_LOWER_PRIO;
+			req->ref_entry = dev->vlan_info.qinq_mcam_idx;
+		} else {
+			req->priority = NPC_MCAM_ANY_PRIO;
+			req->ref_entry = 0;
+		}
+	} else {
+		req->priority = NPC_MCAM_ANY_PRIO;
+		req->ref_entry = 0;
+	}
+
+	req->intf = intf;
+	req->enable_entry = 1;
+	memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+
+	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		return rc;
+
+	return rsp->entry;
+}
+
+static int
+nix_vlan_rx_mkex_offset(uint64_t mask)
+{
+	int nib_count = 0;
+
+	while (mask) {
+		nib_count += mask & 1;
+		mask >>= 1;
+	}
+
+	return nib_count * 4;
+}
+
+static int
+nix_vlan_get_mkex_info(struct otx2_eth_dev *dev)
+{
+	struct vlan_mkex_info *mkex = &dev->vlan_info.mkex;
+	struct otx2_npc_flow_info *npc = &dev->npc_flow;
+	struct npc_xtract_info *x_info = NULL;
+	uint64_t rx_keyx;
+	otx2_dxcfg_t *p;
+	int rc = -EINVAL;
+
+	if (npc == NULL) {
+		otx2_err("Missing npc mkex configuration");
+		return rc;
+	}
+
+#define NPC_KEX_CHAN_NIBBLE_ENA			0x7ULL
+#define NPC_KEX_LB_LTYPE_NIBBLE_ENA		0x1000ULL
+#define NPC_KEX_LB_LTYPE_NIBBLE_MASK		0xFFFULL
+
+	rx_keyx = npc->keyx_supp_nmask[NPC_MCAM_RX];
+	if ((rx_keyx & NPC_KEX_CHAN_NIBBLE_ENA) != NPC_KEX_CHAN_NIBBLE_ENA)
+		return rc;
+
+	if ((rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_ENA) !=
+	    NPC_KEX_LB_LTYPE_NIBBLE_ENA)
+		return rc;
+
+	mkex->lb_lt_offset =
+	    nix_vlan_rx_mkex_offset(rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_MASK);
+
+	p = &npc->prx_dxcfg;
+	x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LA][NPC_LT_LA_ETHER].xtract[0];
+	memcpy(&mkex->la_xtract, x_info, sizeof(struct npc_xtract_info));
+	x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LB][NPC_LT_LB_CTAG].xtract[0];
+	memcpy(&mkex->lb_xtract, x_info, sizeof(struct npc_xtract_info));
+
+	return 0;
+}
+
+int
+otx2_nix_vlan_offload_init(struct rte_eth_dev *eth_dev)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	int rc;
+
+	/* Port initialized for first time or restarted */
+	if (!dev->configured) {
+		rc = nix_vlan_get_mkex_info(dev);
+		if (rc) {
+			otx2_err("Failed to get vlan mkex info rc=%d", rc);
+			return rc;
+		}
+	}
+	return 0;
+}
+
+int
+otx2_nix_vlan_fini(__rte_unused struct rte_eth_dev *eth_dev)
+{
+	return 0;
+}