net/iavf: fix command after PF reset
[dpdk.git] / drivers / net / iavf / iavf_ethdev.c
index 53dc05c..6bb915d 100644 (file)
 #include <rte_memzone.h>
 #include <rte_dev.h>
 
-#include "iavf_log.h"
-#include "base/iavf_prototype.h"
-#include "base/iavf_adminq_cmd.h"
-#include "base/iavf_type.h"
-
 #include "iavf.h"
 #include "iavf_rxtx.h"
+#include "iavf_generic_flow.h"
 
 static int iavf_dev_configure(struct rte_eth_dev *dev);
 static int iavf_dev_start(struct rte_eth_dev *dev);
 static void iavf_dev_stop(struct rte_eth_dev *dev);
 static void iavf_dev_close(struct rte_eth_dev *dev);
-static void iavf_dev_info_get(struct rte_eth_dev *dev,
+static int iavf_dev_reset(struct rte_eth_dev *dev);
+static int iavf_dev_info_get(struct rte_eth_dev *dev,
                             struct rte_eth_dev_info *dev_info);
 static const uint32_t *iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 static int iavf_dev_stats_get(struct rte_eth_dev *dev,
                             struct rte_eth_stats *stats);
-static void iavf_dev_stats_reset(struct rte_eth_dev *dev);
-static void iavf_dev_promiscuous_enable(struct rte_eth_dev *dev);
-static void iavf_dev_promiscuous_disable(struct rte_eth_dev *dev);
-static void iavf_dev_allmulticast_enable(struct rte_eth_dev *dev);
-static void iavf_dev_allmulticast_disable(struct rte_eth_dev *dev);
+static int iavf_dev_stats_reset(struct rte_eth_dev *dev);
+static int iavf_dev_promiscuous_enable(struct rte_eth_dev *dev);
+static int iavf_dev_promiscuous_disable(struct rte_eth_dev *dev);
+static int iavf_dev_allmulticast_enable(struct rte_eth_dev *dev);
+static int iavf_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int iavf_dev_add_mac_addr(struct rte_eth_dev *dev,
                                struct rte_ether_addr *addr,
                                uint32_t index,
@@ -72,9 +69,13 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
                                        uint16_t queue_id);
 static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
                                         uint16_t queue_id);
-
-int iavf_logtype_init;
-int iavf_logtype_driver;
+static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op,
+                    void *arg);
+static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num);
 
 static const struct rte_pci_id pci_id_iavf_map[] = {
        { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_ADAPTIVE_VF) },
@@ -86,6 +87,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .dev_start                  = iavf_dev_start,
        .dev_stop                   = iavf_dev_stop,
        .dev_close                  = iavf_dev_close,
+       .dev_reset                  = iavf_dev_reset,
        .dev_infos_get              = iavf_dev_info_get,
        .dev_supported_ptypes_get   = iavf_dev_supported_ptypes_get,
        .link_update                = iavf_dev_link_update,
@@ -97,6 +99,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .allmulticast_disable       = iavf_dev_allmulticast_disable,
        .mac_addr_add               = iavf_dev_add_mac_addr,
        .mac_addr_remove            = iavf_dev_del_mac_addr,
+       .set_mc_addr_list                       = iavf_set_mc_addr_list,
        .vlan_filter_set            = iavf_dev_vlan_filter_set,
        .vlan_offload_set           = iavf_dev_vlan_offload_set,
        .rx_queue_start             = iavf_dev_rx_queue_start,
@@ -114,41 +117,38 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .rss_hash_conf_get          = iavf_dev_rss_hash_conf_get,
        .rxq_info_get               = iavf_dev_rxq_info_get,
        .txq_info_get               = iavf_dev_txq_info_get,
-       .rx_queue_count             = iavf_dev_rxq_count,
-       .rx_descriptor_status       = iavf_dev_rx_desc_status,
-       .tx_descriptor_status       = iavf_dev_tx_desc_status,
        .mtu_set                    = iavf_dev_mtu_set,
        .rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,
        .rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,
+       .filter_ctrl                = iavf_dev_filter_ctrl,
 };
 
 static int
-iavf_dev_configure(struct rte_eth_dev *dev)
+iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num)
 {
-       struct iavf_adapter *ad =
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+       struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
-       struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
-       struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+       int err;
 
-       ad->rx_bulk_alloc_allowed = true;
-#ifdef RTE_LIBRTE_IAVF_INC_VECTOR
-       /* Initialize to TRUE. If any of Rx queues doesn't meet the
-        * vector Rx/Tx preconditions, it will be reset.
-        */
-       ad->rx_vec_allowed = true;
-       ad->tx_vec_allowed = true;
-#else
-       ad->rx_vec_allowed = false;
-       ad->tx_vec_allowed = false;
-#endif
+       /* flush previous addresses */
+       err = iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                       false);
+       if (err)
+               return err;
+
+       vf->mc_addrs_num = 0;
+
+       /* add new ones */
+       err = iavf_add_del_mc_addr_list(adapter, mc_addrs, mc_addrs_num, true);
+       if (err)
+               return err;
+
+       vf->mc_addrs_num = mc_addrs_num;
+       memcpy(vf->mc_addrs, mc_addrs, mc_addrs_num * sizeof(*mc_addrs));
 
-       /* Vlan stripping setting */
-       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
-               if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-                       iavf_enable_vlan_strip(ad);
-               else
-                       iavf_disable_vlan_strip(ad);
-       }
        return 0;
 }
 
@@ -208,6 +208,41 @@ iavf_init_rss(struct iavf_adapter *adapter)
        return 0;
 }
 
+static int
+iavf_dev_configure(struct rte_eth_dev *dev)
+{
+       struct iavf_adapter *ad =
+               IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+       struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
+       struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+
+       ad->rx_bulk_alloc_allowed = true;
+       /* Initialize to TRUE. If any of Rx queues doesn't meet the
+        * vector Rx/Tx preconditions, it will be reset.
+        */
+       ad->rx_vec_allowed = true;
+       ad->tx_vec_allowed = true;
+
+       if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+               dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
+       /* Vlan stripping setting */
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
+               if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
+                       iavf_enable_vlan_strip(ad);
+               else
+                       iavf_disable_vlan_strip(ad);
+       }
+
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+               if (iavf_init_rss(ad) != 0) {
+                       PMD_DRV_LOG(ERR, "configure rss failed");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 static int
 iavf_init_rxq(struct rte_eth_dev *dev, struct iavf_rx_queue *rxq)
 {
@@ -248,7 +283,7 @@ iavf_init_rxq(struct rte_eth_dev *dev, struct iavf_rx_queue *rxq)
 
        rxq->max_pkt_len = max_pkt_len;
        if ((dev_data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_SCATTER) ||
-           (rxq->max_pkt_len + 2 * IAVF_VLAN_TAG_SIZE) > buf_size) {
+           rxq->max_pkt_len > buf_size) {
                dev_data->scattered_rx = 1;
        }
        IAVF_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
@@ -315,9 +350,10 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev *dev,
                    VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) {
                        /* If WB_ON_ITR supports, enable it */
                        vf->msix_base = IAVF_RX_VEC_START;
-                       IAVF_WRITE_REG(hw, IAVFINT_DYN_CTLN1(vf->msix_base - 1),
-                                     IAVFINT_DYN_CTLN1_ITR_INDX_MASK |
-                                     IAVFINT_DYN_CTLN1_WB_ON_ITR_MASK);
+                       IAVF_WRITE_REG(hw,
+                                      IAVF_VFINT_DYN_CTLN1(vf->msix_base - 1),
+                                      IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK |
+                                      IAVF_VFINT_DYN_CTLN1_WB_ON_ITR_MASK);
                } else {
                        /* If no WB_ON_ITR offload flags, need to set
                         * interrupt for descriptor write back.
@@ -327,12 +363,12 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev *dev,
                        /* set ITR to max */
                        interval = iavf_calc_itr_interval(
                                        IAVF_QUEUE_ITR_INTERVAL_MAX);
-                       IAVF_WRITE_REG(hw, IAVFINT_DYN_CTL01,
-                                     IAVFINT_DYN_CTL01_INTENA_MASK |
-                                     (IAVF_ITR_INDEX_DEFAULT <<
-                                      IAVFINT_DYN_CTL01_ITR_INDX_SHIFT) |
-                                     (interval <<
-                                      IAVFINT_DYN_CTL01_INTERVAL_SHIFT));
+                       IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01,
+                                      IAVF_VFINT_DYN_CTL01_INTENA_MASK |
+                                      (IAVF_ITR_INDEX_DEFAULT <<
+                                       IAVF_VFINT_DYN_CTL01_ITR_INDX_SHIFT) |
+                                      (interval <<
+                                       IAVF_VFINT_DYN_CTL01_INTERVAL_SHIFT));
                }
                IAVF_WRITE_FLUSH(hw);
                /* map all queues to the same interrupt */
@@ -412,12 +448,11 @@ iavf_dev_start(struct rte_eth_dev *dev)
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-       struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct rte_intr_handle *intr_handle = dev->intr_handle;
 
        PMD_INIT_FUNC_TRACE();
 
-       hw->adapter_stopped = 0;
+       adapter->stopped = 0;
 
        vf->max_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
        vf->num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
@@ -428,13 +463,6 @@ iavf_dev_start(struct rte_eth_dev *dev)
                return -1;
        }
 
-       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
-               if (iavf_init_rss(adapter) != 0) {
-                       PMD_DRV_LOG(ERR, "configure rss failed");
-                       goto err_rss;
-               }
-       }
-
        if (iavf_configure_queues(adapter) != 0) {
                PMD_DRV_LOG(ERR, "configure queues failed");
                goto err_queue;
@@ -451,7 +479,11 @@ iavf_dev_start(struct rte_eth_dev *dev)
        }
 
        /* Set all mac addrs */
-       iavf_add_del_all_mac_addr(adapter, TRUE);
+       iavf_add_del_all_mac_addr(adapter, true);
+
+       /* Set all multicast addresses */
+       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                 true);
 
        if (iavf_start_queues(dev) != 0) {
                PMD_DRV_LOG(ERR, "enable queues failed");
@@ -461,23 +493,22 @@ iavf_dev_start(struct rte_eth_dev *dev)
        return 0;
 
 err_mac:
-       iavf_add_del_all_mac_addr(adapter, FALSE);
+       iavf_add_del_all_mac_addr(adapter, false);
 err_queue:
-err_rss:
        return -1;
 }
 
 static void
 iavf_dev_stop(struct rte_eth_dev *dev)
 {
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
-       struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct rte_intr_handle *intr_handle = dev->intr_handle;
 
        PMD_INIT_FUNC_TRACE();
 
-       if (hw->adapter_stopped == 1)
+       if (adapter->stopped == 1)
                return;
 
        iavf_stop_queues(dev);
@@ -491,11 +522,16 @@ iavf_dev_stop(struct rte_eth_dev *dev)
        }
 
        /* remove all mac addrs */
-       iavf_add_del_all_mac_addr(adapter, FALSE);
-       hw->adapter_stopped = 1;
+       iavf_add_del_all_mac_addr(adapter, false);
+
+       /* remove all multicast addresses */
+       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                 false);
+
+       adapter->stopped = 1;
 }
 
-static void
+static int
 iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
@@ -517,7 +553,8 @@ iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
                DEV_RX_OFFLOAD_SCATTER |
                DEV_RX_OFFLOAD_JUMBO_FRAME |
-               DEV_RX_OFFLOAD_VLAN_FILTER;
+               DEV_RX_OFFLOAD_VLAN_FILTER |
+               DEV_RX_OFFLOAD_RSS_HASH;
        dev_info->tx_offload_capa =
                DEV_TX_OFFLOAD_VLAN_INSERT |
                DEV_TX_OFFLOAD_QINQ_INSERT |
@@ -556,6 +593,8 @@ iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                .nb_min = IAVF_MIN_RING_DESC,
                .nb_align = IAVF_ALIGN_RING_DESC,
        };
+
+       return 0;
 }
 
 static const uint32_t *
@@ -582,6 +621,8 @@ iavf_dev_link_update(struct rte_eth_dev *dev,
        struct rte_eth_link new_link;
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
+       memset(&new_link, 0, sizeof(new_link));
+
        /* Only read status info stored in VF, and the info is updated
         *  when receive LINK_CHANGE evnet from PF by Virtchnnl.
         */
@@ -632,7 +673,7 @@ iavf_dev_link_update(struct rte_eth_dev *dev,
        return 0;
 }
 
-static void
+static int
 iavf_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
        struct iavf_adapter *adapter =
@@ -641,14 +682,20 @@ iavf_dev_promiscuous_enable(struct rte_eth_dev *dev)
        int ret;
 
        if (vf->promisc_unicast_enabled)
-               return;
+               return 0;
 
-       ret = iavf_config_promisc(adapter, TRUE, vf->promisc_multicast_enabled);
+       ret = iavf_config_promisc(adapter, true, vf->promisc_multicast_enabled);
        if (!ret)
-               vf->promisc_unicast_enabled = TRUE;
+               vf->promisc_unicast_enabled = true;
+       else if (ret == IAVF_NOT_SUPPORTED)
+               ret = -ENOTSUP;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 iavf_dev_promiscuous_disable(struct rte_eth_dev *dev)
 {
        struct iavf_adapter *adapter =
@@ -657,14 +704,21 @@ iavf_dev_promiscuous_disable(struct rte_eth_dev *dev)
        int ret;
 
        if (!vf->promisc_unicast_enabled)
-               return;
+               return 0;
 
-       ret = iavf_config_promisc(adapter, FALSE, vf->promisc_multicast_enabled);
+       ret = iavf_config_promisc(adapter, false,
+                                 vf->promisc_multicast_enabled);
        if (!ret)
-               vf->promisc_unicast_enabled = FALSE;
+               vf->promisc_unicast_enabled = false;
+       else if (ret == IAVF_NOT_SUPPORTED)
+               ret = -ENOTSUP;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 iavf_dev_allmulticast_enable(struct rte_eth_dev *dev)
 {
        struct iavf_adapter *adapter =
@@ -673,14 +727,20 @@ iavf_dev_allmulticast_enable(struct rte_eth_dev *dev)
        int ret;
 
        if (vf->promisc_multicast_enabled)
-               return;
+               return 0;
 
-       ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, TRUE);
+       ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, true);
        if (!ret)
-               vf->promisc_multicast_enabled = TRUE;
+               vf->promisc_multicast_enabled = true;
+       else if (ret == IAVF_NOT_SUPPORTED)
+               ret = -ENOTSUP;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 iavf_dev_allmulticast_disable(struct rte_eth_dev *dev)
 {
        struct iavf_adapter *adapter =
@@ -689,11 +749,17 @@ iavf_dev_allmulticast_disable(struct rte_eth_dev *dev)
        int ret;
 
        if (!vf->promisc_multicast_enabled)
-               return;
+               return 0;
 
-       ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, FALSE);
+       ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, false);
        if (!ret)
-               vf->promisc_multicast_enabled = FALSE;
+               vf->promisc_multicast_enabled = false;
+       else if (ret == IAVF_NOT_SUPPORTED)
+               ret = -ENOTSUP;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
 static int
@@ -711,7 +777,7 @@ iavf_dev_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr,
                return -EINVAL;
        }
 
-       err = iavf_add_del_eth_addr(adapter, addr, TRUE);
+       err = iavf_add_del_eth_addr(adapter, addr, true);
        if (err) {
                PMD_DRV_LOG(ERR, "fail to add MAC address");
                return -EIO;
@@ -733,7 +799,7 @@ iavf_dev_del_mac_addr(struct rte_eth_dev *dev, uint32_t index)
 
        addr = &dev->data->mac_addrs[index];
 
-       err = iavf_add_del_eth_addr(adapter, addr, FALSE);
+       err = iavf_add_del_eth_addr(adapter, addr, false);
        if (err)
                PMD_DRV_LOG(ERR, "fail to delete MAC address");
 
@@ -951,14 +1017,11 @@ iavf_dev_set_default_mac_addr(struct rte_eth_dev *dev,
        old_addr = (struct rte_ether_addr *)hw->mac.addr;
        perm_addr = (struct rte_ether_addr *)hw->mac.perm_addr;
 
-       if (rte_is_same_ether_addr(mac_addr, old_addr))
-               return 0;
-
        /* If the MAC address is configured by host, skip the setting */
        if (rte_is_valid_assigned_ether_addr(perm_addr))
                return -EPERM;
 
-       ret = iavf_add_del_eth_addr(adapter, old_addr, FALSE);
+       ret = iavf_add_del_eth_addr(adapter, old_addr, false);
        if (ret)
                PMD_DRV_LOG(ERR, "Fail to delete old MAC:"
                            " %02X:%02X:%02X:%02X:%02X:%02X",
@@ -969,7 +1032,7 @@ iavf_dev_set_default_mac_addr(struct rte_eth_dev *dev,
                            old_addr->addr_bytes[4],
                            old_addr->addr_bytes[5]);
 
-       ret = iavf_add_del_eth_addr(adapter, mac_addr, TRUE);
+       ret = iavf_add_del_eth_addr(adapter, mac_addr, true);
        if (ret)
                PMD_DRV_LOG(ERR, "Fail to add new MAC:"
                            " %02X:%02X:%02X:%02X:%02X:%02X",
@@ -1041,20 +1104,21 @@ iavf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        if (ret == 0) {
                iavf_update_stats(vsi, pstats);
                stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
-                                               pstats->rx_broadcast;
+                               pstats->rx_broadcast - pstats->rx_discards;
                stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
                                                pstats->tx_unicast;
                stats->imissed = pstats->rx_discards;
                stats->oerrors = pstats->tx_errors + pstats->tx_discards;
                stats->ibytes = pstats->rx_bytes;
+               stats->ibytes -= stats->ipackets * RTE_ETHER_CRC_LEN;
                stats->obytes = pstats->tx_bytes;
        } else {
                PMD_DRV_LOG(ERR, "Get statistics failed");
        }
-       return -EIO;
+       return ret;
 }
 
-static void
+static int
 iavf_dev_stats_reset(struct rte_eth_dev *dev)
 {
        int ret;
@@ -1066,10 +1130,13 @@ iavf_dev_stats_reset(struct rte_eth_dev *dev)
 
        /* read stat values to clear hardware registers */
        ret = iavf_query_stats(adapter, &pstats);
+       if (ret != 0)
+               return ret;
 
        /* set stats offset base on current values */
-       if (ret == 0)
-               vsi->eth_stats_offset = *pstats;
+       vsi->eth_stats_offset = *pstats;
+
+       return 0;
 }
 
 static int
@@ -1084,21 +1151,22 @@ iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
        msix_intr = pci_dev->intr_handle.intr_vec[queue_id];
        if (msix_intr == IAVF_MISC_VEC_ID) {
                PMD_DRV_LOG(INFO, "MISC is also enabled for control");
-               IAVF_WRITE_REG(hw, IAVFINT_DYN_CTL01,
-                             IAVFINT_DYN_CTL01_INTENA_MASK |
-                             IAVFINT_DYN_CTL01_CLEARPBA_MASK |
-                             IAVFINT_DYN_CTL01_ITR_INDX_MASK);
+               IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01,
+                              IAVF_VFINT_DYN_CTL01_INTENA_MASK |
+                              IAVF_VFINT_DYN_CTL01_CLEARPBA_MASK |
+                              IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK);
        } else {
                IAVF_WRITE_REG(hw,
-                             IAVFINT_DYN_CTLN1(msix_intr - IAVF_RX_VEC_START),
-                             IAVFINT_DYN_CTLN1_INTENA_MASK |
-                             IAVFINT_DYN_CTL01_CLEARPBA_MASK |
-                             IAVFINT_DYN_CTLN1_ITR_INDX_MASK);
+                              IAVF_VFINT_DYN_CTLN1
+                               (msix_intr - IAVF_RX_VEC_START),
+                              IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
+                              IAVF_VFINT_DYN_CTL01_CLEARPBA_MASK |
+                              IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK);
        }
 
        IAVF_WRITE_FLUSH(hw);
 
-       rte_intr_enable(&pci_dev->intr_handle);
+       rte_intr_ack(&pci_dev->intr_handle);
 
        return 0;
 }
@@ -1117,7 +1185,7 @@ iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
        }
 
        IAVF_WRITE_REG(hw,
-                     IAVFINT_DYN_CTLN1(msix_intr - IAVF_RX_VEC_START),
+                     IAVF_VFINT_DYN_CTLN1(msix_intr - IAVF_RX_VEC_START),
                      0);
 
        IAVF_WRITE_FLUSH(hw);
@@ -1130,9 +1198,9 @@ iavf_check_vf_reset_done(struct iavf_hw *hw)
        int i, reset;
 
        for (i = 0; i < IAVF_RESET_WAIT_CNT; i++) {
-               reset = IAVF_READ_REG(hw, IAVFGEN_RSTAT) &
-                       IAVFGEN_RSTAT_VFR_STATE_MASK;
-               reset = reset >> IAVFGEN_RSTAT_VFR_STATE_SHIFT;
+               reset = IAVF_READ_REG(hw, IAVF_VFGEN_RSTAT) &
+                       IAVF_VFGEN_RSTAT_VFR_STATE_MASK;
+               reset = reset >> IAVF_VFGEN_RSTAT_VFR_STATE_SHIFT;
                if (reset == VIRTCHNL_VFR_VFACTIVE ||
                    reset == VIRTCHNL_VFR_COMPLETED)
                        break;
@@ -1209,6 +1277,16 @@ iavf_init_vf(struct rte_eth_dev *dev)
                        goto err_rss;
                }
        }
+
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC) {
+               if (iavf_get_supported_rxdid(adapter) != 0) {
+                       PMD_INIT_LOG(ERR, "failed to do get supported rxdid");
+                       goto err_rss;
+               }
+       }
+
+       vf->vf_reset = false;
+
        return 0;
 err_rss:
        rte_free(vf->rss_key);
@@ -1229,10 +1307,13 @@ static inline void
 iavf_enable_irq0(struct iavf_hw *hw)
 {
        /* Enable admin queue interrupt trigger */
-       IAVF_WRITE_REG(hw, IAVFINT_ICR0_ENA1, IAVFINT_ICR0_ENA1_ADMINQ_MASK);
+       IAVF_WRITE_REG(hw, IAVF_VFINT_ICR0_ENA1,
+                      IAVF_VFINT_ICR0_ENA1_ADMINQ_MASK);
 
-       IAVF_WRITE_REG(hw, IAVFINT_DYN_CTL01, IAVFINT_DYN_CTL01_INTENA_MASK |
-               IAVFINT_DYN_CTL01_CLEARPBA_MASK | IAVFINT_DYN_CTL01_ITR_INDX_MASK);
+       IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01,
+                      IAVF_VFINT_DYN_CTL01_INTENA_MASK |
+                      IAVF_VFINT_DYN_CTL01_CLEARPBA_MASK |
+                      IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK);
 
        IAVF_WRITE_FLUSH(hw);
 }
@@ -1241,9 +1322,9 @@ static inline void
 iavf_disable_irq0(struct iavf_hw *hw)
 {
        /* Disable all interrupt types */
-       IAVF_WRITE_REG(hw, IAVFINT_ICR0_ENA1, 0);
-       IAVF_WRITE_REG(hw, IAVFINT_DYN_CTL01,
-                     IAVFINT_DYN_CTL01_ITR_INDX_MASK);
+       IAVF_WRITE_REG(hw, IAVF_VFINT_ICR0_ENA1, 0);
+       IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01,
+                      IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK);
        IAVF_WRITE_FLUSH(hw);
 }
 
@@ -1260,6 +1341,34 @@ iavf_dev_interrupt_handler(void *param)
        iavf_enable_irq0(hw);
 }
 
+static int
+iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op,
+                    void *arg)
+{
+       int ret = 0;
+
+       if (!dev)
+               return -EINVAL;
+
+       switch (filter_type) {
+       case RTE_ETH_FILTER_GENERIC:
+               if (filter_op != RTE_ETH_FILTER_GET)
+                       return -EINVAL;
+               *(const void **)arg = &iavf_flow_ops;
+               break;
+       default:
+               PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
+                           filter_type);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+
 static int
 iavf_dev_init(struct rte_eth_dev *eth_dev)
 {
@@ -1267,11 +1376,15 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
                IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter);
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+       int ret = 0;
 
        PMD_INIT_FUNC_TRACE();
 
        /* assign ops func pointer */
        eth_dev->dev_ops = &iavf_eth_dev_ops;
+       eth_dev->rx_queue_count = iavf_dev_rxq_count;
+       eth_dev->rx_descriptor_status = iavf_dev_rx_desc_status;
+       eth_dev->tx_descriptor_status = iavf_dev_tx_desc_status;
        eth_dev->rx_pkt_burst = &iavf_recv_pkts;
        eth_dev->tx_pkt_burst = &iavf_xmit_pkts;
        eth_dev->tx_pkt_prepare = &iavf_prep_pkts;
@@ -1297,12 +1410,21 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
        hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
        hw->back = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private);
        adapter->eth_dev = eth_dev;
+       adapter->stopped = 1;
+
+       /* Pass the information to the rte_eth_dev_close() that it should also
+        * release the private port resources.
+        */
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
 
        if (iavf_init_vf(eth_dev) != 0) {
                PMD_INIT_LOG(ERR, "Init vf failed");
                return -1;
        }
 
+       /* set default ptype table */
+       adapter->ptype_tbl = iavf_get_default_ptype_table();
+
        /* copy mac addr */
        eth_dev->data->mac_addrs = rte_zmalloc(
                "iavf_mac", RTE_ETHER_ADDR_LEN * IAVF_NUM_MACADDR_MAX, 0);
@@ -1332,6 +1454,12 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
        /* configure and enable device interrupt */
        iavf_enable_irq0(hw);
 
+       ret = iavf_flow_init(adapter);
+       if (ret) {
+               PMD_INIT_LOG(ERR, "Failed to initialize flow");
+               return ret;
+       }
+
        return 0;
 }
 
@@ -1341,8 +1469,13 @@ iavf_dev_close(struct rte_eth_dev *dev)
        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct iavf_adapter *adapter =
+               IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
        iavf_dev_stop(dev);
+       iavf_flow_flush(dev, NULL);
+       iavf_flow_uninit(adapter);
        iavf_shutdown_adminq(hw);
        /* disable uio intr before callback unregister */
        rte_intr_disable(intr_handle);
@@ -1351,22 +1484,21 @@ iavf_dev_close(struct rte_eth_dev *dev)
        rte_intr_callback_unregister(intr_handle,
                                     iavf_dev_interrupt_handler, dev);
        iavf_disable_irq0(hw);
-}
-
-static int
-iavf_dev_uninit(struct rte_eth_dev *dev)
-{
-       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-       struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-
-       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-               return -EPERM;
 
        dev->dev_ops = NULL;
        dev->rx_pkt_burst = NULL;
        dev->tx_pkt_burst = NULL;
-       if (hw->adapter_stopped == 0)
-               iavf_dev_close(dev);
+
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+               if (vf->rss_lut) {
+                       rte_free(vf->rss_lut);
+                       vf->rss_lut = NULL;
+               }
+               if (vf->rss_key) {
+                       rte_free(vf->rss_key);
+                       vf->rss_key = NULL;
+               }
+       }
 
        rte_free(vf->vf_res);
        vf->vsi_res = NULL;
@@ -1374,22 +1506,79 @@ iavf_dev_uninit(struct rte_eth_dev *dev)
 
        rte_free(vf->aq_resp);
        vf->aq_resp = NULL;
+}
 
-       if (vf->rss_lut) {
-               rte_free(vf->rss_lut);
-               vf->rss_lut = NULL;
-       }
-       if (vf->rss_key) {
-               rte_free(vf->rss_key);
-               vf->rss_key = NULL;
-       }
+static int
+iavf_dev_uninit(struct rte_eth_dev *dev)
+{
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return -EPERM;
+
+       iavf_dev_close(dev);
+
+       return 0;
+}
+
+/*
+ * Reset VF device only to re-initialize resources in PMD layer
+ */
+static int
+iavf_dev_reset(struct rte_eth_dev *dev)
+{
+       int ret;
+
+       ret = iavf_dev_uninit(dev);
+       if (ret)
+               return ret;
+
+       return iavf_dev_init(dev);
+}
+
+static int
+iavf_dcf_cap_check_handler(__rte_unused const char *key,
+                          const char *value, __rte_unused void *opaque)
+{
+       if (strcmp(value, "dcf"))
+               return -1;
 
        return 0;
 }
 
+static int
+iavf_dcf_cap_selected(struct rte_devargs *devargs)
+{
+       struct rte_kvargs *kvlist;
+       const char *key = "cap";
+       int ret = 0;
+
+       if (devargs == NULL)
+               return 0;
+
+       kvlist = rte_kvargs_parse(devargs->args, NULL);
+       if (kvlist == NULL)
+               return 0;
+
+       if (!rte_kvargs_count(kvlist, key))
+               goto exit;
+
+       /* dcf capability selected when there's a key-value pair: cap=dcf */
+       if (rte_kvargs_process(kvlist, key,
+                              iavf_dcf_cap_check_handler, NULL) < 0)
+               goto exit;
+
+       ret = 1;
+
+exit:
+       rte_kvargs_free(kvlist);
+       return ret;
+}
+
 static int eth_iavf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
                             struct rte_pci_device *pci_dev)
 {
+       if (iavf_dcf_cap_selected(pci_dev->device.devargs))
+               return 1;
+
        return rte_eth_dev_pci_generic_probe(pci_dev,
                sizeof(struct iavf_adapter), iavf_dev_init);
 }
@@ -1402,8 +1591,7 @@ static int eth_iavf_pci_remove(struct rte_pci_device *pci_dev)
 /* Adaptive virtual function driver struct */
 static struct rte_pci_driver rte_iavf_pmd = {
        .id_table = pci_id_iavf_map,
-       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
-                    RTE_PCI_DRV_IOVA_AS_VA,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
        .probe = eth_iavf_pci_probe,
        .remove = eth_iavf_pci_remove,
 };
@@ -1411,90 +1599,15 @@ static struct rte_pci_driver rte_iavf_pmd = {
 RTE_PMD_REGISTER_PCI(net_iavf, rte_iavf_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_iavf, pci_id_iavf_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_iavf, "* igb_uio | vfio-pci");
-RTE_INIT(iavf_init_log)
-{
-       iavf_logtype_init = rte_log_register("pmd.net.iavf.init");
-       if (iavf_logtype_init >= 0)
-               rte_log_set_level(iavf_logtype_init, RTE_LOG_NOTICE);
-       iavf_logtype_driver = rte_log_register("pmd.net.iavf.driver");
-       if (iavf_logtype_driver >= 0)
-               rte_log_set_level(iavf_logtype_driver, RTE_LOG_NOTICE);
-}
-
-/* memory func for base code */
-enum iavf_status_code
-iavf_allocate_dma_mem_d(__rte_unused struct iavf_hw *hw,
-                      struct iavf_dma_mem *mem,
-                      u64 size,
-                      u32 alignment)
-{
-       const struct rte_memzone *mz = NULL;
-       char z_name[RTE_MEMZONE_NAMESIZE];
-
-       if (!mem)
-               return IAVF_ERR_PARAM;
-
-       snprintf(z_name, sizeof(z_name), "iavf_dma_%"PRIu64, rte_rand());
-       mz = rte_memzone_reserve_bounded(z_name, size, SOCKET_ID_ANY,
-                       RTE_MEMZONE_IOVA_CONTIG, alignment, RTE_PGSIZE_2M);
-       if (!mz)
-               return IAVF_ERR_NO_MEMORY;
-
-       mem->size = size;
-       mem->va = mz->addr;
-       mem->pa = mz->phys_addr;
-       mem->zone = (const void *)mz;
-       PMD_DRV_LOG(DEBUG,
-                   "memzone %s allocated with physical address: %"PRIu64,
-                   mz->name, mem->pa);
-
-       return IAVF_SUCCESS;
-}
-
-enum iavf_status_code
-iavf_free_dma_mem_d(__rte_unused struct iavf_hw *hw,
-                  struct iavf_dma_mem *mem)
-{
-       if (!mem)
-               return IAVF_ERR_PARAM;
-
-       PMD_DRV_LOG(DEBUG,
-                   "memzone %s to be freed with physical address: %"PRIu64,
-                   ((const struct rte_memzone *)mem->zone)->name, mem->pa);
-       rte_memzone_free((const struct rte_memzone *)mem->zone);
-       mem->zone = NULL;
-       mem->va = NULL;
-       mem->pa = (u64)0;
-
-       return IAVF_SUCCESS;
-}
-
-enum iavf_status_code
-iavf_allocate_virt_mem_d(__rte_unused struct iavf_hw *hw,
-                       struct iavf_virt_mem *mem,
-                       u32 size)
-{
-       if (!mem)
-               return IAVF_ERR_PARAM;
-
-       mem->size = size;
-       mem->va = rte_zmalloc("iavf", size, 0);
-
-       if (mem->va)
-               return IAVF_SUCCESS;
-       else
-               return IAVF_ERR_NO_MEMORY;
-}
-
-enum iavf_status_code
-iavf_free_virt_mem_d(__rte_unused struct iavf_hw *hw,
-                   struct iavf_virt_mem *mem)
-{
-       if (!mem)
-               return IAVF_ERR_PARAM;
-
-       rte_free(mem->va);
-       mem->va = NULL;
-
-       return IAVF_SUCCESS;
-}
+RTE_PMD_REGISTER_PARAM_STRING(net_iavf, "cap=dcf");
+RTE_LOG_REGISTER(iavf_logtype_init, pmd.net.iavf.init, NOTICE);
+RTE_LOG_REGISTER(iavf_logtype_driver, pmd.net.iavf.driver, NOTICE);
+#ifdef RTE_LIBRTE_IAVF_DEBUG_RX
+RTE_LOG_REGISTER(iavf_logtype_rx, pmd.net.iavf.rx, DEBUG);
+#endif
+#ifdef RTE_LIBRTE_IAVF_DEBUG_TX
+RTE_LOG_REGISTER(iavf_logtype_tx, pmd.net.iavf.tx, DEBUG);
+#endif
+#ifdef RTE_LIBRTE_IAVF_DEBUG_TX_FREE
+RTE_LOG_REGISTER(iavf_logtype_tx_free, pmd.net.iavf.tx_free, DEBUG);
+#endif