Reconfiguration is needed to support QinQ stripping and insertion,
as hardware does not support them by default.

Signed-off-by: Helin Zhang <helin.zhang at intel.com>
---
 lib/librte_pmd_i40e/i40e_ethdev.c | 48 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c 
b/lib/librte_pmd_i40e/i40e_ethdev.c
index 43762f2..9b4bf06 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -211,6 +211,7 @@ static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev,
                                void *arg);
 static void i40e_configure_registers(struct i40e_hw *hw);
 static void i40e_hw_init(struct i40e_hw *hw);
+static int i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi);

 static const struct rte_pci_id pci_id_i40e_map[] = {
 #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -3055,6 +3056,7 @@ i40e_vsi_setup(struct i40e_pf *pf,
                 * macvlan filter which is expected and cannot be removed.
                 */
                i40e_update_default_filter_setting(vsi);
+               i40e_config_qinq(hw, vsi);
        } else if (type == I40E_VSI_SRIOV) {
                memset(&ctxt, 0, sizeof(ctxt));
                /**
@@ -3095,6 +3097,8 @@ i40e_vsi_setup(struct i40e_pf *pf,
                 * Since VSI is not created yet, only configure parameter,
                 * will add vsi below.
                 */
+
+               i40e_config_qinq(hw, vsi);
        } else if (type == I40E_VSI_VMDQ2) {
                memset(&ctxt, 0, sizeof(ctxt));
                /*
@@ -5714,3 +5718,47 @@ i40e_configure_registers(struct i40e_hw *hw)
                        "0x%"PRIx32, reg_table[i].val, reg_table[i].addr);
        }
 }
+
+#define I40E_VSI_TSR(_i)            (0x00050800 + ((_i) * 4))
+#define I40E_VSI_TSR_QINQ_CONFIG    0xc030
+#define I40E_VSI_L2TAGSTXVALID(_i)  (0x00042800 + ((_i) * 4))
+#define I40E_VSI_L2TAGSTXVALID_QINQ 0xab
+static int
+i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi)
+{
+       uint32_t reg;
+       int ret;
+
+       if (vsi->vsi_id >= I40E_MAX_NUM_VSIS) {
+               PMD_DRV_LOG(ERR, "VSI ID exceeds the maximum");
+               return -EINVAL;
+       }
+
+       /* Configure for double VLAN RX stripping */
+       reg = I40E_READ_REG(hw, I40E_VSI_TSR(vsi->vsi_id));
+       if ((reg & I40E_VSI_TSR_QINQ_CONFIG) != I40E_VSI_TSR_QINQ_CONFIG) {
+               reg |= I40E_VSI_TSR_QINQ_CONFIG;
+               ret = i40e_aq_debug_write_register(hw,
+                       I40E_VSI_TSR(vsi->vsi_id), reg, NULL);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to update VSI_TSR[%d]",
+                                                       vsi->vsi_id);
+                       return I40E_ERR_CONFIG;
+               }
+       }
+
+       /* Configure for double VLAN TX insertion */
+       reg = I40E_READ_REG(hw, I40E_VSI_L2TAGSTXVALID(vsi->vsi_id));
+       if ((reg & 0xff) != I40E_VSI_L2TAGSTXVALID_QINQ) {
+               reg = I40E_VSI_L2TAGSTXVALID_QINQ;
+               ret = i40e_aq_debug_write_register(hw,
+                       I40E_VSI_L2TAGSTXVALID(vsi->vsi_id), reg, NULL);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "Failed to update "
+                               "VSI_L2TAGSTXVALID[%d]", vsi->vsi_id);
+                       return I40E_ERR_CONFIG;
+               }
+       }
+
+       return 0;
+}
-- 
1.9.3

Reply via email to