net/ixgbe: avoid multiple definitions of bool
[dpdk.git] / drivers / net / ixgbe / ixgbe_ethdev.c
index a9203fa..e335187 100644 (file)
@@ -23,6 +23,7 @@
 #include <rte_bus_pci.h>
 #include <rte_branch_prediction.h>
 #include <rte_memory.h>
+#include <rte_kvargs.h>
 #include <rte_eal.h>
 #include <rte_alarm.h>
 #include <rte_ether.h>
 #define IXGBE_EXVET_VET_EXT_SHIFT              16
 #define IXGBE_DMATXCTL_VT_MASK                 0xFFFF0000
 
+#define IXGBEVF_DEVARG_PFLINK_FULLCHK          "pflink_fullchk"
+
+static const char * const ixgbevf_valid_arguments[] = {
+       IXGBEVF_DEVARG_PFLINK_FULLCHK,
+       NULL
+};
+
 static int eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params);
 static int eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev);
 static int ixgbe_fdir_filter_init(struct rte_eth_dev *eth_dev);
@@ -141,10 +149,10 @@ static int  ixgbe_dev_set_link_up(struct rte_eth_dev *dev);
 static int  ixgbe_dev_set_link_down(struct rte_eth_dev *dev);
 static void ixgbe_dev_close(struct rte_eth_dev *dev);
 static int  ixgbe_dev_reset(struct rte_eth_dev *dev);
-static void ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev);
-static void ixgbe_dev_promiscuous_disable(struct rte_eth_dev *dev);
-static void ixgbe_dev_allmulticast_enable(struct rte_eth_dev *dev);
-static void ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev);
+static int ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev);
+static int ixgbe_dev_promiscuous_disable(struct rte_eth_dev *dev);
+static int ixgbe_dev_allmulticast_enable(struct rte_eth_dev *dev);
+static int ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int ixgbe_dev_link_update(struct rte_eth_dev *dev,
                                int wait_to_complete);
 static int ixgbe_dev_stats_get(struct rte_eth_dev *dev,
@@ -156,8 +164,8 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 static int
 ixgbe_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids,
                uint64_t *values, unsigned int n);
-static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
-static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
 static int ixgbe_dev_xstats_get_names(struct rte_eth_dev *dev,
        struct rte_eth_xstat_name *xstats_names,
        unsigned int size);
@@ -174,11 +182,11 @@ static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
                                             uint8_t is_rx);
 static int ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
                                 size_t fw_size);
-static void ixgbe_dev_info_get(struct rte_eth_dev *dev,
-                              struct rte_eth_dev_info *dev_info);
+static int ixgbe_dev_info_get(struct rte_eth_dev *dev,
+                             struct rte_eth_dev_info *dev_info);
 static const uint32_t *ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev);
-static void ixgbevf_dev_info_get(struct rte_eth_dev *dev,
-                                struct rte_eth_dev_info *dev_info);
+static int ixgbevf_dev_info_get(struct rte_eth_dev *dev,
+                               struct rte_eth_dev_info *dev_info);
 static int ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 
 static int ixgbe_vlan_filter_set(struct rte_eth_dev *dev,
@@ -247,7 +255,7 @@ static void ixgbevf_intr_disable(struct rte_eth_dev *dev);
 static void ixgbevf_intr_enable(struct rte_eth_dev *dev);
 static int ixgbevf_dev_stats_get(struct rte_eth_dev *dev,
                struct rte_eth_stats *stats);
-static void ixgbevf_dev_stats_reset(struct rte_eth_dev *dev);
+static int ixgbevf_dev_stats_reset(struct rte_eth_dev *dev);
 static int ixgbevf_vlan_filter_set(struct rte_eth_dev *dev,
                uint16_t vlan_id, int on);
 static void ixgbevf_vlan_strip_queue_set(struct rte_eth_dev *dev,
@@ -262,10 +270,10 @@ static int ixgbevf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 static void ixgbevf_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
                                 uint8_t queue, uint8_t msix_vector);
 static void ixgbevf_configure_msix(struct rte_eth_dev *dev);
-static void ixgbevf_dev_promiscuous_enable(struct rte_eth_dev *dev);
-static void ixgbevf_dev_promiscuous_disable(struct rte_eth_dev *dev);
-static void ixgbevf_dev_allmulticast_enable(struct rte_eth_dev *dev);
-static void ixgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev);
+static int ixgbevf_dev_promiscuous_enable(struct rte_eth_dev *dev);
+static int ixgbevf_dev_promiscuous_disable(struct rte_eth_dev *dev);
+static int ixgbevf_dev_allmulticast_enable(struct rte_eth_dev *dev);
+static int ixgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev);
 
 /* For Eth VMDQ APIs support */
 static int ixgbe_uc_hash_table_set(struct rte_eth_dev *dev, struct
@@ -370,6 +378,7 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
                                         struct rte_eth_udp_tunnel *udp_tunnel);
 static int ixgbe_filter_restore(struct rte_eth_dev *dev);
 static void ixgbe_l2_tunnel_conf(struct rte_eth_dev *dev);
+static int ixgbe_wait_for_link_up(struct ixgbe_hw *hw);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -411,6 +420,16 @@ static void ixgbe_l2_tunnel_conf(struct rte_eth_dev *dev);
 int ixgbe_logtype_init;
 int ixgbe_logtype_driver;
 
+#ifdef RTE_LIBRTE_IXGBE_DEBUG_RX
+int ixgbe_logtype_rx;
+#endif
+#ifdef RTE_LIBRTE_IXGBE_DEBUG_TX
+int ixgbe_logtype_tx;
+#endif
+#ifdef RTE_LIBRTE_IXGBE_DEBUG_TX_FREE
+int ixgbe_logtype_tx_free;
+#endif
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -462,6 +481,7 @@ static const struct rte_pci_id pci_id_ixgbe_map[] = {
        { RTE_PCI_DEVICE(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_A_1G_T_L) },
        { RTE_PCI_DEVICE(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KX4) },
        { RTE_PCI_DEVICE(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_KR) },
+       { RTE_PCI_DEVICE(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X550EM_X_XFI) },
 #ifdef RTE_LIBRTE_IXGBE_BYPASS
        { RTE_PCI_DEVICE(IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BYPASS) },
 #endif
@@ -1076,6 +1096,8 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 
        PMD_INIT_FUNC_TRACE();
 
+       ixgbe_dev_macsec_setting_reset(eth_dev);
+
        eth_dev->dev_ops = &ixgbe_eth_dev_ops;
        eth_dev->rx_pkt_burst = &ixgbe_recv_pkts;
        eth_dev->tx_pkt_burst = &ixgbe_xmit_pkts;
@@ -1169,6 +1191,7 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        diag = ixgbe_bypass_init_hw(hw);
 #else
        diag = ixgbe_init_hw(hw);
+       hw->mac.autotry_restart = false;
 #endif /* RTE_LIBRTE_IXGBE_BYPASS */
 
        /*
@@ -1236,6 +1259,11 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
                return -ENOMEM;
        }
 
+       /* 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;
+
        /* initialize the vfta */
        memset(shadow_vfta, 0, sizeof(*shadow_vfta));
 
@@ -1274,6 +1302,8 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
        /* enable support intr */
        ixgbe_enable_intr(eth_dev);
 
+       ixgbe_dev_set_link_down(eth_dev);
+
        /* initialize filter info */
        memset(filter_info, 0,
               sizeof(struct ixgbe_filter_info));
@@ -1302,73 +1332,12 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 static int
 eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 {
-       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
-       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
-       struct ixgbe_hw *hw;
-       int retries = 0;
-       int ret;
-
        PMD_INIT_FUNC_TRACE();
 
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
-       hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
-
-       if (hw->adapter_stopped == 0)
-               ixgbe_dev_close(eth_dev);
-
-       eth_dev->dev_ops = NULL;
-       eth_dev->rx_pkt_burst = NULL;
-       eth_dev->tx_pkt_burst = NULL;
-
-       /* Unlock any pending hardware semaphore */
-       ixgbe_swfw_lock_reset(hw);
-
-       /* disable uio intr before callback unregister */
-       rte_intr_disable(intr_handle);
-
-       do {
-               ret = rte_intr_callback_unregister(intr_handle,
-                               ixgbe_dev_interrupt_handler, eth_dev);
-               if (ret >= 0) {
-                       break;
-               } else if (ret != -EAGAIN) {
-                       PMD_INIT_LOG(ERR,
-                               "intr callback unregister failed: %d",
-                               ret);
-                       return ret;
-               }
-               rte_delay_ms(100);
-       } while (retries++ < (10 + IXGBE_LINK_UP_TIME));
-
-       /* cancel the delay handler before remove dev */
-       rte_eal_alarm_cancel(ixgbe_dev_interrupt_delayed_handler, eth_dev);
-
-       /* cancel the link handler before remove dev */
-       rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, eth_dev);
-
-       /* uninitialize PF if max_vfs not zero */
-       ixgbe_pf_host_uninit(eth_dev);
-
-       /* remove all the fdir filters & hash */
-       ixgbe_fdir_filter_uninit(eth_dev);
-
-       /* remove all the L2 tunnel filters & hash */
-       ixgbe_l2_tn_filter_uninit(eth_dev);
-
-       /* Remove all ntuple filters of the device */
-       ixgbe_ntuple_filter_uninit(eth_dev);
-
-       /* clear all the filters list */
-       ixgbe_filterlist_flush();
-
-       /* Remove all Traffic Manager configuration */
-       ixgbe_tm_conf_uninit(eth_dev);
-
-#ifdef RTE_LIBRTE_SECURITY
-       rte_free(eth_dev->security_ctx);
-#endif
+       ixgbe_dev_close(eth_dev);
 
        return 0;
 }
@@ -1549,6 +1518,45 @@ generate_random_mac_addr(struct rte_ether_addr *mac_addr)
        memcpy(&mac_addr->addr_bytes[3], &random, 3);
 }
 
+static int
+devarg_handle_int(__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, 0);
+       if (*n == USHRT_MAX && errno == ERANGE)
+               return -1;
+
+       return 0;
+}
+
+static void
+ixgbevf_parse_devargs(struct ixgbe_adapter *adapter,
+                     struct rte_devargs *devargs)
+{
+       struct rte_kvargs *kvlist;
+       uint16_t pflink_fullchk;
+
+       if (devargs == NULL)
+               return;
+
+       kvlist = rte_kvargs_parse(devargs->args, ixgbevf_valid_arguments);
+       if (kvlist == NULL)
+               return;
+
+       if (rte_kvargs_count(kvlist, IXGBEVF_DEVARG_PFLINK_FULLCHK) == 1 &&
+           rte_kvargs_process(kvlist, IXGBEVF_DEVARG_PFLINK_FULLCHK,
+                              devarg_handle_int, &pflink_fullchk) == 0 &&
+           pflink_fullchk == 1)
+               adapter->pflink_fullchk = 1;
+
+       rte_kvargs_free(kvlist);
+}
+
 /*
  * Virtual Function device init
  */
@@ -1597,6 +1605,9 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
                return 0;
        }
 
+       ixgbevf_parse_devargs(eth_dev->data->dev_private,
+                             pci_dev->device.devargs);
+
        rte_eth_copy_pci_info(eth_dev, pci_dev);
 
        hw->device_id = pci_dev->id.device_id;
@@ -1660,6 +1671,11 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
                return -ENOMEM;
        }
 
+       /* 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;
+
        /* Generate a random MAC address, if none was assigned by PF. */
        if (rte_is_zero_ether_addr(perm_addr)) {
                generate_random_mac_addr(perm_addr);
@@ -1711,30 +1727,12 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
 static int
 eth_ixgbevf_dev_uninit(struct rte_eth_dev *eth_dev)
 {
-       struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
-       struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
-       struct ixgbe_hw *hw;
-
        PMD_INIT_FUNC_TRACE();
 
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return 0;
 
-       hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
-
-       if (hw->adapter_stopped == 0)
-               ixgbevf_dev_close(eth_dev);
-
-       eth_dev->dev_ops = NULL;
-       eth_dev->rx_pkt_burst = NULL;
-       eth_dev->tx_pkt_burst = NULL;
-
-       /* Disable the interrupts for VF */
-       ixgbevf_intr_disable(eth_dev);
-
-       rte_intr_disable(intr_handle);
-       rte_intr_callback_unregister(intr_handle,
-                                    ixgbevf_dev_interrupt_handler, eth_dev);
+       ixgbevf_dev_close(eth_dev);
 
        return 0;
 }
@@ -1808,18 +1806,19 @@ static int eth_ixgbe_pci_remove(struct rte_pci_device *pci_dev)
 
        ethdev = rte_eth_dev_allocated(pci_dev->device.name);
        if (!ethdev)
-               return -ENODEV;
+               return 0;
 
        if (ethdev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR)
-               return rte_eth_dev_destroy(ethdev, ixgbe_vf_representor_uninit);
+               return rte_eth_dev_pci_generic_remove(pci_dev,
+                                       ixgbe_vf_representor_uninit);
        else
-               return rte_eth_dev_destroy(ethdev, eth_ixgbe_dev_uninit);
+               return rte_eth_dev_pci_generic_remove(pci_dev,
+                                               eth_ixgbe_dev_uninit);
 }
 
 static struct rte_pci_driver rte_ixgbe_pmd = {
        .id_table = pci_id_ixgbe_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_ixgbe_pci_probe,
        .remove = eth_ixgbe_pci_remove,
 };
@@ -1841,7 +1840,7 @@ static int eth_ixgbevf_pci_remove(struct rte_pci_device *pci_dev)
  */
 static struct rte_pci_driver rte_ixgbevf_pmd = {
        .id_table = pci_id_ixgbevf_map,
-       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
        .probe = eth_ixgbevf_pci_probe,
        .remove = eth_ixgbevf_pci_remove,
 };
@@ -2407,11 +2406,14 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)
 {
        struct ixgbe_interrupt *intr =
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
        int ret;
 
        PMD_INIT_FUNC_TRACE();
+
+       if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+               dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
        /* multipe queue mode checking */
        ret  = ixgbe_check_mq_mode(dev);
        if (ret != 0) {
@@ -2465,9 +2467,12 @@ ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
        uint32_t queue_end;
        uint16_t total_rate = 0;
        struct rte_pci_device *pci_dev;
+       int ret;
 
        pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-       rte_eth_link_get_nowait(dev->data->port_id, &link);
+       ret = rte_eth_link_get_nowait(dev->data->port_id, &link);
+       if (ret < 0)
+               return ret;
 
        if (vf >= pci_dev->max_vfs)
                return -EINVAL;
@@ -2540,7 +2545,8 @@ ixgbe_dev_start(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;
        uint32_t intr_vector = 0;
-       int err, link_up = 0, negotiate = 0;
+       int err;
+       bool link_up = false, negotiate = 0;
        uint32_t speed = 0;
        uint32_t allowed_speeds = 0;
        int mask = 0;
@@ -2549,20 +2555,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        uint32_t *link_speeds;
        struct ixgbe_tm_conf *tm_conf =
                IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
+       struct ixgbe_macsec_setting *macsec_setting =
+               IXGBE_DEV_PRIVATE_TO_MACSEC_SETTING(dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
 
-       /* IXGBE devices don't support:
-       *    - half duplex (checked afterwards for valid speeds)
-       *    - fixed speed: TODO implement
-       */
-       if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
-               PMD_INIT_LOG(ERR,
-               "Invalid link_speeds for port %u, fix speed not supported",
-                               dev->data->port_id);
-               return -EINVAL;
-       }
-
        /* Stop the link setup handler before resetting the HW. */
        rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
 
@@ -2718,7 +2715,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
        }
 
        link_speeds = &dev->data->dev_conf.link_speeds;
-       if (*link_speeds & ~allowed_speeds) {
+
+       /* Ignore autoneg flag bit and check the validity of 
+        * link_speed 
+        */
+       if (((*link_speeds) >> 1) & ~(allowed_speeds >> 1)) {
                PMD_INIT_LOG(ERR, "Invalid link setting");
                goto error;
        }
@@ -2795,12 +2796,21 @@ skip_link_setup:
                            "please call hierarchy_commit() "
                            "before starting the port");
 
+       /* wait for the controller to acquire link */
+       err = ixgbe_wait_for_link_up(hw);
+       if (err)
+               goto error;
+
        /*
         * Update link status right before return, because it may
         * start link configuration process in a separate thread.
         */
        ixgbe_dev_link_update(dev, 0);
 
+       /* setup the macsec setting register */
+       if (macsec_setting->offload_en)
+               ixgbe_dev_macsec_register_enable(dev, macsec_setting);
+
        return 0;
 
 error:
@@ -2816,8 +2826,7 @@ static void
 ixgbe_dev_stop(struct rte_eth_dev *dev)
 {
        struct rte_eth_link link;
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
        struct ixgbe_hw *hw =
                IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        struct ixgbe_vf_info *vfinfo =
@@ -2828,6 +2837,9 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
        struct ixgbe_tm_conf *tm_conf =
                IXGBE_DEV_PRIVATE_TO_TM_CONF(dev->data->dev_private);
 
+       if (hw->adapter_stopped)
+               return;
+
        PMD_INIT_FUNC_TRACE();
 
        rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
@@ -2880,6 +2892,8 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
        tm_conf->committed = false;
 
        adapter->rss_reta_updated = 0;
+
+       hw->adapter_stopped = true;
 }
 
 /*
@@ -2907,6 +2921,7 @@ ixgbe_dev_set_link_up(struct rte_eth_dev *dev)
        } else {
                /* Turn on the laser */
                ixgbe_enable_tx_laser(hw);
+               ixgbe_dev_link_update(dev, 0);
        }
 
        return 0;
@@ -2937,6 +2952,7 @@ ixgbe_dev_set_link_down(struct rte_eth_dev *dev)
        } else {
                /* Turn off the laser */
                ixgbe_disable_tx_laser(hw);
+               ixgbe_dev_link_update(dev, 0);
        }
 
        return 0;
@@ -2950,13 +2966,16 @@ ixgbe_dev_close(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw =
                IXGBE_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;
+       int retries = 0;
+       int ret;
 
        PMD_INIT_FUNC_TRACE();
 
        ixgbe_pf_reset_hw(hw);
 
        ixgbe_dev_stop(dev);
-       hw->adapter_stopped = 1;
 
        ixgbe_dev_free_queues(dev);
 
@@ -2964,6 +2983,55 @@ ixgbe_dev_close(struct rte_eth_dev *dev)
 
        /* reprogram the RAR[0] in case user changed it. */
        ixgbe_set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV);
+
+       dev->dev_ops = NULL;
+       dev->rx_pkt_burst = NULL;
+       dev->tx_pkt_burst = NULL;
+
+       /* Unlock any pending hardware semaphore */
+       ixgbe_swfw_lock_reset(hw);
+
+       /* disable uio intr before callback unregister */
+       rte_intr_disable(intr_handle);
+
+       do {
+               ret = rte_intr_callback_unregister(intr_handle,
+                               ixgbe_dev_interrupt_handler, dev);
+               if (ret >= 0 || ret == -ENOENT) {
+                       break;
+               } else if (ret != -EAGAIN) {
+                       PMD_INIT_LOG(ERR,
+                               "intr callback unregister failed: %d",
+                               ret);
+               }
+               rte_delay_ms(100);
+       } while (retries++ < (10 + IXGBE_LINK_UP_TIME));
+
+       /* cancel the delay handler before remove dev */
+       rte_eal_alarm_cancel(ixgbe_dev_interrupt_delayed_handler, dev);
+
+       /* uninitialize PF if max_vfs not zero */
+       ixgbe_pf_host_uninit(dev);
+
+       /* remove all the fdir filters & hash */
+       ixgbe_fdir_filter_uninit(dev);
+
+       /* remove all the L2 tunnel filters & hash */
+       ixgbe_l2_tn_filter_uninit(dev);
+
+       /* Remove all ntuple filters of the device */
+       ixgbe_ntuple_filter_uninit(dev);
+
+       /* clear all the filters list */
+       ixgbe_filterlist_flush();
+
+       /* Remove all Traffic Manager configuration */
+       ixgbe_tm_conf_uninit(dev);
+
+#ifdef RTE_LIBRTE_SECURITY
+       rte_free(dev->security_ctx);
+#endif
+
 }
 
 /*
@@ -3269,7 +3337,7 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        return 0;
 }
 
-static void
+static int
 ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw_stats *stats =
@@ -3280,6 +3348,8 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 
        /* Reset software totals */
        memset(stats, 0, sizeof(*stats));
+
+       return 0;
 }
 
 /* This function calculates the number of xstats based on the current config */
@@ -3601,7 +3671,7 @@ ixgbe_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids,
        return n;
 }
 
-static void
+static int
 ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw_stats *stats =
@@ -3618,6 +3688,8 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
        /* Reset software totals */
        memset(stats, 0, sizeof(*stats));
        memset(macsec_stats, 0, sizeof(*macsec_stats));
+
+       return 0;
 }
 
 static void
@@ -3692,7 +3764,7 @@ ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        return 0;
 }
 
-static void
+static int
 ixgbevf_dev_stats_reset(struct rte_eth_dev *dev)
 {
        struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
@@ -3706,6 +3778,8 @@ ixgbevf_dev_stats_reset(struct rte_eth_dev *dev)
        hw_stats->vfgorc = 0;
        hw_stats->vfgptc = 0;
        hw_stats->vfgotc = 0;
+
+       return 0;
 }
 
 static int
@@ -3729,7 +3803,7 @@ ixgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
                return 0;
 }
 
-static void
+static int
 ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
@@ -3795,6 +3869,11 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
 
        dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G;
+       if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
+                       hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)
+               dev_info->speed_capa = ETH_LINK_SPEED_10M |
+                       ETH_LINK_SPEED_100M | ETH_LINK_SPEED_1G;
+
        if (hw->mac.type == ixgbe_mac_X540 ||
            hw->mac.type == ixgbe_mac_X540_vf ||
            hw->mac.type == ixgbe_mac_X550 ||
@@ -3813,6 +3892,8 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        dev_info->default_txportconf.nb_queues = 1;
        dev_info->default_rxportconf.ring_size = 256;
        dev_info->default_txportconf.ring_size = 256;
+
+       return 0;
 }
 
 static const uint32_t *
@@ -3846,7 +3927,7 @@ ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
            dev->rx_pkt_burst == ixgbe_recv_pkts_bulk_alloc)
                return ptypes;
 
-#if defined(RTE_ARCH_X86)
+#if defined(RTE_ARCH_X86) || defined(RTE_MACHINE_CPUFLAG_NEON)
        if (dev->rx_pkt_burst == ixgbe_recv_pkts_vec ||
            dev->rx_pkt_burst == ixgbe_recv_scattered_pkts_vec)
                return ptypes;
@@ -3854,7 +3935,7 @@ ixgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
        return NULL;
 }
 
-static void
+static int
 ixgbevf_dev_info_get(struct rte_eth_dev *dev,
                     struct rte_eth_dev_info *dev_info)
 {
@@ -3878,6 +3959,9 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev,
                                     dev_info->rx_queue_offload_capa);
        dev_info->tx_queue_offload_capa = ixgbe_get_tx_queue_offloads(dev);
        dev_info->tx_offload_capa = ixgbe_get_tx_port_offloads(dev);
+       dev_info->hash_key_size = IXGBE_HKEY_MAX_INDEX * sizeof(uint32_t);
+       dev_info->reta_size = ixgbe_reta_size_get(hw->mac.type);
+       dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL;
 
        dev_info->default_rxconf = (struct rte_eth_rxconf) {
                .rx_thresh = {
@@ -3903,12 +3987,16 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev,
 
        dev_info->rx_desc_lim = rx_desc_lim;
        dev_info->tx_desc_lim = tx_desc_lim;
+
+       return 0;
 }
 
 static int
 ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
-                  int *link_up, int wait_to_complete)
+                  bool *link_up, int wait_to_complete)
 {
+       struct ixgbe_adapter *adapter = container_of(hw,
+                                                    struct ixgbe_adapter, hw);
        struct ixgbe_mbx_info *mbx = &hw->mbx;
        struct ixgbe_mac_info *mac = &hw->mac;
        uint32_t links_reg, in_msg;
@@ -3969,6 +4057,15 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
                *speed = IXGBE_LINK_SPEED_UNKNOWN;
        }
 
+       if (wait_to_complete == 0 && adapter->pflink_fullchk == 0) {
+               if (*speed == IXGBE_LINK_SPEED_UNKNOWN)
+                       mac->get_link_status = true;
+               else
+                       mac->get_link_status = false;
+
+               goto out;
+       }
+
        /* if the read failed it could just be a mailbox collision, best wait
         * until we are called again and don't report an error
         */
@@ -4017,6 +4114,37 @@ ixgbe_dev_setup_link_alarm_handler(void *param)
        intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
 }
 
+/*
+ * In freebsd environment, nic_uio drivers do not support interrupts,
+ * rte_intr_callback_register() will fail to register interrupts.
+ * We can not make link status to change from down to up by interrupt
+ * callback. So we need to wait for the controller to acquire link
+ * when ports start.
+ * It returns 0 on link up.
+ */
+static int
+ixgbe_wait_for_link_up(struct ixgbe_hw *hw)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+       const int nb_iter = 25;
+#else
+       const int nb_iter = 0;
+#endif
+       int err, i;
+       bool link_up = false;
+       uint32_t speed = 0;
+
+       for (i = 0; i < nb_iter; i++) {
+               err = ixgbe_check_link(hw, &speed, &link_up, 0);
+               if (err)
+                       return err;
+               if (link_up)
+                       return 0;
+               msec_delay(200);
+       }
+       return 0;
+}
+
 /* return 0 means link status changed, -1 means not changed */
 int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
@@ -4027,15 +4155,17 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
        ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
        struct ixgbe_interrupt *intr =
                IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
-       int link_up;
+       bool link_up;
        int diag;
        int wait = 1;
+       u32 esdp_reg;
 
        memset(&link, 0, sizeof(link));
        link.link_status = ETH_LINK_DOWN;
        link.link_speed = ETH_SPEED_NUM_NONE;
        link.link_duplex = ETH_LINK_HALF_DUPLEX;
-       link.link_autoneg = ETH_LINK_AUTONEG;
+       link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+                       ETH_LINK_SPEED_FIXED);
 
        hw->mac.get_link_status = true;
 
@@ -4057,6 +4187,12 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
                return rte_eth_linkstatus_set(dev, &link);
        }
 
+       if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {
+               esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+               if ((esdp_reg & IXGBE_ESDP_SDP3))
+                       link_up = 0;
+       }
+
        if (link_up == 0) {
                if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {
                        intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
@@ -4077,7 +4213,6 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
                        link.link_speed = ETH_SPEED_NUM_10M;
                else
                        link.link_speed = ETH_SPEED_NUM_100M;
-               link.link_duplex = ETH_LINK_FULL_DUPLEX;
                break;
 
        case IXGBE_LINK_SPEED_100_FULL:
@@ -4116,7 +4251,7 @@ ixgbevf_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
        return ixgbe_dev_link_update_share(dev, wait_to_complete, 1);
 }
 
-static void
+static int
 ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -4125,9 +4260,11 @@ ixgbe_dev_promiscuous_enable(struct rte_eth_dev *dev)
        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
        fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+       return 0;
 }
 
-static void
+static int
 ixgbe_dev_promiscuous_disable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -4140,9 +4277,11 @@ ixgbe_dev_promiscuous_disable(struct rte_eth_dev *dev)
        else
                fctrl &= (~IXGBE_FCTRL_MPE);
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+       return 0;
 }
 
-static void
+static int
 ixgbe_dev_allmulticast_enable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -4151,20 +4290,24 @@ ixgbe_dev_allmulticast_enable(struct rte_eth_dev *dev)
        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
        fctrl |= IXGBE_FCTRL_MPE;
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+       return 0;
 }
 
-static void
+static int
 ixgbe_dev_allmulticast_disable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t fctrl;
 
        if (dev->data->promiscuous == 1)
-               return; /* must remain in all_multicast mode */
+               return 0; /* must remain in all_multicast mode */
 
        fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
        fctrl &= (~IXGBE_FCTRL_MPE);
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
+
+       return 0;
 }
 
 /**
@@ -4442,7 +4585,7 @@ ixgbe_dev_interrupt_delayed_handler(void *param)
 
        PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
        ixgbe_enable_intr(dev);
-       rte_intr_enable(intr_handle);
+       rte_intr_ack(intr_handle);
 }
 
 /**
@@ -4814,8 +4957,7 @@ ixgbe_dev_rss_reta_update(struct rte_eth_dev *dev,
        uint8_t j, mask;
        uint32_t reta, r;
        uint16_t idx, shift;
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint32_t reta_reg;
 
@@ -4958,8 +5100,11 @@ ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        struct rte_eth_dev_info dev_info;
        uint32_t frame_size = mtu + IXGBE_ETH_OVERHEAD;
        struct rte_eth_dev_data *dev_data = dev->data;
+       int ret;
 
-       ixgbe_dev_info_get(dev, &dev_info);
+       ret = ixgbe_dev_info_get(dev, &dev_info);
+       if (ret != 0)
+               return ret;
 
        /* check that mtu is within the allowed range */
        if (mtu < RTE_ETHER_MIN_MTU || frame_size > dev_info.max_rx_pktlen)
@@ -5048,12 +5193,14 @@ static int
 ixgbevf_dev_configure(struct rte_eth_dev *dev)
 {
        struct rte_eth_conf *conf = &dev->data->dev_conf;
-       struct ixgbe_adapter *adapter =
-                       (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
 
        PMD_INIT_LOG(DEBUG, "Configured Virtual Function port id: %d",
                     dev->data->port_id);
 
+       if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+               dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
        /*
         * VF has no ability to enable/disable HW CRC
         * Keep the persistent behavior the same as Host PF
@@ -5174,6 +5321,8 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
         */
        ixgbevf_dev_link_update(dev, 0);
 
+       hw->adapter_stopped = false;
+
        return 0;
 }
 
@@ -5181,11 +5330,13 @@ static void
 ixgbevf_dev_stop(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = 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;
 
+       if (hw->adapter_stopped)
+               return;
+
        PMD_INIT_FUNC_TRACE();
 
        rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
@@ -5220,6 +5371,8 @@ static void
 ixgbevf_dev_close(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_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;
 
        PMD_INIT_FUNC_TRACE();
 
@@ -5235,6 +5388,14 @@ ixgbevf_dev_close(struct rte_eth_dev *dev)
         * after stop, close and detach of the VF
         **/
        ixgbevf_remove_mac_addr(dev, 0);
+
+       dev->dev_ops = NULL;
+       dev->rx_pkt_burst = NULL;
+       dev->tx_pkt_burst = NULL;
+
+       rte_intr_disable(intr_handle);
+       rte_intr_callback_unregister(intr_handle,
+                                    ixgbevf_dev_interrupt_handler, dev);
 }
 
 /*
@@ -5706,7 +5867,7 @@ ixgbevf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
        RTE_SET_USED(queue_id);
        IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, intr->mask);
 
-       rte_intr_enable(intr_handle);
+       rte_intr_ack(intr_handle);
 
        return 0;
 }
@@ -5755,7 +5916,7 @@ ixgbe_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
                mask &= (1 << (queue_id - 32));
                IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
        }
-       rte_intr_enable(intr_handle);
+       rte_intr_ack(intr_handle);
 
        return 0;
 }
@@ -5838,7 +5999,8 @@ ixgbe_set_ivar_map(struct ixgbe_hw *hw, int8_t direction,
                IXGBE_WRITE_REG(hw, IXGBE_IVAR(idx), tmp);
        } else if ((hw->mac.type == ixgbe_mac_82599EB) ||
                        (hw->mac.type == ixgbe_mac_X540) ||
-                       (hw->mac.type == ixgbe_mac_X550)) {
+                       (hw->mac.type == ixgbe_mac_X550) ||
+                       (hw->mac.type == ixgbe_mac_X550EM_x)) {
                if (direction == -1) {
                        /* other causes */
                        idx = ((queue & 1) * 8);
@@ -5968,6 +6130,7 @@ ixgbe_configure_msix(struct rte_eth_dev *dev)
                case ixgbe_mac_82599EB:
                case ixgbe_mac_X540:
                case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
                        ixgbe_set_ivar_map(hw, -1, 1, IXGBE_MISC_VEC_ID);
                        break;
                default:
@@ -6666,8 +6829,8 @@ ixgbe_add_del_ethertype_filter(struct rte_eth_dev *dev,
        if (filter->queue >= IXGBE_MAX_RX_QUEUE_NUM)
                return -EINVAL;
 
-       if (filter->ether_type == RTE_ETHER_TYPE_IPv4 ||
-               filter->ether_type == RTE_ETHER_TYPE_IPv6) {
+       if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
+               filter->ether_type == RTE_ETHER_TYPE_IPV6) {
                PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in"
                        " ethertype filter.", filter->ether_type);
                return -EINVAL;
@@ -6944,8 +7107,7 @@ static void
 ixgbe_start_timecounters(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
        struct rte_eth_link link;
        uint32_t incval = 0;
        uint32_t shift = 0;
@@ -7013,8 +7175,7 @@ ixgbe_start_timecounters(struct rte_eth_dev *dev)
 static int
 ixgbe_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
 {
-       struct ixgbe_adapter *adapter =
-                       (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
 
        adapter->systime_tc.nsec += delta;
        adapter->rx_tstamp_tc.nsec += delta;
@@ -7027,8 +7188,7 @@ static int
 ixgbe_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
 {
        uint64_t ns;
-       struct ixgbe_adapter *adapter =
-                       (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
 
        ns = rte_timespec_to_ns(ts);
        /* Set the timecounters to a new value. */
@@ -7043,8 +7203,7 @@ static int
 ixgbe_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
 {
        uint64_t ns, systime_cycles;
-       struct ixgbe_adapter *adapter =
-                       (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
 
        systime_cycles = ixgbe_read_systime_cyclecounter(dev);
        ns = rte_timecounter_update(&adapter->systime_tc, systime_cycles);
@@ -7125,8 +7284,7 @@ ixgbe_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
                                 uint32_t flags __rte_unused)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
        uint32_t tsync_rxctl;
        uint64_t rx_tstamp_cycles;
        uint64_t ns;
@@ -7147,8 +7305,7 @@ ixgbe_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
                                 struct timespec *timestamp)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       struct ixgbe_adapter *adapter =
-               (struct ixgbe_adapter *)dev->data->dev_private;
+       struct ixgbe_adapter *adapter = dev->data->dev_private;
        uint32_t tsync_txctl;
        uint64_t tx_tstamp_cycles;
        uint64_t ns;
@@ -7387,6 +7544,9 @@ ixgbe_reta_size_get(enum ixgbe_mac_type mac_type) {
        case ixgbe_mac_X550EM_x_vf:
        case ixgbe_mac_X550EM_a_vf:
                return ETH_RSS_RETA_SIZE_64;
+       case ixgbe_mac_X540_vf:
+       case ixgbe_mac_82599_vf:
+               return 0;
        default:
                return ETH_RSS_RETA_SIZE_128;
        }
@@ -8338,36 +8498,89 @@ ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
        return ret;
 }
 
-static void
+static int
 ixgbevf_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int ret;
+
+       switch (hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_PROMISC)) {
+       case IXGBE_SUCCESS:
+               ret = 0;
+               break;
+       case IXGBE_ERR_FEATURE_NOT_SUPPORTED:
+               ret = -ENOTSUP;
+               break;
+       default:
+               ret = -EAGAIN;
+               break;
+       }
 
-       hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_PROMISC);
+       return ret;
 }
 
-static void
+static int
 ixgbevf_dev_promiscuous_disable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int ret;
+
+       switch (hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_NONE)) {
+       case IXGBE_SUCCESS:
+               ret = 0;
+               break;
+       case IXGBE_ERR_FEATURE_NOT_SUPPORTED:
+               ret = -ENOTSUP;
+               break;
+       default:
+               ret = -EAGAIN;
+               break;
+       }
 
-       hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_NONE);
+       return ret;
 }
 
-static void
+static int
 ixgbevf_dev_allmulticast_enable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int ret;
+       int mode = IXGBEVF_XCAST_MODE_ALLMULTI;
+
+       switch (hw->mac.ops.update_xcast_mode(hw, mode)) {
+       case IXGBE_SUCCESS:
+               ret = 0;
+               break;
+       case IXGBE_ERR_FEATURE_NOT_SUPPORTED:
+               ret = -ENOTSUP;
+               break;
+       default:
+               ret = -EAGAIN;
+               break;
+       }
 
-       hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_ALLMULTI);
+       return ret;
 }
 
-static void
+static int
 ixgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev)
 {
        struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int ret;
+
+       switch (hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_MULTI)) {
+       case IXGBE_SUCCESS:
+               ret = 0;
+               break;
+       case IXGBE_ERR_FEATURE_NOT_SUPPORTED:
+               ret = -ENOTSUP;
+               break;
+       default:
+               ret = -EAGAIN;
+               break;
+       }
 
-       hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_MULTI);
+       return ret;
 }
 
 static void ixgbevf_mbx_process(struct rte_eth_dev *dev)
@@ -8664,12 +8877,157 @@ ixgbe_clear_all_l2_tn_filter(struct rte_eth_dev *dev)
        return 0;
 }
 
+void
+ixgbe_dev_macsec_setting_save(struct rte_eth_dev *dev,
+                               struct ixgbe_macsec_setting *macsec_setting)
+{
+       struct ixgbe_macsec_setting *macsec =
+               IXGBE_DEV_PRIVATE_TO_MACSEC_SETTING(dev->data->dev_private);
+
+       macsec->offload_en = macsec_setting->offload_en;
+       macsec->encrypt_en = macsec_setting->encrypt_en;
+       macsec->replayprotect_en = macsec_setting->replayprotect_en;
+}
+
+void
+ixgbe_dev_macsec_setting_reset(struct rte_eth_dev *dev)
+{
+       struct ixgbe_macsec_setting *macsec =
+               IXGBE_DEV_PRIVATE_TO_MACSEC_SETTING(dev->data->dev_private);
+
+       macsec->offload_en = 0;
+       macsec->encrypt_en = 0;
+       macsec->replayprotect_en = 0;
+}
+
+void
+ixgbe_dev_macsec_register_enable(struct rte_eth_dev *dev,
+                               struct ixgbe_macsec_setting *macsec_setting)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t ctrl;
+       uint8_t en = macsec_setting->encrypt_en;
+       uint8_t rp = macsec_setting->replayprotect_en;
+
+       /**
+        * Workaround:
+        * As no ixgbe_disable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        * The hardware support has been checked by
+        * ixgbe_disable_sec_rx_path().
+        */
+       ixgbe_disable_sec_tx_path_generic(hw);
+
+       /* Enable Ethernet CRC (required by MACsec offload) */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+       ctrl |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_RXCRCSTRP;
+       IXGBE_WRITE_REG(hw, IXGBE_HLREG0, ctrl);
+
+       /* Enable the TX and RX crypto engines */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+       ctrl &= ~IXGBE_SECTXCTRL_SECTX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+       ctrl &= ~IXGBE_SECRXCTRL_SECRX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
+       ctrl &= ~IXGBE_SECTX_MINSECIFG_MASK;
+       ctrl |= 0x3;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, ctrl);
+
+       /* Enable SA lookup */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
+       ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
+       ctrl |= en ? IXGBE_LSECTXCTRL_AUTH_ENCRYPT :
+                    IXGBE_LSECTXCTRL_AUTH;
+       ctrl |= IXGBE_LSECTXCTRL_AISCI;
+       ctrl &= ~IXGBE_LSECTXCTRL_PNTHRSH_MASK;
+       ctrl |= IXGBE_MACSEC_PNTHRSH & IXGBE_LSECTXCTRL_PNTHRSH_MASK;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
+       ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
+       ctrl |= IXGBE_LSECRXCTRL_STRICT << IXGBE_LSECRXCTRL_EN_SHIFT;
+       ctrl &= ~IXGBE_LSECRXCTRL_PLSH;
+       if (rp)
+               ctrl |= IXGBE_LSECRXCTRL_RP;
+       else
+               ctrl &= ~IXGBE_LSECRXCTRL_RP;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
+
+       /* Start the data paths */
+       ixgbe_enable_sec_rx_path(hw);
+       /**
+        * Workaround:
+        * As no ixgbe_enable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        */
+       ixgbe_enable_sec_tx_path_generic(hw);
+}
+
+void
+ixgbe_dev_macsec_register_disable(struct rte_eth_dev *dev)
+{
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       uint32_t ctrl;
+
+       /**
+        * Workaround:
+        * As no ixgbe_disable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        * The hardware support has been checked by
+        * ixgbe_disable_sec_rx_path().
+        */
+       ixgbe_disable_sec_tx_path_generic(hw);
+
+       /* Disable the TX and RX crypto engines */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
+       ctrl |= IXGBE_SECTXCTRL_SECTX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+       ctrl |= IXGBE_SECRXCTRL_SECRX_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
+
+       /* Disable SA lookup */
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
+       ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
+       ctrl |= IXGBE_LSECTXCTRL_DISABLE;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
+
+       ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
+       ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
+       ctrl |= IXGBE_LSECRXCTRL_DISABLE << IXGBE_LSECRXCTRL_EN_SHIFT;
+       IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
+
+       /* Start the data paths */
+       ixgbe_enable_sec_rx_path(hw);
+       /**
+        * Workaround:
+        * As no ixgbe_enable_sec_rx_path equivalent is
+        * implemented for tx in the base code, and we are
+        * not allowed to modify the base code in DPDK, so
+        * just call the hand-written one directly for now.
+        */
+       ixgbe_enable_sec_tx_path_generic(hw);
+}
+
 RTE_PMD_REGISTER_PCI(net_ixgbe, rte_ixgbe_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe, pci_id_ixgbe_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe, "* igb_uio | uio_pci_generic | vfio-pci");
 RTE_PMD_REGISTER_PCI(net_ixgbe_vf, rte_ixgbevf_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_ixgbe_vf, pci_id_ixgbevf_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_ixgbe_vf, "* igb_uio | vfio-pci");
+RTE_PMD_REGISTER_PARAM_STRING(net_ixgbe_vf,
+                             IXGBEVF_DEVARG_PFLINK_FULLCHK "=<0|1>");
 
 RTE_INIT(ixgbe_init_log)
 {
@@ -8679,4 +9037,21 @@ RTE_INIT(ixgbe_init_log)
        ixgbe_logtype_driver = rte_log_register("pmd.net.ixgbe.driver");
        if (ixgbe_logtype_driver >= 0)
                rte_log_set_level(ixgbe_logtype_driver, RTE_LOG_NOTICE);
+#ifdef RTE_LIBRTE_IXGBE_DEBUG_RX
+       ixgbe_logtype_rx = rte_log_register("pmd.net.ixgbe.rx");
+       if (ixgbe_logtype_rx >= 0)
+               rte_log_set_level(ixgbe_logtype_rx, RTE_LOG_DEBUG);
+#endif
+
+#ifdef RTE_LIBRTE_IXGBE_DEBUG_TX
+       ixgbe_logtype_tx = rte_log_register("pmd.net.ixgbe.tx");
+       if (ixgbe_logtype_tx >= 0)
+               rte_log_set_level(ixgbe_logtype_tx, RTE_LOG_DEBUG);
+#endif
+
+#ifdef RTE_LIBRTE_IXGBE_DEBUG_TX_FREE
+       ixgbe_logtype_tx_free = rte_log_register("pmd.net.ixgbe.tx_free");
+       if (ixgbe_logtype_tx_free >= 0)
+               rte_log_set_level(ixgbe_logtype_tx_free, RTE_LOG_DEBUG);
+#endif
 }