All of lore.kernel.org
 help / color / mirror / Atom feed
From: alvinx.zhang@intel.com
To: dev@dpdk.org
Cc: haiyue.wang@intel.com, xiaolong.ye@intel.com,
	qi.z.zhang@intel.com, beilei.xing@intel.com,
	Alvin Zhang <alvinx.zhang@intel.com>
Subject: [dpdk-dev] [PATCH v1 10/15] net/igc: implement feature of VLAN
Date: Mon,  9 Mar 2020 16:24:02 +0800	[thread overview]
Message-ID: <1583742247-370386-10-git-send-email-alvinx.zhang@intel.com> (raw)
In-Reply-To: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com>

From: Alvin Zhang <alvinx.zhang@intel.com>

Below ops ware added:
vlan_filter_set
vlan_offload_set
vlan_tpid_set
vlan_strip_queue_set

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
---
 doc/guides/nics/features/igc.ini |   2 +
 drivers/net/igc/igc_ethdev.c     | 169 +++++++++++++++++++++++++++++++++++++++
 drivers/net/igc/igc_ethdev.h     |  13 +++
 drivers/net/igc/igc_txrx.c       |  28 +++++++
 drivers/net/igc/igc_txrx.h       |   3 +-
 5 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/igc.ini b/doc/guides/nics/features/igc.ini
index 81d2a3b..f5c862b 100644
--- a/doc/guides/nics/features/igc.ini
+++ b/doc/guides/nics/features/igc.ini
@@ -29,6 +29,8 @@ Rx interrupt         = Y
 Flow control         = Y
 RSS key update       = Y
 RSS reta update      = Y
+VLAN filter          = Y
+VLAN offload         = Y
 Linux UIO            = Y
 Linux VFIO           = Y
 x86-64               = Y
diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c
index 022bfaf..ae3c42b 100644
--- a/drivers/net/igc/igc_ethdev.c
+++ b/drivers/net/igc/igc_ethdev.c
@@ -43,6 +43,13 @@
 /* MSI-X other interrupt vector */
 #define IGC_MSIX_OTHER_INTR_VEC		0
 
+/* External VLAN Enable bit mask */
+#define IGC_CTRL_EXT_EXT_VLAN		(1 << 26)
+
+/* External VLAN Ether Type bit mask and shift */
+#define IGC_VET_EXT			0xFFFF0000
+#define IGC_VET_EXT_SHIFT		16
+
 /* Per Queue Good Packets Received Count */
 #define IGC_PQGPRC(idx)		(0x10010 + 0x100 * (idx))
 /* Per Queue Good Octets Received Count */
@@ -221,6 +228,11 @@ static int eth_igc_rss_hash_update(struct rte_eth_dev *dev,
 			struct rte_eth_rss_conf *rss_conf);
 static int eth_igc_rss_hash_conf_get(struct rte_eth_dev *dev,
 			struct rte_eth_rss_conf *rss_conf);
+static int
+eth_igc_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on);
+static int eth_igc_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int eth_igc_vlan_tpid_set(struct rte_eth_dev *dev,
+		      enum rte_vlan_type vlan_type, uint16_t tpid);
 
 static const struct eth_dev_ops eth_igc_ops = {
 	.dev_configure		= eth_igc_configure,
@@ -273,6 +285,10 @@ static int eth_igc_rss_hash_conf_get(struct rte_eth_dev *dev,
 	.reta_query		= eth_igc_rss_reta_query,
 	.rss_hash_update	= eth_igc_rss_hash_update,
 	.rss_hash_conf_get	= eth_igc_rss_hash_conf_get,
+	.vlan_filter_set	= eth_igc_vlan_filter_set,
+	.vlan_offload_set	= eth_igc_vlan_offload_set,
+	.vlan_tpid_set		= eth_igc_vlan_tpid_set,
+	.vlan_strip_queue_set	= eth_igc_vlan_strip_queue_set,
 };
 
 /*
@@ -944,6 +960,11 @@ static int eth_igc_rss_hash_conf_get(struct rte_eth_dev *dev,
 
 	igc_clear_hw_cntrs_base_generic(hw);
 
+	/* VLAN Offload Settings */
+	eth_igc_vlan_offload_set(dev,
+		ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK |
+		ETH_VLAN_EXTEND_MASK);
+
 	/* Setup link speed and duplex */
 	speeds = &dev->data->dev_conf.link_speeds;
 	if (*speeds == ETH_LINK_SPEED_AUTONEG) {
@@ -2362,6 +2383,154 @@ static int eth_igc_rss_hash_conf_get(struct rte_eth_dev *dev,
 }
 
 static int
+eth_igc_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	struct igc_vfta *shadow_vfta = IGC_DEV_PRIVATE_VFTA(dev);
+	uint32_t vfta;
+	uint32_t vid_idx;
+	uint32_t vid_bit;
+
+	vid_idx = (vlan_id >> IGC_VFTA_ENTRY_SHIFT) & IGC_VFTA_ENTRY_MASK;
+	vid_bit = 1u << (vlan_id & IGC_VFTA_ENTRY_BIT_SHIFT_MASK);
+	vfta = shadow_vfta->vfta[vid_idx];
+	if (on)
+		vfta |= vid_bit;
+	else
+		vfta &= ~vid_bit;
+	IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, vid_idx, vfta);
+
+	/* update local VFTA copy */
+	shadow_vfta->vfta[vid_idx] = vfta;
+
+	return 0;
+}
+
+static void
+igc_vlan_hw_filter_disable(struct rte_eth_dev *dev)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	igc_read_reg_check_clear_bits(hw, IGC_RCTL,
+			IGC_RCTL_CFIEN | IGC_RCTL_VFE);
+}
+
+static void
+igc_vlan_hw_filter_enable(struct rte_eth_dev *dev)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	struct igc_vfta *shadow_vfta = IGC_DEV_PRIVATE_VFTA(dev);
+	uint32_t reg_val;
+	int i;
+
+	/* Filter Table Enable, CFI not used for packet acceptance */
+	reg_val = IGC_READ_REG(hw, IGC_RCTL);
+	reg_val &= ~IGC_RCTL_CFIEN;
+	reg_val |= IGC_RCTL_VFE;
+	IGC_WRITE_REG(hw, IGC_RCTL, reg_val);
+
+	/* restore VFTA table */
+	for (i = 0; i < IGC_VFTA_SIZE; i++)
+		IGC_WRITE_REG_ARRAY(hw, IGC_VFTA, i, shadow_vfta->vfta[i]);
+}
+
+static void
+igc_vlan_hw_strip_disable(struct rte_eth_dev *dev)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+
+	igc_read_reg_check_clear_bits(hw, IGC_CTRL, IGC_CTRL_VME);
+}
+
+static void
+igc_vlan_hw_strip_enable(struct rte_eth_dev *dev)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+
+	igc_read_reg_check_set_bits(hw, IGC_CTRL, IGC_CTRL_VME);
+}
+
+static void
+igc_vlan_hw_extend_disable(struct rte_eth_dev *dev)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+
+	igc_read_reg_check_clear_bits(hw, IGC_CTRL_EXT, IGC_CTRL_EXT_EXT_VLAN);
+
+	/* Update maximum packet length */
+	if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
+		IGC_WRITE_REG(hw, IGC_RLPML,
+			dev->data->dev_conf.rxmode.max_rx_pkt_len +
+						VLAN_TAG_SIZE);
+}
+
+static void
+igc_vlan_hw_extend_enable(struct rte_eth_dev *dev)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+
+	igc_read_reg_check_set_bits(hw, IGC_CTRL_EXT, IGC_CTRL_EXT_EXT_VLAN);
+
+	/* Update maximum packet length */
+	if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
+		IGC_WRITE_REG(hw, IGC_RLPML,
+			dev->data->dev_conf.rxmode.max_rx_pkt_len +
+						2 * VLAN_TAG_SIZE);
+}
+
+static int
+eth_igc_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	struct rte_eth_rxmode *rxmode;
+
+	rxmode = &dev->data->dev_conf.rxmode;
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
+			igc_vlan_hw_strip_enable(dev);
+		else
+			igc_vlan_hw_strip_disable(dev);
+	}
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
+			igc_vlan_hw_filter_enable(dev);
+		else
+			igc_vlan_hw_filter_disable(dev);
+	}
+
+	if (mask & ETH_VLAN_EXTEND_MASK) {
+		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_EXTEND)
+			igc_vlan_hw_extend_enable(dev);
+		else
+			igc_vlan_hw_extend_disable(dev);
+	}
+
+	return 0;
+}
+
+static int
+eth_igc_vlan_tpid_set(struct rte_eth_dev *dev,
+		      enum rte_vlan_type vlan_type,
+		      uint16_t tpid)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	uint32_t reg_val;
+
+	/* only outer TPID of double VLAN can be configured*/
+	if (vlan_type == ETH_VLAN_TYPE_OUTER) {
+		reg_val = IGC_READ_REG(hw, IGC_VET);
+		reg_val = (reg_val & (~IGC_VET_EXT)) |
+			((uint32_t)tpid << IGC_VET_EXT_SHIFT);
+		IGC_WRITE_REG(hw, IGC_VET, reg_val);
+
+		return 0;
+	}
+
+	/* all other TPID values are read-only*/
+	PMD_DRV_LOG(ERR, "Not supported");
+	return -ENOTSUP;
+}
+
+static int
 eth_igc_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	struct rte_pci_device *pci_dev)
 {
diff --git a/drivers/net/igc/igc_ethdev.h b/drivers/net/igc/igc_ethdev.h
index 63c7abf..1a157ee 100644
--- a/drivers/net/igc/igc_ethdev.h
+++ b/drivers/net/igc/igc_ethdev.h
@@ -17,6 +17,10 @@
 #endif
 
 #define IGC_RSS_RDT_SIZD		128
+
+/* VLAN filter table size */
+#define IGC_VFTA_SIZE			128
+
 #define IGC_QUEUE_PAIRS_NUM		4
 
 #define IGC_HKEY_MAX_INDEX		10
@@ -117,6 +121,11 @@ struct igc_hw_queue_stats {
 	/* per transmit queue drop packet count */
 };
 
+/* local vfta copy */
+struct igc_vfta {
+	uint32_t vfta[IGC_VFTA_SIZE];
+};
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -128,6 +137,7 @@ struct igc_adapter {
 	int16_t rxq_stats_map[IGC_QUEUE_PAIRS_NUM];
 
 	struct igc_interrupt	intr;
+	struct igc_vfta	shadow_vfta;
 	bool		stopped;
 };
 
@@ -145,6 +155,9 @@ struct igc_adapter {
 #define IGC_DEV_PRIVATE_INTR(_dev) \
 	(&((struct igc_adapter *)(_dev)->data->dev_private)->intr)
 
+#define IGC_DEV_PRIVATE_VFTA(_dev) \
+	(&((struct igc_adapter *)(_dev)->data->dev_private)->shadow_vfta)
+
 static inline void
 igc_read_reg_check_set_bits(struct igc_hw *hw, uint32_t reg, uint32_t bits)
 {
diff --git a/drivers/net/igc/igc_txrx.c b/drivers/net/igc/igc_txrx.c
index f797d51..9147fe8 100644
--- a/drivers/net/igc/igc_txrx.c
+++ b/drivers/net/igc/igc_txrx.c
@@ -2123,3 +2123,31 @@ int eth_igc_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 	qinfo->conf.tx_thresh.wthresh = txq->wthresh;
 	qinfo->conf.offloads = txq->offloads;
 }
+
+void
+eth_igc_vlan_strip_queue_set(struct rte_eth_dev *dev,
+			uint16_t rx_queue_id, int on)
+{
+	struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev);
+	struct igc_rx_queue *rxq = dev->data->rx_queues[rx_queue_id];
+	uint32_t reg_val;
+
+	if (rx_queue_id >= IGC_QUEUE_PAIRS_NUM) {
+		PMD_DRV_LOG(ERR, "Queue index(%u) illegal, max is %u",
+			rx_queue_id, IGC_QUEUE_PAIRS_NUM - 1);
+		return;
+	}
+
+	reg_val = IGC_READ_REG(hw, IGC_DVMOLR(rx_queue_id));
+	if (on) {
+		/* If vlan been stripped off, the CRC is meaningless. */
+		reg_val |= IGC_DVMOLR_STRVLAN | IGC_DVMOLR_STRCRC;
+		rxq->offloads |= ETH_VLAN_STRIP_MASK;
+	} else {
+		reg_val &= ~(IGC_DVMOLR_STRVLAN | IGC_DVMOLR_HIDVLAN);
+		if (dev->data->dev_conf.rxmode.offloads & ETH_VLAN_STRIP_MASK)
+			rxq->offloads &= ~ETH_VLAN_STRIP_MASK;
+	}
+
+	IGC_WRITE_REG(hw, IGC_DVMOLR(rx_queue_id), reg_val);
+}
diff --git a/drivers/net/igc/igc_txrx.h b/drivers/net/igc/igc_txrx.h
index e594acc..df7b071 100644
--- a/drivers/net/igc/igc_txrx.h
+++ b/drivers/net/igc/igc_txrx.h
@@ -44,7 +44,8 @@ void eth_igc_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	struct rte_eth_rxq_info *qinfo);
 void eth_igc_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 	struct rte_eth_txq_info *qinfo);
-
+void eth_igc_vlan_strip_queue_set(struct rte_eth_dev *dev,
+			uint16_t rx_queue_id, int on);
 #ifdef __cplusplus
 }
 #endif
-- 
1.8.3.1


  parent reply	other threads:[~2020-03-09  8:30 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-09  8:23 [dpdk-dev] [PATCH v1 01/15] net/igc: add igc PMD alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 02/15] net/igc: update base share codes alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 03/15] net/igc: device initialization alvinx.zhang
2020-03-12  4:42   ` Ye Xiaolong
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 04/15] net/igc: implement device base ops alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 05/15] net/igc: support reception and transmission of packets alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 06/15] net/igc: implement status API alvinx.zhang
2020-03-09  8:23 ` [dpdk-dev] [PATCH v1 07/15] net/igc: enable Rx queue interrupts alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 08/15] net/igc: implement flow control ops alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 09/15] net/igc: implement RSS API alvinx.zhang
2020-03-09  8:24 ` alvinx.zhang [this message]
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 11/15] net/igc: implement ether-type filter alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 12/15] net/igc: implement 2-tuple filter alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 13/15] net/igc: implement TCP SYN filter alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 14/15] net/igc: implement hash filter configure alvinx.zhang
2020-03-09  8:24 ` [dpdk-dev] [PATCH v1 15/15] net/igc: implement flow API alvinx.zhang
2020-03-09  8:35 ` [dpdk-dev] [PATCH v1 01/15] net/igc: add igc PMD Ye Xiaolong
2020-03-12  3:09 ` Ye Xiaolong
2020-03-20  2:46 ` [dpdk-dev] [PATCH v2 00/14] " alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 01/14] net/igc: add " alvinx.zhang
2020-04-03 12:21     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 02/14] net/igc: support device initialization alvinx.zhang
2020-04-03 12:23     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 03/14] net/igc: implement device base ops alvinx.zhang
2020-04-03 12:24     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 04/14] net/igc: support reception and transmission of packets alvinx.zhang
2020-04-03 12:27     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 05/14] net/igc: implement status API alvinx.zhang
2020-04-03 12:24     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 06/14] net/igc: enable Rx queue interrupts alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 07/14] net/igc: implement flow control ops alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 08/14] net/igc: implement RSS API alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 09/14] net/igc: implement feature of VLAN alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 10/14] net/igc: implement ether-type filter alvinx.zhang
2020-04-03 12:26     ` Ferruh Yigit
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 11/14] net/igc: implement 2-tuple filter alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 12/14] net/igc: implement TCP SYN filter alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 13/14] net/igc: implement hash filter configure alvinx.zhang
2020-03-20  2:46   ` [dpdk-dev] [PATCH v2 14/14] net/igc: implement flow API alvinx.zhang
2020-04-03 12:26     ` Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1583742247-370386-10-git-send-email-alvinx.zhang@intel.com \
    --to=alvinx.zhang@intel.com \
    --cc=beilei.xing@intel.com \
    --cc=dev@dpdk.org \
    --cc=haiyue.wang@intel.com \
    --cc=qi.z.zhang@intel.com \
    --cc=xiaolong.ye@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.