diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index b41b0028b2..c9b8740323 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -193,6 +193,8 @@ New Features
   * Added power-saving during polling within the ``rte_event_dequeue_burst()`` API.
   * Added support for DMA adapter.
 
+* **Added setting lanes for hns3 PF driver.**
+  * This feature add support for setting lanes and report lanes.
 
 Removed Items
 -------------
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 79a8c1edad..31ff7b35d8 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -753,7 +753,9 @@ struct hns3_config_mac_mode_cmd {
 struct hns3_config_mac_speed_dup_cmd {
 	uint8_t speed_dup;
 	uint8_t mac_change_fec_en;
-	uint8_t rsv[22];
+	uint8_t rsv[4];
+	uint8_t lanes;
+	uint8_t rsv1[17];
 };
 
 #define HNS3_TQP_ENABLE_B		0
@@ -789,12 +791,15 @@ struct hns3_sfp_type {
 #define HNS3_FIBER_LINK_SPEED_1G_BIT		BIT(0)
 #define HNS3_FIBER_LINK_SPEED_10G_BIT		BIT(1)
 #define HNS3_FIBER_LINK_SPEED_25G_BIT		BIT(2)
-#define HNS3_FIBER_LINK_SPEED_50G_BIT		BIT(3)
-#define HNS3_FIBER_LINK_SPEED_100G_BIT		BIT(4)
+#define HNS3_FIBER_LINK_SPEED_50G_R2_BIT	BIT(3)
+#define HNS3_FIBER_LINK_SPEED_100G_R4_BIT	BIT(4)
 #define HNS3_FIBER_LINK_SPEED_40G_BIT		BIT(5)
 #define HNS3_FIBER_LINK_SPEED_100M_BIT		BIT(6)
 #define HNS3_FIBER_LINK_SPEED_10M_BIT		BIT(7)
-#define HNS3_FIBER_LINK_SPEED_200G_BIT		BIT(8)
+#define HNS3_FIBER_LINK_SPEED_200G_EXT_BIT	BIT(8)
+#define HNS3_FIBER_LINK_SPEED_50G_R1_BIT	BIT(9)
+#define HNS3_FIBER_LINK_SPEED_100G_R2_BIT	BIT(10)
+#define HNS3_FIBER_LINK_SPEED_200G_R4_BIT	BIT(11)
 
 #define HNS3_FIBER_FEC_AUTO_BIT		BIT(0)
 #define HNS3_FIBER_FEC_BASER_BIT	BIT(1)
@@ -823,7 +828,7 @@ struct hns3_sfp_info_cmd {
 	uint32_t supported_speed; /* speed supported by current media */
 	uint32_t module_type;
 	uint8_t fec_ability; /* supported fec modes, see HNS3_FIBER_FEC_XXX_BIT */
-	uint8_t rsv0;
+	uint8_t lanes;
 	uint8_t pause_status;
 	uint8_t rsv1[5];
 };
diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index 28c26b049c..b6db012993 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -93,6 +93,8 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 
 	info->dev_capa = RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP |
 			 RTE_ETH_DEV_CAPA_FLOW_SHARED_OBJECT_KEEP;
+	if (!hns->is_vf)
+		info->dev_capa |= RTE_ETH_DEV_CAPA_SETTING_LANES;
 	if (hns3_dev_get_support(hw, INDEP_TXRX))
 		info->dev_capa |= RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
 				  RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 1b380ac75f..7f36c193a6 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -63,12 +63,12 @@ struct hns3_intr_state {
 	uint32_t hw_err_state;
 };
 
-#define HNS3_SPEEDS_SUPP_FEC (RTE_ETH_LINK_SPEED_10G | \
-			      RTE_ETH_LINK_SPEED_25G | \
-			      RTE_ETH_LINK_SPEED_40G | \
-			      RTE_ETH_LINK_SPEED_50G | \
-			      RTE_ETH_LINK_SPEED_100G | \
-			      RTE_ETH_LINK_SPEED_200G)
+#define HNS3_SPEED_NUM_10G_BIT	RTE_BIT32(1)
+#define HNS3_SPEED_NUM_25G_BIT	RTE_BIT32(2)
+#define HNS3_SPEED_NUM_40G_BIT	RTE_BIT32(3)
+#define HNS3_SPEED_NUM_50G_BIT	RTE_BIT32(4)
+#define HNS3_SPEED_NUM_100G_BIT	RTE_BIT32(5)
+#define HNS3_SPEED_NUM_200G_BIT	RTE_BIT32(6)
 
 static const struct rte_eth_fec_capa speed_fec_capa_tbl[] = {
 	{ RTE_ETH_SPEED_NUM_10G, RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
@@ -2234,13 +2234,17 @@ hns3_get_firber_port_speed_capa(uint32_t supported_speed)
 	if (supported_speed & HNS3_FIBER_LINK_SPEED_25G_BIT)
 		speed_capa |= RTE_ETH_LINK_SPEED_25G;
 	if (supported_speed & HNS3_FIBER_LINK_SPEED_40G_BIT)
-		speed_capa |= RTE_ETH_LINK_SPEED_40G;
-	if (supported_speed & HNS3_FIBER_LINK_SPEED_50G_BIT)
+		speed_capa |= RTE_ETH_LINK_SPEED_40G_4LANES;
+	if (supported_speed & HNS3_FIBER_LINK_SPEED_50G_R1_BIT)
 		speed_capa |= RTE_ETH_LINK_SPEED_50G;
-	if (supported_speed & HNS3_FIBER_LINK_SPEED_100G_BIT)
-		speed_capa |= RTE_ETH_LINK_SPEED_100G;
-	if (supported_speed & HNS3_FIBER_LINK_SPEED_200G_BIT)
-		speed_capa |= RTE_ETH_LINK_SPEED_200G;
+	if (supported_speed & HNS3_FIBER_LINK_SPEED_50G_R2_BIT)
+		speed_capa |= RTE_ETH_LINK_SPEED_50G_2LANES;
+	if (supported_speed & HNS3_FIBER_LINK_SPEED_100G_R4_BIT)
+		speed_capa |= RTE_ETH_LINK_SPEED_100G_4LANES;
+	if (supported_speed & HNS3_FIBER_LINK_SPEED_100G_R2_BIT)
+		speed_capa |= RTE_ETH_LINK_SPEED_100G_2LANES;
+	if (supported_speed & HNS3_FIBER_LINK_SPEED_200G_R4_BIT)
+		speed_capa |= RTE_ETH_LINK_SPEED_200G_4LANES;
 
 	return speed_capa;
 }
@@ -2308,6 +2312,7 @@ hns3_setup_linkstatus(struct rte_eth_dev *eth_dev,
 	if (!mac->link_status)
 		new_link->link_speed = RTE_ETH_SPEED_NUM_NONE;
 
+	new_link->link_lanes = mac->link_lanes;
 	new_link->link_duplex = mac->link_duplex;
 	new_link->link_status = mac->link_status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN;
 	new_link->link_autoneg = mac->link_autoneg;
@@ -2934,7 +2939,8 @@ hns3_map_tqp(struct hns3_hw *hw)
 }
 
 static int
-hns3_cfg_mac_speed_dup_hw(struct hns3_hw *hw, uint32_t speed, uint8_t duplex)
+hns3_cfg_mac_speed_dup_hw(struct hns3_hw *hw, uint32_t speed, uint8_t lanes,
+			  uint8_t duplex)
 {
 	struct hns3_config_mac_speed_dup_cmd *req;
 	struct hns3_cmd_desc desc;
@@ -2989,6 +2995,7 @@ hns3_cfg_mac_speed_dup_hw(struct hns3_hw *hw, uint32_t speed, uint8_t duplex)
 	}
 
 	hns3_set_bit(req->mac_change_fec_en, HNS3_CFG_MAC_SPEED_CHANGE_EN_B, 1);
+	req->lanes = lanes;
 
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret)
@@ -3643,7 +3650,10 @@ hns3_mac_init(struct hns3_hw *hw)
 
 	pf->support_sfp_query = true;
 	mac->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
-	ret = hns3_cfg_mac_speed_dup_hw(hw, mac->link_speed, mac->link_duplex);
+	/* If lane is set to 0, the firmware selects the default lane. */
+	mac->link_lanes = RTE_ETH_LANES_UNKNOWN;
+	ret = hns3_cfg_mac_speed_dup_hw(hw, mac->link_speed, mac->link_lanes,
+					mac->link_duplex);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Config mac speed dup fail ret = %d", ret);
 		return ret;
@@ -4052,6 +4062,7 @@ hns3_get_sfp_info(struct hns3_hw *hw, struct hns3_mac *mac_info)
 		return 0;
 
 	mac_info->link_speed = rte_le_to_cpu_32(resp->sfp_speed);
+	mac_info->link_lanes = resp->lanes;
 	/*
 	 * if resp->supported_speed is 0, it means it's an old version
 	 * firmware, do not update these params.
@@ -4088,16 +4099,18 @@ hns3_check_speed_dup(uint8_t duplex, uint32_t speed)
 }
 
 static int
-hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex)
+hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t lanes,
+		       uint8_t duplex)
 {
 	struct hns3_mac *mac = &hw->mac;
 	int ret;
 
 	duplex = hns3_check_speed_dup(duplex, speed);
-	if (mac->link_speed == speed && mac->link_duplex == duplex)
+	if (mac->link_speed == speed && mac->link_lanes == lanes &&
+	    mac->link_duplex == duplex)
 		return 0;
 
-	ret = hns3_cfg_mac_speed_dup_hw(hw, speed, duplex);
+	ret = hns3_cfg_mac_speed_dup_hw(hw, speed, lanes, duplex);
 	if (ret)
 		return ret;
 
@@ -4106,6 +4119,7 @@ hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex)
 		return ret;
 
 	mac->link_speed = speed;
+	mac->link_lanes = lanes;
 	mac->link_duplex = duplex;
 
 	return 0;
@@ -4150,6 +4164,7 @@ hns3_update_fiber_link_info(struct hns3_hw *hw)
 		}
 
 		mac->link_speed = mac_info.link_speed;
+		mac->link_lanes = mac_info.link_lanes;
 		mac->supported_speed = mac_info.supported_speed;
 		mac->support_autoneg = mac_info.support_autoneg;
 		mac->link_autoneg = mac_info.link_autoneg;
@@ -4161,7 +4176,7 @@ hns3_update_fiber_link_info(struct hns3_hw *hw)
 	}
 
 	/* Config full duplex for SFP */
-	return hns3_cfg_mac_speed_dup(hw, mac_info.link_speed,
+	return hns3_cfg_mac_speed_dup(hw, mac_info.link_speed, mac_info.link_lanes,
 				      RTE_ETH_LINK_FULL_DUPLEX);
 }
 
@@ -4512,11 +4527,11 @@ hns3_set_firber_default_support_speed(struct hns3_hw *hw)
 	case RTE_ETH_SPEED_NUM_40G:
 		return HNS3_FIBER_LINK_SPEED_40G_BIT;
 	case RTE_ETH_SPEED_NUM_50G:
-		return HNS3_FIBER_LINK_SPEED_50G_BIT;
+		return HNS3_FIBER_LINK_SPEED_50G_R2_BIT;
 	case RTE_ETH_SPEED_NUM_100G:
-		return HNS3_FIBER_LINK_SPEED_100G_BIT;
+		return HNS3_FIBER_LINK_SPEED_100G_R4_BIT;
 	case RTE_ETH_SPEED_NUM_200G:
-		return HNS3_FIBER_LINK_SPEED_200G_BIT;
+		return HNS3_FIBER_LINK_SPEED_200G_R4_BIT;
 	default:
 		hns3_warn(hw, "invalid speed %u Mbps.", mac->link_speed);
 		return 0;
@@ -4769,17 +4784,23 @@ hns3_convert_link_speeds2bitmap_fiber(uint32_t link_speeds)
 	case RTE_ETH_LINK_SPEED_25G:
 		speed_bit = HNS3_FIBER_LINK_SPEED_25G_BIT;
 		break;
-	case RTE_ETH_LINK_SPEED_40G:
+	case RTE_ETH_LINK_SPEED_40G_4LANES:
 		speed_bit = HNS3_FIBER_LINK_SPEED_40G_BIT;
 		break;
 	case RTE_ETH_LINK_SPEED_50G:
-		speed_bit = HNS3_FIBER_LINK_SPEED_50G_BIT;
+		speed_bit = HNS3_FIBER_LINK_SPEED_50G_R1_BIT;
 		break;
-	case RTE_ETH_LINK_SPEED_100G:
-		speed_bit = HNS3_FIBER_LINK_SPEED_100G_BIT;
+	case RTE_ETH_LINK_SPEED_50G_2LANES:
+		speed_bit = HNS3_FIBER_LINK_SPEED_50G_R2_BIT;
 		break;
-	case RTE_ETH_LINK_SPEED_200G:
-		speed_bit = HNS3_FIBER_LINK_SPEED_200G_BIT;
+	case RTE_ETH_LINK_SPEED_100G_4LANES:
+		speed_bit = HNS3_FIBER_LINK_SPEED_100G_R4_BIT;
+		break;
+	case RTE_ETH_LINK_SPEED_100G_2LANES:
+		speed_bit = HNS3_FIBER_LINK_SPEED_100G_R2_BIT;
+		break;
+	case RTE_ETH_LINK_SPEED_200G_4LANES:
+		speed_bit = HNS3_FIBER_LINK_SPEED_200G_R4_BIT;
 		break;
 	default:
 		speed_bit = 0;
@@ -4900,7 +4921,7 @@ hns3_set_fiber_port_link_speed(struct hns3_hw *hw,
 		return 0;
 	}
 
-	return hns3_cfg_mac_speed_dup(hw, cfg->speed, cfg->duplex);
+	return hns3_cfg_mac_speed_dup(hw, cfg->speed, cfg->lanes, cfg->duplex);
 }
 
 const char *
@@ -4954,7 +4975,7 @@ hns3_apply_link_speed(struct hns3_hw *hw)
 			hns3_err(hw, "failed to parse link mode, ret = %d", ret);
 			return ret;
 		}
-		cfg.speed = mode_onfo.speed_num;
+		cfg.lanes = mode_info.lanes;
 		cfg.speed = mode_info.speed_num;
 		cfg.duplex = mode_info.duplex;
 	}
@@ -5927,20 +5948,49 @@ hns3_reset_service(void *param)
 		hns3_msix_process(hns, reset_level);
 }
 
+static uint32_t
+hns3_speed_num_capa_bit(uint32_t speed_num)
+{
+	uint32_t speed_bit;
+
+	switch (speed_num) {
+	case RTE_ETH_SPEED_NUM_10G:
+		speed_bit = HNS3_SPEED_NUM_10G_BIT;
+		break;
+	case RTE_ETH_SPEED_NUM_25G:
+		speed_bit = HNS3_SPEED_NUM_25G_BIT;
+		break;
+	case RTE_ETH_SPEED_NUM_40G:
+		speed_bit = HNS3_SPEED_NUM_40G_BIT;
+		break;
+	case RTE_ETH_SPEED_NUM_50G:
+		speed_bit = HNS3_SPEED_NUM_50G_BIT;
+		break;
+	case RTE_ETH_SPEED_NUM_100G:
+		speed_bit = HNS3_SPEED_NUM_100G_BIT;
+		break;
+	case RTE_ETH_SPEED_NUM_200G:
+		speed_bit = HNS3_SPEED_NUM_200G_BIT;
+		break;
+	default:
+		speed_bit = 0;
+		break;
+	}
+
+	return speed_bit;
+}
+
 static uint32_t
 hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
-			uint32_t speed_capa)
+			uint32_t speed_num_capa)
 {
 	uint32_t speed_bit;
 	uint32_t num = 0;
 	uint32_t i;
 
 	for (i = 0; i < RTE_DIM(speed_fec_capa_tbl); i++) {
-		speed_bit =
-			rte_eth_speed_bitflag(speed_fec_capa_tbl[i].speed,
-					      RTE_ETH_LANES_UNKNOWN,
-					      RTE_ETH_LINK_FULL_DUPLEX);
-		if ((speed_capa & speed_bit) == 0)
+		speed_bit = hns3_speed_num_capa_bit(speed_fec_capa_tbl[i].speed);
+		if ((speed_num_capa & speed_bit) == 0)
 			continue;
 
 		speed_fec_capa[num].speed = speed_fec_capa_tbl[i].speed;
@@ -5951,6 +6001,34 @@ hns3_get_speed_fec_capa(struct rte_eth_fec_capa *speed_fec_capa,
 	return num;
 }
 
+static uint32_t
+hns3_get_speed_num_capa(struct hns3_hw *hw)
+{
+	uint32_t speed_num_capa = 0;
+	uint32_t speed_capa;
+
+	speed_capa = hns3_get_speed_capa(hw);
+
+	if (speed_capa & RTE_ETH_LINK_SPEED_10G)
+		speed_num_capa |= HNS3_SPEED_NUM_10G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_25G)
+		speed_num_capa |= HNS3_SPEED_NUM_25G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_40G_4LANES)
+		speed_num_capa |= HNS3_SPEED_NUM_40G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_50G)
+		speed_num_capa |= HNS3_SPEED_NUM_50G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_50G_2LANES)
+		speed_num_capa |= HNS3_SPEED_NUM_50G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_100G_4LANES)
+		speed_num_capa |= HNS3_SPEED_NUM_100G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_100G_2LANES)
+		speed_num_capa |= HNS3_SPEED_NUM_100G_BIT;
+	if (speed_capa & RTE_ETH_LINK_SPEED_200G_4LANES)
+		speed_num_capa |= HNS3_SPEED_NUM_200G_BIT;
+
+	return speed_num_capa;
+}
+
 static int
 hns3_fec_get_capability(struct rte_eth_dev *dev,
 			struct rte_eth_fec_capa *speed_fec_capa,
@@ -5958,11 +6036,11 @@ hns3_fec_get_capability(struct rte_eth_dev *dev,
 {
 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	unsigned int speed_num;
-	uint32_t speed_capa;
+	uint32_t speed_num_capa;
 
-	speed_capa = hns3_get_speed_capa(hw);
-	/* speed_num counts number of speed capabilities */
-	speed_num = rte_popcount32(speed_capa & HNS3_SPEEDS_SUPP_FEC);
+	speed_num_capa = hns3_get_speed_num_capa(hw);
+	/* speed_num counts number of speed number capabilities */
+	speed_num = rte_popcount32(speed_num_capa);
 	if (speed_num == 0)
 		return -ENOTSUP;
 
@@ -5975,7 +6053,7 @@ hns3_fec_get_capability(struct rte_eth_dev *dev,
 		return -EINVAL;
 	}
 
-	return hns3_get_speed_fec_capa(speed_fec_capa, speed_capa);
+	return hns3_get_speed_fec_capa(speed_fec_capa, speed_num_capa);
 }
 
 
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 12d8299def..070fc76420 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -168,6 +168,7 @@ struct hns3_set_link_speed_cfg {
 	uint32_t speed;
 	uint8_t duplex  : 1;
 	uint8_t autoneg : 1;
+	uint8_t lanes   : 4;
 };
 
 /* mac media type */
@@ -190,6 +191,7 @@ struct hns3_mac {
 	uint8_t link_autoneg : 1; /* RTE_ETH_LINK_[AUTONEG/FIXED] */
 	uint8_t link_status  : 1; /* RTE_ETH_LINK_[DOWN/UP] */
 	uint32_t link_speed;      /* RTE_ETH_SPEED_NUM_ */
+	uint8_t link_lanes;       /* RTE_ETH_LANES_ */
 	/*
 	 * Some firmware versions support only the SFP speed query. In addition
 	 * to the SFP speed query, some firmware supports the query of the speed
