HNAE3_DEV_SUPPORT_MC_MAC_MNG_B,
        HNAE3_DEV_SUPPORT_CQ_B,
        HNAE3_DEV_SUPPORT_FEC_STATS_B,
+       HNAE3_DEV_SUPPORT_LANE_NUM_B,
 };
 
 #define hnae3_ae_dev_fd_supported(ae_dev) \
 #define hnae3_ae_dev_fec_stats_supported(ae_dev) \
        test_bit(HNAE3_DEV_SUPPORT_FEC_STATS_B, (ae_dev)->caps)
 
+#define hnae3_ae_dev_lane_num_supported(ae_dev) \
+       test_bit(HNAE3_DEV_SUPPORT_LANE_NUM_B, (ae_dev)->caps)
+
 enum HNAE3_PF_CAP_BITS {
        HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
 };
        void (*client_stop)(struct hnae3_handle *handle);
        int (*get_status)(struct hnae3_handle *handle);
        void (*get_ksettings_an_result)(struct hnae3_handle *handle,
-                                       u8 *auto_neg, u32 *speed, u8 *duplex);
+                                       u8 *auto_neg, u32 *speed, u8 *duplex,
+                                       u32 *lane_num);
 
        int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int speed,
-                                  u8 duplex);
+                                  u8 duplex, u8 lane_num);
 
        void (*get_media_type)(struct hnae3_handle *handle, u8 *media_type,
                               u8 *module_type);
 
        {HCLGE_COMM_CAP_GRO_B, HNAE3_DEV_SUPPORT_GRO_B},
        {HCLGE_COMM_CAP_FD_B, HNAE3_DEV_SUPPORT_FD_B},
        {HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B},
+       {HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
 };
 
 static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
 
        HCLGE_COMM_CAP_GRO_B = 20,
        HCLGE_COMM_CAP_FD_B = 21,
        HCLGE_COMM_CAP_FEC_STATS_B = 25,
+       HCLGE_COMM_CAP_LANE_NUM_B = 27,
 };
 
 enum HCLGE_COMM_API_CAP_BITS {
 
        }, {
                .name = "support FEC statistics",
                .cap_bit = HNAE3_DEV_SUPPORT_FEC_STATS_B,
+       }, {
+               .name = "support lane num",
+               .cap_bit = HNAE3_DEV_SUPPORT_LANE_NUM_B,
        }
 };
 
 
                ops->get_ksettings_an_result(h,
                                             &cmd->base.autoneg,
                                             &cmd->base.speed,
-                                            &cmd->base.duplex);
+                                            &cmd->base.duplex,
+                                            &cmd->lanes);
 
        /* 2.get link mode */
        if (ops->get_link_mode)
        const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
        u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
        u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
+       u32 lane_num;
        u8 autoneg;
        u32 speed;
        u8 duplex;
                return 0;
 
        if (ops->get_ksettings_an_result) {
-               ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex);
+               ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex, &lane_num);
                if (cmd->base.autoneg == autoneg && cmd->base.speed == speed &&
-                   cmd->base.duplex == duplex)
+                   cmd->base.duplex == duplex && cmd->lanes == lane_num)
                        return 0;
        }
 
        if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
                return -EINVAL;
 
+       if (cmd->lanes && !hnae3_ae_dev_lane_num_supported(ae_dev))
+               return -EOPNOTSUPP;
+
        netif_dbg(handle, drv, netdev,
-                 "set link(%s): autoneg=%u, speed=%u, duplex=%u\n",
+                 "set link(%s): autoneg=%u, speed=%u, duplex=%u, lanes=%u\n",
                  netdev->phydev ? "phy" : "mac",
-                 cmd->base.autoneg, cmd->base.speed, cmd->base.duplex);
+                 cmd->base.autoneg, cmd->base.speed, cmd->base.duplex,
+                 cmd->lanes);
 
        /* Only support ksettings_set for netdev with phy attached for now */
        if (netdev->phydev) {
 
        if (ops->cfg_mac_speed_dup_h)
                ret = ops->cfg_mac_speed_dup_h(handle, cmd->base.speed,
-                                              cmd->base.duplex);
+                                              cmd->base.duplex, (u8)(cmd->lanes));
 
        return ret;
 }
 static const struct ethtool_ops hns3_ethtool_ops = {
        .supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
        .supported_ring_params = HNS3_ETHTOOL_RING,
+       .cap_link_lanes_supported = true,
        .self_test = hns3_self_test,
        .get_drvinfo = hns3_get_drvinfo,
        .get_link = hns3_get_link,
 
 
 #define HCLGE_CFG_MAC_SPEED_CHANGE_EN_B        0
        u8 mac_change_fec_en;
-       u8 rsv[22];
+       u8 rsv[4];
+       u8 lane_num;
+       u8 rsv1[17];
 };
 
 #define HCLGE_TQP_ENABLE_B             0
        __le32 speed_ability; /* speed ability for current media */
        __le32 module_type;
        u8 fec_ability;
-       u8 rsv[7];
+       u8 lane_num;
+       u8 rsv[6];
 };
 
 #define HCLGE_MAC_CFG_FEC_AUTO_EN_B    0
 
 }
 
 static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed,
-                                     u8 duplex)
+                                     u8 duplex, u8 lane_num)
 {
        struct hclge_config_mac_speed_dup_cmd *req;
        struct hclge_desc desc;
                        speed_fw);
        hnae3_set_bit(req->mac_change_fec_en, HCLGE_CFG_MAC_SPEED_CHANGE_EN_B,
                      1);
+       req->lane_num = lane_num;
 
        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
        if (ret) {
        return 0;
 }
 
-int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
+int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex, u8 lane_num)
 {
        struct hclge_mac *mac = &hdev->hw.mac;
        int ret;
 
        duplex = hclge_check_speed_dup(duplex, speed);
        if (!mac->support_autoneg && mac->speed == speed &&
-           mac->duplex == duplex)
+           mac->duplex == duplex && (mac->lane_num == lane_num || lane_num == 0))
                return 0;
 
-       ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex);
+       ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex, lane_num);
        if (ret)
                return ret;
 
        hdev->hw.mac.speed = speed;
        hdev->hw.mac.duplex = duplex;
+       if (!lane_num)
+               hdev->hw.mac.lane_num = lane_num;
 
        return 0;
 }
 
 static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed,
-                                    u8 duplex)
+                                    u8 duplex, u8 lane_num)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
 
-       return hclge_cfg_mac_speed_dup(hdev, speed, duplex);
+       return hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num);
 }
 
 static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
        hdev->support_sfp_query = true;
        hdev->hw.mac.duplex = HCLGE_MAC_FULL;
        ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
-                                        hdev->hw.mac.duplex);
+                                        hdev->hw.mac.duplex, hdev->hw.mac.lane_num);
        if (ret)
                return ret;
 
                mac->autoneg = resp->autoneg;
                mac->support_autoneg = resp->autoneg_ability;
                mac->speed_type = QUERY_ACTIVE_SPEED;
+               mac->lane_num = resp->lane_num;
                if (!resp->active_fec)
                        mac->fec_mode = 0;
                else
                        return 0;
                }
                return hclge_cfg_mac_speed_dup(hdev, mac->speed,
-                                              HCLGE_MAC_FULL);
+                                              HCLGE_MAC_FULL, mac->lane_num);
        } else {
                if (speed == HCLGE_MAC_SPEED_UNKNOWN)
                        return 0; /* do nothing if no SFP */
 
                /* must config full duplex for SFP */
-               return hclge_cfg_mac_speed_dup(hdev, speed, HCLGE_MAC_FULL);
+               return hclge_cfg_mac_speed_dup(hdev, speed, HCLGE_MAC_FULL, 0);
        }
 }
 
 }
 
 static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
-                                         u8 *auto_neg, u32 *speed, u8 *duplex)
+                                         u8 *auto_neg, u32 *speed, u8 *duplex, u32 *lane_num)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
                *duplex = hdev->hw.mac.duplex;
        if (auto_neg)
                *auto_neg = hdev->hw.mac.autoneg;
+       if (lane_num)
+               *lane_num = hdev->hw.mac.lane_num;
 }
 
 static void hclge_get_media_type(struct hnae3_handle *handle, u8 *media_type,
 
        u8 duplex;
        u8 support_autoneg;
        u8 speed_type;  /* 0: sfp speed, 1: active speed */
+       u8 lane_num;
        u32 speed;
        u32 max_speed;
        u32 speed_ability; /* speed ability supported by current media */
 }
 
 int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport);
-int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex);
+int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex, u8 lane_num);
 int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
                          u16 vlan_id, bool is_kill);
 int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable);
 
        speed = netdev->phydev->speed;
        duplex = netdev->phydev->duplex;
 
-       ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex);
+       ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex, 0);
        if (ret)
                netdev_err(netdev, "failed to adjust link.\n");
 
 
 
 static void hclgevf_get_ksettings_an_result(struct hnae3_handle *handle,
                                            u8 *auto_neg, u32 *speed,
-                                           u8 *duplex)
+                                           u8 *duplex, u32 *lane_num)
 {
        struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);