[v2,5/6] net/hns3: support setting lanes

Message ID 20240322070923.244417-6-huangdengdui@huawei.com (mailing list archive)
State New
Delegated to: Ferruh Yigit
Headers
Series support setting lanes |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Dengdui Huang March 22, 2024, 7:09 a.m. UTC
  Some speeds can be achieved with different number of lanes. For example,
100Gbps can be achieved using two lanes of 50Gbps or four lanes of 25Gbps.
When use different lanes, the port cannot be up. This patch add support
for setting lanes and report lanes.

In addition, when reporting FEC capability, it is incorrect to calculate
speed_num from the speed function when one speed supports a different
number of lanes. This patch modifies it together.

Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
 doc/guides/rel_notes/release_24_03.rst |   2 +
 drivers/net/hns3/hns3_cmd.h            |  15 ++-
 drivers/net/hns3/hns3_common.c         |   2 +
 drivers/net/hns3/hns3_ethdev.c         | 158 ++++++++++++++++++-------
 drivers/net/hns3/hns3_ethdev.h         |   2 +
 5 files changed, 134 insertions(+), 45 deletions(-)
  

Patch

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