From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id C593FA04DC; Mon, 19 Oct 2020 11:07:44 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 73DA3D013; Mon, 19 Oct 2020 10:53:50 +0200 (CEST) Received: from smtpproxy21.qq.com (smtpbg704.qq.com [203.205.195.105]) by dpdk.org (Postfix) with ESMTP id 3447CC944 for ; Mon, 19 Oct 2020 10:53:18 +0200 (CEST) X-QQ-mid: bizesmtp6t1603097594tqvoo0f0m Received: from localhost.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Mon, 19 Oct 2020 16:53:13 +0800 (CST) X-QQ-SSF: 01400000002000C0C000B00A0000000 X-QQ-FEAT: IyFUh2Wdp9o/1XRL2pM5GgdYcMgpkZv8HhDCHynzwqHLYZ8EJgvtqC/TcPibL EIDYgHg4CkXFztn86nVrSI+/UCRDOLEj5Bt4YUEE/T997VDSV/XMIaOEfrHeTzByCBkYoLh plXCbgoNaRQE/rIprNokWTuTxextXthdYJhxJB+qJMG/ey44/1oxNAQyiLBbRBlMSVw4MqU Qu3kFR5jQ6Xm6FscHcZdi84ScClxQGI1VoyfAMT8rY4JLVyjx4ToK6D6+pxAslpggZRy3iQ ySDLeXS2MNtMJhNnujLI8k68ymxi1DKwC6N6JtByI1x4PJ6iYKccE9z3hW3sI50J0rnD7Pn Z0XieccQmUA/U4j3gA= X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Mon, 19 Oct 2020 16:53:53 +0800 Message-Id: <20201019085415.82207-37-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.18.4 In-Reply-To: <20201019085415.82207-1-jiawenwu@trustnetic.com> References: <20201019085415.82207-1-jiawenwu@trustnetic.com> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v4 36/58] net/txgbe: add VLAN handle support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add VLAN filter, tpid, offload and strip set support. Signed-off-by: Jiawen Wu --- doc/guides/nics/features/txgbe.ini | 1 + doc/guides/nics/txgbe.rst | 3 +- drivers/net/txgbe/base/txgbe_hw.c | 31 +++ drivers/net/txgbe/base/txgbe_hw.h | 1 + drivers/net/txgbe/base/txgbe_type.h | 2 + drivers/net/txgbe/txgbe_ethdev.c | 370 ++++++++++++++++++++++++++++ drivers/net/txgbe/txgbe_ethdev.h | 34 +++ 7 files changed, 441 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/features/txgbe.ini b/doc/guides/nics/features/txgbe.ini index ad7513eca..bd39d6642 100644 --- a/doc/guides/nics/features/txgbe.ini +++ b/doc/guides/nics/features/txgbe.ini @@ -15,6 +15,7 @@ LRO = Y TSO = Y Unicast MAC filter = Y Multicast MAC filter = Y +VLAN filter = Y CRC offload = P VLAN offload = P QinQ offload = P diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst index b020aaf98..212167d22 100644 --- a/doc/guides/nics/txgbe.rst +++ b/doc/guides/nics/txgbe.rst @@ -11,9 +11,10 @@ Features -------- - Multiple queues for TX and RX -- MAC filtering +- MAC/VLAN filtering - Packet type information - Checksum offload +- VLAN/QinQ stripping and inserting - TSO offload - Port hardware statistics - Jumbo frames diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 5e81464e9..f3524ec2b 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -12,6 +12,7 @@ #define TXGBE_RAPTOR_MAX_RX_QUEUES 128 #define TXGBE_RAPTOR_RAR_ENTRIES 128 #define TXGBE_RAPTOR_MC_TBL_SIZE 128 +#define TXGBE_RAPTOR_VFT_TBL_SIZE 128 static s32 txgbe_setup_copper_link_raptor(struct txgbe_hw *hw, u32 speed, @@ -39,6 +40,9 @@ s32 txgbe_start_hw(struct txgbe_hw *hw) /* Set the media type */ hw->phy.media_type = hw->phy.get_media_type(hw); + /* Clear the VLAN filter table */ + hw->mac.clear_vfta(hw); + /* Clear statistics registers */ hw->mac.clear_hw_cntrs(hw); @@ -907,6 +911,31 @@ s32 txgbe_init_uta_tables(struct txgbe_hw *hw) return 0; } +/** + * txgbe_clear_vfta - Clear VLAN filter table + * @hw: pointer to hardware structure + * + * Clears the VLAN filer table, and the VMDq index associated with the filter + **/ +s32 txgbe_clear_vfta(struct txgbe_hw *hw) +{ + u32 offset; + + DEBUGFUNC("txgbe_clear_vfta"); + + for (offset = 0; offset < hw->mac.vft_size; offset++) + wr32(hw, TXGBE_VLANTBL(offset), 0); + + for (offset = 0; offset < TXGBE_NUM_POOL; offset++) { + wr32(hw, TXGBE_PSRVLANIDX, offset); + wr32(hw, TXGBE_PSRVLAN, 0); + wr32(hw, TXGBE_PSRVLANPLM(0), 0); + wr32(hw, TXGBE_PSRVLANPLM(1), 0); + } + + return 0; +} + /** * txgbe_need_crosstalk_fix - Determine if we need to do cross talk fix * @hw: pointer to hardware structure @@ -1593,6 +1622,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) mac->init_rx_addrs = txgbe_init_rx_addrs; mac->enable_rx = txgbe_enable_rx; mac->disable_rx = txgbe_disable_rx; + mac->clear_vfta = txgbe_clear_vfta; mac->init_uta_tables = txgbe_init_uta_tables; mac->setup_sfp = txgbe_setup_sfp_modules; /* Link */ @@ -1618,6 +1648,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw) rom->calc_checksum = txgbe_calc_eeprom_checksum; mac->mcft_size = TXGBE_RAPTOR_MC_TBL_SIZE; + mac->vft_size = TXGBE_RAPTOR_VFT_TBL_SIZE; mac->num_rar_entries = TXGBE_RAPTOR_RAR_ENTRIES; mac->max_rx_queues = TXGBE_RAPTOR_MAX_RX_QUEUES; mac->max_tx_queues = TXGBE_RAPTOR_MAX_TX_QUEUES; diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index 48543b951..ac4f7fbe8 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -34,6 +34,7 @@ s32 txgbe_get_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr); s32 txgbe_set_san_mac_addr(struct txgbe_hw *hw, u8 *san_mac_addr); s32 txgbe_init_uta_tables(struct txgbe_hw *hw); +s32 txgbe_clear_vfta(struct txgbe_hw *hw); s32 txgbe_check_mac_link(struct txgbe_hw *hw, u32 *speed, bool *link_up, bool link_up_wait_to_complete); diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 76f769008..dc038a5ba 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -10,6 +10,7 @@ #define TXGBE_FRAME_SIZE_MAX (9728) /* Maximum frame size, +FCS */ #define TXGBE_FRAME_SIZE_DFT (1518) /* Default frame size, +FCS */ +#define TXGBE_NUM_POOL (64) #define TXGBE_MAX_UP 8 #define TXGBE_MAX_QP (128) #define TXGBE_MAX_UTA 128 @@ -507,6 +508,7 @@ struct txgbe_mac_info { u32 mta_shadow[TXGBE_MAX_MTA]; s32 mc_filter_type; u32 mcft_size; + u32 vft_size; u32 num_rar_entries; u32 max_tx_queues; u32 max_rx_queues; diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index e6b0489d7..30dd922be 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -28,6 +28,9 @@ static int txgbe_dev_close(struct rte_eth_dev *dev); static int txgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); static int txgbe_dev_stats_reset(struct rte_eth_dev *dev); +static void txgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue); +static void txgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, + uint16_t queue); static void txgbe_dev_link_status_print(struct rte_eth_dev *dev); static int txgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on); @@ -40,6 +43,24 @@ static void txgbe_dev_interrupt_handler(void *param); static void txgbe_dev_interrupt_delayed_handler(void *param); static void txgbe_configure_msix(struct rte_eth_dev *dev); +#define TXGBE_SET_HWSTRIP(h, q) do {\ + uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \ + uint32_t bit = (q) % (sizeof((h)->bitmap[0]) * NBBY); \ + (h)->bitmap[idx] |= 1 << bit;\ + } while (0) + +#define TXGBE_CLEAR_HWSTRIP(h, q) do {\ + uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \ + uint32_t bit = (q) % (sizeof((h)->bitmap[0]) * NBBY); \ + (h)->bitmap[idx] &= ~(1 << bit);\ + } while (0) + +#define TXGBE_GET_HWSTRIP(h, q, r) do {\ + uint32_t idx = (q) / (sizeof((h)->bitmap[0]) * NBBY); \ + uint32_t bit = (q) % (sizeof((h)->bitmap[0]) * NBBY); \ + (r) = (h)->bitmap[idx] >> bit & 1;\ + } while (0) + /* * The set of PCI devices this driver supports */ @@ -320,6 +341,8 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); struct txgbe_hw *hw = TXGBE_DEV_HW(eth_dev); + struct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(eth_dev); + struct txgbe_hwstrip *hwstrip = TXGBE_DEV_HWSTRIP(eth_dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; const struct rte_memzone *mz; uint16_t csum; @@ -460,6 +483,12 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -ENOMEM; } + /* initialize the vfta */ + memset(shadow_vfta, 0, sizeof(*shadow_vfta)); + + /* initialize the hw strip bitmap*/ + memset(hwstrip, 0, sizeof(*hwstrip)); + if (txgbe_is_sfp(hw) && hw->phy.sfp_type != txgbe_sfp_type_not_present) PMD_INIT_LOG(DEBUG, "MAC: %d, PHY: %d, SFP+: %d", (int)hw->mac.type, (int)hw->phy.type, @@ -548,6 +577,334 @@ static struct rte_pci_driver rte_txgbe_pmd = { .remove = eth_txgbe_pci_remove, }; +static int +txgbe_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(dev); + uint32_t vfta; + uint32_t vid_idx; + uint32_t vid_bit; + + vid_idx = (uint32_t)((vlan_id >> 5) & 0x7F); + vid_bit = (uint32_t)(1 << (vlan_id & 0x1F)); + vfta = rd32(hw, TXGBE_VLANTBL(vid_idx)); + if (on) + vfta |= vid_bit; + else + vfta &= ~vid_bit; + wr32(hw, TXGBE_VLANTBL(vid_idx), vfta); + + /* update local VFTA copy */ + shadow_vfta->vfta[vid_idx] = vfta; + + return 0; +} + +static void +txgbe_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_rx_queue *rxq; + bool restart; + uint32_t rxcfg, rxbal, rxbah; + + if (on) + txgbe_vlan_hw_strip_enable(dev, queue); + else + txgbe_vlan_hw_strip_disable(dev, queue); + + rxq = dev->data->rx_queues[queue]; + rxbal = rd32(hw, TXGBE_RXBAL(rxq->reg_idx)); + rxbah = rd32(hw, TXGBE_RXBAH(rxq->reg_idx)); + rxcfg = rd32(hw, TXGBE_RXCFG(rxq->reg_idx)); + if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) { + restart = (rxcfg & TXGBE_RXCFG_ENA) && + !(rxcfg & TXGBE_RXCFG_VLAN); + rxcfg |= TXGBE_RXCFG_VLAN; + } else { + restart = (rxcfg & TXGBE_RXCFG_ENA) && + (rxcfg & TXGBE_RXCFG_VLAN); + rxcfg &= ~TXGBE_RXCFG_VLAN; + } + rxcfg &= ~TXGBE_RXCFG_ENA; + + if (restart) { + /* set vlan strip for ring */ + txgbe_dev_rx_queue_stop(dev, queue); + wr32(hw, TXGBE_RXBAL(rxq->reg_idx), rxbal); + wr32(hw, TXGBE_RXBAH(rxq->reg_idx), rxbah); + wr32(hw, TXGBE_RXCFG(rxq->reg_idx), rxcfg); + txgbe_dev_rx_queue_start(dev, queue); + } +} + +static int +txgbe_vlan_tpid_set(struct rte_eth_dev *dev, + enum rte_vlan_type vlan_type, + uint16_t tpid) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int ret = 0; + uint32_t portctrl, vlan_ext, qinq; + + portctrl = rd32(hw, TXGBE_PORTCTL); + + vlan_ext = (portctrl & TXGBE_PORTCTL_VLANEXT); + qinq = vlan_ext && (portctrl & TXGBE_PORTCTL_QINQ); + switch (vlan_type) { + case ETH_VLAN_TYPE_INNER: + if (vlan_ext) { + wr32m(hw, TXGBE_VLANCTL, + TXGBE_VLANCTL_TPID_MASK, + TXGBE_VLANCTL_TPID(tpid)); + wr32m(hw, TXGBE_DMATXCTRL, + TXGBE_DMATXCTRL_TPID_MASK, + TXGBE_DMATXCTRL_TPID(tpid)); + } else { + ret = -ENOTSUP; + PMD_DRV_LOG(ERR, "Inner type is not supported" + " by single VLAN"); + } + + if (qinq) { + wr32m(hw, TXGBE_TAGTPID(0), + TXGBE_TAGTPID_LSB_MASK, + TXGBE_TAGTPID_LSB(tpid)); + } + break; + case ETH_VLAN_TYPE_OUTER: + if (vlan_ext) { + /* Only the high 16-bits is valid */ + wr32m(hw, TXGBE_EXTAG, + TXGBE_EXTAG_VLAN_MASK, + TXGBE_EXTAG_VLAN(tpid)); + } else { + wr32m(hw, TXGBE_VLANCTL, + TXGBE_VLANCTL_TPID_MASK, + TXGBE_VLANCTL_TPID(tpid)); + wr32m(hw, TXGBE_DMATXCTRL, + TXGBE_DMATXCTRL_TPID_MASK, + TXGBE_DMATXCTRL_TPID(tpid)); + } + + if (qinq) { + wr32m(hw, TXGBE_TAGTPID(0), + TXGBE_TAGTPID_MSB_MASK, + TXGBE_TAGTPID_MSB(tpid)); + } + break; + default: + PMD_DRV_LOG(ERR, "Unsupported VLAN type %d", vlan_type); + return -EINVAL; + } + + return ret; +} + +void +txgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t vlnctrl; + + PMD_INIT_FUNC_TRACE(); + + /* Filter Table Disable */ + vlnctrl = rd32(hw, TXGBE_VLANCTL); + vlnctrl &= ~TXGBE_VLANCTL_VFE; + wr32(hw, TXGBE_VLANCTL, vlnctrl); +} + +void +txgbe_vlan_hw_filter_enable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_vfta *shadow_vfta = TXGBE_DEV_VFTA(dev); + uint32_t vlnctrl; + uint16_t i; + + PMD_INIT_FUNC_TRACE(); + + /* Filter Table Enable */ + vlnctrl = rd32(hw, TXGBE_VLANCTL); + vlnctrl &= ~TXGBE_VLANCTL_CFIENA; + vlnctrl |= TXGBE_VLANCTL_VFE; + wr32(hw, TXGBE_VLANCTL, vlnctrl); + + /* write whatever is in local vfta copy */ + for (i = 0; i < TXGBE_VFTA_SIZE; i++) + wr32(hw, TXGBE_VLANTBL(i), shadow_vfta->vfta[i]); +} + +void +txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on) +{ + struct txgbe_hwstrip *hwstrip = TXGBE_DEV_HWSTRIP(dev); + struct txgbe_rx_queue *rxq; + + if (queue >= TXGBE_MAX_RX_QUEUE_NUM) + return; + + if (on) + TXGBE_SET_HWSTRIP(hwstrip, queue); + else + TXGBE_CLEAR_HWSTRIP(hwstrip, queue); + + if (queue >= dev->data->nb_rx_queues) + return; + + rxq = dev->data->rx_queues[queue]; + + if (on) { + rxq->vlan_flags = PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED; + rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; + } else { + rxq->vlan_flags = PKT_RX_VLAN; + rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; + } +} + +static void +txgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev, uint16_t queue) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_RXCFG(queue)); + ctrl &= ~TXGBE_RXCFG_VLAN; + wr32(hw, TXGBE_RXCFG(queue), ctrl); + + /* record those setting for HW strip per queue */ + txgbe_vlan_hw_strip_bitmap_set(dev, queue, 0); +} + +static void +txgbe_vlan_hw_strip_enable(struct rte_eth_dev *dev, uint16_t queue) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_RXCFG(queue)); + ctrl |= TXGBE_RXCFG_VLAN; + wr32(hw, TXGBE_RXCFG(queue), ctrl); + + /* record those setting for HW strip per queue */ + txgbe_vlan_hw_strip_bitmap_set(dev, queue, 1); +} + +static void +txgbe_vlan_hw_extend_disable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_PORTCTL); + ctrl &= ~TXGBE_PORTCTL_VLANEXT; + ctrl &= ~TXGBE_PORTCTL_QINQ; + wr32(hw, TXGBE_PORTCTL, ctrl); +} + +static void +txgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode; + uint32_t ctrl; + + PMD_INIT_FUNC_TRACE(); + + ctrl = rd32(hw, TXGBE_PORTCTL); + ctrl |= TXGBE_PORTCTL_VLANEXT; + if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP || + txmode->offloads & DEV_TX_OFFLOAD_QINQ_INSERT) + ctrl |= TXGBE_PORTCTL_QINQ; + wr32(hw, TXGBE_PORTCTL, ctrl); +} + +void +txgbe_vlan_hw_strip_config(struct rte_eth_dev *dev) +{ + struct txgbe_rx_queue *rxq; + uint16_t i; + + PMD_INIT_FUNC_TRACE(); + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + + if (rxq->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) + txgbe_vlan_strip_queue_set(dev, i, 1); + else + txgbe_vlan_strip_queue_set(dev, i, 0); + } +} + +void +txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, int mask) +{ + uint16_t i; + struct rte_eth_rxmode *rxmode; + struct txgbe_rx_queue *rxq; + + if (mask & ETH_VLAN_STRIP_MASK) { + rxmode = &dev->data->dev_conf.rxmode; + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + rxq->offloads |= DEV_RX_OFFLOAD_VLAN_STRIP; + } + else + for (i = 0; i < dev->data->nb_rx_queues; i++) { + rxq = dev->data->rx_queues[i]; + rxq->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP; + } + } +} + +static int +txgbe_vlan_offload_config(struct rte_eth_dev *dev, int mask) +{ + struct rte_eth_rxmode *rxmode; + rxmode = &dev->data->dev_conf.rxmode; + + if (mask & ETH_VLAN_STRIP_MASK) + txgbe_vlan_hw_strip_config(dev); + + if (mask & ETH_VLAN_FILTER_MASK) { + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) + txgbe_vlan_hw_filter_enable(dev); + else + txgbe_vlan_hw_filter_disable(dev); + } + + if (mask & ETH_VLAN_EXTEND_MASK) { + if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_EXTEND) + txgbe_vlan_hw_extend_enable(dev); + else + txgbe_vlan_hw_extend_disable(dev); + } + + return 0; +} + +static int +txgbe_vlan_offload_set(struct rte_eth_dev *dev, int mask) +{ + txgbe_config_vlan_strip_on_all_queues(dev, mask); + + txgbe_vlan_offload_config(dev, mask); + + return 0; +} + static int txgbe_check_vf_rss_rxq_num(struct rte_eth_dev *dev, uint16_t nb_rx_q) { @@ -772,6 +1129,7 @@ txgbe_dev_start(struct rte_eth_dev *dev) bool link_up = false, negotiate = 0; uint32_t speed = 0; uint32_t allowed_speeds = 0; + int mask = 0; int status; uint32_t *link_speeds; @@ -844,6 +1202,14 @@ txgbe_dev_start(struct rte_eth_dev *dev) goto error; } + mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | + ETH_VLAN_EXTEND_MASK; + err = txgbe_vlan_offload_config(dev, mask); + if (err) { + PMD_INIT_LOG(ERR, "Unable to set VLAN offload"); + goto error; + } + err = txgbe_dev_rxtx_start(dev); if (err < 0) { PMD_INIT_LOG(ERR, "Unable to start rxtx queues"); @@ -2431,6 +2797,10 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = { .xstats_get_names_by_id = txgbe_dev_xstats_get_names_by_id, .queue_stats_mapping_set = txgbe_dev_queue_stats_mapping_set, .dev_supported_ptypes_get = txgbe_dev_supported_ptypes_get, + .vlan_filter_set = txgbe_vlan_filter_set, + .vlan_tpid_set = txgbe_vlan_tpid_set, + .vlan_offload_set = txgbe_vlan_offload_set, + .vlan_strip_queue_set = txgbe_vlan_strip_queue_set, .rx_queue_start = txgbe_dev_rx_queue_start, .rx_queue_stop = txgbe_dev_rx_queue_stop, .tx_queue_start = txgbe_dev_tx_queue_start, diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index e18ddc1c5..ad57e0b61 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -19,12 +19,19 @@ * Defines that were not part of txgbe_type.h as they are not used by the * FreeBSD driver. */ +#define TXGBE_VFTA_SIZE 128 #define TXGBE_VLAN_TAG_SIZE 4 #define TXGBE_HKEY_MAX_INDEX 10 /*Default value of Max Rx Queue*/ #define TXGBE_MAX_RX_QUEUE_NUM 128 #define TXGBE_VMDQ_DCB_NB_QUEUES TXGBE_MAX_RX_QUEUE_NUM +#ifndef NBBY +#define NBBY 8 /* number of bits in a byte */ +#endif +#define TXGBE_HWSTRIP_BITMAP_SIZE \ + (TXGBE_MAX_RX_QUEUE_NUM / (sizeof(uint32_t) * NBBY)) + #define TXGBE_QUEUE_ITR_INTERVAL_DEFAULT 500 /* 500us */ #define TXGBE_RSS_OFFLOAD_ALL ( \ @@ -59,6 +66,14 @@ struct txgbe_stat_mappings { uint32_t rqsm[TXGBE_NB_STAT_MAPPING]; }; +struct txgbe_vfta { + uint32_t vfta[TXGBE_VFTA_SIZE]; +}; + +struct txgbe_hwstrip { + uint32_t bitmap[TXGBE_HWSTRIP_BITMAP_SIZE]; +}; + struct txgbe_uta_info { uint8_t uc_filter_type; uint16_t uta_in_use; @@ -73,6 +88,8 @@ struct txgbe_adapter { struct txgbe_hw_stats stats; struct txgbe_interrupt intr; struct txgbe_stat_mappings stat_mappings; + struct txgbe_vfta shadow_vfta; + struct txgbe_hwstrip hwstrip; struct txgbe_uta_info uta_info; bool rx_bulk_alloc_allowed; }; @@ -92,6 +109,15 @@ struct txgbe_adapter { #define TXGBE_DEV_STAT_MAPPINGS(dev) \ (&((struct txgbe_adapter *)(dev)->data->dev_private)->stat_mappings) +#define TXGBE_DEV_VFTA(dev) \ + (&((struct txgbe_adapter *)(dev)->data->dev_private)->shadow_vfta) + +#define TXGBE_DEV_HWSTRIP(dev) \ + (&((struct txgbe_adapter *)(dev)->data->dev_private)->hwstrip) + +#define TXGBE_DEV_VFDATA(dev) \ + (&((struct txgbe_adapter *)(dev)->data->dev_private)->vfdata) + #define TXGBE_DEV_UTA_INFO(dev) \ (&((struct txgbe_adapter *)(dev)->data->dev_private)->uta_info) @@ -198,4 +224,12 @@ void txgbe_dev_setup_link_alarm_handler(void *param); void txgbe_read_stats_registers(struct txgbe_hw *hw, struct txgbe_hw_stats *hw_stats); +void txgbe_vlan_hw_filter_enable(struct rte_eth_dev *dev); +void txgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev); +void txgbe_vlan_hw_strip_config(struct rte_eth_dev *dev); +void txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, + uint16_t queue, bool on); +void txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, + int mask); + #endif /* _TXGBE_ETHDEV_H_ */ -- 2.18.4