net/i40e: use set switch AQ instead of register setting
[dpdk.git] / drivers / net / i40e / i40e_ethdev.c
index e02fbb1..2823d08 100644 (file)
@@ -919,7 +919,7 @@ i40e_init_ethtype_filter_list(struct rte_eth_dev *dev)
        /* Initialize ethertype filter rule list and hash */
        TAILQ_INIT(&ethertype_rule->ethertype_list);
        snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE,
-                "ethertype_%s", dev->data->name);
+                "ethertype_%s", dev->device->name);
        ethertype_rule->hash_table = rte_hash_create(&ethertype_hash_params);
        if (!ethertype_rule->hash_table) {
                PMD_INIT_LOG(ERR, "Failed to create ethertype hash table!");
@@ -964,7 +964,7 @@ i40e_init_tunnel_filter_list(struct rte_eth_dev *dev)
        /* Initialize tunnel filter rule list and hash */
        TAILQ_INIT(&tunnel_rule->tunnel_list);
        snprintf(tunnel_hash_name, RTE_HASH_NAMESIZE,
-                "tunnel_%s", dev->data->name);
+                "tunnel_%s", dev->device->name);
        tunnel_rule->hash_table = rte_hash_create(&tunnel_hash_params);
        if (!tunnel_rule->hash_table) {
                PMD_INIT_LOG(ERR, "Failed to create tunnel hash table!");
@@ -1009,7 +1009,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
        /* Initialize flow director filter rule list and hash */
        TAILQ_INIT(&fdir_info->fdir_list);
        snprintf(fdir_hash_name, RTE_HASH_NAMESIZE,
-                "fdir_%s", dev->data->name);
+                "fdir_%s", dev->device->name);
        fdir_info->hash_table = rte_hash_create(&fdir_hash_params);
        if (!fdir_info->hash_table) {
                PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
@@ -1142,11 +1142,8 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
        config_floating_veb(dev);
        /* Clear PXE mode */
        i40e_clear_pxe_mode(hw);
-       ret = i40e_dev_sync_phy_type(hw);
-       if (ret) {
-               PMD_INIT_LOG(ERR, "Failed to sync phy type: %d", ret);
-               goto err_sync_phy_type;
-       }
+       i40e_dev_sync_phy_type(hw);
+
        /*
         * On X710, performance number is far from the expectation on recent
         * firmware versions. The fix for this issue may not be integrated in
@@ -1331,7 +1328,6 @@ err_msix_pool_init:
 err_qp_pool_init:
 err_parameter_init:
 err_get_capabilities:
-err_sync_phy_type:
        (void)i40e_shutdown_adminq(hw);
 
        return ret;
@@ -1470,9 +1466,14 @@ i40e_dev_configure(struct rte_eth_dev *dev)
        struct i40e_adapter *ad =
                I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
        enum rte_eth_rx_mq_mode mq_mode = dev->data->dev_conf.rxmode.mq_mode;
        int i, ret;
 
+       ret = i40e_dev_sync_phy_type(hw);
+       if (ret)
+               return ret;
+
        /* Initialize to TRUE. If any of Rx queues doesn't meet the
         * bulk allocation or vector Rx preconditions we will reset it.
         */
@@ -2973,71 +2974,93 @@ i40e_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 }
 
 static int
-i40e_vlan_tpid_set(struct rte_eth_dev *dev,
-                  enum rte_vlan_type vlan_type,
-                  uint16_t tpid)
+i40e_vlan_tpid_set_by_registers(struct rte_eth_dev *dev,
+                               enum rte_vlan_type vlan_type,
+                               uint16_t tpid, int qinq)
 {
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       uint64_t reg_r = 0, reg_w = 0;
-       uint16_t reg_id = 0;
-       int ret = 0;
-       int qinq = dev->data->dev_conf.rxmode.hw_vlan_extend;
+       uint64_t reg_r = 0;
+       uint64_t reg_w = 0;
+       uint16_t reg_id = 3;
+       int ret;
 
-       switch (vlan_type) {
-       case ETH_VLAN_TYPE_OUTER:
-               if (qinq)
+       if (qinq) {
+               if (vlan_type == ETH_VLAN_TYPE_OUTER)
                        reg_id = 2;
-               else
-                       reg_id = 3;
-               break;
-       case ETH_VLAN_TYPE_INNER:
-               if (qinq)
-                       reg_id = 3;
-               else {
-                       ret = -EINVAL;
-                       PMD_DRV_LOG(ERR,
-                               "Unsupported vlan type in single vlan.");
-                       return ret;
-               }
-               break;
-       default:
-               ret = -EINVAL;
-               PMD_DRV_LOG(ERR, "Unsupported vlan type %d", vlan_type);
-               return ret;
        }
+
        ret = i40e_aq_debug_read_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id),
                                          &reg_r, NULL);
        if (ret != I40E_SUCCESS) {
                PMD_DRV_LOG(ERR,
                           "Fail to debug read from I40E_GL_SWT_L2TAGCTRL[%d]",
                           reg_id);
-               ret = -EIO;
-               return ret;
+               return -EIO;
        }
        PMD_DRV_LOG(DEBUG,
-               "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: 0x%08"PRIx64,
-               reg_id, reg_r);
+                   "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: 0x%08"PRIx64,
+                   reg_id, reg_r);
 
        reg_w = reg_r & (~(I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK));
        reg_w |= ((uint64_t)tpid << I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT);
        if (reg_r == reg_w) {
-               ret = 0;
                PMD_DRV_LOG(DEBUG, "No need to write");
-               return ret;
+               return 0;
        }
 
        ret = i40e_aq_debug_write_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id),
                                           reg_w, NULL);
        if (ret != I40E_SUCCESS) {
-               ret = -EIO;
                PMD_DRV_LOG(ERR,
-                       "Fail to debug write to I40E_GL_SWT_L2TAGCTRL[%d]",
-                       reg_id);
-               return ret;
+                           "Fail to debug write to I40E_GL_SWT_L2TAGCTRL[%d]",
+                           reg_id);
+               return -EIO;
        }
        PMD_DRV_LOG(DEBUG,
-               "Debug write 0x%08"PRIx64" to I40E_GL_SWT_L2TAGCTRL[%d]",
-               reg_w, reg_id);
+                   "Debug write 0x%08"PRIx64" to I40E_GL_SWT_L2TAGCTRL[%d]",
+                   reg_w, reg_id);
+
+       return 0;
+}
+
+static int
+i40e_vlan_tpid_set(struct rte_eth_dev *dev,
+                  enum rte_vlan_type vlan_type,
+                  uint16_t tpid)
+{
+       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int qinq = dev->data->dev_conf.rxmode.hw_vlan_extend;
+       int ret = 0;
+
+       if ((vlan_type != ETH_VLAN_TYPE_INNER &&
+            vlan_type != ETH_VLAN_TYPE_OUTER) ||
+           (!qinq && vlan_type == ETH_VLAN_TYPE_INNER)) {
+               PMD_DRV_LOG(ERR,
+                           "Unsupported vlan type.");
+               return -EINVAL;
+       }
+       /* 802.1ad frames ability is added in NVM API 1.7*/
+       if (hw->flags & I40E_HW_FLAG_802_1AD_CAPABLE) {
+               if (qinq) {
+                       if (vlan_type == ETH_VLAN_TYPE_OUTER)
+                               hw->first_tag = rte_cpu_to_le_16(tpid);
+                       else if (vlan_type == ETH_VLAN_TYPE_INNER)
+                               hw->second_tag = rte_cpu_to_le_16(tpid);
+               } else {
+                       if (vlan_type == ETH_VLAN_TYPE_OUTER)
+                               hw->second_tag = rte_cpu_to_le_16(tpid);
+               }
+               ret = i40e_aq_set_switch_config(hw, 0, 0, NULL);
+               if (ret != I40E_SUCCESS) {
+                       PMD_DRV_LOG(ERR,
+                                   "Set switch config failed aq_err: %d",
+                                   hw->aq.asq_last_status);
+                       ret = -EIO;
+               }
+       } else
+               /* If NVM API < 1.7, keep the register setting */
+               ret = i40e_vlan_tpid_set_by_registers(dev, vlan_type,
+                                                     tpid, qinq);
 
        return ret;
 }
@@ -3066,7 +3089,7 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
        if (mask & ETH_VLAN_EXTEND_MASK) {
                if (dev->data->dev_conf.rxmode.hw_vlan_extend) {
                        i40e_vsi_config_double_vlan(vsi, TRUE);
-                       /* Set global registers with default ether type value */
+                       /* Set global registers with default ethertype. */
                        i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_OUTER,
                                           ETHER_TYPE_VLAN);
                        i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_INNER,
@@ -9176,8 +9199,11 @@ i40e_dev_sync_phy_type(struct i40e_hw *hw)
        status = i40e_aq_get_phy_capabilities(hw, false, true, &phy_ab,
                                              NULL);
 
-       if (status)
+       if (status) {
+               PMD_INIT_LOG(WARNING, "Failed to sync phy type: status=%d",
+                       status);
                return ret;
+       }
 
        return 0;
 }