net/txgbe: support VF interrupt
[dpdk.git] / drivers / net / txgbe / txgbe_ethdev.c
index aa01c22..23f9d17 100644 (file)
@@ -7,7 +7,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>
@@ -547,6 +547,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 +704,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;
 }
 
@@ -1542,6 +1554,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();
 
@@ -1745,6 +1758,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.
@@ -1777,6 +1795,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;
@@ -1829,6 +1848,9 @@ 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);
 
@@ -1941,6 +1963,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;
 }
 
@@ -4847,6 +4879,109 @@ 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);
+               wr32(hw, TXGBE_VXLANPORTGPE, 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;
+       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);
+               wr32(hw, TXGBE_VXLANPORTGPE, 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;
+       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)
@@ -4949,6 +5084,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,
@@ -5021,6 +5223,9 @@ 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,
 };