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