net/i40e: determine number of queues per VF at run time
[dpdk.git] / drivers / net / i40e / i40e_ethdev.c
index 536365d..3dc026f 100644 (file)
@@ -1,34 +1,5 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
  */
 
 #include <stdio.h>
@@ -43,6 +14,7 @@
 #include <rte_eal.h>
 #include <rte_string_fns.h>
 #include <rte_pci.h>
+#include <rte_bus_pci.h>
 #include <rte_ether.h>
 #include <rte_ethdev.h>
 #include <rte_ethdev_pci.h>
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -258,7 +226,7 @@ static void i40e_dev_allmulticast_enable(struct rte_eth_dev *dev);
 static void i40e_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
 static int i40e_dev_set_link_down(struct rte_eth_dev *dev);
-static void i40e_dev_stats_get(struct rte_eth_dev *dev,
+static int i40e_dev_stats_get(struct rte_eth_dev *dev,
                               struct rte_eth_stats *stats);
 static int i40e_dev_xstats_get(struct rte_eth_dev *dev,
                               struct rte_eth_xstat *xstats, unsigned n);
@@ -280,7 +248,7 @@ static int i40e_vlan_filter_set(struct rte_eth_dev *dev,
 static int i40e_vlan_tpid_set(struct rte_eth_dev *dev,
                              enum rte_vlan_type vlan_type,
                              uint16_t tpid);
-static void i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40e_vlan_strip_queue_set(struct rte_eth_dev *dev,
                                      uint16_t queue,
                                      int on);
@@ -310,7 +278,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
                bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -654,7 +621,8 @@ static int eth_i40e_pci_remove(struct rte_pci_device *pci_dev)
 
 static struct rte_pci_driver rte_i40e_pmd = {
        .id_table = pci_id_i40e_map,
-       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+       .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
+                    RTE_PCI_DRV_IOVA_AS_VA,
        .probe = eth_i40e_pci_probe,
        .remove = eth_i40e_pci_remove,
 };
@@ -704,23 +672,22 @@ RTE_PMD_REGISTER_KMOD_DEP(net_i40e, "* igb_uio | uio_pci_generic | vfio-pci");
 static inline void i40e_GLQF_reg_init(struct i40e_hw *hw)
 {
        /*
-        * Initialize registers for flexible payload, which should be set by NVM.
-        * This should be removed from code once it is fixed in NVM.
+        * Force global configuration for flexible payload
+        * to the first 16 bytes of the corresponding L2/L3/L4 paylod.
+        * This should be removed from code once proper
+        * configuration API is added to avoid configuration conflicts
+        * between ports of the same device.
         */
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(18), 0x00000030);
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(19), 0x00000030);
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(26), 0x0000002B);
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(30), 0x0000002B);
        I40E_WRITE_REG(hw, I40E_GLQF_ORT(33), 0x000000E0);
        I40E_WRITE_REG(hw, I40E_GLQF_ORT(34), 0x000000E3);
        I40E_WRITE_REG(hw, I40E_GLQF_ORT(35), 0x000000E6);
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(20), 0x00000031);
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(23), 0x00000031);
-       I40E_WRITE_REG(hw, I40E_GLQF_ORT(63), 0x0000002D);
-       I40E_WRITE_REG(hw, I40E_GLQF_PIT(16), 0x00007480);
-       I40E_WRITE_REG(hw, I40E_GLQF_PIT(17), 0x00007440);
 
-       /* Initialize registers for parsing packet type of QinQ */
+       /*
+        * Initialize registers for parsing packet type of QinQ
+        * This should be removed from code once proper
+        * configuration API is added to avoid configuration conflicts
+        * between ports of the same device.
+        */
        I40E_WRITE_REG(hw, I40E_GLQF_ORT(40), 0x00000029);
        I40E_WRITE_REG(hw, I40E_GLQF_PIT(9), 0x00009420);
 }
@@ -1010,7 +977,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
        struct rte_hash_parameters fdir_hash_params = {
                .name = fdir_hash_name,
                .entries = I40E_MAX_FDIR_FILTER_NUM,
-               .key_len = sizeof(struct rte_eth_fdir_input),
+               .key_len = sizeof(struct i40e_fdir_input),
                .hash_func = rte_hash_crc,
                .hash_func_init_val = 0,
                .socket_id = rte_socket_id(),
@@ -1058,6 +1025,20 @@ i40e_init_customized_info(struct i40e_pf *pf)
        pf->gtp_support = false;
 }
 
+void
+i40e_init_queue_region_conf(struct rte_eth_dev *dev)
+{
+       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_queue_regions *info = &pf->queue_region;
+       uint16_t i;
+
+       for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+               i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+       memset(info, 0, sizeof(struct i40e_queue_regions));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1091,7 +1072,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        intr_handle = &pci_dev->intr_handle;
 
        rte_eth_copy_pci_info(dev, pci_dev);
-       dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
 
        pf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        pf->adapter->eth_dev = dev;
@@ -1337,6 +1317,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        if (ret < 0)
                goto err_init_fdir_filter_list;
 
+       /* initialize queue region configuration */
+       i40e_init_queue_region_conf(dev);
+
        return 0;
 
 err_init_fdir_filter_list:
@@ -1646,7 +1629,7 @@ __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
        /* Write first RX queue to Link list register as the head element */
        if (vsi->type != I40E_VSI_SRIOV) {
                uint16_t interval =
-                       i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+                       i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL, 1);
 
                if (msix_vect == I40E_MISC_VEC_ID) {
                        I40E_WRITE_REG(hw, I40E_PFINT_LNKLST0,
@@ -1777,7 +1760,7 @@ i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
        uint16_t interval = i40e_calc_itr_interval(\
-               RTE_LIBRTE_I40E_ITR_INTERVAL);
+               RTE_LIBRTE_I40E_ITR_INTERVAL, 1);
        uint16_t msix_intr, i;
 
        if (rte_intr_allow_others(intr_handle))
@@ -2036,6 +2019,16 @@ i40e_dev_start(struct rte_eth_dev *dev)
                }
        }
 
+       /* Enable mac loopback mode */
+       if (dev->data->dev_conf.lpbk_mode == I40E_AQ_LB_MODE_NONE ||
+           dev->data->dev_conf.lpbk_mode == I40E_AQ_LB_PHY_LOCAL) {
+               ret = i40e_aq_set_lb_modes(hw, dev->data->dev_conf.lpbk_mode, NULL);
+               if (ret != I40E_SUCCESS) {
+                       PMD_DRV_LOG(ERR, "fail to set loopback link");
+                       goto err_up;
+               }
+       }
+
        /* Apply link configure */
        if (dev->data->dev_conf.link_speeds & ~(ETH_LINK_SPEED_100M |
                                ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
@@ -2142,6 +2135,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
        /* reset hierarchy commit */
        pf->tm_conf.committed = false;
 
+       /* Remove all the queue region configuration */
+       i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
        hw->adapter_stopped = 1;
 }
 
@@ -2728,7 +2724,7 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
 }
 
 /* Get all statistics of a port */
-static void
+static int
 i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -2828,6 +2824,7 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
                    ns->checksum_error);
        PMD_DRV_LOG(DEBUG, "fdir_match:               %"PRIu64"", ns->fd_sb_match);
        PMD_DRV_LOG(DEBUG, "***************** PF stats end ********************");
+       return 0;
 }
 
 /* Reset the statistics */
@@ -3205,7 +3202,7 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
        return ret;
 }
 
-static void
+static int
 i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -3238,6 +3235,8 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
                else
                        i40e_vsi_config_double_vlan(vsi, FALSE);
        }
+
+       return 0;
 }
 
 static void
@@ -3824,7 +3823,7 @@ i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,
 
        mem->size = size;
        mem->va = mz->addr;
-       mem->pa = mz->phys_addr;
+       mem->pa = mz->iova;
        mem->zone = (const void *)mz;
        PMD_DRV_LOG(DEBUG,
                "memzone %s allocated with physical address: %"PRIu64,
@@ -3953,6 +3952,69 @@ i40e_get_cap(struct i40e_hw *hw)
        return ret;
 }
 
+#define RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF       4
+#define QUEUE_NUM_PER_VF_ARG                   "queue-num-per-vf"
+RTE_PMD_REGISTER_PARAM_STRING(net_i40e,        QUEUE_NUM_PER_VF_ARG "=1|2|4|8|16");
+
+static int i40e_pf_parse_vf_queue_number_handler(const char *key,
+               const char *value,
+               void *opaque)
+{
+       struct i40e_pf *pf;
+       unsigned long num;
+       char *end;
+
+       pf = (struct i40e_pf *)opaque;
+       RTE_SET_USED(key);
+
+       errno = 0;
+       num = strtoul(value, &end, 0);
+       if (errno != 0 || end == value || *end != 0) {
+               PMD_DRV_LOG(WARNING, "Wrong VF queue number = %s, Now it is "
+                           "kept the value = %hu", value, pf->vf_nb_qp_max);
+               return -(EINVAL);
+       }
+
+       if (num <= I40E_MAX_QP_NUM_PER_VF && rte_is_power_of_2(num))
+               pf->vf_nb_qp_max = (uint16_t)num;
+       else
+               /* here return 0 to make next valid same argument work */
+               PMD_DRV_LOG(WARNING, "Wrong VF queue number = %lu, it must be "
+                           "power of 2 and equal or less than 16 !, Now it is "
+                           "kept the value = %hu", num, pf->vf_nb_qp_max);
+
+       return 0;
+}
+
+static int i40e_pf_config_vf_rxq_number(struct rte_eth_dev *dev)
+{
+       static const char * const valid_keys[] = {QUEUE_NUM_PER_VF_ARG, NULL};
+       struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct rte_kvargs *kvlist;
+
+       /* set default queue number per VF as 4 */
+       pf->vf_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
+
+       if (dev->device->devargs == NULL)
+               return 0;
+
+       kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);
+       if (kvlist == NULL)
+               return -(EINVAL);
+
+       if (rte_kvargs_count(kvlist, QUEUE_NUM_PER_VF_ARG) > 1)
+               PMD_DRV_LOG(WARNING, "More than one argument \"%s\" and only "
+                           "the first invalid or last valid one is used !",
+                           QUEUE_NUM_PER_VF_ARG);
+
+       rte_kvargs_process(kvlist, QUEUE_NUM_PER_VF_ARG,
+                          i40e_pf_parse_vf_queue_number_handler, pf);
+
+       rte_kvargs_free(kvlist);
+
+       return 0;
+}
+
 static int
 i40e_pf_parameter_init(struct rte_eth_dev *dev)
 {
@@ -3965,6 +4027,9 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
                PMD_INIT_LOG(ERR, "HW configuration doesn't support SRIOV");
                return -EINVAL;
        }
+
+       i40e_pf_config_vf_rxq_number(dev);
+
        /* Add the parameter init for LFC */
        pf->fc_conf.pause_time = I40E_DEFAULT_PAUSE_TIME;
        pf->fc_conf.high_water[I40E_MAX_TRAFFIC_CLASS] = I40E_DEFAULT_HIGH_WATER;
@@ -3974,7 +4039,6 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
        pf->max_num_vsi = hw->func_caps.num_vsis;
        pf->lan_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF;
        pf->vmdq_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
-       pf->vf_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
 
        /* FDir queue/VSI allocation */
        pf->fdir_qp_offset = 0;
@@ -4004,7 +4068,7 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
        pf->vf_qp_offset = pf->lan_qp_offset + pf->lan_nb_qps;
        if (hw->func_caps.sr_iov_1_1 && pci_dev->max_vfs) {
                pf->flags |= I40E_FLAG_SRIOV;
-               pf->vf_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
+               pf->vf_nb_qps = pf->vf_nb_qp_max;
                pf->vf_num = pci_dev->max_vfs;
                PMD_DRV_LOG(DEBUG,
                        "%u VF VSIs, %u queues per VF VSI, in total %u queues",
@@ -5297,10 +5361,14 @@ i40e_dev_init_vlan(struct rte_eth_dev *dev)
        int mask = 0;
 
        /* Apply vlan offload setting */
-       mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
-       i40e_vlan_offload_set(dev, mask);
-
-       /* Apply double-vlan setting, not implemented yet */
+       mask = ETH_VLAN_STRIP_MASK |
+              ETH_VLAN_FILTER_MASK |
+              ETH_VLAN_EXTEND_MASK;
+       ret = i40e_vlan_offload_set(dev, mask);
+       if (ret) {
+               PMD_DRV_LOG(INFO, "Failed to update vlan offload");
+               return ret;
+       }
 
        /* Apply pvid setting */
        ret = i40e_vlan_pvid_set(dev, data->dev_conf.txmode.pvid,
@@ -6929,7 +6997,7 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
                        uint8_t add)
 {
        uint16_t ip_type;
-       uint32_t ipv4_addr;
+       uint32_t ipv4_addr, ipv4_addr_le;
        uint8_t i, tun_type = 0;
        /* internal varialbe to convert ipv6 byte order */
        uint32_t convert_ipv6[4];
@@ -6962,8 +7030,9 @@ i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
        if (tunnel_filter->ip_type == RTE_TUNNEL_IPTYPE_IPV4) {
                ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4;
                ipv4_addr = rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv4_addr);
+               ipv4_addr_le = rte_cpu_to_le_32(ipv4_addr);
                rte_memcpy(&pfilter->element.ipaddr.v4.data,
-                               &rte_cpu_to_le_32(ipv4_addr),
+                               &ipv4_addr_le,
                                sizeof(pfilter->element.ipaddr.v4.data));
        } else {
                ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6;
@@ -7280,7 +7349,7 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
                      uint8_t add)
 {
        uint16_t ip_type;
-       uint32_t ipv4_addr;
+       uint32_t ipv4_addr, ipv4_addr_le;
        uint8_t i, tun_type = 0;
        /* internal variable to convert ipv6 byte order */
        uint32_t convert_ipv6[4];
@@ -7316,8 +7385,9 @@ i40e_dev_consistent_tunnel_filter_set(struct i40e_pf *pf,
        if (tunnel_filter->ip_type == I40E_TUNNEL_IPTYPE_IPV4) {
                ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV4;
                ipv4_addr = rte_be_to_cpu_32(tunnel_filter->ip_addr.ipv4_addr);
+               ipv4_addr_le = rte_cpu_to_le_32(ipv4_addr);
                rte_memcpy(&pfilter->element.ipaddr.v4.data,
-                               &rte_cpu_to_le_32(ipv4_addr),
+                               &ipv4_addr_le,
                                sizeof(pfilter->element.ipaddr.v4.data));
        } else {
                ip_type = I40E_AQC_ADD_CLOUD_FLAGS_IPV6;
@@ -9331,7 +9401,7 @@ i40e_pctype_to_flowtype(const struct i40e_adapter *adapter,
 
 /* For both X710 and XL710 */
 #define I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE_1     0x10000200
-#define I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE_2     0x20000200
+#define I40E_GL_SWR_PRI_JOIN_MAP_0_VALUE_2     0x203F0200
 #define I40E_GL_SWR_PRI_JOIN_MAP_0             0x26CE00
 
 #define I40E_GL_SWR_PRI_JOIN_MAP_2_VALUE 0x011f0200
@@ -10470,7 +10540,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -10658,7 +10728,7 @@ i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        uint16_t interval =
-               i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+               i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL, 1);
        uint16_t msix_intr;
 
        msix_intr = intr_handle->intr_vec[queue_id];
@@ -11049,14 +11119,14 @@ i40e_update_customized_ptype(struct rte_eth_dev *dev, uint8_t *pkg,
                               struct rte_pmd_i40e_proto_info *proto)
 {
        struct rte_pmd_i40e_ptype_mapping *ptype_mapping;
-       uint8_t port_id = dev->data->port_id;
+       uint16_t port_id = dev->data->port_id;
        uint32_t ptype_num;
        struct rte_pmd_i40e_ptype_info *ptype;
        uint32_t buff_size;
        uint8_t proto_id;
-       char name[16];
+       char name[RTE_PMD_I40E_DDP_NAME_SIZE];
        uint32_t i, j, n;
-       bool inner_ip;
+       bool in_tunnel;
        int ret;
 
        /* get information about new ptype num */
@@ -11101,7 +11171,7 @@ i40e_update_customized_ptype(struct rte_eth_dev *dev, uint8_t *pkg,
        for (i = 0; i < ptype_num; i++) {
                ptype_mapping[i].hw_ptype = ptype[i].ptype_id;
                ptype_mapping[i].sw_ptype = 0;
-               inner_ip = false;
+               in_tunnel = false;
                for (j = 0; j < RTE_PMD_I40E_PROTO_NUM; j++) {
                        proto_id = ptype[i].protocols[j];
                        if (proto_id == RTE_PMD_I40E_PROTO_UNUSED)
@@ -11111,52 +11181,91 @@ i40e_update_customized_ptype(struct rte_eth_dev *dev, uint8_t *pkg,
                                        continue;
                                memset(name, 0, sizeof(name));
                                strcpy(name, proto[n].name);
-                               if (!strncmp(name, "IPV4", 4) && !inner_ip) {
+                               if (!strncmp(name, "PPPOE", 5))
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_L2_ETHER_PPPOE;
+                               else if (!strncmp(name, "OIPV4", 5)) {
                                        ptype_mapping[i].sw_ptype |=
                                                RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
-                                       inner_ip = true;
+                                       in_tunnel = true;
                                } else if (!strncmp(name, "IPV4", 4) &&
-                                          inner_ip) {
+                                          !in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
-                                           RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN;
-                               } else if (!strncmp(name, "IPV6", 4) &&
-                                          !inner_ip) {
+                                               RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
+                               else if (!strncmp(name, "IPV4FRAG", 8) &&
+                                        in_tunnel) {
                                        ptype_mapping[i].sw_ptype |=
-                                               RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
-                                       inner_ip = true;
-                               } else if (!strncmp(name, "IPV6", 4) &&
-                                          inner_ip) {
+                                           RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN;
                                        ptype_mapping[i].sw_ptype |=
-                                           RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN;
-                               } else if (!strncmp(name, "IPV4FRAG", 8)) {
+                                               RTE_PTYPE_INNER_L4_FRAG;
+                               } else if (!strncmp(name, "IPV4", 4) &&
+                                          in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
                                            RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN;
+                               else if (!strncmp(name, "OIPV6", 5)) {
                                        ptype_mapping[i].sw_ptype |=
-                                               RTE_PTYPE_INNER_L4_FRAG;
-                               } else if (!strncmp(name, "IPV6FRAG", 8)) {
+                                               RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+                                       in_tunnel = true;
+                               } else if (!strncmp(name, "IPV6", 4) &&
+                                          !in_tunnel)
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+                               else if (!strncmp(name, "IPV6FRAG", 8) &&
+                                        in_tunnel) {
                                        ptype_mapping[i].sw_ptype |=
                                            RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN;
                                        ptype_mapping[i].sw_ptype |=
                                                RTE_PTYPE_INNER_L4_FRAG;
-                               } else if (!strncmp(name, "GTPC", 4))
+                               } else if (!strncmp(name, "IPV6", 4) &&
+                                          in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
-                                               RTE_PTYPE_TUNNEL_GTPC;
-                               else if (!strncmp(name, "GTPU", 4))
+                                           RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN;
+                               else if (!strncmp(name, "UDP", 3) && !in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
-                                               RTE_PTYPE_TUNNEL_GTPU;
-                               else if (!strncmp(name, "UDP", 3))
+                                               RTE_PTYPE_L4_UDP;
+                               else if (!strncmp(name, "UDP", 3) && in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
                                                RTE_PTYPE_INNER_L4_UDP;
-                               else if (!strncmp(name, "TCP", 3))
+                               else if (!strncmp(name, "TCP", 3) && !in_tunnel)
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_L4_TCP;
+                               else if (!strncmp(name, "TCP", 3) && in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
                                                RTE_PTYPE_INNER_L4_TCP;
-                               else if (!strncmp(name, "SCTP", 4))
+                               else if (!strncmp(name, "SCTP", 4) &&
+                                        !in_tunnel)
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_L4_SCTP;
+                               else if (!strncmp(name, "SCTP", 4) && in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
                                                RTE_PTYPE_INNER_L4_SCTP;
-                               else if (!strncmp(name, "ICMP", 4) ||
-                                        !strncmp(name, "ICMPV6", 6))
+                               else if ((!strncmp(name, "ICMP", 4) ||
+                                         !strncmp(name, "ICMPV6", 6)) &&
+                                        !in_tunnel)
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_L4_ICMP;
+                               else if ((!strncmp(name, "ICMP", 4) ||
+                                         !strncmp(name, "ICMPV6", 6)) &&
+                                        in_tunnel)
                                        ptype_mapping[i].sw_ptype |=
                                                RTE_PTYPE_INNER_L4_ICMP;
+                               else if (!strncmp(name, "GTPC", 4)) {
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_TUNNEL_GTPC;
+                                       in_tunnel = true;
+                               } else if (!strncmp(name, "GTPU", 4)) {
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_TUNNEL_GTPU;
+                                       in_tunnel = true;
+                               } else if (!strncmp(name, "GRENAT", 6)) {
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_TUNNEL_GRENAT;
+                                       in_tunnel = true;
+                               } else if (!strncmp(name, "L2TPv2CTL", 9)) {
+                                       ptype_mapping[i].sw_ptype |=
+                                               RTE_PTYPE_TUNNEL_L2TP;
+                                       in_tunnel = true;
+                               }
 
                                break;
                        }