net/ice: support L4 for QinQ switch filter
[dpdk.git] / drivers / net / txgbe / txgbe_ethdev.c
index eadb44a..0063994 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2015-2020
+ * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
  */
 
 #include <stdio.h>
@@ -7,7 +8,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <rte_common.h>
-#include <rte_ethdev_pci.h>
+#include <ethdev_pci.h>
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
@@ -16,6 +17,7 @@
 #include <rte_memory.h>
 #include <rte_eal.h>
 #include <rte_alarm.h>
+#include <rte_kvargs.h>
 
 #include "txgbe_logs.h"
 #include "base/txgbe.h"
@@ -105,6 +107,7 @@ static void txgbe_vlan_hw_strip_disable(struct rte_eth_dev *dev,
 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);
 static int txgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev);
+static int txgbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev);
 static int txgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
 static int txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
 static int txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
@@ -138,8 +141,8 @@ static void txgbe_l2_tunnel_conf(struct rte_eth_dev *dev);
  * The set of PCI devices this driver supports
  */
 static const struct rte_pci_id pci_id_txgbe_map[] = {
-       { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_RAPTOR_SFP) },
-       { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_WX1820_SFP) },
+       { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_SP1000) },
+       { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_WX1820) },
        { .vendor_id = 0, /* sentinel */ },
 };
 
@@ -469,6 +472,71 @@ txgbe_swfw_lock_reset(struct txgbe_hw *hw)
        hw->mac.release_swfw_sync(hw, mask);
 }
 
+static int
+txgbe_handle_devarg(__rte_unused const char *key, const char *value,
+                 void *extra_args)
+{
+       uint16_t *n = extra_args;
+
+       if (value == NULL || extra_args == NULL)
+               return -EINVAL;
+
+       *n = (uint16_t)strtoul(value, NULL, 10);
+       if (*n == USHRT_MAX && errno == ERANGE)
+               return -1;
+
+       return 0;
+}
+
+static void
+txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs)
+{
+       struct rte_kvargs *kvlist;
+       u16 auto_neg = 1;
+       u16 poll = 0;
+       u16 present = 1;
+       u16 sgmii = 0;
+       u16 ffe_set = 0;
+       u16 ffe_main = 27;
+       u16 ffe_pre = 8;
+       u16 ffe_post = 44;
+
+       if (devargs == NULL)
+               goto null;
+
+       kvlist = rte_kvargs_parse(devargs->args, txgbe_valid_arguments);
+       if (kvlist == NULL)
+               goto null;
+
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_AUTO,
+                          &txgbe_handle_devarg, &auto_neg);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_KR_POLL,
+                          &txgbe_handle_devarg, &poll);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_KR_PRESENT,
+                          &txgbe_handle_devarg, &present);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_KX_SGMII,
+                          &txgbe_handle_devarg, &sgmii);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_SET,
+                          &txgbe_handle_devarg, &ffe_set);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_MAIN,
+                          &txgbe_handle_devarg, &ffe_main);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE,
+                          &txgbe_handle_devarg, &ffe_pre);
+       rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST,
+                          &txgbe_handle_devarg, &ffe_post);
+       rte_kvargs_free(kvlist);
+
+null:
+       hw->devarg.auto_neg = auto_neg;
+       hw->devarg.poll = poll;
+       hw->devarg.present = present;
+       hw->devarg.sgmii = sgmii;
+       hw->phy.ffe_set = ffe_set;
+       hw->phy.ffe_main = ffe_main;
+       hw->phy.ffe_pre = ffe_pre;
+       hw->phy.ffe_post = ffe_post;
+}
+
 static int
 eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 {
@@ -537,6 +605,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        hw->isb_dma = TMZ_PADDR(mz);
        hw->isb_mem = TMZ_VADDR(mz);
 
+       txgbe_parse_devargs(hw, pci_dev->device.devargs);
        /* Initialize the shared code (base driver) */
        err = txgbe_init_shared_code(hw);
        if (err != 0) {
@@ -547,6 +616,12 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        /* Unlock any pending hardware semaphore */
        txgbe_swfw_lock_reset(hw);
 
+#ifdef RTE_LIB_SECURITY
+       /* Initialize security_ctx only for primary process*/
+       if (txgbe_ipsec_ctx_create(eth_dev))
+               return -ENOMEM;
+#endif
+
        /* Initialize DCB configuration*/
        memset(dcb_config, 0, sizeof(struct txgbe_dcb_config));
        txgbe_dcb_init(hw, dcb_config);
@@ -698,9 +773,15 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        /* initialize l2 tunnel filter list & hash */
        txgbe_l2_tn_filter_init(eth_dev);
 
+       /* initialize flow filter lists */
+       txgbe_filterlist_init();
+
        /* initialize bandwidth configuration info */
        memset(bw_conf, 0, sizeof(struct txgbe_bw_conf));
 
+       /* initialize Traffic Manager configuration */
+       txgbe_tm_conf_init(eth_dev);
+
        return 0;
 }
 
@@ -850,32 +931,10 @@ static int
 eth_txgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                struct rte_pci_device *pci_dev)
 {
-       struct rte_eth_dev *pf_ethdev;
-       struct rte_eth_devargs eth_da;
-       int retval;
-
-       if (pci_dev->device.devargs) {
-               retval = rte_eth_devargs_parse(pci_dev->device.devargs->args,
-                               &eth_da);
-               if (retval)
-                       return retval;
-       } else {
-               memset(&eth_da, 0, sizeof(eth_da));
-       }
-
-       retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
+       return rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
                        sizeof(struct txgbe_adapter),
                        eth_dev_pci_specific_init, pci_dev,
                        eth_txgbe_dev_init, NULL);
-
-       if (retval || eth_da.nb_representor_ports < 1)
-               return retval;
-
-       pf_ethdev = rte_eth_dev_allocated(pci_dev->device.name);
-       if (pf_ethdev == NULL)
-               return -ENODEV;
-
-       return 0;
 }
 
 static int eth_txgbe_pci_remove(struct rte_pci_device *pci_dev)
@@ -884,7 +943,7 @@ static int eth_txgbe_pci_remove(struct rte_pci_device *pci_dev)
 
        ethdev = rte_eth_dev_allocated(pci_dev->device.name);
        if (!ethdev)
-               return -ENODEV;
+               return 0;
 
        return rte_eth_dev_destroy(ethdev, eth_txgbe_dev_uninit);
 }
@@ -1127,7 +1186,6 @@ txgbe_vlan_hw_extend_disable(struct rte_eth_dev *dev)
 
        ctrl = rd32(hw, TXGBE_PORTCTL);
        ctrl &= ~TXGBE_PORTCTL_VLANEXT;
-       ctrl &= ~TXGBE_PORTCTL_QINQ;
        wr32(hw, TXGBE_PORTCTL, ctrl);
 }
 
@@ -1135,17 +1193,38 @@ 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);
+}
+
+static void
+txgbe_qinq_hw_strip_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_QINQ;
+       wr32(hw, TXGBE_PORTCTL, ctrl);
+}
+
+static void
+txgbe_qinq_hw_strip_enable(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_QINQ | TXGBE_PORTCTL_VLANEXT;
        wr32(hw, TXGBE_PORTCTL, ctrl);
 }
 
@@ -1212,6 +1291,13 @@ txgbe_vlan_offload_config(struct rte_eth_dev *dev, int mask)
                        txgbe_vlan_hw_extend_disable(dev);
        }
 
+       if (mask & ETH_QINQ_STRIP_MASK) {
+               if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP)
+                       txgbe_qinq_hw_strip_enable(dev);
+               else
+                       txgbe_qinq_hw_strip_disable(dev);
+       }
+
        return 0;
 }
 
@@ -1442,6 +1528,7 @@ txgbe_dev_phy_intr_setup(struct rte_eth_dev *dev)
        gpie |= TXGBE_GPIOBIT_6;
        wr32(hw, TXGBE_GPIOINTEN, gpie);
        intr->mask_misc |= TXGBE_ICRMISC_GPIO;
+       intr->mask_misc |= TXGBE_ICRMISC_ANDONE;
 }
 
 int
@@ -1542,6 +1629,7 @@ txgbe_dev_start(struct rte_eth_dev *dev)
        int status;
        uint16_t vf, idx;
        uint32_t *link_speeds;
+       struct txgbe_tm_conf *tm_conf = TXGBE_DEV_TM_CONF(dev);
 
        PMD_INIT_FUNC_TRACE();
 
@@ -1576,6 +1664,7 @@ txgbe_dev_start(struct rte_eth_dev *dev)
                return -1;
        hw->mac.start_hw(hw);
        hw->mac.get_link_status = true;
+       hw->dev_start = true;
 
        /* configure PF module if SRIOV enabled */
        txgbe_pf_host_configure(dev);
@@ -1633,6 +1722,12 @@ txgbe_dev_start(struct rte_eth_dev *dev)
        txgbe_configure_port(dev);
        txgbe_configure_dcb(dev);
 
+       if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_NONE) {
+               err = txgbe_fdir_configure(dev);
+               if (err)
+                       goto error;
+       }
+
        /* Restore vf rate limit */
        if (vfinfo != NULL) {
                for (vf = 0; vf < pci_dev->max_vfs; vf++)
@@ -1668,7 +1763,8 @@ txgbe_dev_start(struct rte_eth_dev *dev)
                hw->mac.enable_tx_laser(hw);
        }
 
-       err = hw->mac.check_link(hw, &speed, &link_up, 0);
+       if ((hw->subsystem_device_id & 0xFF) != TXGBE_DEV_ID_KR_KX_KX4)
+               err = hw->mac.check_link(hw, &speed, &link_up, 0);
        if (err)
                goto error;
        dev->data->dev_link.link_status = link_up;
@@ -1711,6 +1807,7 @@ txgbe_dev_start(struct rte_eth_dev *dev)
 skip_link_setup:
 
        if (rte_intr_allow_others(intr_handle)) {
+               txgbe_dev_misc_interrupt_setup(dev);
                /* check if lsc interrupt is enabled */
                if (dev->data->dev_conf.intr_conf.lsc != 0)
                        txgbe_dev_lsc_interrupt_setup(dev, TRUE);
@@ -1739,6 +1836,11 @@ skip_link_setup:
        txgbe_l2_tunnel_conf(dev);
        txgbe_filter_restore(dev);
 
+       if (tm_conf->root && !tm_conf->committed)
+               PMD_DRV_LOG(WARNING,
+                           "please call hierarchy_commit() "
+                           "before starting the port");
+
        /*
         * Update link status right before return, because it may
         * start link configuration process in a separate thread.
@@ -1771,6 +1873,7 @@ txgbe_dev_stop(struct rte_eth_dev *dev)
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        int vf;
+       struct txgbe_tm_conf *tm_conf = TXGBE_DEV_TM_CONF(dev);
 
        if (hw->adapter_stopped)
                return 0;
@@ -1823,11 +1926,15 @@ txgbe_dev_stop(struct rte_eth_dev *dev)
                intr_handle->intr_vec = NULL;
        }
 
+       /* reset hierarchy commit */
+       tm_conf->committed = false;
+
        adapter->rss_reta_updated = 0;
        wr32m(hw, TXGBE_LEDCTL, 0xFFFFFFFF, TXGBE_LEDCTL_SEL_MASK);
 
        hw->adapter_stopped = true;
        dev->data->dev_started = 0;
+       hw->dev_start = false;
 
        return 0;
 }
@@ -1935,6 +2042,16 @@ txgbe_dev_close(struct rte_eth_dev *dev)
        /* Remove all ntuple filters of the device */
        txgbe_ntuple_filter_uninit(dev);
 
+       /* clear all the filters list */
+       txgbe_filterlist_flush();
+
+       /* Remove all Traffic Manager configuration */
+       txgbe_tm_conf_uninit(dev);
+
+#ifdef RTE_LIB_SECURITY
+       rte_free(dev->security_ctx);
+#endif
+
        return ret;
 }
 
@@ -2042,6 +2159,7 @@ txgbe_read_stats_registers(struct txgbe_hw *hw,
 
        hw_stats->rx_bytes += rd64(hw, TXGBE_DMARXOCTL);
        hw_stats->tx_bytes += rd64(hw, TXGBE_DMATXOCTL);
+       hw_stats->rx_dma_drop += rd32(hw, TXGBE_DMARXDROP);
        hw_stats->rx_drop_packets += rd32(hw, TXGBE_PBRXDROP);
 
        /* MAC Stats */
@@ -2190,7 +2308,8 @@ txgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        }
 
        /* Rx Errors */
-       stats->imissed  = hw_stats->rx_total_missed_packets;
+       stats->imissed  = hw_stats->rx_total_missed_packets +
+                         hw_stats->rx_dma_drop;
        stats->ierrors  = hw_stats->rx_crc_errors +
                          hw_stats->rx_mac_short_packet_dropped +
                          hw_stats->rx_length_errors +
@@ -2463,18 +2582,17 @@ static int
 txgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
 {
        struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
-       u16 eeprom_verh, eeprom_verl;
        u32 etrack_id;
        int ret;
 
-       hw->rom.readw_sw(hw, TXGBE_EEPROM_VERSION_H, &eeprom_verh);
-       hw->rom.readw_sw(hw, TXGBE_EEPROM_VERSION_L, &eeprom_verl);
+       hw->phy.get_fw_version(hw, &etrack_id);
 
-       etrack_id = (eeprom_verh << 16) | eeprom_verl;
        ret = snprintf(fw_version, fw_size, "0x%08x", etrack_id);
+       if (ret < 0)
+               return -EINVAL;
 
        ret += 1; /* add the size of '\0' */
-       if (fw_size < (u32)ret)
+       if (fw_size < (size_t)ret)
                return ret;
        else
                return 0;
@@ -2610,12 +2728,17 @@ txgbe_dev_link_update_share(struct rte_eth_dev *dev,
        }
 
        if (link_up == 0) {
-               if (hw->phy.media_type == txgbe_media_type_fiber) {
+               if ((hw->subsystem_device_id & 0xFF) ==
+                               TXGBE_DEV_ID_KR_KX_KX4) {
+                       hw->mac.bp_down_event(hw);
+               } else if (hw->phy.media_type == txgbe_media_type_fiber) {
                        intr->flags |= TXGBE_FLAG_NEED_LINK_CONFIG;
                        rte_eal_alarm_set(10,
                                txgbe_dev_setup_link_alarm_handler, dev);
                }
                return rte_eth_linkstatus_set(dev, &link);
+       } else if (!hw->dev_start) {
+               return rte_eth_linkstatus_set(dev, &link);
        }
 
        intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG;
@@ -2745,6 +2868,20 @@ txgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on)
        return 0;
 }
 
+static int
+txgbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev)
+{
+       struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+       u64 mask;
+
+       mask = TXGBE_ICR_MASK;
+       mask &= (1ULL << TXGBE_MISC_VEC_ID);
+       intr->mask |= mask;
+       intr->mask_misc |= TXGBE_ICRMISC_GPIO;
+       intr->mask_misc |= TXGBE_ICRMISC_ANDONE;
+       return 0;
+}
+
 /**
  * It clears the interrupt causes and enables the interrupt.
  * It will be called once only during nic initialized.
@@ -2760,9 +2897,11 @@ static int
 txgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
 {
        struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+       u64 mask;
 
-       intr->mask[0] |= TXGBE_ICR_MASK;
-       intr->mask[1] |= TXGBE_ICR_MASK;
+       mask = TXGBE_ICR_MASK;
+       mask &= ~((1ULL << TXGBE_RX_VEC_START) - 1);
+       intr->mask |= mask;
 
        return 0;
 }
@@ -2818,6 +2957,9 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
        if (eicr & TXGBE_ICRMISC_LSC)
                intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE;
 
+       if (eicr & TXGBE_ICRMISC_ANDONE)
+               intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG;
+
        if (eicr & TXGBE_ICRMISC_VFMBX)
                intr->flags |= TXGBE_FLAG_MAILBOX;
 
@@ -2895,6 +3037,13 @@ txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
                intr->flags &= ~TXGBE_FLAG_PHY_INTERRUPT;
        }
 
+       if (intr->flags & TXGBE_FLAG_NEED_AN_CONFIG) {
+               if (hw->devarg.auto_neg == 1 && hw->devarg.poll == 0) {
+                       hw->mac.kr_handle(hw);
+                       intr->flags &= ~TXGBE_FLAG_NEED_AN_CONFIG;
+               }
+       }
+
        if (intr->flags & TXGBE_FLAG_NEED_LINK_UPDATE) {
                struct rte_eth_link link;
 
@@ -2908,6 +3057,11 @@ txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
                        /* handle it 1 sec later, wait it being stable */
                        timeout = TXGBE_LINK_UP_CHECK_TIMEOUT;
                /* likely to down */
+               else if ((hw->subsystem_device_id & 0xFF) ==
+                               TXGBE_DEV_ID_KR_KX_KX4 &&
+                               hw->devarg.auto_neg == 1)
+                       /* handle it 2 sec later for backplane AN73 */
+                       timeout = 2000;
                else
                        /* handle it 4 sec later, wait it being stable */
                        timeout = TXGBE_LINK_DOWN_CHECK_TIMEOUT;
@@ -2918,10 +3072,12 @@ txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
                                      (void *)dev) < 0) {
                        PMD_DRV_LOG(ERR, "Error setting alarm");
                } else {
-                       /* remember original mask */
-                       intr->mask_misc_orig = intr->mask_misc;
                        /* only disable lsc interrupt */
                        intr->mask_misc &= ~TXGBE_ICRMISC_LSC;
+
+                       intr->mask_orig = intr->mask;
+                       /* only disable all misc interrupts */
+                       intr->mask &= ~(1ULL << TXGBE_MISC_VEC_ID);
                }
        }
 
@@ -2982,8 +3138,10 @@ txgbe_dev_interrupt_delayed_handler(void *param)
        }
 
        /* restore original mask */
-       intr->mask_misc = intr->mask_misc_orig;
-       intr->mask_misc_orig = 0;
+       intr->mask_misc |= TXGBE_ICRMISC_LSC;
+
+       intr->mask = intr->mask_orig;
+       intr->mask_orig = 0;
 
        PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
        txgbe_enable_intr(dev);
@@ -3219,7 +3377,7 @@ txgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
                if (!mask)
                        continue;
 
-               reta = rd32a(hw, TXGBE_REG_RSSTBL, i >> 2);
+               reta = rd32at(hw, TXGBE_REG_RSSTBL, i >> 2);
                for (j = 0; j < 4; j++) {
                        if (RS8(mask, j, 0x1)) {
                                reta  &= ~(MS32(8 * j, 0xFF));
@@ -3227,7 +3385,7 @@ txgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
                                                8 * j, 0xFF);
                        }
                }
-               wr32a(hw, TXGBE_REG_RSSTBL, i >> 2, reta);
+               wr32at(hw, TXGBE_REG_RSSTBL, i >> 2, reta);
        }
        adapter->rss_reta_updated = 1;
 
@@ -3260,7 +3418,7 @@ txgbe_dev_rss_reta_query(struct rte_eth_dev *dev,
                if (!mask)
                        continue;
 
-               reta = rd32a(hw, TXGBE_REG_RSSTBL, i >> 2);
+               reta = rd32at(hw, TXGBE_REG_RSSTBL, i >> 2);
                for (j = 0; j < 4; j++) {
                        if (RS8(mask, j, 0x1))
                                reta_conf[idx].reta[shift + j] =
@@ -4038,27 +4196,11 @@ txgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
 }
 
 static int
-txgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,
-                    enum rte_filter_type filter_type,
-                    enum rte_filter_op filter_op,
-                    void *arg)
+txgbe_dev_flow_ops_get(__rte_unused struct rte_eth_dev *dev,
+                      const struct rte_flow_ops **ops)
 {
-       int ret = 0;
-
-       switch (filter_type) {
-       case RTE_ETH_FILTER_GENERIC:
-               if (filter_op != RTE_ETH_FILTER_GET)
-                       return -EINVAL;
-               *(const void **)arg = &txgbe_flow_ops;
-               break;
-       default:
-               PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
-                                                       filter_type);
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
+       *ops = &txgbe_flow_ops;
+       return 0;
 }
 
 static u8 *
@@ -4083,7 +4225,7 @@ txgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,
 
        hw = TXGBE_DEV_HW(dev);
        mc_addr_list = (u8 *)mc_addr_set;
-       return txgbe_update_mc_addr_list(hw, mc_addr_list, nb_mc_addr,
+       return hw->mac.update_mc_addr_list(hw, mc_addr_list, nb_mc_addr,
                                         txgbe_dev_addr_list_itr, TRUE);
 }
 
@@ -4486,6 +4628,7 @@ txgbe_rss_update_sp(enum txgbe_mac_type mac_type)
 {
        switch (mac_type) {
        case txgbe_mac_raptor:
+       case txgbe_mac_raptor_vf:
                return 1;
        default:
                return 0;
@@ -4841,6 +4984,125 @@ txgbe_e_tag_forwarding_en_dis(struct rte_eth_dev *dev, bool en)
        return ret;
 }
 
+/* Add UDP tunneling port */
+static int
+txgbe_dev_udp_tunnel_port_add(struct rte_eth_dev *dev,
+                             struct rte_eth_udp_tunnel *udp_tunnel)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       int ret = 0;
+
+       if (udp_tunnel == NULL)
+               return -EINVAL;
+
+       switch (udp_tunnel->prot_type) {
+       case RTE_TUNNEL_TYPE_VXLAN:
+               if (udp_tunnel->udp_port == 0) {
+                       PMD_DRV_LOG(ERR, "Add VxLAN port 0 is not allowed.");
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_VXLANPORT, udp_tunnel->udp_port);
+               break;
+       case RTE_TUNNEL_TYPE_GENEVE:
+               if (udp_tunnel->udp_port == 0) {
+                       PMD_DRV_LOG(ERR, "Add Geneve port 0 is not allowed.");
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_GENEVEPORT, udp_tunnel->udp_port);
+               break;
+       case RTE_TUNNEL_TYPE_TEREDO:
+               if (udp_tunnel->udp_port == 0) {
+                       PMD_DRV_LOG(ERR, "Add Teredo port 0 is not allowed.");
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_TEREDOPORT, udp_tunnel->udp_port);
+               break;
+       case RTE_TUNNEL_TYPE_VXLAN_GPE:
+               if (udp_tunnel->udp_port == 0) {
+                       PMD_DRV_LOG(ERR, "Add VxLAN port 0 is not allowed.");
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_VXLANPORTGPE, udp_tunnel->udp_port);
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "Invalid tunnel type");
+               ret = -EINVAL;
+               break;
+       }
+
+       txgbe_flush(hw);
+
+       return ret;
+}
+
+/* Remove UDP tunneling port */
+static int
+txgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
+                             struct rte_eth_udp_tunnel *udp_tunnel)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       int ret = 0;
+       uint16_t cur_port;
+
+       if (udp_tunnel == NULL)
+               return -EINVAL;
+
+       switch (udp_tunnel->prot_type) {
+       case RTE_TUNNEL_TYPE_VXLAN:
+               cur_port = (uint16_t)rd32(hw, TXGBE_VXLANPORT);
+               if (cur_port != udp_tunnel->udp_port) {
+                       PMD_DRV_LOG(ERR, "Port %u does not exist.",
+                                       udp_tunnel->udp_port);
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_VXLANPORT, 0);
+               break;
+       case RTE_TUNNEL_TYPE_GENEVE:
+               cur_port = (uint16_t)rd32(hw, TXGBE_GENEVEPORT);
+               if (cur_port != udp_tunnel->udp_port) {
+                       PMD_DRV_LOG(ERR, "Port %u does not exist.",
+                                       udp_tunnel->udp_port);
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_GENEVEPORT, 0);
+               break;
+       case RTE_TUNNEL_TYPE_TEREDO:
+               cur_port = (uint16_t)rd32(hw, TXGBE_TEREDOPORT);
+               if (cur_port != udp_tunnel->udp_port) {
+                       PMD_DRV_LOG(ERR, "Port %u does not exist.",
+                                       udp_tunnel->udp_port);
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_TEREDOPORT, 0);
+               break;
+       case RTE_TUNNEL_TYPE_VXLAN_GPE:
+               cur_port = (uint16_t)rd32(hw, TXGBE_VXLANPORTGPE);
+               if (cur_port != udp_tunnel->udp_port) {
+                       PMD_DRV_LOG(ERR, "Port %u does not exist.",
+                                       udp_tunnel->udp_port);
+                       ret = -EINVAL;
+                       break;
+               }
+               wr32(hw, TXGBE_VXLANPORTGPE, 0);
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "Invalid tunnel type");
+               ret = -EINVAL;
+               break;
+       }
+
+       txgbe_flush(hw);
+
+       return ret;
+}
+
 /* restore n-tuple filter */
 static inline void
 txgbe_ntuple_filter_restore(struct rte_eth_dev *dev)
@@ -4904,13 +5166,26 @@ txgbe_l2_tn_filter_restore(struct rte_eth_dev *dev)
        }
 }
 
+/* restore rss filter */
+static inline void
+txgbe_rss_filter_restore(struct rte_eth_dev *dev)
+{
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+
+       if (filter_info->rss_info.conf.queue_num)
+               txgbe_config_rss_filter(dev,
+                       &filter_info->rss_info, TRUE);
+}
+
 static int
 txgbe_filter_restore(struct rte_eth_dev *dev)
 {
        txgbe_ntuple_filter_restore(dev);
        txgbe_ethertype_filter_restore(dev);
        txgbe_syn_filter_restore(dev);
+       txgbe_fdir_filter_restore(dev);
        txgbe_l2_tn_filter_restore(dev);
+       txgbe_rss_filter_restore(dev);
 
        return 0;
 }
@@ -4930,6 +5205,73 @@ txgbe_l2_tunnel_conf(struct rte_eth_dev *dev)
        (void)txgbe_update_e_tag_eth_type(hw, l2_tn_info->e_tag_ether_type);
 }
 
+/* remove all the n-tuple filters */
+void
+txgbe_clear_all_ntuple_filter(struct rte_eth_dev *dev)
+{
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+       struct txgbe_5tuple_filter *p_5tuple;
+
+       while ((p_5tuple = TAILQ_FIRST(&filter_info->fivetuple_list)))
+               txgbe_remove_5tuple_filter(dev, p_5tuple);
+}
+
+/* remove all the ether type filters */
+void
+txgbe_clear_all_ethertype_filter(struct rte_eth_dev *dev)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+       int i;
+
+       for (i = 0; i < TXGBE_ETF_ID_MAX; i++) {
+               if (filter_info->ethertype_mask & (1 << i) &&
+                   !filter_info->ethertype_filters[i].conf) {
+                       (void)txgbe_ethertype_filter_remove(filter_info,
+                                                           (uint8_t)i);
+                       wr32(hw, TXGBE_ETFLT(i), 0);
+                       wr32(hw, TXGBE_ETCLS(i), 0);
+                       txgbe_flush(hw);
+               }
+       }
+}
+
+/* remove the SYN filter */
+void
+txgbe_clear_syn_filter(struct rte_eth_dev *dev)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_filter_info *filter_info = TXGBE_DEV_FILTER(dev);
+
+       if (filter_info->syn_info & TXGBE_SYNCLS_ENA) {
+               filter_info->syn_info = 0;
+
+               wr32(hw, TXGBE_SYNCLS, 0);
+               txgbe_flush(hw);
+       }
+}
+
+/* remove all the L2 tunnel filters */
+int
+txgbe_clear_all_l2_tn_filter(struct rte_eth_dev *dev)
+{
+       struct txgbe_l2_tn_info *l2_tn_info = TXGBE_DEV_L2_TN(dev);
+       struct txgbe_l2_tn_filter *l2_tn_filter;
+       struct txgbe_l2_tunnel_conf l2_tn_conf;
+       int ret = 0;
+
+       while ((l2_tn_filter = TAILQ_FIRST(&l2_tn_info->l2_tn_list))) {
+               l2_tn_conf.l2_tunnel_type = l2_tn_filter->key.l2_tn_type;
+               l2_tn_conf.tunnel_id      = l2_tn_filter->key.tn_id;
+               l2_tn_conf.pool           = l2_tn_filter->pool;
+               ret = txgbe_dev_l2_tunnel_filter_del(dev, &l2_tn_conf);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static const struct eth_dev_ops txgbe_eth_dev_ops = {
        .dev_configure              = txgbe_dev_configure,
        .dev_infos_get              = txgbe_dev_info_get,
@@ -4984,7 +5326,7 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = {
        .reta_query                 = txgbe_dev_rss_reta_query,
        .rss_hash_update            = txgbe_dev_rss_hash_update,
        .rss_hash_conf_get          = txgbe_dev_rss_hash_conf_get,
-       .filter_ctrl                = txgbe_dev_filter_ctrl,
+       .flow_ops_get               = txgbe_dev_flow_ops_get,
        .set_mc_addr_list           = txgbe_dev_set_mc_addr_list,
        .rxq_info_get               = txgbe_rxq_info_get,
        .txq_info_get               = txgbe_txq_info_get,
@@ -5002,23 +5344,36 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = {
        .timesync_adjust_time       = txgbe_timesync_adjust_time,
        .timesync_read_time         = txgbe_timesync_read_time,
        .timesync_write_time        = txgbe_timesync_write_time,
+       .udp_tunnel_port_add        = txgbe_dev_udp_tunnel_port_add,
+       .udp_tunnel_port_del        = txgbe_dev_udp_tunnel_port_del,
+       .tm_ops_get                 = txgbe_tm_ops_get,
        .tx_done_cleanup            = txgbe_dev_tx_done_cleanup,
 };
 
 RTE_PMD_REGISTER_PCI(net_txgbe, rte_txgbe_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_txgbe, pci_id_txgbe_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_txgbe, "* igb_uio | uio_pci_generic | vfio-pci");
-
-RTE_LOG_REGISTER(txgbe_logtype_init, pmd.net.txgbe.init, NOTICE);
-RTE_LOG_REGISTER(txgbe_logtype_driver, pmd.net.txgbe.driver, NOTICE);
+RTE_PMD_REGISTER_PARAM_STRING(net_txgbe,
+                             TXGBE_DEVARG_BP_AUTO "=<0|1>"
+                             TXGBE_DEVARG_KR_POLL "=<0|1>"
+                             TXGBE_DEVARG_KR_PRESENT "=<0|1>"
+                             TXGBE_DEVARG_KX_SGMII "=<0|1>"
+                             TXGBE_DEVARG_FFE_SET "=<0-4>"
+                             TXGBE_DEVARG_FFE_MAIN "=<uint16>"
+                             TXGBE_DEVARG_FFE_PRE "=<uint16>"
+                             TXGBE_DEVARG_FFE_POST "=<uint16>");
+
+RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE);
+RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE);
+RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_bp, bp, NOTICE);
 
 #ifdef RTE_LIBRTE_TXGBE_DEBUG_RX
-       RTE_LOG_REGISTER(txgbe_logtype_rx, pmd.net.txgbe.rx, DEBUG);
+       RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_rx, rx, DEBUG);
 #endif
 #ifdef RTE_LIBRTE_TXGBE_DEBUG_TX
-       RTE_LOG_REGISTER(txgbe_logtype_tx, pmd.net.txgbe.tx, DEBUG);
+       RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_tx, tx, DEBUG);
 #endif
 
 #ifdef RTE_LIBRTE_TXGBE_DEBUG_TX_FREE
-       RTE_LOG_REGISTER(txgbe_logtype_tx_free, pmd.net.txgbe.tx_free, DEBUG);
+       RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_tx_free, tx_free, DEBUG);
 #endif