+static void
+hns3_uninit_pf(struct rte_eth_dev *eth_dev)
+{
+ struct hns3_adapter *hns = eth_dev->data->dev_private;
+ struct rte_device *dev = eth_dev->device;
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
+ struct hns3_hw *hw = &hns->hw;
+
+ PMD_INIT_FUNC_TRACE();
+
+ hns3_tm_conf_uninit(eth_dev);
+ hns3_enable_hw_error_intr(hns, false);
+ hns3_rss_uninit(hns);
+ (void)hns3_config_gro(hw, false);
+ hns3_promisc_uninit(hw);
+ hns3_flow_uninit(eth_dev);
+ hns3_fdir_filter_uninit(hns);
+ hns3_uninit_umv_space(hw);
+ hns3_tqp_stats_uninit(hw);
+ hns3_config_mac_tnl_int(hw, false);
+ hns3_pf_disable_irq0(hw);
+ rte_intr_disable(pci_dev->intr_handle);
+ hns3_intr_unregister(pci_dev->intr_handle, hns3_interrupt_handler,
+ eth_dev);
+ hns3_config_all_msix_error(hw, false);
+ hns3_cmd_uninit(hw);
+ hns3_cmd_destroy_queue(hw);
+ hw->io_base = NULL;
+}
+
+static uint32_t
+hns3_convert_link_speeds2bitmap_copper(uint32_t link_speeds)
+{
+ uint32_t speed_bit;
+
+ switch (link_speeds & ~RTE_ETH_LINK_SPEED_FIXED) {
+ case RTE_ETH_LINK_SPEED_10M:
+ speed_bit = HNS3_PHY_LINK_SPEED_10M_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_10M_HD:
+ speed_bit = HNS3_PHY_LINK_SPEED_10M_HD_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_100M:
+ speed_bit = HNS3_PHY_LINK_SPEED_100M_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_100M_HD:
+ speed_bit = HNS3_PHY_LINK_SPEED_100M_HD_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_1G:
+ speed_bit = HNS3_PHY_LINK_SPEED_1000M_BIT;
+ break;
+ default:
+ speed_bit = 0;
+ break;
+ }
+
+ return speed_bit;
+}
+
+static uint32_t
+hns3_convert_link_speeds2bitmap_fiber(uint32_t link_speeds)
+{
+ uint32_t speed_bit;
+
+ switch (link_speeds & ~RTE_ETH_LINK_SPEED_FIXED) {
+ case RTE_ETH_LINK_SPEED_1G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_1G_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_10G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_10G_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_25G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_25G_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_40G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_40G_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_50G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_50G_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_100G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_100G_BIT;
+ break;
+ case RTE_ETH_LINK_SPEED_200G:
+ speed_bit = HNS3_FIBER_LINK_SPEED_200G_BIT;
+ break;
+ default:
+ speed_bit = 0;
+ break;
+ }
+
+ return speed_bit;
+}
+
+static int
+hns3_check_port_speed(struct hns3_hw *hw, uint32_t link_speeds)
+{
+ struct hns3_mac *mac = &hw->mac;
+ uint32_t supported_speed = mac->supported_speed;
+ uint32_t speed_bit = 0;
+
+ if (mac->media_type == HNS3_MEDIA_TYPE_COPPER)
+ speed_bit = hns3_convert_link_speeds2bitmap_copper(link_speeds);
+ else if (mac->media_type == HNS3_MEDIA_TYPE_FIBER)
+ speed_bit = hns3_convert_link_speeds2bitmap_fiber(link_speeds);
+
+ if (!(speed_bit & supported_speed)) {
+ hns3_err(hw, "link_speeds(0x%x) exceeds the supported speed capability or is incorrect.",
+ link_speeds);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static uint32_t
+hns3_get_link_speed(uint32_t link_speeds)
+{
+ uint32_t speed = RTE_ETH_SPEED_NUM_NONE;
+
+ if (link_speeds & RTE_ETH_LINK_SPEED_10M ||
+ link_speeds & RTE_ETH_LINK_SPEED_10M_HD)
+ speed = RTE_ETH_SPEED_NUM_10M;
+ if (link_speeds & RTE_ETH_LINK_SPEED_100M ||
+ link_speeds & RTE_ETH_LINK_SPEED_100M_HD)
+ speed = RTE_ETH_SPEED_NUM_100M;
+ if (link_speeds & RTE_ETH_LINK_SPEED_1G)
+ speed = RTE_ETH_SPEED_NUM_1G;
+ if (link_speeds & RTE_ETH_LINK_SPEED_10G)
+ speed = RTE_ETH_SPEED_NUM_10G;
+ if (link_speeds & RTE_ETH_LINK_SPEED_25G)
+ speed = RTE_ETH_SPEED_NUM_25G;
+ if (link_speeds & RTE_ETH_LINK_SPEED_40G)
+ speed = RTE_ETH_SPEED_NUM_40G;
+ if (link_speeds & RTE_ETH_LINK_SPEED_50G)
+ speed = RTE_ETH_SPEED_NUM_50G;
+ if (link_speeds & RTE_ETH_LINK_SPEED_100G)
+ speed = RTE_ETH_SPEED_NUM_100G;
+ if (link_speeds & RTE_ETH_LINK_SPEED_200G)
+ speed = RTE_ETH_SPEED_NUM_200G;
+
+ return speed;
+}
+
+static uint8_t
+hns3_get_link_duplex(uint32_t link_speeds)
+{
+ if ((link_speeds & RTE_ETH_LINK_SPEED_10M_HD) ||
+ (link_speeds & RTE_ETH_LINK_SPEED_100M_HD))
+ return RTE_ETH_LINK_HALF_DUPLEX;
+ else
+ return RTE_ETH_LINK_FULL_DUPLEX;
+}
+
+static int
+hns3_set_copper_port_link_speed(struct hns3_hw *hw,
+ struct hns3_set_link_speed_cfg *cfg)
+{
+ struct hns3_cmd_desc desc[HNS3_PHY_PARAM_CFG_BD_NUM];
+ struct hns3_phy_params_bd0_cmd *req;
+ uint16_t i;
+
+ for (i = 0; i < HNS3_PHY_PARAM_CFG_BD_NUM - 1; i++) {
+ hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_PHY_PARAM_CFG,
+ false);
+ desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
+ }
+ hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_PHY_PARAM_CFG, false);
+ req = (struct hns3_phy_params_bd0_cmd *)desc[0].data;
+ req->autoneg = cfg->autoneg;
+
+ /*
+ * The full speed capability is used to negotiate when
+ * auto-negotiation is enabled.
+ */
+ if (cfg->autoneg) {
+ req->advertising = HNS3_PHY_LINK_SPEED_10M_BIT |
+ HNS3_PHY_LINK_SPEED_10M_HD_BIT |
+ HNS3_PHY_LINK_SPEED_100M_BIT |
+ HNS3_PHY_LINK_SPEED_100M_HD_BIT |
+ HNS3_PHY_LINK_SPEED_1000M_BIT;
+ } else {
+ req->speed = cfg->speed;
+ req->duplex = cfg->duplex;
+ }
+
+ return hns3_cmd_send(hw, desc, HNS3_PHY_PARAM_CFG_BD_NUM);
+}
+
+static int
+hns3_set_autoneg(struct hns3_hw *hw, bool enable)
+{
+ struct hns3_config_auto_neg_cmd *req;
+ struct hns3_cmd_desc desc;
+ uint32_t flag = 0;
+ int ret;
+
+ hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CONFIG_AN_MODE, false);
+
+ req = (struct hns3_config_auto_neg_cmd *)desc.data;
+ if (enable)
+ hns3_set_bit(flag, HNS3_MAC_CFG_AN_EN_B, 1);
+ req->cfg_an_cmd_flag = rte_cpu_to_le_32(flag);
+
+ ret = hns3_cmd_send(hw, &desc, 1);
+ if (ret)
+ hns3_err(hw, "autoneg set cmd failed, ret = %d.", ret);
+
+ return ret;
+}
+
+static int
+hns3_set_fiber_port_link_speed(struct hns3_hw *hw,
+ struct hns3_set_link_speed_cfg *cfg)
+{
+ int ret;
+
+ if (hw->mac.support_autoneg) {
+ ret = hns3_set_autoneg(hw, cfg->autoneg);
+ if (ret) {
+ hns3_err(hw, "failed to configure auto-negotiation.");
+ return ret;
+ }
+
+ /*
+ * To enable auto-negotiation, we only need to open the switch
+ * of auto-negotiation, then firmware sets all speed
+ * capabilities.
+ */
+ if (cfg->autoneg)
+ return 0;
+ }
+
+ /*
+ * Some hardware doesn't support auto-negotiation, but users may not
+ * configure link_speeds (default 0), which means auto-negotiation.
+ * In this case, a warning message need to be printed, instead of
+ * an error.
+ */
+ if (cfg->autoneg) {
+ hns3_warn(hw, "auto-negotiation is not supported, use default fixed speed!");
+ return 0;
+ }
+
+ return hns3_cfg_mac_speed_dup(hw, cfg->speed, cfg->duplex);
+}
+
+static int
+hns3_set_port_link_speed(struct hns3_hw *hw,
+ struct hns3_set_link_speed_cfg *cfg)
+{
+ int ret;
+
+ if (hw->mac.media_type == HNS3_MEDIA_TYPE_COPPER) {
+#if defined(RTE_HNS3_ONLY_1630_FPGA)
+ struct hns3_pf *pf = HNS3_DEV_HW_TO_PF(hw);
+ if (pf->is_tmp_phy)
+ return 0;
+#endif
+
+ ret = hns3_set_copper_port_link_speed(hw, cfg);
+ if (ret) {
+ hns3_err(hw, "failed to set copper port link speed,"
+ "ret = %d.", ret);
+ return ret;
+ }
+ } else if (hw->mac.media_type == HNS3_MEDIA_TYPE_FIBER) {
+ ret = hns3_set_fiber_port_link_speed(hw, cfg);
+ if (ret) {
+ hns3_err(hw, "failed to set fiber port link speed,"
+ "ret = %d.", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int
+hns3_apply_link_speed(struct hns3_hw *hw)