net/i40e: fix parsing QinQ packets type
[dpdk.git] / drivers / net / i40e / i40e_ethdev.c
index 7fa9ef2..535380a 100644 (file)
 /* Source MAC address */
 #define I40E_REG_INSET_L2_SMAC                   0x1C00000000000000ULL
 /* Outer (S-Tag) VLAN tag in the outer L2 header */
-#define I40E_REG_INSET_L2_OUTER_VLAN             0x0200000000000000ULL
+#define I40E_REG_INSET_L2_OUTER_VLAN             0x0000000004000000ULL
 /* Inner (C-Tag) or single VLAN tag in the outer L2 header */
 #define I40E_REG_INSET_L2_INNER_VLAN             0x0080000000000000ULL
 /* Single VLAN tag in the inner L2 header */
@@ -705,10 +705,6 @@ rte_i40e_dev_atomic_write_link_status(struct rte_eth_dev *dev,
 DRIVER_REGISTER_PCI(net_i40e, rte_i40e_pmd.pci_drv);
 DRIVER_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
 
-/*
- * Initialize registers for flexible payload, which should be set by NVM.
- * This should be removed from code once it is fixed in NVM.
- */
 #ifndef I40E_GLQF_ORT
 #define I40E_GLQF_ORT(_i)    (0x00268900 + ((_i) * 4))
 #endif
@@ -716,8 +712,12 @@ DRIVER_REGISTER_PCI_TABLE(net_i40e, pci_id_i40e_map);
 #define I40E_GLQF_PIT(_i)    (0x00268C80 + ((_i) * 4))
 #endif
 
-static inline void i40e_flex_payload_reg_init(struct i40e_hw *hw)
+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.
+        */
        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);
@@ -728,10 +728,12 @@ static inline void i40e_flex_payload_reg_init(struct i40e_hw *hw)
        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);
-
-       /* GLQF_PIT Registers */
        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 */
+       I40E_WRITE_REG(hw, I40E_GLQF_ORT(40), 0x00000029);
+       I40E_WRITE_REG(hw, I40E_GLQF_PIT(9), 0x00009420);
 }
 
 #define I40E_FLOW_CONTROL_ETHERTYPE  0x8808
@@ -915,6 +917,9 @@ config_floating_veb(struct rte_eth_dev *dev)
        }
 }
 
+#define I40E_L2_TAGS_S_TAG_SHIFT 1
+#define I40E_L2_TAGS_S_TAG_MASK I40E_MASK(0x1, I40E_L2_TAGS_S_TAG_SHIFT)
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -985,11 +990,12 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        }
 
        /*
-        * To work around the NVM issue,initialize registers
-        * for flexible payload by software.
-        * It should be removed once issues are fixed in NVM.
+        * To work around the NVM issue, initialize registers
+        * for flexible payload and packet type of QinQ by
+        * software. It should be removed once issues are fixed
+        * in NVM.
         */
-       i40e_flex_payload_reg_init(hw);
+       i40e_GLQF_reg_init(hw);
 
        /* Initialize the input set for filters (hash and fd) to default value */
        i40e_filter_input_set_init(pf);
@@ -1103,6 +1109,13 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        /* Disable double vlan by default */
        i40e_vsi_config_double_vlan(vsi, FALSE);
 
+       /* Disable S-TAG identification by default */
+       ret = I40E_READ_REG(hw, I40E_PRT_L2TAGSEN);
+       if (ret & I40E_L2_TAGS_S_TAG_MASK) {
+               ret &= ~I40E_L2_TAGS_S_TAG_MASK;
+               I40E_WRITE_REG(hw, I40E_PRT_L2TAGSEN, ret);
+       }
+
        if (!vsi->max_macaddrs)
                len = ETHER_ADDR_LEN;
        else
@@ -7719,7 +7732,16 @@ i40e_hash_filter_inset_select(struct i40e_hw *hw,
                PMD_DRV_LOG(ERR, "invalid flow_type input.");
                return -EINVAL;
        }
+
+#ifdef X722_SUPPORT
+       /* get translated pctype value in fd pctype register */
+       pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(hw,
+               I40E_GLQF_FD_PCTYPES((int)i40e_flowtype_to_pctype(
+               conf->flow_type)));
+#else
        pctype = i40e_flowtype_to_pctype(conf->flow_type);
+#endif
+
        ret = i40e_parse_input_set(&input_set, pctype, conf->field,
                                   conf->inset_size);
        if (ret) {
@@ -7788,7 +7810,9 @@ i40e_fdir_filter_inset_select(struct i40e_pf *pf,
                PMD_DRV_LOG(ERR, "invalid flow_type input.");
                return -EINVAL;
        }
+
        pctype = i40e_flowtype_to_pctype(conf->flow_type);
+
        ret = i40e_parse_input_set(&input_set, pctype, conf->field,
                                   conf->inset_size);
        if (ret) {