DPDK patches and discussions
 help / color / mirror / Atom feed
* [RFC 0/2] Add support for link speed lanes
@ 2024-03-22 22:25 Damodharam Ammepalli
  2024-03-22 22:25 ` [RFC 1/2] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
                   ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-03-22 22:25 UTC (permalink / raw)
  To: dev

[-- Attachment #1: Type: text/plain, Size: 1514 bytes --]

BRCM576xx NIC modules support speeds with different lanes configuration.
This is an alternate proposal to
https://patchwork.dpdk.org/project/dpdk/list/?series=31593

Please provide your review. Broadcom driver patches will follow.

Damodharam Ammepalli (2):
  lib/ethdev: Add link_speed lanes support into rte lib
  testpmd: Add speed lanes to testpmd config and show command

 app/test-pmd/cmdline.c     | 142 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c      |  13 ++--
 lib/ethdev/ethdev_driver.h |  49 +++++++++++++
 lib/ethdev/rte_ethdev.c    |  26 +++++++
 lib/ethdev/rte_ethdev.h    |  52 ++++++++++++++
 lib/ethdev/version.map     |   2 +
 6 files changed, 280 insertions(+), 4 deletions(-)

-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4233 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [RFC 1/2] lib/ethdev: Add link_speed lanes support into rte lib
  2024-03-22 22:25 [RFC 0/2] Add support for link speed lanes Damodharam Ammepalli
@ 2024-03-22 22:25 ` Damodharam Ammepalli
  2024-03-22 22:25 ` [RFC 2/2] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
  2024-05-22 20:59 ` [RFC 0/2] Add support for link speed lanes Ferruh Yigit
  2 siblings, 0 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-03-22 22:25 UTC (permalink / raw)
  To: dev; +Cc: Kalesh AP, Ajit Khaparde

[-- Attachment #1: Type: text/plain, Size: 7036 bytes --]

Update the eth_dev_ops structure with new function vectors
to get and set number of speed lanes. This will help user to
configure  the same fixed speed with different number of lanes
based on the physical carrier type.

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 lib/ethdev/ethdev_driver.h | 49 +++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_ethdev.c    | 26 +++++++++++++++++++
 lib/ethdev/rte_ethdev.h    | 52 ++++++++++++++++++++++++++++++++++++++
 lib/ethdev/version.map     |  2 ++
 4 files changed, 129 insertions(+)

diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index 0dbf2dd6a2..b1f473e4de 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -1179,6 +1179,51 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
 					uint16_t queue_id, uint16_t offset,
 					uint16_t num, FILE *file);
 
+/**
+ * @internal
+ * Get number of current active lanes and max supported lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes_capa
+ *   Number of active lanes that the link is trained up.
+ *   Max number of lanes supported by HW
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get speed_lanes data success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev,
+				     struct rte_eth_speed_lanes_capa *speed_lanes_capa);
+
+/**
+ * @internal
+ * Set speed lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes_capa
+ *   Non-negative number of lanes
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set lanes success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes_capa);
+
 /**
  * @internal
  * Dump Tx descriptor info to a file.
@@ -1474,6 +1519,10 @@ struct eth_dev_ops {
 	eth_count_aggr_ports_t count_aggr_ports;
 	/** Map a Tx queue with an aggregated port of the DPDK port */
 	eth_map_aggr_tx_affinity_t map_aggr_tx_affinity;
+	/** Get number of speed lanes supported and active lanes */
+	eth_speed_lanes_get_t speed_lanes_get;
+	/** Set number of speed lanes */
+	eth_speed_lanes_set_t speed_lanes_set;
 };
 
 /**
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index f1c658f49e..45e2f7645b 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -7008,4 +7008,30 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
 	return ret;
 }
 
+int
+rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_get == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, capa));
+}
+
+int
+rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_set == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
+}
+
 RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 147257d6a2..caae1f27c6 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -1997,6 +1997,12 @@ struct rte_eth_fec_capa {
 	uint32_t capa;  /**< FEC capabilities bitmask */
 };
 
+/* A structure used to get and set lanes capabilities per link speed */
+struct rte_eth_speed_lanes_capa {
+	uint32_t active_lanes;
+	uint32_t max_lanes_cap;
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -6917,6 +6923,52 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
 	return rc;
 }
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get maximum speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes_capa
+ *   speed_lanes_capa is out only with max speed lanes capabilities.
+ *   If set to NULL, then its assumed zero or not supported.
+ *
+ * @return
+ *   - A non-negative value of active lanes that currently link is up with.
+ *   - A non-negative value that this HW scales up to for all speeds.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes_capa* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes
+ *   speed_lanes a non-zero value of number lanes for this speeds.
+ *
+ * @return
+ *  - (>=0) valid input and supported by driver or hardware.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 79f6f5293b..9c27980f3a 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -325,6 +325,8 @@ EXPERIMENTAL {
 	rte_flow_template_table_resizable;
 	rte_flow_template_table_resize;
 	rte_flow_template_table_resize_complete;
+	rte_eth_speed_lanes_get;
+	rte_eth_speed_lanes_set;
 };
 
 INTERNAL {
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4233 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [RFC 2/2] testpmd: Add speed lanes to testpmd config and show command
  2024-03-22 22:25 [RFC 0/2] Add support for link speed lanes Damodharam Ammepalli
  2024-03-22 22:25 ` [RFC 1/2] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
@ 2024-03-22 22:25 ` Damodharam Ammepalli
  2024-05-22 20:59 ` [RFC 0/2] Add support for link speed lanes Ferruh Yigit
  2 siblings, 0 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-03-22 22:25 UTC (permalink / raw)
  To: dev; +Cc: Kalesh AP, Ajit Khaparde

[-- Attachment #1: Type: text/plain, Size: 9534 bytes --]

Add speed lanes configuration and display commands support
to testpmd. Also provide display the lanes info show device info.

testpmd>
testpmd> port stop 0
testpmd> port config 0 speed_lanes 4
testpmd> port config 0 speed 200000 duplex full
testpmd> port start 0
testpmd> show port summary 0
Number of available ports: 2
Port MAC Address       Name         Driver         Status   Link     Lanes
0    14:23:F2:C3:BA:D2 0000:b1:00.0 net_bnxt       up       200 Gbps 4
testpmd>

testpmd> show port info 0

********************* Infos for port 0  *********************
MAC address: 14:23:F2:C3:BA:D2
Device name: 0000:b1:00.0
Driver name: net_bnxt
Firmware-version: 228.9.115.0
Connect to socket: 2
memory allocation on the socket: 2
Link status: up
Link speed: 200 Gbps
Lanes: 4
Link duplex: full-duplex
Autoneg status: Off

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 app/test-pmd/cmdline.c | 142 +++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  13 ++--
 2 files changed, 151 insertions(+), 4 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b7759e38a8..785e5dd4de 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1361,6 +1361,27 @@ struct cmd_config_speed_all {
 	cmdline_fixed_string_t value2;
 };
 
+static int
+cmd_validate_lanes(portid_t pid, uint32_t *lanes)
+{
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
+	int ret;
+
+	ret = rte_eth_speed_lanes_get(pid, &spd_lanes);
+	/* if not supported default lanes to 0 */
+	if (ret == -ENOTSUP) {
+		*lanes = 0;
+		return 0;
+	}
+
+	if (*lanes > spd_lanes.max_lanes_cap) {
+		fprintf(stderr, "Invalid lanes %d configuration\n", *lanes);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int
 parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 {
@@ -1676,6 +1697,125 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
 	},
 };
 
+/* *** configure speed_lanes for all ports *** */
+struct cmd_config_speed_lanes_all {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_all_parsed(void *parsed_result,
+				  __rte_unused struct cmdline *cl,
+				  __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_all *res = parsed_result;
+	portid_t pid;
+
+	if (!all_ports_stopped()) {
+		fprintf(stderr, "Please stop all ports first\n");
+		return;
+	}
+
+	RTE_ETH_FOREACH_DEV(pid) {
+		if (cmd_validate_lanes(pid, &res->lanes))
+			return;
+		rte_eth_speed_lanes_set(pid, res->lanes);
+	}
+
+	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
+				 "config");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
+	.f = cmd_config_speed_lanes_all_parsed,
+	.data = NULL,
+	.help_str = "port config all speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_all_port,
+		(void *)&cmd_config_speed_lanes_all_keyword,
+		(void *)&cmd_config_speed_lanes_all_all,
+		(void *)&cmd_config_speed_lanes_all_item,
+		(void *)&cmd_config_speed_lanes_all_lanes,
+		NULL,
+	},
+};
+
+/* *** configure speed_lanes for specific port *** */
+struct cmd_config_speed_lanes_specific {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	uint16_t port_id;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_specific_parsed(void *parsed_result,
+				       __rte_unused struct cmdline *cl,
+				       __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_specific *res = parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!port_is_stopped(res->port_id)) {
+		fprintf(stderr, "Please stop port %u first\n", res->port_id);
+		return;
+	}
+
+	if (cmd_validate_lanes(res->port_id, &res->lanes))
+		return;
+	rte_eth_speed_lanes_set(res->port_id, res->lanes);
+
+	cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
+				 "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
+				 "config");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
+			      RTE_UINT16);
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
+			      RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
+	.f = cmd_config_speed_lanes_specific_parsed,
+	.data = NULL,
+	.help_str = "port config <port_id> speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_specific_port,
+		(void *)&cmd_config_speed_lanes_specific_keyword,
+		(void *)&cmd_config_speed_lanes_specific_id,
+		(void *)&cmd_config_speed_lanes_specific_item,
+		(void *)&cmd_config_speed_lanes_specific_lanes,
+		NULL,
+	},
+};
+
 /* *** configure txq/rxq, txd/rxd *** */
 struct cmd_config_rx_tx {
 	cmdline_fixed_string_t port;
@@ -13381,6 +13521,8 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_port_cman_config,
 	(cmdline_parse_inst_t *)&cmd_set_port_cman_config,
 	(cmdline_parse_inst_t *)&cmd_config_tx_affinity_map,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index ba1007ace6..9f846c5e84 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -779,6 +779,7 @@ port_infos_display(portid_t port_id)
 	struct rte_ether_addr mac_addr;
 	struct rte_eth_link link;
 	struct rte_eth_dev_info dev_info;
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
 	int vlan_offload;
 	struct rte_mempool * mp;
 	static const char *info_border = "*********************";
@@ -828,6 +829,8 @@ port_infos_display(portid_t port_id)
 
 	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
 	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
+	rte_eth_speed_lanes_get(port_id, &spd_lanes);
+	printf("Lanes: %d\n", spd_lanes.active_lanes);
 	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
 	       ("full-duplex") : ("half-duplex"));
 	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
@@ -962,8 +965,8 @@ port_summary_header_display(void)
 
 	port_number = rte_eth_dev_count_avail();
 	printf("Number of available ports: %i\n", port_number);
-	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
-			"Driver", "Status", "Link");
+	printf("%-4s %-17s %-12s %-14s %-8s %-8s %s\n", "Port", "MAC Address", "Name",
+			"Driver", "Status", "Link", "Lanes");
 }
 
 void
@@ -972,6 +975,7 @@ port_summary_display(portid_t port_id)
 	struct rte_ether_addr mac_addr;
 	struct rte_eth_link link;
 	struct rte_eth_dev_info dev_info;
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
 	char name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 
@@ -993,10 +997,11 @@ port_summary_display(portid_t port_id)
 	if (ret != 0)
 		return;
 
-	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
+	rte_eth_speed_lanes_get(port_id, &spd_lanes);
+	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s %d\n",
 		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
 		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
-		rte_eth_link_speed_to_str(link.link_speed));
+		rte_eth_link_speed_to_str(link.link_speed), spd_lanes.active_lanes);
 }
 
 void
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4233 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC 0/2] Add support for link speed lanes
  2024-03-22 22:25 [RFC 0/2] Add support for link speed lanes Damodharam Ammepalli
  2024-03-22 22:25 ` [RFC 1/2] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
  2024-03-22 22:25 ` [RFC 2/2] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
@ 2024-05-22 20:59 ` Ferruh Yigit
  2024-05-28 21:19   ` Damodharam Ammepalli
  2 siblings, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-05-22 20:59 UTC (permalink / raw)
  To: Damodharam Ammepalli, Ajit Khaparde
  Cc: dev, Thomas Monjalon, huangdengdui, lihuisong (C),
	stephen, fengchengwen, haijie1

On 3/22/2024 10:25 PM, Damodharam Ammepalli wrote:
> BRCM576xx NIC modules support speeds with different lanes configuration.
> This is an alternate proposal to
> https://patchwork.dpdk.org/project/dpdk/list/?series=31593
> 
> Please provide your review. Broadcom driver patches will follow.
> 
> Damodharam Ammepalli (2):
>   lib/ethdev: Add link_speed lanes support into rte lib
>   testpmd: Add speed lanes to testpmd config and show command
> 

Hi Damodharam,

As discussed in other thread, having dedicated APIs for setting lane
makes API more clear, so we can continue with this design.

This RFC proposes two APIs, but agreement on other thread was around
three new APIs.

Copy/pasting Thomas's suggestion
"
 There are 3 needs:
	- set PHY lane config
	- get PHY lane config
	- get PHY lane capabilities
"

And "get PHY lane capabilities" should return capability per speed,
similar to FEC one.


Can you please update this RFC to have three APIs as mentioned above?

Thanks,
Ferruh


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [RFC 0/2] Add support for link speed lanes
  2024-05-22 20:59 ` [RFC 0/2] Add support for link speed lanes Ferruh Yigit
@ 2024-05-28 21:19   ` Damodharam Ammepalli
  2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-05-28 21:19 UTC (permalink / raw)
  To: Ferruh Yigit, Ajit Khaparde
  Cc: dev, Thomas Monjalon, huangdengdui, lihuisong (C),
	stephen, fengchengwen, haijie1

[-- Attachment #1: Type: text/plain, Size: 2491 bytes --]

 From: Ferruh Yigit <ferruh.yigit@amd.com>
Date: Wednesday, May 22, 2024 at 2:00 PM
To: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>, Ajit Khaparde
<ajit.khaparde@broadcom.com>
Cc: dev@dpdk.org <dev@dpdk.org>, Thomas Monjalon <thomas@monjalon.net>,
huangdengdui <huangdengdui@huawei.com>, lihuisong (C) <lihuisong@huawei.com>,
stephen@networkplumber.org <stephen@networkplumber.org>,
fengchengwen@huawei.com <fengchengwen@huawei.com>, haijie1@huawei.com <
haijie1@huawei.com>
Subject: Re: [RFC 0/2] Add support for link speed lanes

On 3/22/2024 10:25 PM, Damodharam Ammepalli wrote:
> BRCM576xx NIC modules support speeds with different lanes configuration.
> This is an alternate proposal to
>
https://www.google.com/url?q=https://patchwork.dpdk.org/project/dpdk/list/?series%3D31593&source=gmail-imap&ust=1717016402000000&usg=AOvVaw1jrFok7jqKY0zhtLzKKg1Z
>
> Please provide your review. Broadcom driver patches will follow.
>
> Damodharam Ammepalli (2):
>   lib/ethdev: Add link_speed lanes support into rte lib
>   testpmd: Add speed lanes to testpmd config and show command
>

Hi Damodharam,

As discussed in other thread, having dedicated APIs for setting lane
makes API more clear, so we can continue with this design.

This RFC proposes two APIs, but agreement on other thread was around
three new APIs.

Copy/pasting Thomas's suggestion
"
 There are 3 needs:
        - set PHY lane config
        - get PHY lane config
        - get PHY lane capabilities
"

And "get PHY lane capabilities" should return capability per speed,
similar to FEC one.


Can you please update this RFC to have three APIs as mentioned above?

Thanks,
Ferruh

Noted Ferruh. Will update this RFC as commented.

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

[-- Attachment #2: Type: text/html, Size: 4661 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 0/4] Add support for link speed lanes
  2024-05-28 21:19   ` Damodharam Ammepalli
@ 2024-06-02  2:45     ` Damodharam Ammepalli
  2024-06-02  2:45       ` [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
                         ` (4 more replies)
  0 siblings, 5 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-02  2:45 UTC (permalink / raw)
  To: dev

NIC adapters can support speeds with different lanes configuration.

This patchset will allow users:
- get the Lanes capability per speed supported by the ethernet
  controller.
- set the lanes configuration using a new CLI
- Display the user configured lanes
--
v1->v2

Added speed lanes capability and display on testpmd shell.
testpmd> show port 0 speed_lanes capabilities

 Supported speeds         Valid lanes
-----------------------------------
 10 Gbps                  1
 25 Gbps                  1
 40 Gbps                  4
 50 Gbps                  1 2
 100 Gbps                 1 2 4
 200 Gbps                 2 4
 400 Gbps                 4 8
testpmd>

Damodharam Ammepalli (4):
  lib/ethdev: Add link_speed lanes support into rte lib
  testpmd: Add speed lanes to testpmd config and show command
  lib/ethdev: add support for displaying lanes capability
  testpmd: add support for displaying lanes capability

 app/test-pmd/cmdline.c     | 270 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c      |  13 +-
 lib/ethdev/ethdev_driver.h |  70 ++++++++++
 lib/ethdev/rte_ethdev.c    |  39 ++++++
 lib/ethdev/rte_ethdev.h    |  84 ++++++++++++
 lib/ethdev/version.map     |   3 +
 6 files changed, 475 insertions(+), 4 deletions(-)

-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib
  2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
@ 2024-06-02  2:45       ` Damodharam Ammepalli
  2024-06-11 23:39         ` Ferruh Yigit
  2024-06-02  2:45       ` [PATCH v2 2/4] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
                         ` (3 subsequent siblings)
  4 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-02  2:45 UTC (permalink / raw)
  To: dev; +Cc: Kalesh AP, Ajit Khaparde

Update the eth_dev_ops structure with new function vectors
to get and set number of speed lanes. This will help user to
configure  the same fixed speed with different number of lanes
based on the physical carrier type.

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 lib/ethdev/ethdev_driver.h | 49 +++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_ethdev.c    | 26 +++++++++++++++++++
 lib/ethdev/rte_ethdev.h    | 52 ++++++++++++++++++++++++++++++++++++++
 lib/ethdev/version.map     |  2 ++
 4 files changed, 129 insertions(+)

diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index 0dbf2dd6a2..b1f473e4de 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -1179,6 +1179,51 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
 					uint16_t queue_id, uint16_t offset,
 					uint16_t num, FILE *file);
 
+/**
+ * @internal
+ * Get number of current active lanes and max supported lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes_capa
+ *   Number of active lanes that the link is trained up.
+ *   Max number of lanes supported by HW
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get speed_lanes data success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev,
+				     struct rte_eth_speed_lanes_capa *speed_lanes_capa);
+
+/**
+ * @internal
+ * Set speed lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes_capa
+ *   Non-negative number of lanes
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set lanes success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes_capa);
+
 /**
  * @internal
  * Dump Tx descriptor info to a file.
@@ -1474,6 +1519,10 @@ struct eth_dev_ops {
 	eth_count_aggr_ports_t count_aggr_ports;
 	/** Map a Tx queue with an aggregated port of the DPDK port */
 	eth_map_aggr_tx_affinity_t map_aggr_tx_affinity;
+	/** Get number of speed lanes supported and active lanes */
+	eth_speed_lanes_get_t speed_lanes_get;
+	/** Set number of speed lanes */
+	eth_speed_lanes_set_t speed_lanes_set;
 };
 
 /**
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index f1c658f49e..45e2f7645b 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -7008,4 +7008,30 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
 	return ret;
 }
 
+int
+rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_get == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, capa));
+}
+
+int
+rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_set == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
+}
+
 RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 147257d6a2..caae1f27c6 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -1997,6 +1997,12 @@ struct rte_eth_fec_capa {
 	uint32_t capa;  /**< FEC capabilities bitmask */
 };
 
+/* A structure used to get and set lanes capabilities per link speed */
+struct rte_eth_speed_lanes_capa {
+	uint32_t active_lanes;
+	uint32_t max_lanes_cap;
+};
+
 #define RTE_ETH_ALL RTE_MAX_ETHPORTS
 
 /* Macros to check for valid port */
@@ -6917,6 +6923,52 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
 	return rc;
 }
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get maximum speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes_capa
+ *   speed_lanes_capa is out only with max speed lanes capabilities.
+ *   If set to NULL, then its assumed zero or not supported.
+ *
+ * @return
+ *   - A non-negative value of active lanes that currently link is up with.
+ *   - A non-negative value that this HW scales up to for all speeds.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes_capa* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes
+ *   speed_lanes a non-zero value of number lanes for this speeds.
+ *
+ * @return
+ *  - (>=0) valid input and supported by driver or hardware.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 79f6f5293b..9c27980f3a 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -325,6 +325,8 @@ EXPERIMENTAL {
 	rte_flow_template_table_resizable;
 	rte_flow_template_table_resize;
 	rte_flow_template_table_resize_complete;
+	rte_eth_speed_lanes_get;
+	rte_eth_speed_lanes_set;
 };
 
 INTERNAL {
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 2/4] testpmd: Add speed lanes to testpmd config and show command
  2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
  2024-06-02  2:45       ` [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
@ 2024-06-02  2:45       ` Damodharam Ammepalli
  2024-06-11 23:39         ` Ferruh Yigit
  2024-06-02  2:45       ` [PATCH v2 3/4] lib/ethdev: add support for displaying lanes capability Damodharam Ammepalli
                         ` (2 subsequent siblings)
  4 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-02  2:45 UTC (permalink / raw)
  To: dev; +Cc: Kalesh AP, Ajit Khaparde

Add speed lanes configuration and display commands support
to testpmd. Also provide display the lanes info show device info.

testpmd>
testpmd> port stop 0
testpmd> port config 0 speed_lanes 4
testpmd> port config 0 speed 200000 duplex full
testpmd> port start 0
testpmd> show port summary 0
Number of available ports: 2
Port MAC Address       Name         Driver         Status   Link     Lanes
0    14:23:F2:C3:BA:D2 0000:b1:00.0 net_bnxt       up       200 Gbps 4
testpmd>

testpmd> show port info 0

********************* Infos for port 0  *********************
MAC address: 14:23:F2:C3:BA:D2
Device name: 0000:b1:00.0
Driver name: net_bnxt
Firmware-version: 228.9.115.0
Connect to socket: 2
memory allocation on the socket: 2
Link status: up
Link speed: 200 Gbps
Lanes: 4
Link duplex: full-duplex
Autoneg status: Off

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
---
 app/test-pmd/cmdline.c | 142 +++++++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c  |  13 ++--
 2 files changed, 151 insertions(+), 4 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b7759e38a8..785e5dd4de 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1361,6 +1361,27 @@ struct cmd_config_speed_all {
 	cmdline_fixed_string_t value2;
 };
 
+static int
+cmd_validate_lanes(portid_t pid, uint32_t *lanes)
+{
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
+	int ret;
+
+	ret = rte_eth_speed_lanes_get(pid, &spd_lanes);
+	/* if not supported default lanes to 0 */
+	if (ret == -ENOTSUP) {
+		*lanes = 0;
+		return 0;
+	}
+
+	if (*lanes > spd_lanes.max_lanes_cap) {
+		fprintf(stderr, "Invalid lanes %d configuration\n", *lanes);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int
 parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
 {
@@ -1676,6 +1697,125 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
 	},
 };
 
+/* *** configure speed_lanes for all ports *** */
+struct cmd_config_speed_lanes_all {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_all_parsed(void *parsed_result,
+				  __rte_unused struct cmdline *cl,
+				  __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_all *res = parsed_result;
+	portid_t pid;
+
+	if (!all_ports_stopped()) {
+		fprintf(stderr, "Please stop all ports first\n");
+		return;
+	}
+
+	RTE_ETH_FOREACH_DEV(pid) {
+		if (cmd_validate_lanes(pid, &res->lanes))
+			return;
+		rte_eth_speed_lanes_set(pid, res->lanes);
+	}
+
+	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
+				 "config");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
+	.f = cmd_config_speed_lanes_all_parsed,
+	.data = NULL,
+	.help_str = "port config all speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_all_port,
+		(void *)&cmd_config_speed_lanes_all_keyword,
+		(void *)&cmd_config_speed_lanes_all_all,
+		(void *)&cmd_config_speed_lanes_all_item,
+		(void *)&cmd_config_speed_lanes_all_lanes,
+		NULL,
+	},
+};
+
+/* *** configure speed_lanes for specific port *** */
+struct cmd_config_speed_lanes_specific {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	uint16_t port_id;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_specific_parsed(void *parsed_result,
+				       __rte_unused struct cmdline *cl,
+				       __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_specific *res = parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!port_is_stopped(res->port_id)) {
+		fprintf(stderr, "Please stop port %u first\n", res->port_id);
+		return;
+	}
+
+	if (cmd_validate_lanes(res->port_id, &res->lanes))
+		return;
+	rte_eth_speed_lanes_set(res->port_id, res->lanes);
+
+	cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
+				 "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
+				 "config");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
+			      RTE_UINT16);
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
+			      RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
+	.f = cmd_config_speed_lanes_specific_parsed,
+	.data = NULL,
+	.help_str = "port config <port_id> speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_specific_port,
+		(void *)&cmd_config_speed_lanes_specific_keyword,
+		(void *)&cmd_config_speed_lanes_specific_id,
+		(void *)&cmd_config_speed_lanes_specific_item,
+		(void *)&cmd_config_speed_lanes_specific_lanes,
+		NULL,
+	},
+};
+
 /* *** configure txq/rxq, txd/rxd *** */
 struct cmd_config_rx_tx {
 	cmdline_fixed_string_t port;
@@ -13381,6 +13521,8 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_port_cman_config,
 	(cmdline_parse_inst_t *)&cmd_set_port_cman_config,
 	(cmdline_parse_inst_t *)&cmd_config_tx_affinity_map,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index ba1007ace6..9f846c5e84 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -779,6 +779,7 @@ port_infos_display(portid_t port_id)
 	struct rte_ether_addr mac_addr;
 	struct rte_eth_link link;
 	struct rte_eth_dev_info dev_info;
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
 	int vlan_offload;
 	struct rte_mempool * mp;
 	static const char *info_border = "*********************";
@@ -828,6 +829,8 @@ port_infos_display(portid_t port_id)
 
 	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
 	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
+	rte_eth_speed_lanes_get(port_id, &spd_lanes);
+	printf("Lanes: %d\n", spd_lanes.active_lanes);
 	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
 	       ("full-duplex") : ("half-duplex"));
 	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
@@ -962,8 +965,8 @@ port_summary_header_display(void)
 
 	port_number = rte_eth_dev_count_avail();
 	printf("Number of available ports: %i\n", port_number);
-	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
-			"Driver", "Status", "Link");
+	printf("%-4s %-17s %-12s %-14s %-8s %-8s %s\n", "Port", "MAC Address", "Name",
+			"Driver", "Status", "Link", "Lanes");
 }
 
 void
@@ -972,6 +975,7 @@ port_summary_display(portid_t port_id)
 	struct rte_ether_addr mac_addr;
 	struct rte_eth_link link;
 	struct rte_eth_dev_info dev_info;
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
 	char name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 
@@ -993,10 +997,11 @@ port_summary_display(portid_t port_id)
 	if (ret != 0)
 		return;
 
-	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
+	rte_eth_speed_lanes_get(port_id, &spd_lanes);
+	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s %d\n",
 		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
 		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
-		rte_eth_link_speed_to_str(link.link_speed));
+		rte_eth_link_speed_to_str(link.link_speed), spd_lanes.active_lanes);
 }
 
 void
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 3/4] lib/ethdev: add support for displaying lanes capability
  2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
  2024-06-02  2:45       ` [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
  2024-06-02  2:45       ` [PATCH v2 2/4] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
@ 2024-06-02  2:45       ` Damodharam Ammepalli
  2024-06-11 23:39         ` Ferruh Yigit
  2024-06-02  2:45       ` [PATCH v2 4/4] testpmd: " Damodharam Ammepalli
  2024-06-11 23:38       ` [PATCH v2 0/4] Add support for link speed lanes Ferruh Yigit
  4 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-02  2:45 UTC (permalink / raw)
  To: dev

Add new rte_lib callback to display ethernet controller's
supporting speeds and bitmap of supported lanes per speed.

The new command display looks like this.

testpmd> show port 0 speed_lanes capabilities

 Supported speeds         Valid lanes
-----------------------------------
 10 Gbps                  1
 25 Gbps                  1
 40 Gbps                  4
 50 Gbps                  1 2
 100 Gbps                 1 2 4
 200 Gbps                 2 4
 400 Gbps                 4 8
testpmd>

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
---
 lib/ethdev/ethdev_driver.h | 21 +++++++++++++++++++++
 lib/ethdev/rte_ethdev.c    | 13 +++++++++++++
 lib/ethdev/rte_ethdev.h    | 32 ++++++++++++++++++++++++++++++++
 lib/ethdev/version.map     |  1 +
 4 files changed, 67 insertions(+)

diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index b1f473e4de..5951986cec 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -1224,6 +1224,26 @@ typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev,
  */
 typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes_capa);
 
+/**
+ * @internal
+ * Get speed vs number of lanes supported bitmap that controller supports
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes_capa
+ *   int array of size max speeds bitmap ie 17
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, driver updates the speed_lanes_capa bitmap.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_get_capa_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes_bmap);
+
 /**
  * @internal
  * Dump Tx descriptor info to a file.
@@ -1523,6 +1543,7 @@ struct eth_dev_ops {
 	eth_speed_lanes_get_t speed_lanes_get;
 	/** Set number of speed lanes */
 	eth_speed_lanes_set_t speed_lanes_set;
+	eth_speed_lanes_get_capa_t speed_lanes_get_capa;
 };
 
 /**
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index 45e2f7645b..1ac5174d62 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -7021,6 +7021,19 @@ rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa)
 	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, capa));
 }
 
+int
+rte_eth_speed_lanes_get_capa(uint16_t port_id, uint32_t *speed_lanes_bmap)
+{
+        struct rte_eth_dev *dev;
+
+        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+        dev = &rte_eth_devices[port_id];
+
+        if (*dev->dev_ops->speed_lanes_get == NULL)
+                return -ENOTSUP;
+        return eth_err(port_id, (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_bmap));
+}
+
 int
 rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
 {
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index caae1f27c6..b8a29416b6 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -308,6 +308,16 @@ struct rte_eth_stats {
 #define RTE_ETH_LINK_SPEED_400G    RTE_BIT32(16) /**< 400 Gbps */
 /**@}*/
 
+/**@{@name Link speed lane capabilities
+ * Device supported speeds lane bitmap flags
+ */
+#define RTE_ETH_LINK_SPEED_MAX_BIT	17 /**< RTE_ETH_LINK_SPEED_400G bit position + 1 */
+#define LANE_1	RTE_BIT32(1)
+#define LANE_2 	RTE_BIT32(2)
+#define LANE_4 	RTE_BIT32(4)
+#define LANE_8 	RTE_BIT32(8)
+/**@}*/
+
 /**@{@name Link speed
  * Ethernet numeric link speeds in Mbps
  */
@@ -6969,6 +6979,28 @@ int rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *c
 __rte_experimental
 int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes_bmap
+ *   speed_lanes_bmap int array updated by driver by valid lanes bmap.
+ *
+ * @return
+ *  - (>=0) valid input and supported by driver or hardware.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get_capa(uint16_t port_id, uint32_t *speed_lanes_bmap);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 9c27980f3a..c453494b8d 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -327,6 +327,7 @@ EXPERIMENTAL {
 	rte_flow_template_table_resize_complete;
 	rte_eth_speed_lanes_get;
 	rte_eth_speed_lanes_set;
+	rte_eth_speed_lanes_get_capa;
 };
 
 INTERNAL {
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 4/4] testpmd: add support for displaying lanes capability
  2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
                         ` (2 preceding siblings ...)
  2024-06-02  2:45       ` [PATCH v2 3/4] lib/ethdev: add support for displaying lanes capability Damodharam Ammepalli
@ 2024-06-02  2:45       ` Damodharam Ammepalli
  2024-06-11 23:39         ` Ferruh Yigit
  2024-06-11 23:38       ` [PATCH v2 0/4] Add support for link speed lanes Ferruh Yigit
  4 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-02  2:45 UTC (permalink / raw)
  To: dev

Add a new api support that displays the speeds and bitmap of 
supported lanes configuration by the ethernet controller.
This patch adds support in the testpmd cli chain.

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
---
 app/test-pmd/cmdline.c | 128 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 785e5dd4de..8b0a85f632 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1637,6 +1637,133 @@ static cmdline_parse_inst_t cmd_config_loopback_all = {
 	},
 };
 
+/* *** display speed lanes per port capabilities *** */
+struct cmd_show_speed_lanes_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static const char*
+get_device_infos_display_speeds(uint32_t speed_capa)
+{
+        if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
+                return(" 10 Mbps half-duplex  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_10M)
+                return(" 10 Mbps full-duplex  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
+                return(" 100 Mbps half-duplex  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_100M)
+                return(" 100 Mbps full-duplex  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_1G)
+                return(" 1 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
+                return(" 2.5 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_5G)
+                return(" 5 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_10G)
+                return(" 10 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_20G)
+                return(" 20 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_25G)
+                return(" 25 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_40G)
+                return(" 40 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_50G)
+                return(" 50 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_56G)
+                return(" 56 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_100G)
+                return(" 100 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_200G)
+                return(" 200 Gbps  ");
+        if (speed_capa & RTE_ETH_LINK_SPEED_400G)
+                return(" 400 Gbps  ");
+
+	return("Unkown");
+}
+
+static void
+cmd_show_speed_lanes_parsed(void *parsed_result,
+			    __rte_unused struct cmdline *cl,
+			    __rte_unused void *data)
+{
+	struct cmd_show_speed_lanes_result *res = parsed_result;
+	uint32_t speed_lanes_bmap[RTE_ETH_LINK_SPEED_MAX_BIT] = {0};
+	struct rte_eth_speed_lanes_capa spd_lanes = {0};
+	struct rte_eth_dev_info dev_info;
+	//char lanes_speed_str[128] = {0};
+	bool skip_spd_chk = false;
+	int ret, i;
+	uint32_t j;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	/* get max lanes this nic supports */
+	ret = rte_eth_speed_lanes_get(res->cmd_pid, &spd_lanes);
+        if (ret == -ENOTSUP)
+		return;
+
+	/* Pull out capability if nic supports */
+	ret = rte_eth_speed_lanes_get_capa(res->cmd_pid, speed_lanes_bmap);
+        if (ret == -ENOTSUP)
+		return;
+
+	ret = eth_dev_info_get_print_err(res->cmd_pid, &dev_info);
+	/* when link is down, PHY does not report any speeds */
+	if (ret == 0)
+		skip_spd_chk = true;
+
+	printf("\n%-25s %-10s", " Supported speeds", "Valid lanes");
+	printf("\n-----------------------------------");
+        for (i = 1; i <= RTE_ETH_LINK_SPEED_MAX_BIT; i++) {
+		if ((dev_info.speed_capa & RTE_BIT32(i) || skip_spd_chk) &&
+		    (speed_lanes_bmap[i])) {
+			printf("\n%-25s ",
+			       get_device_infos_display_speeds(RTE_BIT32(i))) ;
+			for (j = 0; j <= spd_lanes.max_lanes_cap; j++) {
+				if (RTE_BIT32(j) & speed_lanes_bmap[i])
+					printf("%-2d", j);
+			}
+		}
+        }
+	printf("\n");
+}
+
+static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_show, "show");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_port, "port");
+static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
+			      cmd_pid, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "speed_lanes");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "capabilities");
+
+static cmdline_parse_inst_t cmd_show_speed_lanes = {
+	.f = cmd_show_speed_lanes_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> speed_lanes capabilities",
+	.tokens = {
+		(void *)&cmd_show_speed_lanes_show,
+		(void *)&cmd_show_speed_lanes_port,
+		(void *)&cmd_show_speed_lanes_pid,
+		(void *)&cmd_show_speed_lanes_keyword,
+		(void *)&cmd_show_speed_lanes_cap_keyword,
+		NULL,
+	},
+};
+
 /* *** configure loopback for specific port *** */
 struct cmd_config_loopback_specific {
 	cmdline_fixed_string_t port;
@@ -13523,6 +13650,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_config_tx_affinity_map,
 	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
 	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
+	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,
 	NULL,
 };
 
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 0/4] Add support for link speed lanes
  2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
                         ` (3 preceding siblings ...)
  2024-06-02  2:45       ` [PATCH v2 4/4] testpmd: " Damodharam Ammepalli
@ 2024-06-11 23:38       ` Ferruh Yigit
  2024-06-12 17:46         ` Damodharam Ammepalli
  4 siblings, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-06-11 23:38 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev; +Cc: Dengdui Huang

On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> NIC adapters can support speeds with different lanes configuration.
> 
> This patchset will allow users:
> - get the Lanes capability per speed supported by the ethernet
>   controller.
> - set the lanes configuration using a new CLI
> - Display the user configured lanes
> --
> v1->v2
> 
> Added speed lanes capability and display on testpmd shell.
> testpmd> show port 0 speed_lanes capabilities
> 
>  Supported speeds         Valid lanes
> -----------------------------------
>  10 Gbps                  1
>  25 Gbps                  1
>  40 Gbps                  4
>  50 Gbps                  1 2
>  100 Gbps                 1 2 4
>  200 Gbps                 2 4
>  400 Gbps                 4 8
> testpmd>
> 
> Damodharam Ammepalli (4):
>   lib/ethdev: Add link_speed lanes support into rte lib
>   testpmd: Add speed lanes to testpmd config and show command
>   lib/ethdev: add support for displaying lanes capability
>   testpmd: add support for displaying lanes capability
> 

Please cc Dengdui, as they are working on same issue.


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib
  2024-06-02  2:45       ` [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
@ 2024-06-11 23:39         ` Ferruh Yigit
  2024-06-14 18:27           ` Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-06-11 23:39 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev; +Cc: Kalesh AP, Ajit Khaparde, Dengdui Huang

On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> Update the eth_dev_ops structure with new function vectors
> to get and set number of speed lanes. This will help user to
> configure  the same fixed speed with different number of lanes
> based on the physical carrier type.
> 
> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
> ---
>  lib/ethdev/ethdev_driver.h | 49 +++++++++++++++++++++++++++++++++++
>  lib/ethdev/rte_ethdev.c    | 26 +++++++++++++++++++
>  lib/ethdev/rte_ethdev.h    | 52 ++++++++++++++++++++++++++++++++++++++
>  lib/ethdev/version.map     |  2 ++
>  4 files changed, 129 insertions(+)
> 
> diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> index 0dbf2dd6a2..b1f473e4de 100644
> --- a/lib/ethdev/ethdev_driver.h
> +++ b/lib/ethdev/ethdev_driver.h
> @@ -1179,6 +1179,51 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
>  					uint16_t queue_id, uint16_t offset,
>  					uint16_t num, FILE *file);
>  
> +/**
> + * @internal
> + * Get number of current active lanes and max supported lanes
>

There is already a 'eth_speed_lanes_get_capa' dev_ops, why max supported
lanes returned in this call, instead of capa?

> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes_capa
> + *   Number of active lanes that the link is trained up.
> + *   Max number of lanes supported by HW
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, get speed_lanes data success.
>

Success, speed_lanes_capa filled.

> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev,
> +				     struct rte_eth_speed_lanes_capa *speed_lanes_capa);
> +
> +/**
> + * @internal
> + * Set speed lanes
>

As we are on the subject, we all understand what "speed lane" is in this
context, but I am not sure if the naming is descriptive enough, how this
is referenced in datasheet?

> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes_capa
> + *   Non-negative number of lanes
> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, set lanes success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EINVAL
> + *   Unsupported mode requested.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes_capa);
> +

These new dev_ops seems inserted in between 'rx_descriptor_dump' &
'tx_descriptor_dump' dev_ops.
Can you please move them just below 'eth_link_update_t'?



>  /**
>   * @internal
>   * Dump Tx descriptor info to a file.
> @@ -1474,6 +1519,10 @@ struct eth_dev_ops {
>  	eth_count_aggr_ports_t count_aggr_ports;
>  	/** Map a Tx queue with an aggregated port of the DPDK port */
>  	eth_map_aggr_tx_affinity_t map_aggr_tx_affinity;
> +	/** Get number of speed lanes supported and active lanes */
> +	eth_speed_lanes_get_t speed_lanes_get;
> +	/** Set number of speed lanes */
> +	eth_speed_lanes_set_t speed_lanes_set;
>  };
>  
>  /**
> diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> index f1c658f49e..45e2f7645b 100644
> --- a/lib/ethdev/rte_ethdev.c
> +++ b/lib/ethdev/rte_ethdev.c
> @@ -7008,4 +7008,30 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
>  	return ret;
>  }
>  
> +int
> +rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->speed_lanes_get == NULL)
> +		return -ENOTSUP;
> +	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, capa));
>

Shouldn't we verify if 'capa' is not NULL in API?

> +}
> +
> +int
> +rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->speed_lanes_set == NULL)
> +		return -ENOTSUP;
> +	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
> +}
> +
>  RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index 147257d6a2..caae1f27c6 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -1997,6 +1997,12 @@ struct rte_eth_fec_capa {
>  	uint32_t capa;  /**< FEC capabilities bitmask */
>  };
>  
> +/* A structure used to get and set lanes capabilities per link speed */
> +struct rte_eth_speed_lanes_capa {
> +	uint32_t active_lanes;
> +	uint32_t max_lanes_cap;
> +};
> +
>  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
>  
>  /* Macros to check for valid port */
> @@ -6917,6 +6923,52 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
>  	return rc;
>  }
>  
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get maximum speed lanes supported by the NIC.
>

Isn't this API to get the current lane number?

> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes_capa
> + *   speed_lanes_capa is out only with max speed lanes capabilities.
> + *   If set to NULL, then its assumed zero or not supported.
>

Why NULL 'capa' is supported?

> + *
> + * @return
> + *   - A non-negative value of active lanes that currently link is up with.
> + *   - A non-negative value that this HW scales up to for all speeds.
>

Isn't the return value only for status, error or success, and data
stored in 'capa' pointer?


> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *speed_lanes_capa* invalid
>

This is 'get' function, how 'speed_lanes_capa' can be invalid?

> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set speed lanes supported by the NIC.
>

Should we document somewhere that this is only for the case Auto
Negotiation (AN) is disabled, otherwise AN will figure out the lanes.

> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes
> + *   speed_lanes a non-zero value of number lanes for this speeds.
>

Please reword 'this speeds'

> + *
> + * @return
> + *  - (>=0) valid input and supported by driver or hardware.
>

Lanes set successfully?


> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *speed_lanes* invalid
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> index 79f6f5293b..9c27980f3a 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -325,6 +325,8 @@ EXPERIMENTAL {
>  	rte_flow_template_table_resizable;
>  	rte_flow_template_table_resize;
>  	rte_flow_template_table_resize_complete;
> +	rte_eth_speed_lanes_get;
> +	rte_eth_speed_lanes_set;
>

Please follow the syntax in the file, add "# added in 24.07" comment and
add new APIs under it alphabetically sorted way.


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 2/4] testpmd: Add speed lanes to testpmd config and show command
  2024-06-02  2:45       ` [PATCH v2 2/4] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
@ 2024-06-11 23:39         ` Ferruh Yigit
  0 siblings, 0 replies; 33+ messages in thread
From: Ferruh Yigit @ 2024-06-11 23:39 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev; +Cc: Kalesh AP, Ajit Khaparde, Dengdui Huang

On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> Add speed lanes configuration and display commands support
> to testpmd. Also provide display the lanes info show device info.
> 
> testpmd>
> testpmd> port stop 0
> testpmd> port config 0 speed_lanes 4
> testpmd> port config 0 speed 200000 duplex full
> testpmd> port start 0
> testpmd> show port summary 0
> Number of available ports: 2
> Port MAC Address       Name         Driver         Status   Link     Lanes
> 0    14:23:F2:C3:BA:D2 0000:b1:00.0 net_bnxt       up       200 Gbps 4
> testpmd>
> 
> testpmd> show port info 0
> 
> ********************* Infos for port 0  *********************
> MAC address: 14:23:F2:C3:BA:D2
> Device name: 0000:b1:00.0
> Driver name: net_bnxt
> Firmware-version: 228.9.115.0
> Connect to socket: 2
> memory allocation on the socket: 2
> Link status: up
> Link speed: 200 Gbps
> Lanes: 4
> Link duplex: full-duplex
> Autoneg status: Off
> 
> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
> ---
>  app/test-pmd/cmdline.c | 142 +++++++++++++++++++++++++++++++++++++++++
>  app/test-pmd/config.c  |  13 ++--
>  2 files changed, 151 insertions(+), 4 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index b7759e38a8..785e5dd4de 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -1361,6 +1361,27 @@ struct cmd_config_speed_all {
>  	cmdline_fixed_string_t value2;
>  };
>  
> +static int
> +cmd_validate_lanes(portid_t pid, uint32_t *lanes)
> +{
> +	struct rte_eth_speed_lanes_capa spd_lanes = {0};
> +	int ret;
> +
> +	ret = rte_eth_speed_lanes_get(pid, &spd_lanes);
>

Wouldn't it be better to validate value with provided capabilities?

> +	/* if not supported default lanes to 0 */
> +	if (ret == -ENOTSUP) {
> +		*lanes = 0;
> +		return 0;
> +	}
> +
> +	if (*lanes > spd_lanes.max_lanes_cap) {
> +		fprintf(stderr, "Invalid lanes %d configuration\n", *lanes);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  static int
>  parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
>  {
> @@ -1676,6 +1697,125 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
>  	},
>  };
>  
> +/* *** configure speed_lanes for all ports *** */
> +struct cmd_config_speed_lanes_all {
> +	cmdline_fixed_string_t port;
> +	cmdline_fixed_string_t keyword;
> +	cmdline_fixed_string_t all;
> +	cmdline_fixed_string_t item;
> +	uint32_t lanes;
> +};
> +
> +static void
> +cmd_config_speed_lanes_all_parsed(void *parsed_result,
> +				  __rte_unused struct cmdline *cl,
> +				  __rte_unused void *data)
> +{
> +	struct cmd_config_speed_lanes_all *res = parsed_result;
> +	portid_t pid;
> +
> +	if (!all_ports_stopped()) {
> +		fprintf(stderr, "Please stop all ports first\n");
> +		return;
> +	}
> +
> +	RTE_ETH_FOREACH_DEV(pid) {
> +		if (cmd_validate_lanes(pid, &res->lanes))
> +			return;
> +		rte_eth_speed_lanes_set(pid, res->lanes);
> +	}
> +
> +	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
> +}
> +
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
> +				 "config");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
> +				 "speed_lanes");
> +static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
> +	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
> +
> +static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
> +	.f = cmd_config_speed_lanes_all_parsed,
> +	.data = NULL,
> +	.help_str = "port config all speed_lanes <value>",
> +	.tokens = {
> +		(void *)&cmd_config_speed_lanes_all_port,
> +		(void *)&cmd_config_speed_lanes_all_keyword,
> +		(void *)&cmd_config_speed_lanes_all_all,
> +		(void *)&cmd_config_speed_lanes_all_item,
> +		(void *)&cmd_config_speed_lanes_all_lanes,
> +		NULL,
> +	},
> +};
> +
> +/* *** configure speed_lanes for specific port *** */
> +struct cmd_config_speed_lanes_specific {
> +	cmdline_fixed_string_t port;
> +	cmdline_fixed_string_t keyword;
> +	uint16_t port_id;
> +	cmdline_fixed_string_t item;
> +	uint32_t lanes;
> +};
> +
> +static void
> +cmd_config_speed_lanes_specific_parsed(void *parsed_result,
> +				       __rte_unused struct cmdline *cl,
> +				       __rte_unused void *data)
> +{
> +	struct cmd_config_speed_lanes_specific *res = parsed_result;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	if (!port_is_stopped(res->port_id)) {
> +		fprintf(stderr, "Please stop port %u first\n", res->port_id);
> +		return;
> +	}
> +
> +	if (cmd_validate_lanes(res->port_id, &res->lanes))
> +		return;
> +	rte_eth_speed_lanes_set(res->port_id, res->lanes);
> +
> +	cmd_reconfig_device_queue(res->port_id, 1, 1);
> +}
> +
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
> +				 "port");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
> +				 "config");
> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
> +	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
> +			      RTE_UINT16);
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
> +				 "speed_lanes");
> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
> +	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
> +			      RTE_UINT32);
> +
> +static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
> +	.f = cmd_config_speed_lanes_specific_parsed,
> +	.data = NULL,
> +	.help_str = "port config <port_id> speed_lanes <value>",
> +	.tokens = {
> +		(void *)&cmd_config_speed_lanes_specific_port,
> +		(void *)&cmd_config_speed_lanes_specific_keyword,
> +		(void *)&cmd_config_speed_lanes_specific_id,
> +		(void *)&cmd_config_speed_lanes_specific_item,
> +		(void *)&cmd_config_speed_lanes_specific_lanes,
> +		NULL,
> +	},
> +};
> +

These new commands are added between 'cmd_config_loopback_all' &
'cmd_config_loopback_specific' commands, please pay more attention where
to add new code.
Can you please add them just after 'cmd_config_speed_specific' to group
related functionality together?

>  /* *** configure txq/rxq, txd/rxd *** */
>  struct cmd_config_rx_tx {
>  	cmdline_fixed_string_t port;
> @@ -13381,6 +13521,8 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>  	(cmdline_parse_inst_t *)&cmd_show_port_cman_config,
>  	(cmdline_parse_inst_t *)&cmd_set_port_cman_config,
>  	(cmdline_parse_inst_t *)&cmd_config_tx_affinity_map,
> +	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> +	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
>

Can you please keep the same order where function implementations added
above?


>  	NULL,
>  };
>  
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index ba1007ace6..9f846c5e84 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -779,6 +779,7 @@ port_infos_display(portid_t port_id)
>  	struct rte_ether_addr mac_addr;
>  	struct rte_eth_link link;
>  	struct rte_eth_dev_info dev_info;
> +	struct rte_eth_speed_lanes_capa spd_lanes = {0};
>  	int vlan_offload;
>  	struct rte_mempool * mp;
>  	static const char *info_border = "*********************";
> @@ -828,6 +829,8 @@ port_infos_display(portid_t port_id)
>  
>  	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
>  	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
> +	rte_eth_speed_lanes_get(port_id, &spd_lanes);
> +	printf("Lanes: %d\n", spd_lanes.active_lanes);
>

Please print only if getting lane number is supported.


>  	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
>  	       ("full-duplex") : ("half-duplex"));
>  	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
> @@ -962,8 +965,8 @@ port_summary_header_display(void)
>  
>  	port_number = rte_eth_dev_count_avail();
>  	printf("Number of available ports: %i\n", port_number);
> -	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
> -			"Driver", "Status", "Link");
> +	printf("%-4s %-17s %-12s %-14s %-8s %-8s %s\n", "Port", "MAC Address", "Name",
> +			"Driver", "Status", "Link", "Lanes");
>  }
>  
>  void
> @@ -972,6 +975,7 @@ port_summary_display(portid_t port_id)
>  	struct rte_ether_addr mac_addr;
>  	struct rte_eth_link link;
>  	struct rte_eth_dev_info dev_info;
> +	struct rte_eth_speed_lanes_capa spd_lanes = {0};
>  	char name[RTE_ETH_NAME_MAX_LEN];
>  	int ret;
>  
> @@ -993,10 +997,11 @@ port_summary_display(portid_t port_id)
>  	if (ret != 0)
>  		return;
>  
> -	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> +	rte_eth_speed_lanes_get(port_id, &spd_lanes);
> +	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s %d\n",
>  		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
>  		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
> -		rte_eth_link_speed_to_str(link.link_speed));
> +		rte_eth_link_speed_to_str(link.link_speed), spd_lanes.active_lanes);
>

This is summary info, lots of details already omitted, 'lanes'
information is not imported enough to list here, can you please drop
this change?


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 3/4] lib/ethdev: add support for displaying lanes capability
  2024-06-02  2:45       ` [PATCH v2 3/4] lib/ethdev: add support for displaying lanes capability Damodharam Ammepalli
@ 2024-06-11 23:39         ` Ferruh Yigit
  0 siblings, 0 replies; 33+ messages in thread
From: Ferruh Yigit @ 2024-06-11 23:39 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev; +Cc: Dengdui Huang

On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> Add new rte_lib callback to display ethernet controller's
> supporting speeds and bitmap of supported lanes per speed.
> 
> The new command display looks like this.
> 
> testpmd> show port 0 speed_lanes capabilities
> 
>  Supported speeds         Valid lanes
> -----------------------------------
>  10 Gbps                  1
>  25 Gbps                  1
>  40 Gbps                  4
>  50 Gbps                  1 2
>  100 Gbps                 1 2 4
>  200 Gbps                 2 4
>  400 Gbps                 4 8
> testpmd>
> 

Can you please merge this patch with first one, no need to have
capability API its own patch


Also testpmd patch to get above output is not added yet, please merge
testpmd patch and ethdev patch together. Same for others.

> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> ---
>  lib/ethdev/ethdev_driver.h | 21 +++++++++++++++++++++
>  lib/ethdev/rte_ethdev.c    | 13 +++++++++++++
>  lib/ethdev/rte_ethdev.h    | 32 ++++++++++++++++++++++++++++++++
>  lib/ethdev/version.map     |  1 +
>  4 files changed, 67 insertions(+)
> 
> diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> index b1f473e4de..5951986cec 100644
> --- a/lib/ethdev/ethdev_driver.h
> +++ b/lib/ethdev/ethdev_driver.h
> @@ -1224,6 +1224,26 @@ typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev,
>   */
>  typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes_capa);
>  
> +/**
> + * @internal
> + * Get speed vs number of lanes supported bitmap that controller supports
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes_capa
> + *   int array of size max speeds bitmap ie 17
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, driver updates the speed_lanes_capa bitmap.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_speed_lanes_get_capa_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes_bmap);
> +
>

'speed_lanes_bmap' is an array of bitmaps, and each element in array for
a specific speed, but speed is not explicit, it is found by index
defined by 'RTE_ETH_LINK_SPEED_XXX'.
Instead, for more explicit information, can you please check "struct
rte_eth_fec_capa" and 'rte_eth_fec_get_capability()' API?
Also using same logic helps on consistency.


>  /**
>   * @internal
>   * Dump Tx descriptor info to a file.
> @@ -1523,6 +1543,7 @@ struct eth_dev_ops {
>  	eth_speed_lanes_get_t speed_lanes_get;
>  	/** Set number of speed lanes */
>  	eth_speed_lanes_set_t speed_lanes_set;
> +	eth_speed_lanes_get_capa_t speed_lanes_get_capa;
>  };
>  
>  /**
> diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> index 45e2f7645b..1ac5174d62 100644
> --- a/lib/ethdev/rte_ethdev.c
> +++ b/lib/ethdev/rte_ethdev.c
> @@ -7021,6 +7021,19 @@ rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa)
>  	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, capa));
>  }
>  
> +int
> +rte_eth_speed_lanes_get_capa(uint16_t port_id, uint32_t *speed_lanes_bmap)
> +{
> +        struct rte_eth_dev *dev;
> +
> +        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +        dev = &rte_eth_devices[port_id];
> +
> +        if (*dev->dev_ops->speed_lanes_get == NULL)
> +                return -ENOTSUP;
>

Should we verify if 'speed_lanes_bmap' parameter is NULL in the API?

> +        return eth_err(port_id, (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_bmap));
> +}
> +
>  int
>  rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
>  {
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index caae1f27c6..b8a29416b6 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -308,6 +308,16 @@ struct rte_eth_stats {
>  #define RTE_ETH_LINK_SPEED_400G    RTE_BIT32(16) /**< 400 Gbps */
>  /**@}*/
>  
> +/**@{@name Link speed lane capabilities
> + * Device supported speeds lane bitmap flags
> + */
> +#define RTE_ETH_LINK_SPEED_MAX_BIT	17 /**< RTE_ETH_LINK_SPEED_400G bit position + 1 */
> +#define LANE_1	RTE_BIT32(1)
> +#define LANE_2 	RTE_BIT32(2)
> +#define LANE_4 	RTE_BIT32(4)
> +#define LANE_8 	RTE_BIT32(8)
>

If capability get updated similarly to FEC one, above defines are not
needed.


> +/**@}*/
> +
>  /**@{@name Link speed
>   * Ethernet numeric link speeds in Mbps
>   */
> @@ -6969,6 +6979,28 @@ int rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *c
>  __rte_experimental
>  int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
>  
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set speed lanes supported by the NIC.
>

Set??

> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes_bmap
> + *   speed_lanes_bmap int array updated by driver by valid lanes bmap.
> + *
> + * @return
> + *  - (>=0) valid input and supported by driver or hardware.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *speed_lanes* invalid
>

'speed_lanes_bmap'


> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_get_capa(uint16_t port_id, uint32_t *speed_lanes_bmap);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> index 9c27980f3a..c453494b8d 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -327,6 +327,7 @@ EXPERIMENTAL {
>  	rte_flow_template_table_resize_complete;
>  	rte_eth_speed_lanes_get;
>  	rte_eth_speed_lanes_set;
> +	rte_eth_speed_lanes_get_capa;
>  };
>  
>  INTERNAL {


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 4/4] testpmd: add support for displaying lanes capability
  2024-06-02  2:45       ` [PATCH v2 4/4] testpmd: " Damodharam Ammepalli
@ 2024-06-11 23:39         ` Ferruh Yigit
  2024-06-12 17:53           ` Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-06-11 23:39 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev

On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> Add a new api support that displays the speeds and bitmap of 
> supported lanes configuration by the ethernet controller.
> This patch adds support in the testpmd cli chain.
> 
> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> ---
>  app/test-pmd/cmdline.c | 128 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 128 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 785e5dd4de..8b0a85f632 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -1637,6 +1637,133 @@ static cmdline_parse_inst_t cmd_config_loopback_all = {
>  	},
>  };
>  
> +/* *** display speed lanes per port capabilities *** */
> +struct cmd_show_speed_lanes_result {
> +	cmdline_fixed_string_t cmd_show;
> +	cmdline_fixed_string_t cmd_port;
> +	cmdline_fixed_string_t cmd_keyword;
> +	portid_t cmd_pid;
> +};
> +
> +static const char*
> +get_device_infos_display_speeds(uint32_t speed_capa)
> +{
> +        if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
> +                return(" 10 Mbps half-duplex  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_10M)
> +                return(" 10 Mbps full-duplex  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
> +                return(" 100 Mbps half-duplex  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_100M)
> +                return(" 100 Mbps full-duplex  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_1G)
> +                return(" 1 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
> +                return(" 2.5 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_5G)
> +                return(" 5 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_10G)
> +                return(" 10 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_20G)
> +                return(" 20 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_25G)
> +                return(" 25 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_40G)
> +                return(" 40 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_50G)
> +                return(" 50 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_56G)
> +                return(" 56 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_100G)
> +                return(" 100 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_200G)
> +                return(" 200 Gbps  ");
> +        if (speed_capa & RTE_ETH_LINK_SPEED_400G)
> +                return(" 400 Gbps  ");
> +
> +	return("Unkown");
> +}
>

As far as I remember, there was already a function to convert speed to
string, can you please double check?


> +
> +static void
> +cmd_show_speed_lanes_parsed(void *parsed_result,
> +			    __rte_unused struct cmdline *cl,
> +			    __rte_unused void *data)
> +{
> +	struct cmd_show_speed_lanes_result *res = parsed_result;
> +	uint32_t speed_lanes_bmap[RTE_ETH_LINK_SPEED_MAX_BIT] = {0};
> +	struct rte_eth_speed_lanes_capa spd_lanes = {0};
>

I think this function will change completely because of previous
comments, but as a generic comment, can you please prefer full 'speed'
wording instead of 'spd'.

> +	struct rte_eth_dev_info dev_info;
> +	//char lanes_speed_str[128] = {0};
> +	bool skip_spd_chk = false;
> +	int ret, i;
> +	uint32_t j;
> +
> +	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> +		fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
> +		return;
> +	}
> +
> +	/* get max lanes this nic supports */
> +	ret = rte_eth_speed_lanes_get(res->cmd_pid, &spd_lanes);
> +        if (ret == -ENOTSUP)
> +		return;
> +
> +	/* Pull out capability if nic supports */
> +	ret = rte_eth_speed_lanes_get_capa(res->cmd_pid, speed_lanes_bmap);
> +        if (ret == -ENOTSUP)
> +		return;
> +
> +	ret = eth_dev_info_get_print_err(res->cmd_pid, &dev_info);
> +	/* when link is down, PHY does not report any speeds */
> +	if (ret == 0)
> +		skip_spd_chk = true;
> +
> +	printf("\n%-25s %-10s", " Supported speeds", "Valid lanes");
> +	printf("\n-----------------------------------");
> +        for (i = 1; i <= RTE_ETH_LINK_SPEED_MAX_BIT; i++) {
> +		if ((dev_info.speed_capa & RTE_BIT32(i) || skip_spd_chk) &&
> +		    (speed_lanes_bmap[i])) {
> +			printf("\n%-25s ",
> +			       get_device_infos_display_speeds(RTE_BIT32(i))) ;
> +			for (j = 0; j <= spd_lanes.max_lanes_cap; j++) {
> +				if (RTE_BIT32(j) & speed_lanes_bmap[i])
> +					printf("%-2d", j);
> +			}
> +		}
> +        }
> +	printf("\n");
> +}
> +
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_show, "show");
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_port, "port");
> +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
> +	TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
> +			      cmd_pid, RTE_UINT16);
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_keyword, "speed_lanes");
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_keyword, "capabilities");
> +
> +static cmdline_parse_inst_t cmd_show_speed_lanes = {
> +	.f = cmd_show_speed_lanes_parsed,
> +	.data = NULL,
> +	.help_str = "show port <port_id> speed_lanes capabilities",
> +	.tokens = {
> +		(void *)&cmd_show_speed_lanes_show,
> +		(void *)&cmd_show_speed_lanes_port,
> +		(void *)&cmd_show_speed_lanes_pid,
> +		(void *)&cmd_show_speed_lanes_keyword,
> +		(void *)&cmd_show_speed_lanes_cap_keyword,
> +		NULL,
> +	},
> +};
> +
>  /* *** configure loopback for specific port *** */
>  struct cmd_config_loopback_specific {
>  	cmdline_fixed_string_t port;
> @@ -13523,6 +13650,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>  	(cmdline_parse_inst_t *)&cmd_config_tx_affinity_map,
>  	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
>  	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> +	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,
>  	NULL,
>  };
>  


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 0/4] Add support for link speed lanes
  2024-06-11 23:38       ` [PATCH v2 0/4] Add support for link speed lanes Ferruh Yigit
@ 2024-06-12 17:46         ` Damodharam Ammepalli
  0 siblings, 0 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-12 17:46 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Dengdui Huang

Hi Ferruh,
Thanks for the review. Will implement the review comments.
Have a question in patch 4/4, you can directly index into that
patchset for my question.

Thanks
Damo

On Tue, Jun 11, 2024 at 4:39 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> > NIC adapters can support speeds with different lanes configuration.
> >
> > This patchset will allow users:
> > - get the Lanes capability per speed supported by the ethernet
> >   controller.
> > - set the lanes configuration using a new CLI
> > - Display the user configured lanes
> > --
> > v1->v2
> >
> > Added speed lanes capability and display on testpmd shell.
> > testpmd> show port 0 speed_lanes capabilities
> >
> >  Supported speeds         Valid lanes
> > -----------------------------------
> >  10 Gbps                  1
> >  25 Gbps                  1
> >  40 Gbps                  4
> >  50 Gbps                  1 2
> >  100 Gbps                 1 2 4
> >  200 Gbps                 2 4
> >  400 Gbps                 4 8
> > testpmd>
> >
> > Damodharam Ammepalli (4):
> >   lib/ethdev: Add link_speed lanes support into rte lib
> >   testpmd: Add speed lanes to testpmd config and show command
> >   lib/ethdev: add support for displaying lanes capability
> >   testpmd: add support for displaying lanes capability
> >
>
> Please cc Dengdui, as they are working on same issue.
>

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 4/4] testpmd: add support for displaying lanes capability
  2024-06-11 23:39         ` Ferruh Yigit
@ 2024-06-12 17:53           ` Damodharam Ammepalli
  2024-06-12 20:57             ` Ferruh Yigit
  0 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-12 17:53 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Dengdui Huang, fengchengwen

On Tue, Jun 11, 2024 at 4:39 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> > Add a new api support that displays the speeds and bitmap of
> > supported lanes configuration by the ethernet controller.
> > This patch adds support in the testpmd cli chain.
> >
> > Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> > ---
> >  app/test-pmd/cmdline.c | 128 +++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 128 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> > index 785e5dd4de..8b0a85f632 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -1637,6 +1637,133 @@ static cmdline_parse_inst_t cmd_config_loopback_all = {
> >       },
> >  };
> >
> > +/* *** display speed lanes per port capabilities *** */
> > +struct cmd_show_speed_lanes_result {
> > +     cmdline_fixed_string_t cmd_show;
> > +     cmdline_fixed_string_t cmd_port;
> > +     cmdline_fixed_string_t cmd_keyword;
> > +     portid_t cmd_pid;
> > +};
> > +
> > +static const char*
> > +get_device_infos_display_speeds(uint32_t speed_capa)
> > +{
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
> > +                return(" 10 Mbps half-duplex  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_10M)
> > +                return(" 10 Mbps full-duplex  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
> > +                return(" 100 Mbps half-duplex  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_100M)
> > +                return(" 100 Mbps full-duplex  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_1G)
> > +                return(" 1 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
> > +                return(" 2.5 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_5G)
> > +                return(" 5 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_10G)
> > +                return(" 10 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_20G)
> > +                return(" 20 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_25G)
> > +                return(" 25 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_40G)
> > +                return(" 40 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_50G)
> > +                return(" 50 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_56G)
> > +                return(" 56 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_100G)
> > +                return(" 100 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_200G)
> > +                return(" 200 Gbps  ");
> > +        if (speed_capa & RTE_ETH_LINK_SPEED_400G)
> > +                return(" 400 Gbps  ");
> > +
> > +     return("Unkown");
> > +}
> >
>
> As far as I remember, there was already a function to convert speed to
> string, can you please double check?
>

Yes. I picked up from this. app/test-pmd/config.c:device_infos_display_speeds()
Can I make this function
app/test-pmd/config.c:device_infos_display_speeds() a non-static and
declare it in testpmd.h?

>
> > +
> > +static void
> > +cmd_show_speed_lanes_parsed(void *parsed_result,
> > +                         __rte_unused struct cmdline *cl,
> > +                         __rte_unused void *data)
> > +{
> > +     struct cmd_show_speed_lanes_result *res = parsed_result;
> > +     uint32_t speed_lanes_bmap[RTE_ETH_LINK_SPEED_MAX_BIT] = {0};
> > +     struct rte_eth_speed_lanes_capa spd_lanes = {0};
> >
>
> I think this function will change completely because of previous
> comments, but as a generic comment, can you please prefer full 'speed'
> wording instead of 'spd'.
>
> > +     struct rte_eth_dev_info dev_info;
> > +     //char lanes_speed_str[128] = {0};
> > +     bool skip_spd_chk = false;
> > +     int ret, i;
> > +     uint32_t j;
> > +
> > +     if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> > +             fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
> > +             return;
> > +     }
> > +
> > +     /* get max lanes this nic supports */
> > +     ret = rte_eth_speed_lanes_get(res->cmd_pid, &spd_lanes);
> > +        if (ret == -ENOTSUP)
> > +             return;
> > +
> > +     /* Pull out capability if nic supports */
> > +     ret = rte_eth_speed_lanes_get_capa(res->cmd_pid, speed_lanes_bmap);
> > +        if (ret == -ENOTSUP)
> > +             return;
> > +
> > +     ret = eth_dev_info_get_print_err(res->cmd_pid, &dev_info);
> > +     /* when link is down, PHY does not report any speeds */
> > +     if (ret == 0)
> > +             skip_spd_chk = true;
> > +
> > +     printf("\n%-25s %-10s", " Supported speeds", "Valid lanes");
> > +     printf("\n-----------------------------------");
> > +        for (i = 1; i <= RTE_ETH_LINK_SPEED_MAX_BIT; i++) {
> > +             if ((dev_info.speed_capa & RTE_BIT32(i) || skip_spd_chk) &&
> > +                 (speed_lanes_bmap[i])) {
> > +                     printf("\n%-25s ",
> > +                            get_device_infos_display_speeds(RTE_BIT32(i))) ;
> > +                     for (j = 0; j <= spd_lanes.max_lanes_cap; j++) {
> > +                             if (RTE_BIT32(j) & speed_lanes_bmap[i])
> > +                                     printf("%-2d", j);
> > +                     }
> > +             }
> > +        }
> > +     printf("\n");
> > +}
> > +
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_show, "show");
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_port, "port");
> > +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
> > +     TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                           cmd_pid, RTE_UINT16);
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_keyword, "speed_lanes");
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_keyword, "capabilities");
> > +
> > +static cmdline_parse_inst_t cmd_show_speed_lanes = {
> > +     .f = cmd_show_speed_lanes_parsed,
> > +     .data = NULL,
> > +     .help_str = "show port <port_id> speed_lanes capabilities",
> > +     .tokens = {
> > +             (void *)&cmd_show_speed_lanes_show,
> > +             (void *)&cmd_show_speed_lanes_port,
> > +             (void *)&cmd_show_speed_lanes_pid,
> > +             (void *)&cmd_show_speed_lanes_keyword,
> > +             (void *)&cmd_show_speed_lanes_cap_keyword,
> > +             NULL,
> > +     },
> > +};
> > +
> >  /* *** configure loopback for specific port *** */
> >  struct cmd_config_loopback_specific {
> >       cmdline_fixed_string_t port;
> > @@ -13523,6 +13650,7 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
> >       (cmdline_parse_inst_t *)&cmd_config_tx_affinity_map,
> >       (cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> >       (cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> > +     (cmdline_parse_inst_t *)&cmd_show_speed_lanes,
> >       NULL,
> >  };
> >
>

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 4/4] testpmd: add support for displaying lanes capability
  2024-06-12 17:53           ` Damodharam Ammepalli
@ 2024-06-12 20:57             ` Ferruh Yigit
  0 siblings, 0 replies; 33+ messages in thread
From: Ferruh Yigit @ 2024-06-12 20:57 UTC (permalink / raw)
  To: Damodharam Ammepalli; +Cc: dev, Dengdui Huang, fengchengwen

On 6/12/2024 6:53 PM, Damodharam Ammepalli wrote:
> On Tue, Jun 11, 2024 at 4:39 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
>>> Add a new api support that displays the speeds and bitmap of
>>> supported lanes configuration by the ethernet controller.
>>> This patch adds support in the testpmd cli chain.
>>>
>>> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
>>> ---
>>>  app/test-pmd/cmdline.c | 128 +++++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 128 insertions(+)
>>>
>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
>>> index 785e5dd4de..8b0a85f632 100644
>>> --- a/app/test-pmd/cmdline.c
>>> +++ b/app/test-pmd/cmdline.c
>>> @@ -1637,6 +1637,133 @@ static cmdline_parse_inst_t cmd_config_loopback_all = {
>>>       },
>>>  };
>>>
>>> +/* *** display speed lanes per port capabilities *** */
>>> +struct cmd_show_speed_lanes_result {
>>> +     cmdline_fixed_string_t cmd_show;
>>> +     cmdline_fixed_string_t cmd_port;
>>> +     cmdline_fixed_string_t cmd_keyword;
>>> +     portid_t cmd_pid;
>>> +};
>>> +
>>> +static const char*
>>> +get_device_infos_display_speeds(uint32_t speed_capa)
>>> +{
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_10M_HD)
>>> +                return(" 10 Mbps half-duplex  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_10M)
>>> +                return(" 10 Mbps full-duplex  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_100M_HD)
>>> +                return(" 100 Mbps half-duplex  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_100M)
>>> +                return(" 100 Mbps full-duplex  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_1G)
>>> +                return(" 1 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_2_5G)
>>> +                return(" 2.5 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_5G)
>>> +                return(" 5 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_10G)
>>> +                return(" 10 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_20G)
>>> +                return(" 20 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_25G)
>>> +                return(" 25 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_40G)
>>> +                return(" 40 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_50G)
>>> +                return(" 50 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_56G)
>>> +                return(" 56 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_100G)
>>> +                return(" 100 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_200G)
>>> +                return(" 200 Gbps  ");
>>> +        if (speed_capa & RTE_ETH_LINK_SPEED_400G)
>>> +                return(" 400 Gbps  ");
>>> +
>>> +     return("Unkown");
>>> +}
>>>
>>
>> As far as I remember, there was already a function to convert speed to
>> string, can you please double check?
>>
> 
> Yes. I picked up from this. app/test-pmd/config.c:device_infos_display_speeds()
> Can I make this function
> app/test-pmd/config.c:device_infos_display_speeds() a non-static and
> declare it in testpmd.h?
> 

If we can reduce duplication, I think it make sense. Thanks.


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib
  2024-06-11 23:39         ` Ferruh Yigit
@ 2024-06-14 18:27           ` Damodharam Ammepalli
  2024-06-17 20:34             ` [PATCH v3] ethdev: Add link_speed lanes support Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-14 18:27 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, Kalesh AP, Ajit Khaparde, Dengdui Huang

On Tue, Jun 11, 2024 at 4:39 PM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/2/2024 3:45 AM, Damodharam Ammepalli wrote:
> > Update the eth_dev_ops structure with new function vectors
> > to get and set number of speed lanes. This will help user to
> > configure  the same fixed speed with different number of lanes
> > based on the physical carrier type.
> >
> > Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> > Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
> > Reviewed-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
> > ---
> >  lib/ethdev/ethdev_driver.h | 49 +++++++++++++++++++++++++++++++++++
> >  lib/ethdev/rte_ethdev.c    | 26 +++++++++++++++++++
> >  lib/ethdev/rte_ethdev.h    | 52 ++++++++++++++++++++++++++++++++++++++
> >  lib/ethdev/version.map     |  2 ++
> >  4 files changed, 129 insertions(+)
> >
> > diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> > index 0dbf2dd6a2..b1f473e4de 100644
> > --- a/lib/ethdev/ethdev_driver.h
> > +++ b/lib/ethdev/ethdev_driver.h
> > @@ -1179,6 +1179,51 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
> >                                       uint16_t queue_id, uint16_t offset,
> >                                       uint16_t num, FILE *file);
> >
> > +/**
> > + * @internal
> > + * Get number of current active lanes and max supported lanes
> >
>
> There is already a 'eth_speed_lanes_get_capa' dev_ops, why max supported
> lanes returned in this call, instead of capa?
>
> > + *
> > + * @param dev
> > + *   ethdev handle of port.
> > + * @param speed_lanes_capa
> > + *   Number of active lanes that the link is trained up.
> > + *   Max number of lanes supported by HW
> > + * @return
> > + *   Negative errno value on error, 0 on success.
> > + *
> > + * @retval 0
> > + *   Success, get speed_lanes data success.
> >
>
> Success, speed_lanes_capa filled.
>
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EIO
> > + *   Device is removed.
> > + */
> > +typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev,
> > +                                  struct rte_eth_speed_lanes_capa *speed_lanes_capa);
> > +
> > +/**
> > + * @internal
> > + * Set speed lanes
> >
>
> As we are on the subject, we all understand what "speed lane" is in this
> context, but I am not sure if the naming is descriptive enough, how this
> is referenced in datasheet?
>
In the data sheet there is no special description used. Ethtool says
"link modes"
Eg: caa4bbe ethtool: Add support for 200Gbps (50Gbps per lane) link mode
The cmdline is ethtool -s < int> speed 200000 lanes < int>
Taking our BRCM data sheet as reference. The user can configure
100Gb in three ways, and the hardware trains up the link with these two
user fed configs (speed + lane + drivers default phy auto params)
with the mapped signalling mode given below.

Eg: with this user config, speed 100 lanes 2 , the PHY will train up
fixed speed with
PAM4-56 signalling (if the cable and HW supports)

100Gb (NRZ: 25G per lane, 4 lanes) link speed
100Gb (PAM4-56: 50G per lane, 2 lanes) link speed
100Gb (PAM4-112: 100G per lane, 1 lane) link speed

Let me know if you have a proposal to update the function name or/and
function comments?

> > + *
> > + * @param dev
> > + *   ethdev handle of port.
> > + * @param speed_lanes_capa
> > + *   Non-negative number of lanes
> > + *
> > + * @return
> > + *   Negative errno value on error, 0 on success.
> > + *
> > + * @retval 0
> > + *   Success, set lanes success.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EINVAL
> > + *   Unsupported mode requested.
> > + * @retval -EIO
> > + *   Device is removed.
> > + */
> > +typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes_capa);
> > +
>
> These new dev_ops seems inserted in between 'rx_descriptor_dump' &
> 'tx_descriptor_dump' dev_ops.
> Can you please move them just below 'eth_link_update_t'?
>
Is this change only into the struct eth_dev_ops or applies to the
function declarations also?
>
>
> >  /**
> >   * @internal
> >   * Dump Tx descriptor info to a file.
> > @@ -1474,6 +1519,10 @@ struct eth_dev_ops {
> >       eth_count_aggr_ports_t count_aggr_ports;
> >       /** Map a Tx queue with an aggregated port of the DPDK port */
> >       eth_map_aggr_tx_affinity_t map_aggr_tx_affinity;
> > +     /** Get number of speed lanes supported and active lanes */
> > +     eth_speed_lanes_get_t speed_lanes_get;
> > +     /** Set number of speed lanes */
> > +     eth_speed_lanes_set_t speed_lanes_set;
> >  };
> >
> >  /**
> > diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> > index f1c658f49e..45e2f7645b 100644
> > --- a/lib/ethdev/rte_ethdev.c
> > +++ b/lib/ethdev/rte_ethdev.c
> > @@ -7008,4 +7008,30 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
> >       return ret;
> >  }
> >
> > +int
> > +rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa)
> > +{
> > +     struct rte_eth_dev *dev;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (*dev->dev_ops->speed_lanes_get == NULL)
> > +             return -ENOTSUP;
> > +     return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, capa));
> >
>
> Shouldn't we verify if 'capa' is not NULL in API?
>
> > +}
> > +
> > +int
> > +rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> > +{
> > +     struct rte_eth_dev *dev;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (*dev->dev_ops->speed_lanes_set == NULL)
> > +             return -ENOTSUP;
> > +     return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
> > +}
> > +
> >  RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> > index 147257d6a2..caae1f27c6 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -1997,6 +1997,12 @@ struct rte_eth_fec_capa {
> >       uint32_t capa;  /**< FEC capabilities bitmask */
> >  };
> >
> > +/* A structure used to get and set lanes capabilities per link speed */
> > +struct rte_eth_speed_lanes_capa {
> > +     uint32_t active_lanes;
> > +     uint32_t max_lanes_cap;
> > +};
> > +
> >  #define RTE_ETH_ALL RTE_MAX_ETHPORTS
> >
> >  /* Macros to check for valid port */
> > @@ -6917,6 +6923,52 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
> >       return rc;
> >  }
> >
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get maximum speed lanes supported by the NIC.
> >
>
> Isn't this API to get the current lane number?
>
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes_capa
> > + *   speed_lanes_capa is out only with max speed lanes capabilities.
> > + *   If set to NULL, then its assumed zero or not supported.
> >
>
> Why NULL 'capa' is supported?
>
> > + *
> > + * @return
> > + *   - A non-negative value of active lanes that currently link is up with.
> > + *   - A non-negative value that this HW scales up to for all speeds.
> >
>
> Isn't the return value only for status, error or success, and data
> stored in 'capa' pointer?
>
>
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + *   - (-EINVAL)  if *speed_lanes_capa* invalid
> >
>
> This is 'get' function, how 'speed_lanes_capa' can be invalid?
>
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_get(uint16_t port_id, struct rte_eth_speed_lanes_capa *capa);
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Set speed lanes supported by the NIC.
> >
>
> Should we document somewhere that this is only for the case Auto
> Negotiation (AN) is disabled, otherwise AN will figure out the lanes.
>
yes. may be in the command help, we can describe this.

> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes
> > + *   speed_lanes a non-zero value of number lanes for this speeds.
> >
>
> Please reword 'this speeds'
>
> > + *
> > + * @return
> > + *  - (>=0) valid input and supported by driver or hardware.
> >
>
> Lanes set successfully?
>
>
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + *   - (-EINVAL)  if *speed_lanes* invalid
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
> > +
> >  #ifdef __cplusplus
> >  }
> >  #endif
> > diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> > index 79f6f5293b..9c27980f3a 100644
> > --- a/lib/ethdev/version.map
> > +++ b/lib/ethdev/version.map
> > @@ -325,6 +325,8 @@ EXPERIMENTAL {
> >       rte_flow_template_table_resizable;
> >       rte_flow_template_table_resize;
> >       rte_flow_template_table_resize_complete;
> > +     rte_eth_speed_lanes_get;
> > +     rte_eth_speed_lanes_set;
> >
>
> Please follow the syntax in the file, add "# added in 24.07" comment and
> add new APIs under it alphabetically sorted way.
>

As you suggested, I have consolidated all the 4 patches (testpmd +
lib) into one single patch and addressed the comments in my local
patch.
If you can comment on the function name changes, will update and push
a new revision soon.

Thanks
Damo

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3] ethdev: Add link_speed lanes support
  2024-06-14 18:27           ` Damodharam Ammepalli
@ 2024-06-17 20:34             ` Damodharam Ammepalli
  2024-06-20  3:23               ` huangdengdui
  2024-07-05 17:35               ` [PATCH v3] " Ferruh Yigit
  0 siblings, 2 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-17 20:34 UTC (permalink / raw)
  To: dev; +Cc: huangdengdui, ajit.khaparde, kalesh-anakkur.purayil, ferruh.yigit

Update the eth_dev_ops structure with new function vectors
to get, get capabilities and set ethernet link speed lanes.
Update the testpmd to provide required config and information
display infrastructure.

The supporting ethernet controller driver will register callbacks
to avail link speed lanes config and get services. This lanes
configuration is applicable only when the nic is forced to fixed
speeds. In Autonegiation mode, the hardware automatically
negotiates the number of lanes.

These are the new commands.

testpmd> show port 0 speed_lanes capabilities

 Supported speeds         Valid lanes
-----------------------------------
 10 Gbps                  1
 25 Gbps                  1
 40 Gbps                  4
 50 Gbps                  1 2
 100 Gbps                 1 2 4
 200 Gbps                 2 4
 400 Gbps                 4 8
testpmd>

testpmd>
testpmd> port stop 0
testpmd> port config 0 speed_lanes 4
testpmd> port config 0 speed 200000 duplex full
testpmd> port start 0
testpmd>
testpmd> show port info 0

********************* Infos for port 0  *********************
MAC address: 14:23:F2:C3:BA:D2
Device name: 0000:b1:00.0
Driver name: net_bnxt
Firmware-version: 228.9.115.0
Connect to socket: 2
memory allocation on the socket: 2
Link status: up
Link speed: 200 Gbps
Active Lanes: 4
Link duplex: full-duplex
Autoneg status: Off

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
---
v2->v3 Consolidating the testpmd and rtelib patches into a single patch
as requested.

 app/test-pmd/cmdline.c     | 224 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c      |  65 ++++++++++-
 app/test-pmd/testpmd.h     |   4 +
 lib/ethdev/ethdev_driver.h |  77 +++++++++++++
 lib/ethdev/rte_ethdev.c    |  51 +++++++++
 lib/ethdev/rte_ethdev.h    |  90 +++++++++++++++
 lib/ethdev/version.map     |   5 +
 7 files changed, 514 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b7759e38a8..6eb5ca9a82 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1560,6 +1560,110 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
 	},
 };
 
+static int
+parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
+{
+	int ret;
+	uint32_t lanes_capa;
+
+	ret = parse_speed_lanes(lanes, &lanes_capa);
+	if (ret < 0) {
+		fprintf(stderr, "Unknown speed lane value: %d for port %d\n", lanes, pid);
+		return -1;
+	}
+
+	ret = rte_eth_speed_lanes_set(pid, lanes_capa);
+	if (ret == -ENOTSUP) {
+		fprintf(stderr, "Function not implemented\n");
+		return -1;
+	} else if (ret < 0) {
+		fprintf(stderr, "Set speed lanes failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/* *** display speed lanes per port capabilities *** */
+struct cmd_show_speed_lanes_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_speed_lanes_parsed(void *parsed_result,
+			    __rte_unused struct cmdline *cl,
+			    __rte_unused void *data)
+{
+	struct cmd_show_speed_lanes_result *res = parsed_result;
+	struct rte_eth_speed_lanes_capa *speed_lanes_capa;
+	unsigned int num;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
+	if (ret == -ENOTSUP) {
+		fprintf(stderr, "Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
+		return;
+	}
+
+	num = (unsigned int)ret;
+	speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
+	if (speed_lanes_capa == NULL) {
+		fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
+		return;
+	}
+
+	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
+	if (ret < 0) {
+		fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
+		goto out;
+	}
+
+	show_speed_lanes_capability(num, speed_lanes_capa);
+out:
+	free(speed_lanes_capa);
+}
+
+static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_show, "show");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_port, "port");
+static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
+			      cmd_pid, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "speed_lanes");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "capabilities");
+
+static cmdline_parse_inst_t cmd_show_speed_lanes = {
+	.f = cmd_show_speed_lanes_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> speed_lanes capabilities",
+	.tokens = {
+		(void *)&cmd_show_speed_lanes_show,
+		(void *)&cmd_show_speed_lanes_port,
+		(void *)&cmd_show_speed_lanes_pid,
+		(void *)&cmd_show_speed_lanes_keyword,
+		(void *)&cmd_show_speed_lanes_cap_keyword,
+		NULL,
+	},
+};
+
 /* *** configure loopback for all ports *** */
 struct cmd_config_loopback_all {
 	cmdline_fixed_string_t port;
@@ -1676,6 +1780,123 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
 	},
 };
 
+/* *** configure speed_lanes for all ports *** */
+struct cmd_config_speed_lanes_all {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_all_parsed(void *parsed_result,
+				  __rte_unused struct cmdline *cl,
+				  __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_all *res = parsed_result;
+	portid_t pid;
+
+	if (!all_ports_stopped()) {
+		fprintf(stderr, "Please stop all ports first\n");
+		return;
+	}
+
+	RTE_ETH_FOREACH_DEV(pid) {
+		if (parse_speed_lanes_cfg(pid, res->lanes))
+			return;
+	}
+
+	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
+				 "config");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
+	.f = cmd_config_speed_lanes_all_parsed,
+	.data = NULL,
+	.help_str = "port config all speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_all_port,
+		(void *)&cmd_config_speed_lanes_all_keyword,
+		(void *)&cmd_config_speed_lanes_all_all,
+		(void *)&cmd_config_speed_lanes_all_item,
+		(void *)&cmd_config_speed_lanes_all_lanes,
+		NULL,
+	},
+};
+
+/* *** configure speed_lanes for specific port *** */
+struct cmd_config_speed_lanes_specific {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	uint16_t port_id;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_specific_parsed(void *parsed_result,
+				       __rte_unused struct cmdline *cl,
+				       __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_specific *res = parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!port_is_stopped(res->port_id)) {
+		fprintf(stderr, "Please stop port %u first\n", res->port_id);
+		return;
+	}
+
+	if (parse_speed_lanes_cfg(res->port_id, res->lanes))
+		return;
+
+	cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
+				 "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
+				 "config");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
+			      RTE_UINT16);
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
+			      RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
+	.f = cmd_config_speed_lanes_specific_parsed,
+	.data = NULL,
+	.help_str = "port config <port_id> speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_specific_port,
+		(void *)&cmd_config_speed_lanes_specific_keyword,
+		(void *)&cmd_config_speed_lanes_specific_id,
+		(void *)&cmd_config_speed_lanes_specific_item,
+		(void *)&cmd_config_speed_lanes_specific_lanes,
+		NULL,
+	},
+};
+
 /* *** configure txq/rxq, txd/rxd *** */
 struct cmd_config_rx_tx {
 	cmdline_fixed_string_t port;
@@ -13238,6 +13459,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_port_setup_on,
 	(cmdline_parse_inst_t *)&cmd_config_speed_all,
 	(cmdline_parse_inst_t *)&cmd_config_speed_specific,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
+	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,
 	(cmdline_parse_inst_t *)&cmd_config_loopback_all,
 	(cmdline_parse_inst_t *)&cmd_config_loopback_specific,
 	(cmdline_parse_inst_t *)&cmd_config_rx_tx,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 66c3a68c1d..cf3ea50114 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -207,6 +207,32 @@ static const struct {
 	{"gtpu", RTE_ETH_FLOW_GTPU},
 };
 
+static const struct {
+	enum rte_eth_speed_lanes lane;
+	const uint32_t value;
+} speed_lane_name[] = {
+	{
+		.lane = RTE_ETH_SPEED_LANE_NOLANE,
+		.value = 0,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_1,
+		.value = 1,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_2,
+		.value = 2,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_4,
+		.value = 4,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_8,
+		.value = 8,
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
 	char name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 	char fw_version[ETHDEV_FWVERS_LEN];
+	uint32_t lanes;
 
 	if (port_id_is_invalid(port_id, ENABLED_WARN)) {
 		print_valid_ports();
@@ -828,6 +855,8 @@ port_infos_display(portid_t port_id)
 
 	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
 	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
+	if (rte_eth_speed_lanes_get(port_id, &lanes) == 0)
+		printf("Active Lanes: %d\n", lanes);
 	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
 	       ("full-duplex") : ("half-duplex"));
 	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
@@ -962,7 +991,7 @@ port_summary_header_display(void)
 
 	port_number = rte_eth_dev_count_avail();
 	printf("Number of available ports: %i\n", port_number);
-	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
+	printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
 			"Driver", "Status", "Link");
 }
 
@@ -993,7 +1022,7 @@ port_summary_display(portid_t port_id)
 	if (ret != 0)
 		return;
 
-	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
+	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
 		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
 		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
 		rte_eth_link_speed_to_str(link.link_speed));
@@ -7244,3 +7273,35 @@ show_mcast_macs(portid_t port_id)
 		printf("  %s\n", buf);
 	}
 }
+
+int
+parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
+		if (speed_lane_name[i].value == lane) {
+			*speed_lane = lane;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
+{
+	unsigned int i, j;
+
+	printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
+	printf("\n-----------------------------------\n");
+	for (i = 0; i < num; i++) {
+		printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
+
+		for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
+			if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
+				printf("%-2d ", speed_lane_name[j].value);
+		}
+		printf("\n");
+	}
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9facd7f281..fb9ef05cc5 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1253,6 +1253,10 @@ extern int flow_parse(const char *src, void *result, unsigned int size,
 		      struct rte_flow_item **pattern,
 		      struct rte_flow_action **actions);
 
+void show_speed_lanes_capability(uint32_t num,
+				 struct rte_eth_speed_lanes_capa *speed_lanes_capa);
+int parse_speed_lanes(uint32_t lane, uint32_t *speed_lane);
+
 uint64_t str_to_rsstypes(const char *str);
 const char *rsstypes_to_str(uint64_t rss_type);
 
diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index 883e59a927..0f10aec3a1 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -1179,6 +1179,79 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
 					uint16_t queue_id, uint16_t offset,
 					uint16_t num, FILE *file);
 
+/**
+ * @internal
+ * Get number of current active lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes
+ *   Number of active lanes that the link is trained up.
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get speed_lanes data success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
+
+/**
+ * @internal
+ * Set speed lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes
+ *   Non-negative number of lanes
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set lanes success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
+
+/**
+ * @internal
+ * Get supported link speed lanes capability
+ *
+ * @param speed_lanes_capa
+ *   speed_lanes_capa is out only with per-speed capabilities.
+ * @param num
+ *   a number of elements in an speed_speed_lanes_capa array.
+ *
+ * @return
+ *   Negative errno value on error, positive value on success.
+ *
+ * @retval positive value
+ *   A non-negative value lower or equal to num: success. The return value
+ *   is the number of entries filled in the speed lanes array.
+ *   A non-negative value higher than num: error, the given speed lanes capa array
+ *   is too small. The return value corresponds to the num that should
+ *   be given to succeed. The entries in the speed lanes capa array are not valid
+ *   and shall not be used by the caller.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ * @retval -EINVAL
+ *   *num* or *speed_lanes_capa* invalid.
+ */
+typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
+						struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+						unsigned int num);
+
 /**
  * @internal
  * Dump Tx descriptor info to a file.
@@ -1247,6 +1320,10 @@ struct eth_dev_ops {
 	eth_dev_close_t            dev_close;     /**< Close device */
 	eth_dev_reset_t		   dev_reset;	  /**< Reset device */
 	eth_link_update_t          link_update;   /**< Get device link state */
+	eth_speed_lanes_get_t	   speed_lanes_get;	  /**<Get link speed active lanes */
+	eth_speed_lanes_set_t      speed_lanes_set;	  /**<set the link speeds supported lanes */
+	/** Get link speed lanes capability */
+	eth_speed_lanes_get_capability_t speed_lanes_get_capa;
 	/** Check if the device was physically removed */
 	eth_is_removed_t           is_removed;
 
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index f1c658f49e..07cefea307 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -7008,4 +7008,55 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
 	return ret;
 }
 
+int
+rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_get == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
+}
+
+int
+rte_eth_speed_lanes_get_capability(uint16_t port_id,
+				   struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+				   unsigned int num)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (speed_lanes_capa == NULL && num > 0) {
+		RTE_ETHDEV_LOG_LINE(ERR,
+				    "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
+				    port_id);
+		return -EINVAL;
+	}
+
+	if (*dev->dev_ops->speed_lanes_get_capa == NULL)
+		return -ENOTSUP;
+	ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
+
+	return ret;
+}
+
+int
+rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_set == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
+}
+
 RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 548fada1c7..f5bacd4ba4 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -357,6 +357,30 @@ struct rte_eth_link {
 #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
 /**@}*/
 
+/**
+ * This enum indicates the possible link speed lanes of an ethdev port.
+ */
+enum rte_eth_speed_lanes {
+	RTE_ETH_SPEED_LANE_NOLANE = 0,  /**< speed lanes unsupported mode or default */
+	RTE_ETH_SPEED_LANE_1,           /**< Link speed lane  1 */
+	RTE_ETH_SPEED_LANE_2,           /**< Link speed lanes 2 */
+	RTE_ETH_SPEED_LANE_4,           /**< Link speed lanes 4 */
+	RTE_ETH_SPEED_LANE_8,           /**< Link speed lanes 8 */
+	RTE_ETH_SPEED_LANE_MAX,
+};
+
+/* Translate from link speed lanes to speed lanes capa */
+#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
+
+/* This macro indicates link speed lanes capa mask */
+#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
+
+/* A structure used to get and set lanes capabilities per link speed */
+struct rte_eth_speed_lanes_capa {
+	uint32_t speed;
+	uint32_t capa;
+};
+
 /**
  * A structure used to configure the ring threshold registers of an Rx/Tx
  * queue for an Ethernet port.
@@ -6922,6 +6946,72 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
 	return rc;
 }
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get Active lanes.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param lanes
+ *   driver populates a active lanes value whether link is Autonegotiated or Fixed speed.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes
+ *   speed_lanes a non-zero value of number lanes for this speeds.
+ *
+ * @return
+ *  - (>=0) valid input and supported by driver or hardware.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes_bmap
+ *   speed_lanes_bmap int array updated by driver by valid lanes bmap.
+ *
+ * @return
+ *  - (>=0) valid input and supported by driver or hardware.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get_capability(uint16_t port_id,
+				       struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+				       unsigned int num);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 79f6f5293b..db9261946f 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -325,6 +325,11 @@ EXPERIMENTAL {
 	rte_flow_template_table_resizable;
 	rte_flow_template_table_resize;
 	rte_flow_template_table_resize_complete;
+
+	# added in 24.07
+	rte_eth_speed_lanes_get;
+	rte_eth_speed_lanes_get_capability;
+	rte_eth_speed_lanes_set;
 };
 
 INTERNAL {
-- 
2.39.3


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-06-17 20:34             ` [PATCH v3] ethdev: Add link_speed lanes support Damodharam Ammepalli
@ 2024-06-20  3:23               ` huangdengdui
  2024-06-25 21:07                 ` Damodharam Ammepalli
  2024-07-05 17:35               ` [PATCH v3] " Ferruh Yigit
  1 sibling, 1 reply; 33+ messages in thread
From: huangdengdui @ 2024-06-20  3:23 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev
  Cc: ajit.khaparde, kalesh-anakkur.purayil, ferruh.yigit

Hi Damodharam
Here are some suggestions. See below.

On 2024/6/18 4:34, Damodharam Ammepalli wrote:
> Update the eth_dev_ops structure with new function vectors
> to get, get capabilities and set ethernet link speed lanes.
> Update the testpmd to provide required config and information
> display infrastructure.
> 
> The supporting ethernet controller driver will register callbacks
> to avail link speed lanes config and get services. This lanes
> configuration is applicable only when the nic is forced to fixed
> speeds. In Autonegiation mode, the hardware automatically
> negotiates the number of lanes.
> 


> +
>  /* *** configure txq/rxq, txd/rxd *** */
>  struct cmd_config_rx_tx {
>  	cmdline_fixed_string_t port;
> @@ -13238,6 +13459,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>  	(cmdline_parse_inst_t *)&cmd_set_port_setup_on,
>  	(cmdline_parse_inst_t *)&cmd_config_speed_all,
>  	(cmdline_parse_inst_t *)&cmd_config_speed_specific,
> +	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> +	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> +	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,

Please also add to help string and update doc

>  	(cmdline_parse_inst_t *)&cmd_config_loopback_all,
>  	(cmdline_parse_inst_t *)&cmd_config_loopback_specific,
>  	(cmdline_parse_inst_t *)&cmd_config_rx_tx,
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 66c3a68c1d..cf3ea50114 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -207,6 +207,32 @@ static const struct {
>  	{"gtpu", RTE_ETH_FLOW_GTPU},
>  };
>  
> +static const struct {
> +	enum rte_eth_speed_lanes lane;
> +	const uint32_t value;
> +} speed_lane_name[] = {
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_NOLANE,
> +		.value = 0,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_1,
> +		.value = 1,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_2,
> +		.value = 2,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_4,
> +		.value = 4,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_8,
> +		.value = 8,
> +	},
> +};
> +
>  static void
>  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
>  {
> @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
>  	char name[RTE_ETH_NAME_MAX_LEN];
>  	int ret;
>  	char fw_version[ETHDEV_FWVERS_LEN];
> +	uint32_t lanes;
>  
>  	if (port_id_is_invalid(port_id, ENABLED_WARN)) {
>  		print_valid_ports();
> @@ -828,6 +855,8 @@ port_infos_display(portid_t port_id)
>  
>  	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
>  	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
> +	if (rte_eth_speed_lanes_get(port_id, &lanes) == 0)
> +		printf("Active Lanes: %d\n", lanes);

It should not be printed when lanes=0. Or print unknown when lane=0?

>  	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
>  	       ("full-duplex") : ("half-duplex"));
>  	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
> @@ -962,7 +991,7 @@ port_summary_header_display(void)
>  
>  	port_number = rte_eth_dev_count_avail();
>  	printf("Number of available ports: %i\n", port_number);
> -	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
> +	printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
>  			"Driver", "Status", "Link");
>  }
>  
> @@ -993,7 +1022,7 @@ port_summary_display(portid_t port_id)
>  	if (ret != 0)
>  		return;
>  
> -	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> +	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",

Does the lanes need to be printed?

>  		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
>  		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
>  		rte_eth_link_speed_to_str(link.link_speed));
> @@ -7244,3 +7273,35 @@ show_mcast_macs(portid_t port_id)
>  		printf("  %s\n", buf);
>  	}
>  }
> +
> +int
> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
> +{
> +	uint8_t i;
> +
> +	for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
> +		if (speed_lane_name[i].value == lane) {
> +			*speed_lane = lane;
> +			return 0;
> +		}
> +	}
> +	return -1;
> +}
> +
> +void
> +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
> +{
> +	unsigned int i, j;
> +
> +	printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
> +	printf("\n-----------------------------------\n");
> +	for (i = 0; i < num; i++) {
> +		printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
> +
> +		for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
> +			if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
> +				printf("%-2d ", speed_lane_name[j].value);
> +		}
> +		printf("\n");
> +	}
> +}
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index 9facd7f281..fb9ef05cc5 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -1253,6 +1253,10 @@ extern int flow_parse(const char *src, void *result, unsigned int size,
>  		      struct rte_flow_item **pattern,
>  		      struct rte_flow_action **actions);
>  
> +void show_speed_lanes_capability(uint32_t num,
> +				 struct rte_eth_speed_lanes_capa *speed_lanes_capa);
> +int parse_speed_lanes(uint32_t lane, uint32_t *speed_lane);
> +
>  uint64_t str_to_rsstypes(const char *str);
>  const char *rsstypes_to_str(uint64_t rss_type);
>  
> diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> index 883e59a927..0f10aec3a1 100644
> --- a/lib/ethdev/ethdev_driver.h
> +++ b/lib/ethdev/ethdev_driver.h
> @@ -1179,6 +1179,79 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
>  					uint16_t queue_id, uint16_t offset,
>  					uint16_t num, FILE *file);
>  
> +/**
> + * @internal
> + * Get number of current active lanes
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes
> + *   Number of active lanes that the link is trained up.
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, get speed_lanes data success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
> +
> +/**
> + * @internal
> + * Set speed lanes
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes
> + *   Non-negative number of lanes
> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, set lanes success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EINVAL
> + *   Unsupported mode requested.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
> +
> +/**
> + * @internal
> + * Get supported link speed lanes capability
> + *
> + * @param speed_lanes_capa
> + *   speed_lanes_capa is out only with per-speed capabilities.
> + * @param num
> + *   a number of elements in an speed_speed_lanes_capa array.
> + *

Some of the arguments are not documented, not just here.
You can add the 'enable_docs' to verify the document, for example
meson build  -Denable_docs=true

> + * @return
> + *   Negative errno value on error, positive value on success.
> + *
> + * @retval positive value
> + *   A non-negative value lower or equal to num: success. The return value
> + *   is the number of entries filled in the speed lanes array.
> + *   A non-negative value higher than num: error, the given speed lanes capa array
> + *   is too small. The return value corresponds to the num that should
> + *   be given to succeed. The entries in the speed lanes capa array are not valid
> + *   and shall not be used by the caller.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + * @retval -EINVAL
> + *   *num* or *speed_lanes_capa* invalid.
> + */
> +typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
> +						struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> +						unsigned int num);
> +
>  /**
>   * @internal
>   * Dump Tx descriptor info to a file.
> @@ -1247,6 +1320,10 @@ struct eth_dev_ops {
>  	eth_dev_close_t            dev_close;     /**< Close device */
>  	eth_dev_reset_t		   dev_reset;	  /**< Reset device */
>  	eth_link_update_t          link_update;   /**< Get device link state */
> +	eth_speed_lanes_get_t	   speed_lanes_get;	  /**<Get link speed active lanes */
> +	eth_speed_lanes_set_t      speed_lanes_set;	  /**<set the link speeds supported lanes */
> +	/** Get link speed lanes capability */
> +	eth_speed_lanes_get_capability_t speed_lanes_get_capa;
>  	/** Check if the device was physically removed */
>  	eth_is_removed_t           is_removed;
>  
> diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> index f1c658f49e..07cefea307 100644
> --- a/lib/ethdev/rte_ethdev.c
> +++ b/lib/ethdev/rte_ethdev.c
> @@ -7008,4 +7008,55 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
>  	return ret;
>  }
>  
> +int
> +rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->speed_lanes_get == NULL)
> +		return -ENOTSUP;
> +	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
> +}
> +
> +int
> +rte_eth_speed_lanes_get_capability(uint16_t port_id,
> +				   struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> +				   unsigned int num)
> +{
> +	struct rte_eth_dev *dev;
> +	int ret;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (speed_lanes_capa == NULL && num > 0) {
> +		RTE_ETHDEV_LOG_LINE(ERR,
> +				    "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
> +				    port_id);
> +		return -EINVAL;
> +	}
> +
> +	if (*dev->dev_ops->speed_lanes_get_capa == NULL)
> +		return -ENOTSUP;
> +	ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
> +
> +	return ret;
> +}
> +
> +int
> +rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->speed_lanes_set == NULL)
> +		return -ENOTSUP;
> +	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
> +}
> +
>  RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index 548fada1c7..f5bacd4ba4 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -357,6 +357,30 @@ struct rte_eth_link {
>  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
>  /**@}*/
>  
> +/**
> + * This enum indicates the possible link speed lanes of an ethdev port.
> + */
> +enum rte_eth_speed_lanes {
> +	RTE_ETH_SPEED_LANE_NOLANE = 0,  /**< speed lanes unsupported mode or default */
> +	RTE_ETH_SPEED_LANE_1,           /**< Link speed lane  1 */
> +	RTE_ETH_SPEED_LANE_2,           /**< Link speed lanes 2 */
> +	RTE_ETH_SPEED_LANE_4,           /**< Link speed lanes 4 */
> +	RTE_ETH_SPEED_LANE_8,           /**< Link speed lanes 8 */
> +	RTE_ETH_SPEED_LANE_MAX,
> +};

Is it better to make the index equal to the lanes num?
enum rte_eth_speed_lanes {
	RTE_ETH_SPEED_LANE_NOLANE = 0,      /**< speed lanes unsupported mode or default */
	RTE_ETH_SPEED_LANE_1 = 1,           /**< Link speed lane  1 */
	RTE_ETH_SPEED_LANE_2 = 2,           /**< Link speed lanes 2 */
	RTE_ETH_SPEED_LANE_4 = 4,           /**< Link speed lanes 4 */
	RTE_ETH_SPEED_LANE_8 = 8,           /**< Link speed lanes 8 */
	RTE_ETH_SPEED_LANE_MAX,
};

In addition, when lanes = 0, is it better to define it as Unknown?
If default lanes can return 0 lanes, The active lanes are different for each NIC,
users may be confused.

> +
> +/* Translate from link speed lanes to speed lanes capa */
> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> +
> +/* This macro indicates link speed lanes capa mask */
> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> +
> +/* A structure used to get and set lanes capabilities per link speed */
> +struct rte_eth_speed_lanes_capa {
> +	uint32_t speed;
> +	uint32_t capa;
> +};
> +
>  /**
>   * A structure used to configure the ring threshold registers of an Rx/Tx
>   * queue for an Ethernet port.
> @@ -6922,6 +6946,72 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
>  	return rc;
>  }
>  
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get Active lanes.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param lanes
> + *   driver populates a active lanes value whether link is Autonegotiated or Fixed speed.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set speed lanes supported by the NIC.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes
> + *   speed_lanes a non-zero value of number lanes for this speeds.
> + *
> + * @return
> + *  - (>=0) valid input and supported by driver or hardware.

Is it better to change the description to the following:
(0) if successful.

> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
> +

Is it better to name 'speed_lanes'?

> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set speed lanes supported by the NIC.
> + *

Set -> Get

> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes_bmap
> + *   speed_lanes_bmap int array updated by driver by valid lanes bmap.
> + *
> + * @return
> + *  - (>=0) valid input and supported by driver or hardware.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *speed_lanes* invalid
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_get_capability(uint16_t port_id,
> +				       struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> +				       unsigned int num);
> +
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> index 79f6f5293b..db9261946f 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -325,6 +325,11 @@ EXPERIMENTAL {
>  	rte_flow_template_table_resizable;
>  	rte_flow_template_table_resize;
>  	rte_flow_template_table_resize_complete;
> +
> +	# added in 24.07
> +	rte_eth_speed_lanes_get;
> +	rte_eth_speed_lanes_get_capability;
> +	rte_eth_speed_lanes_set;
>  };
>  
>  INTERNAL {

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-06-20  3:23               ` huangdengdui
@ 2024-06-25 21:07                 ` Damodharam Ammepalli
  2024-06-26  2:19                   ` huangdengdui
  0 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-06-25 21:07 UTC (permalink / raw)
  To: huangdengdui; +Cc: dev, ajit.khaparde, kalesh-anakkur.purayil, ferruh.yigit

On Wed, Jun 19, 2024 at 8:23 PM huangdengdui <huangdengdui@huawei.com> wrote:
>
> Hi Damodharam
> Here are some suggestions. See below.
>
Thank you for the review.

> On 2024/6/18 4:34, Damodharam Ammepalli wrote:
> > Update the eth_dev_ops structure with new function vectors
> > to get, get capabilities and set ethernet link speed lanes.
> > Update the testpmd to provide required config and information
> > display infrastructure.
> >
> > The supporting ethernet controller driver will register callbacks
> > to avail link speed lanes config and get services. This lanes
> > configuration is applicable only when the nic is forced to fixed
> > speeds. In Autonegiation mode, the hardware automatically
> > negotiates the number of lanes.
> >
>
>
> > +
> >  /* *** configure txq/rxq, txd/rxd *** */
> >  struct cmd_config_rx_tx {
> >       cmdline_fixed_string_t port;
> > @@ -13238,6 +13459,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
> >       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
> >       (cmdline_parse_inst_t *)&cmd_config_speed_all,
> >       (cmdline_parse_inst_t *)&cmd_config_speed_specific,
> > +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> > +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> > +     (cmdline_parse_inst_t *)&cmd_show_speed_lanes,
>
> Please also add to help string and update doc
ack
>
> >       (cmdline_parse_inst_t *)&cmd_config_loopback_all,
> >       (cmdline_parse_inst_t *)&cmd_config_loopback_specific,
> >       (cmdline_parse_inst_t *)&cmd_config_rx_tx,
> > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> > index 66c3a68c1d..cf3ea50114 100644
> > --- a/app/test-pmd/config.c
> > +++ b/app/test-pmd/config.c
> > @@ -207,6 +207,32 @@ static const struct {
> >       {"gtpu", RTE_ETH_FLOW_GTPU},
> >  };
> >
> > +static const struct {
> > +     enum rte_eth_speed_lanes lane;
> > +     const uint32_t value;
> > +} speed_lane_name[] = {
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_NOLANE,
> > +             .value = 0,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_1,
> > +             .value = 1,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_2,
> > +             .value = 2,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_4,
> > +             .value = 4,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_8,
> > +             .value = 8,
> > +     },
> > +};
> > +
> >  static void
> >  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
> >  {
> > @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
> >       char name[RTE_ETH_NAME_MAX_LEN];
> >       int ret;
> >       char fw_version[ETHDEV_FWVERS_LEN];
> > +     uint32_t lanes;
> >
> >       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
> >               print_valid_ports();
> > @@ -828,6 +855,8 @@ port_infos_display(portid_t port_id)
> >
> >       printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
> >       printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
> > +     if (rte_eth_speed_lanes_get(port_id, &lanes) == 0)
> > +             printf("Active Lanes: %d\n", lanes);
>
> It should not be printed when lanes=0. Or print unknown when lane=0?
Here rte_eth_speed_lanes_get(port_id, &lanes) returns 0 only for lanes
supporting drivers.
For lane supporting drivers, In link down condition, lanes = 0 ( ie
yet to be determined).
ack. printing "unknown" also makes sense.

>
> >       printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
> >              ("full-duplex") : ("half-duplex"));
> >       printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
> > @@ -962,7 +991,7 @@ port_summary_header_display(void)
> >
> >       port_number = rte_eth_dev_count_avail();
> >       printf("Number of available ports: %i\n", port_number);
> > -     printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
> > +     printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
> >                       "Driver", "Status", "Link");
> >  }
> >
> > @@ -993,7 +1022,7 @@ port_summary_display(portid_t port_id)
> >       if (ret != 0)
> >               return;
> >
> > -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> > +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
>
> Does the lanes need to be printed?
Ferruh in the previous comment, asked not to print.

>
> >               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
> >               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
> >               rte_eth_link_speed_to_str(link.link_speed));
> > @@ -7244,3 +7273,35 @@ show_mcast_macs(portid_t port_id)
> >               printf("  %s\n", buf);
> >       }
> >  }
> > +
> > +int
> > +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
> > +{
> > +     uint8_t i;
> > +
> > +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
> > +             if (speed_lane_name[i].value == lane) {
> > +                     *speed_lane = lane;
> > +                     return 0;
> > +             }
> > +     }
> > +     return -1;
> > +}
> > +
> > +void
> > +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
> > +{
> > +     unsigned int i, j;
> > +
> > +     printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
> > +     printf("\n-----------------------------------\n");
> > +     for (i = 0; i < num; i++) {
> > +             printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
> > +
> > +             for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
> > +                     if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
> > +                             printf("%-2d ", speed_lane_name[j].value);
> > +             }
> > +             printf("\n");
> > +     }
> > +}
> > diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> > index 9facd7f281..fb9ef05cc5 100644
> > --- a/app/test-pmd/testpmd.h
> > +++ b/app/test-pmd/testpmd.h
> > @@ -1253,6 +1253,10 @@ extern int flow_parse(const char *src, void *result, unsigned int size,
> >                     struct rte_flow_item **pattern,
> >                     struct rte_flow_action **actions);
> >
> > +void show_speed_lanes_capability(uint32_t num,
> > +                              struct rte_eth_speed_lanes_capa *speed_lanes_capa);
> > +int parse_speed_lanes(uint32_t lane, uint32_t *speed_lane);
> > +
> >  uint64_t str_to_rsstypes(const char *str);
> >  const char *rsstypes_to_str(uint64_t rss_type);
> >
> > diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> > index 883e59a927..0f10aec3a1 100644
> > --- a/lib/ethdev/ethdev_driver.h
> > +++ b/lib/ethdev/ethdev_driver.h
> > @@ -1179,6 +1179,79 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
> >                                       uint16_t queue_id, uint16_t offset,
> >                                       uint16_t num, FILE *file);
> >
> > +/**
> > + * @internal
> > + * Get number of current active lanes
> > + *
> > + * @param dev
> > + *   ethdev handle of port.
> > + * @param speed_lanes
> > + *   Number of active lanes that the link is trained up.
> > + * @return
> > + *   Negative errno value on error, 0 on success.
> > + *
> > + * @retval 0
> > + *   Success, get speed_lanes data success.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EIO
> > + *   Device is removed.
> > + */
> > +typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
> > +
> > +/**
> > + * @internal
> > + * Set speed lanes
> > + *
> > + * @param dev
> > + *   ethdev handle of port.
> > + * @param speed_lanes
> > + *   Non-negative number of lanes
> > + *
> > + * @return
> > + *   Negative errno value on error, 0 on success.
> > + *
> > + * @retval 0
> > + *   Success, set lanes success.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EINVAL
> > + *   Unsupported mode requested.
> > + * @retval -EIO
> > + *   Device is removed.
> > + */
> > +typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
> > +
> > +/**
> > + * @internal
> > + * Get supported link speed lanes capability
> > + *
> > + * @param speed_lanes_capa
> > + *   speed_lanes_capa is out only with per-speed capabilities.
> > + * @param num
> > + *   a number of elements in an speed_speed_lanes_capa array.
> > + *
>
> Some of the arguments are not documented, not just here.
> You can add the 'enable_docs' to verify the document, for example
> meson build  -Denable_docs=true
>
Ack. thanks will take care.
> > + * @return
> > + *   Negative errno value on error, positive value on success.
> > + *
> > + * @retval positive value
> > + *   A non-negative value lower or equal to num: success. The return value
> > + *   is the number of entries filled in the speed lanes array.
> > + *   A non-negative value higher than num: error, the given speed lanes capa array
> > + *   is too small. The return value corresponds to the num that should
> > + *   be given to succeed. The entries in the speed lanes capa array are not valid
> > + *   and shall not be used by the caller.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EIO
> > + *   Device is removed.
> > + * @retval -EINVAL
> > + *   *num* or *speed_lanes_capa* invalid.
> > + */
> > +typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
> > +                                             struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> > +                                             unsigned int num);
> > +
> >  /**
> >   * @internal
> >   * Dump Tx descriptor info to a file.
> > @@ -1247,6 +1320,10 @@ struct eth_dev_ops {
> >       eth_dev_close_t            dev_close;     /**< Close device */
> >       eth_dev_reset_t            dev_reset;     /**< Reset device */
> >       eth_link_update_t          link_update;   /**< Get device link state */
> > +     eth_speed_lanes_get_t      speed_lanes_get;       /**<Get link speed active lanes */
> > +     eth_speed_lanes_set_t      speed_lanes_set;       /**<set the link speeds supported lanes */
> > +     /** Get link speed lanes capability */
> > +     eth_speed_lanes_get_capability_t speed_lanes_get_capa;
> >       /** Check if the device was physically removed */
> >       eth_is_removed_t           is_removed;
> >
> > diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> > index f1c658f49e..07cefea307 100644
> > --- a/lib/ethdev/rte_ethdev.c
> > +++ b/lib/ethdev/rte_ethdev.c
> > @@ -7008,4 +7008,55 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
> >       return ret;
> >  }
> >
> > +int
> > +rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
> > +{
> > +     struct rte_eth_dev *dev;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (*dev->dev_ops->speed_lanes_get == NULL)
> > +             return -ENOTSUP;
> > +     return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
> > +}
> > +
> > +int
> > +rte_eth_speed_lanes_get_capability(uint16_t port_id,
> > +                                struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> > +                                unsigned int num)
> > +{
> > +     struct rte_eth_dev *dev;
> > +     int ret;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (speed_lanes_capa == NULL && num > 0) {
> > +             RTE_ETHDEV_LOG_LINE(ERR,
> > +                                 "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
> > +                                 port_id);
> > +             return -EINVAL;
> > +     }
> > +
> > +     if (*dev->dev_ops->speed_lanes_get_capa == NULL)
> > +             return -ENOTSUP;
> > +     ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
> > +
> > +     return ret;
> > +}
> > +
> > +int
> > +rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> > +{
> > +     struct rte_eth_dev *dev;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (*dev->dev_ops->speed_lanes_set == NULL)
> > +             return -ENOTSUP;
> > +     return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
> > +}
> > +
> >  RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> > index 548fada1c7..f5bacd4ba4 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -357,6 +357,30 @@ struct rte_eth_link {
> >  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
> >  /**@}*/
> >
> > +/**
> > + * This enum indicates the possible link speed lanes of an ethdev port.
> > + */
> > +enum rte_eth_speed_lanes {
> > +     RTE_ETH_SPEED_LANE_NOLANE = 0,  /**< speed lanes unsupported mode or default */
> > +     RTE_ETH_SPEED_LANE_1,           /**< Link speed lane  1 */
> > +     RTE_ETH_SPEED_LANE_2,           /**< Link speed lanes 2 */
> > +     RTE_ETH_SPEED_LANE_4,           /**< Link speed lanes 4 */
> > +     RTE_ETH_SPEED_LANE_8,           /**< Link speed lanes 8 */
> > +     RTE_ETH_SPEED_LANE_MAX,
> > +};
>
> Is it better to make the index equal to the lanes num?
> enum rte_eth_speed_lanes {
>         RTE_ETH_SPEED_LANE_NOLANE = 0,      /**< speed lanes unsupported mode or default */
>         RTE_ETH_SPEED_LANE_1 = 1,           /**< Link speed lane  1 */
>         RTE_ETH_SPEED_LANE_2 = 2,           /**< Link speed lanes 2 */
>         RTE_ETH_SPEED_LANE_4 = 4,           /**< Link speed lanes 4 */
>         RTE_ETH_SPEED_LANE_8 = 8,           /**< Link speed lanes 8 */
>         RTE_ETH_SPEED_LANE_MAX,
> };
>
I followed the existing enums code convention in rtelib. Your point
makes sense too.

> In addition, when lanes = 0, is it better to define it as Unknown?
> If default lanes can return 0 lanes, The active lanes are different for each NIC,
> users may be confused.
>
Ack. Are you proposing a new enum RTE_ETH_SPEED_LANE_UKNOWN or rename
RTE_ETH_SPEED_LANE_NOLANE?

> > +
> > +/* Translate from link speed lanes to speed lanes capa */
> > +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> > +
> > +/* This macro indicates link speed lanes capa mask */
> > +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> > +
> > +/* A structure used to get and set lanes capabilities per link speed */
> > +struct rte_eth_speed_lanes_capa {
> > +     uint32_t speed;
> > +     uint32_t capa;
> > +};
> > +
> >  /**
> >   * A structure used to configure the ring threshold registers of an Rx/Tx
> >   * queue for an Ethernet port.
> > @@ -6922,6 +6946,72 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
> >       return rc;
> >  }
> >
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get Active lanes.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param lanes
> > + *   driver populates a active lanes value whether link is Autonegotiated or Fixed speed.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Set speed lanes supported by the NIC.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes
> > + *   speed_lanes a non-zero value of number lanes for this speeds.
> > + *
> > + * @return
> > + *  - (>=0) valid input and supported by driver or hardware.
>
> Is it better to change the description to the following:
> (0) if successful.
>
Ack
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
> > +
>
> Is it better to name 'speed_lanes'?
Are you proposing to rename to rte_speed_lanes_set() function name or
rename variable "speed_lanes_capa" name ?

>
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Set speed lanes supported by the NIC.
> > + *
>
> Set -> Get
Ack
>
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes_bmap
> > + *   speed_lanes_bmap int array updated by driver by valid lanes bmap.
> > + *
> > + * @return
> > + *  - (>=0) valid input and supported by driver or hardware.
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + *   - (-EINVAL)  if *speed_lanes* invalid
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_get_capability(uint16_t port_id,
> > +                                    struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> > +                                    unsigned int num);
> > +
> >  #ifdef __cplusplus
> >  }
> >  #endif
> > diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> > index 79f6f5293b..db9261946f 100644
> > --- a/lib/ethdev/version.map
> > +++ b/lib/ethdev/version.map
> > @@ -325,6 +325,11 @@ EXPERIMENTAL {
> >       rte_flow_template_table_resizable;
> >       rte_flow_template_table_resize;
> >       rte_flow_template_table_resize_complete;
> > +
> > +     # added in 24.07
> > +     rte_eth_speed_lanes_get;
> > +     rte_eth_speed_lanes_get_capability;
> > +     rte_eth_speed_lanes_set;
> >  };
> >
> >  INTERNAL {

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-06-25 21:07                 ` Damodharam Ammepalli
@ 2024-06-26  2:19                   ` huangdengdui
  2024-07-05 17:33                     ` Ferruh Yigit
  0 siblings, 1 reply; 33+ messages in thread
From: huangdengdui @ 2024-06-26  2:19 UTC (permalink / raw)
  To: Damodharam Ammepalli
  Cc: dev, ajit.khaparde, kalesh-anakkur.purayil, ferruh.yigit


On 2024/6/26 5:07, Damodharam Ammepalli wrote:
> On Wed, Jun 19, 2024 at 8:23 PM huangdengdui <huangdengdui@huawei.com> wrote:
>>
>> Hi Damodharam
>> Here are some suggestions. See below.
>>
> Thank you for the review.
> 
>> On 2024/6/18 4:34, Damodharam Ammepalli wrote:
>>> Update the eth_dev_ops structure with new function vectors
>>> to get, get capabilities and set ethernet link speed lanes.
>>> Update the testpmd to provide required config and information
>>> display infrastructure.
>>>
>>> The supporting ethernet controller driver will register callbacks
>>> to avail link speed lanes config and get services. This lanes
>>> configuration is applicable only when the nic is forced to fixed
>>> speeds. In Autonegiation mode, the hardware automatically
>>> negotiates the number of lanes.
>>>
>>
>>
>>> +
>>>  /* *** configure txq/rxq, txd/rxd *** */
>>>  struct cmd_config_rx_tx {
>>>       cmdline_fixed_string_t port;
>>> @@ -13238,6 +13459,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>>>       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,

cut

>>>
>>> @@ -993,7 +1022,7 @@ port_summary_display(portid_t port_id)
>>>       if (ret != 0)
>>>               return;
>>>
>>> -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
>>> +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
>>
>> Does the lanes need to be printed?
> Ferruh in the previous comment, asked not to print.
> 

OK

>>
>>>               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
>>>               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
>>>               rte_eth_link_speed_to_str(link.link_speed));
>>> @@ -7244,3 +7273,35 @@ show_mcast_macs(portid_t port_id)
>>>               printf("  %s\n", buf);
>>>       }
>>>  }
>>> +
>>> +int
>>> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
>>> +{
>>> +     uint8_t i;
>>> +
>>> +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
>>> +             if (speed_lane_name[i].value == lane) {
>>> +                     *speed_lane = lane;
>>> +                     return 0;
>>> +             }
>>> +     }
>>> +     return -1;
>>> +}
>>> +

cut

>>>
>>> +/**
>>> + * This enum indicates the possible link speed lanes of an ethdev port.
>>> + */
>>> +enum rte_eth_speed_lanes {
>>> +     RTE_ETH_SPEED_LANE_NOLANE = 0,  /**< speed lanes unsupported mode or default */
>>> +     RTE_ETH_SPEED_LANE_1,           /**< Link speed lane  1 */
>>> +     RTE_ETH_SPEED_LANE_2,           /**< Link speed lanes 2 */
>>> +     RTE_ETH_SPEED_LANE_4,           /**< Link speed lanes 4 */
>>> +     RTE_ETH_SPEED_LANE_8,           /**< Link speed lanes 8 */
>>> +     RTE_ETH_SPEED_LANE_MAX,
>>> +};
>>
>> Is it better to make the index equal to the lanes num?
>> enum rte_eth_speed_lanes {
>>         RTE_ETH_SPEED_LANE_NOLANE = 0,      /**< speed lanes unsupported mode or default */
>>         RTE_ETH_SPEED_LANE_1 = 1,           /**< Link speed lane  1 */
>>         RTE_ETH_SPEED_LANE_2 = 2,           /**< Link speed lanes 2 */
>>         RTE_ETH_SPEED_LANE_4 = 4,           /**< Link speed lanes 4 */
>>         RTE_ETH_SPEED_LANE_8 = 8,           /**< Link speed lanes 8 */
>>         RTE_ETH_SPEED_LANE_MAX,
>> };
>>
> I followed the existing enums code convention in rtelib. Your point
> makes sense too.
> 

I looked at the other enum code in the lib. There are many similar code styles.
Make the index meaningful to avoid conversion. For example, the parse_speed_lanes() function in this patch

>> In addition, when lanes = 0, is it better to define it as Unknown?
>> If default lanes can return 0 lanes, The active lanes are different for each NIC,
>> users may be confused.
>>
> Ack. Are you proposing a new enum RTE_ETH_SPEED_LANE_UKNOWN or rename
> RTE_ETH_SPEED_LANE_NOLANE?
> 

I suggest changing the name to RTE_ETH_SPEED_LANE_UKNOWN,
Also change the comment to describe it as an unknown lane.

This prevents the driver from always returning lanes=0
even if the driver knows the number of active lanes.

>>> +
>>> +/* Translate from link speed lanes to speed lanes capa */
>>> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
>>> +
>>> +/* This macro indicates link speed lanes capa mask */
>>> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
>>> +
>>> +/* A structure used to get and set lanes capabilities per link speed */
>>> +struct rte_eth_speed_lanes_capa {
>>> +     uint32_t speed;
>>> +     uint32_t capa;
>>> +};
>>> +

cut

>>> +__rte_experimental
>>> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
>>> +
>>
>> Is it better to name 'speed_lanes'?
> Are you proposing to rename to rte_speed_lanes_set() function name or
> rename variable "speed_lanes_capa" name ?
> 

rename variable "speed_lanes_capa" name

>>
>>> +/**
>>> + * @warning
>>> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
>>> + *
>>> + * Set speed lanes supported by the NIC.
>>> + *
>>
>> Set -> Get
> Ack
>>
>>> + * @param port_id

....


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-06-26  2:19                   ` huangdengdui
@ 2024-07-05 17:33                     ` Ferruh Yigit
  2024-07-08 20:35                       ` Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-07-05 17:33 UTC (permalink / raw)
  To: huangdengdui, Damodharam Ammepalli
  Cc: dev, ajit.khaparde, kalesh-anakkur.purayil

On 6/26/2024 3:19 AM, huangdengdui wrote:
> 
> On 2024/6/26 5:07, Damodharam Ammepalli wrote:
>> On Wed, Jun 19, 2024 at 8:23 PM huangdengdui <huangdengdui@huawei.com> wrote:
>>>
>>> Hi Damodharam
>>> Here are some suggestions. See below.
>>>
>> Thank you for the review.
>>
>>> On 2024/6/18 4:34, Damodharam Ammepalli wrote:
>>>> Update the eth_dev_ops structure with new function vectors
>>>> to get, get capabilities and set ethernet link speed lanes.
>>>> Update the testpmd to provide required config and information
>>>> display infrastructure.
>>>>
>>>> The supporting ethernet controller driver will register callbacks
>>>> to avail link speed lanes config and get services. This lanes
>>>> configuration is applicable only when the nic is forced to fixed
>>>> speeds. In Autonegiation mode, the hardware automatically
>>>> negotiates the number of lanes.
>>>>
>>>
>>>
>>>> +
>>>>  /* *** configure txq/rxq, txd/rxd *** */
>>>>  struct cmd_config_rx_tx {
>>>>       cmdline_fixed_string_t port;
>>>> @@ -13238,6 +13459,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>>>>       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
> 
> cut
> 
>>>>
>>>> @@ -993,7 +1022,7 @@ port_summary_display(portid_t port_id)
>>>>       if (ret != 0)
>>>>               return;
>>>>
>>>> -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
>>>> +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
>>>
>>> Does the lanes need to be printed?
>> Ferruh in the previous comment, asked not to print.
>>
> 
> OK
> 
>>>
>>>>               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
>>>>               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
>>>>               rte_eth_link_speed_to_str(link.link_speed));
>>>> @@ -7244,3 +7273,35 @@ show_mcast_macs(portid_t port_id)
>>>>               printf("  %s\n", buf);
>>>>       }
>>>>  }
>>>> +
>>>> +int
>>>> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
>>>> +{
>>>> +     uint8_t i;
>>>> +
>>>> +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
>>>> +             if (speed_lane_name[i].value == lane) {
>>>> +                     *speed_lane = lane;
>>>> +                     return 0;
>>>> +             }
>>>> +     }
>>>> +     return -1;
>>>> +}
>>>> +
> 
> cut
> 
>>>>
>>>> +/**
>>>> + * This enum indicates the possible link speed lanes of an ethdev port.
>>>> + */
>>>> +enum rte_eth_speed_lanes {
>>>> +     RTE_ETH_SPEED_LANE_NOLANE = 0,  /**< speed lanes unsupported mode or default */
>>>> +     RTE_ETH_SPEED_LANE_1,           /**< Link speed lane  1 */
>>>> +     RTE_ETH_SPEED_LANE_2,           /**< Link speed lanes 2 */
>>>> +     RTE_ETH_SPEED_LANE_4,           /**< Link speed lanes 4 */
>>>> +     RTE_ETH_SPEED_LANE_8,           /**< Link speed lanes 8 */
>>>> +     RTE_ETH_SPEED_LANE_MAX,
>>>> +};
>>>
>>> Is it better to make the index equal to the lanes num?
>>> enum rte_eth_speed_lanes {
>>>         RTE_ETH_SPEED_LANE_NOLANE = 0,      /**< speed lanes unsupported mode or default */
>>>         RTE_ETH_SPEED_LANE_1 = 1,           /**< Link speed lane  1 */
>>>         RTE_ETH_SPEED_LANE_2 = 2,           /**< Link speed lanes 2 */
>>>         RTE_ETH_SPEED_LANE_4 = 4,           /**< Link speed lanes 4 */
>>>         RTE_ETH_SPEED_LANE_8 = 8,           /**< Link speed lanes 8 */
>>>         RTE_ETH_SPEED_LANE_MAX,
>>> };
>>>
>> I followed the existing enums code convention in rtelib. Your point
>> makes sense too.
>>
> 
> I looked at the other enum code in the lib. There are many similar code styles.
> Make the index meaningful to avoid conversion. For example, the parse_speed_lanes() function in this patch
> 
>>> In addition, when lanes = 0, is it better to define it as Unknown?
>>> If default lanes can return 0 lanes, The active lanes are different for each NIC,
>>> users may be confused.
>>>
>> Ack. Are you proposing a new enum RTE_ETH_SPEED_LANE_UKNOWN or rename
>> RTE_ETH_SPEED_LANE_NOLANE?
>>
> 
> I suggest changing the name to RTE_ETH_SPEED_LANE_UKNOWN,
> Also change the comment to describe it as an unknown lane.
> 
> This prevents the driver from always returning lanes=0
> even if the driver knows the number of active lanes.
> 
>>>> +
>>>> +/* Translate from link speed lanes to speed lanes capa */
>>>> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
>>>> +
>>>> +/* This macro indicates link speed lanes capa mask */
>>>> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
>>>> +
>>>> +/* A structure used to get and set lanes capabilities per link speed */
>>>> +struct rte_eth_speed_lanes_capa {
>>>> +     uint32_t speed;
>>>> +     uint32_t capa;
>>>> +};
>>>> +
> 
> cut
> 
>>>> +__rte_experimental
>>>> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
>>>> +
>>>
>>> Is it better to name 'speed_lanes'?
>> Are you proposing to rename to rte_speed_lanes_set() function name or
>> rename variable "speed_lanes_capa" name ?
>>
> 
> rename variable "speed_lanes_capa" name
> 

Hi Damodharam,

I was hoping to get this feature for -rc2, as outstanding comments are
not very big, if it can be possible to get new version in next few days
we can proceed with it for this release, otherwise can wait for next
release.

Btw, other issue is testing this new feature, as it is not supported by
many vendors, I expect this test case not included in many test plans.
And because of the HW dependency adding unit test won't be sufficient.
At least for the short term, can we rely Broadcom and Huawei to test it
with the first version this feature is merged?

And I am not sure about what can be the long term solution, any
suggestion is welcome. My concern is as number of this kind of features
are increasing, dpdk is becoming more fragile.




^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-06-17 20:34             ` [PATCH v3] ethdev: Add link_speed lanes support Damodharam Ammepalli
  2024-06-20  3:23               ` huangdengdui
@ 2024-07-05 17:35               ` Ferruh Yigit
  2024-07-08 20:31                 ` Damodharam Ammepalli
  1 sibling, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-07-05 17:35 UTC (permalink / raw)
  To: Damodharam Ammepalli, dev
  Cc: huangdengdui, ajit.khaparde, kalesh-anakkur.purayil

On 6/17/2024 9:34 PM, Damodharam Ammepalli wrote:
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set speed lanes supported by the NIC.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes
> + *   speed_lanes a non-zero value of number lanes for this speeds.
> + *
> + * @return
> + *  - (>=0) valid input and supported by driver or hardware.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if port_id invalid.
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
>

Doc build fails because of "@param speed_lanes":

rte_ethdev.h:6971:
  error: argument 'speed_lanes' of command @param is not found in the
argument list of
  rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
(warning treated as error, aborting now)

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-07-05 17:35               ` [PATCH v3] " Ferruh Yigit
@ 2024-07-08 20:31                 ` Damodharam Ammepalli
  0 siblings, 0 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-07-08 20:31 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: dev, huangdengdui, ajit.khaparde, kalesh-anakkur.purayil

On Fri, Jul 5, 2024 at 10:35 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/17/2024 9:34 PM, Damodharam Ammepalli wrote:
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Set speed lanes supported by the NIC.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes
> > + *   speed_lanes a non-zero value of number lanes for this speeds.
> > + *
> > + * @return
> > + *  - (>=0) valid input and supported by driver or hardware.
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if port_id invalid.
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
> >
>
> Doc build fails because of "@param speed_lanes":
>
> rte_ethdev.h:6971:
>   error: argument 'speed_lanes' of command @param is not found in the
> argument list of
>   rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> (warning treated as error, aborting now)
Ack

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3] ethdev: Add link_speed lanes support
  2024-07-05 17:33                     ` Ferruh Yigit
@ 2024-07-08 20:35                       ` Damodharam Ammepalli
  2024-07-08 23:22                         ` [PATCH v4] " Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-07-08 20:35 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: huangdengdui, dev, ajit.khaparde, kalesh-anakkur.purayil

On Fri, Jul 5, 2024 at 10:33 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 6/26/2024 3:19 AM, huangdengdui wrote:
> >
> > On 2024/6/26 5:07, Damodharam Ammepalli wrote:
> >> On Wed, Jun 19, 2024 at 8:23 PM huangdengdui <huangdengdui@huawei.com> wrote:
> >>>
> >>> Hi Damodharam
> >>> Here are some suggestions. See below.
> >>>
> >> Thank you for the review.
> >>
> >>> On 2024/6/18 4:34, Damodharam Ammepalli wrote:
> >>>> Update the eth_dev_ops structure with new function vectors
> >>>> to get, get capabilities and set ethernet link speed lanes.
> >>>> Update the testpmd to provide required config and information
> >>>> display infrastructure.
> >>>>
> >>>> The supporting ethernet controller driver will register callbacks
> >>>> to avail link speed lanes config and get services. This lanes
> >>>> configuration is applicable only when the nic is forced to fixed
> >>>> speeds. In Autonegiation mode, the hardware automatically
> >>>> negotiates the number of lanes.
> >>>>
> >>>
> >>>
> >>>> +
> >>>>  /* *** configure txq/rxq, txd/rxd *** */
> >>>>  struct cmd_config_rx_tx {
> >>>>       cmdline_fixed_string_t port;
> >>>> @@ -13238,6 +13459,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
> >>>>       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
> >
> > cut
> >
> >>>>
> >>>> @@ -993,7 +1022,7 @@ port_summary_display(portid_t port_id)
> >>>>       if (ret != 0)
> >>>>               return;
> >>>>
> >>>> -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> >>>> +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
> >>>
> >>> Does the lanes need to be printed?
> >> Ferruh in the previous comment, asked not to print.
> >>
> >
> > OK
> >
> >>>
> >>>>               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
> >>>>               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
> >>>>               rte_eth_link_speed_to_str(link.link_speed));
> >>>> @@ -7244,3 +7273,35 @@ show_mcast_macs(portid_t port_id)
> >>>>               printf("  %s\n", buf);
> >>>>       }
> >>>>  }
> >>>> +
> >>>> +int
> >>>> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
> >>>> +{
> >>>> +     uint8_t i;
> >>>> +
> >>>> +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
> >>>> +             if (speed_lane_name[i].value == lane) {
> >>>> +                     *speed_lane = lane;
> >>>> +                     return 0;
> >>>> +             }
> >>>> +     }
> >>>> +     return -1;
> >>>> +}
> >>>> +
> >
> > cut
> >
> >>>>
> >>>> +/**
> >>>> + * This enum indicates the possible link speed lanes of an ethdev port.
> >>>> + */
> >>>> +enum rte_eth_speed_lanes {
> >>>> +     RTE_ETH_SPEED_LANE_NOLANE = 0,  /**< speed lanes unsupported mode or default */
> >>>> +     RTE_ETH_SPEED_LANE_1,           /**< Link speed lane  1 */
> >>>> +     RTE_ETH_SPEED_LANE_2,           /**< Link speed lanes 2 */
> >>>> +     RTE_ETH_SPEED_LANE_4,           /**< Link speed lanes 4 */
> >>>> +     RTE_ETH_SPEED_LANE_8,           /**< Link speed lanes 8 */
> >>>> +     RTE_ETH_SPEED_LANE_MAX,
> >>>> +};
> >>>
> >>> Is it better to make the index equal to the lanes num?
> >>> enum rte_eth_speed_lanes {
> >>>         RTE_ETH_SPEED_LANE_NOLANE = 0,      /**< speed lanes unsupported mode or default */
> >>>         RTE_ETH_SPEED_LANE_1 = 1,           /**< Link speed lane  1 */
> >>>         RTE_ETH_SPEED_LANE_2 = 2,           /**< Link speed lanes 2 */
> >>>         RTE_ETH_SPEED_LANE_4 = 4,           /**< Link speed lanes 4 */
> >>>         RTE_ETH_SPEED_LANE_8 = 8,           /**< Link speed lanes 8 */
> >>>         RTE_ETH_SPEED_LANE_MAX,
> >>> };
> >>>
> >> I followed the existing enums code convention in rtelib. Your point
> >> makes sense too.
> >>
> >
> > I looked at the other enum code in the lib. There are many similar code styles.
> > Make the index meaningful to avoid conversion. For example, the parse_speed_lanes() function in this patch
> >
> >>> In addition, when lanes = 0, is it better to define it as Unknown?
> >>> If default lanes can return 0 lanes, The active lanes are different for each NIC,
> >>> users may be confused.
> >>>
> >> Ack. Are you proposing a new enum RTE_ETH_SPEED_LANE_UKNOWN or rename
> >> RTE_ETH_SPEED_LANE_NOLANE?
> >>
> >
> > I suggest changing the name to RTE_ETH_SPEED_LANE_UKNOWN,
> > Also change the comment to describe it as an unknown lane.
> >
> > This prevents the driver from always returning lanes=0
> > even if the driver knows the number of active lanes.
> >
> >>>> +
> >>>> +/* Translate from link speed lanes to speed lanes capa */
> >>>> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> >>>> +
> >>>> +/* This macro indicates link speed lanes capa mask */
> >>>> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> >>>> +
> >>>> +/* A structure used to get and set lanes capabilities per link speed */
> >>>> +struct rte_eth_speed_lanes_capa {
> >>>> +     uint32_t speed;
> >>>> +     uint32_t capa;
> >>>> +};
> >>>> +
> >
> > cut
> >
> >>>> +__rte_experimental
> >>>> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa);
> >>>> +
> >>>
> >>> Is it better to name 'speed_lanes'?
> >> Are you proposing to rename to rte_speed_lanes_set() function name or
> >> rename variable "speed_lanes_capa" name ?
> >>
> >
> > rename variable "speed_lanes_capa" name
> >
>
> Hi Damodharam,
>
> I was hoping to get this feature for -rc2, as outstanding comments are
> not very big, if it can be possible to get new version in next few days
> we can proceed with it for this release, otherwise can wait for next
> release.
>
> Btw, other issue is testing this new feature, as it is not supported by
> many vendors, I expect this test case not included in many test plans.
> And because of the HW dependency adding unit test won't be sufficient.
> At least for the short term, can we rely Broadcom and Huawei to test it
> with the first version this feature is merged?
>
> And I am not sure about what can be the long term solution, any
> suggestion is welcome. My concern is as number of this kind of features
> are increasing, dpdk is becoming more fragile.
>
>
>
Hi Ferruh,
Yes, I will push a new patch with review comments addressed in a day.
Sure, Broadcom will test it and provide the feedback. Infact, I am unit testing
internally with the brcm driver for every revision of the patch that is pushed.

Thanks
Damo

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v4] ethdev: Add link_speed lanes support
  2024-07-08 20:35                       ` Damodharam Ammepalli
@ 2024-07-08 23:22                         ` Damodharam Ammepalli
  2024-07-08 23:34                           ` Ajit Khaparde
  2024-07-09 11:10                           ` Ferruh Yigit
  0 siblings, 2 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-07-08 23:22 UTC (permalink / raw)
  To: damodharam.ammepalli
  Cc: ajit.khaparde, dev, ferruh.yigit, huangdengdui, kalesh-anakkur.purayil

Update the eth_dev_ops structure with new function vectors
to get, get capabilities and set ethernet link speed lanes.
Update the testpmd to provide required config and information
display infrastructure.

The supporting ethernet controller driver will register callbacks
to avail link speed lanes config and get services. This lanes
configuration is applicable only when the nic is forced to fixed
speeds. In Autonegiation mode, the hardware automatically
negotiates the number of lanes.

These are the new commands.

testpmd> show port 0 speed_lanes capabilities

 Supported speeds         Valid lanes
-----------------------------------
 10 Gbps                  1
 25 Gbps                  1
 40 Gbps                  4
 50 Gbps                  1 2
 100 Gbps                 1 2 4
 200 Gbps                 2 4
 400 Gbps                 4 8
testpmd>

testpmd>
testpmd> port stop 0
testpmd> port config 0 speed_lanes 4
testpmd> port config 0 speed 200000 duplex full
testpmd> port start 0
testpmd>
testpmd> show port info 0

********************* Infos for port 0  *********************
MAC address: 14:23:F2:C3:BA:D2
Device name: 0000:b1:00.0
Driver name: net_bnxt
Firmware-version: 228.9.115.0
Connect to socket: 2
memory allocation on the socket: 2
Link status: up
Link speed: 200 Gbps
Active Lanes: 4
Link duplex: full-duplex
Autoneg status: Off

Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
---
v2->v3 Consolidating the testpmd and rtelib patches into a single patch
as requested.
v3->v4 Addressed comments and fix help string and documentation.

 app/test-pmd/cmdline.c     | 230 +++++++++++++++++++++++++++++++++++++
 app/test-pmd/config.c      |  69 ++++++++++-
 app/test-pmd/testpmd.h     |   4 +
 lib/ethdev/ethdev_driver.h |  77 +++++++++++++
 lib/ethdev/rte_ethdev.c    |  51 ++++++++
 lib/ethdev/rte_ethdev.h    |  92 +++++++++++++++
 lib/ethdev/version.map     |   5 +
 7 files changed, 526 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index b7759e38a8..a507df31d8 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"dump_log_types\n"
 			"    Dumps the log level for all the dpdk modules\n\n"
+
+			"show port (port_id) speed_lanes capabilities"
+			"	Show speed lanes capabilities of a port.\n\n"
 		);
 	}
 
@@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id) txq (queue_id) affinity (value)\n"
 			"    Map a Tx queue with an aggregated port "
 			"of the DPDK port\n\n"
+
+			"port config (port_id|all) speed_lanes (0|1|4|8)\n"
+			"    Set number of lanes for all ports or port_id for a forced speed\n\n"
 		);
 	}
 
@@ -1560,6 +1566,110 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
 	},
 };
 
+static int
+parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
+{
+	int ret;
+	uint32_t lanes_capa;
+
+	ret = parse_speed_lanes(lanes, &lanes_capa);
+	if (ret < 0) {
+		fprintf(stderr, "Unknown speed lane value: %d for port %d\n", lanes, pid);
+		return -1;
+	}
+
+	ret = rte_eth_speed_lanes_set(pid, lanes_capa);
+	if (ret == -ENOTSUP) {
+		fprintf(stderr, "Function not implemented\n");
+		return -1;
+	} else if (ret < 0) {
+		fprintf(stderr, "Set speed lanes failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+/* *** display speed lanes per port capabilities *** */
+struct cmd_show_speed_lanes_result {
+	cmdline_fixed_string_t cmd_show;
+	cmdline_fixed_string_t cmd_port;
+	cmdline_fixed_string_t cmd_keyword;
+	portid_t cmd_pid;
+};
+
+static void
+cmd_show_speed_lanes_parsed(void *parsed_result,
+			    __rte_unused struct cmdline *cl,
+			    __rte_unused void *data)
+{
+	struct cmd_show_speed_lanes_result *res = parsed_result;
+	struct rte_eth_speed_lanes_capa *speed_lanes_capa;
+	unsigned int num;
+	int ret;
+
+	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+		fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
+		return;
+	}
+
+	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
+	if (ret == -ENOTSUP) {
+		fprintf(stderr, "Function not implemented\n");
+		return;
+	} else if (ret < 0) {
+		fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
+		return;
+	}
+
+	num = (unsigned int)ret;
+	speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
+	if (speed_lanes_capa == NULL) {
+		fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
+		return;
+	}
+
+	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
+	if (ret < 0) {
+		fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
+		goto out;
+	}
+
+	show_speed_lanes_capability(num, speed_lanes_capa);
+out:
+	free(speed_lanes_capa);
+}
+
+static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_show, "show");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_port, "port");
+static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
+			      cmd_pid, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "speed_lanes");
+static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
+				 cmd_keyword, "capabilities");
+
+static cmdline_parse_inst_t cmd_show_speed_lanes = {
+	.f = cmd_show_speed_lanes_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> speed_lanes capabilities",
+	.tokens = {
+		(void *)&cmd_show_speed_lanes_show,
+		(void *)&cmd_show_speed_lanes_port,
+		(void *)&cmd_show_speed_lanes_pid,
+		(void *)&cmd_show_speed_lanes_keyword,
+		(void *)&cmd_show_speed_lanes_cap_keyword,
+		NULL,
+	},
+};
+
 /* *** configure loopback for all ports *** */
 struct cmd_config_loopback_all {
 	cmdline_fixed_string_t port;
@@ -1676,6 +1786,123 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
 	},
 };
 
+/* *** configure speed_lanes for all ports *** */
+struct cmd_config_speed_lanes_all {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	cmdline_fixed_string_t all;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_all_parsed(void *parsed_result,
+				  __rte_unused struct cmdline *cl,
+				  __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_all *res = parsed_result;
+	portid_t pid;
+
+	if (!all_ports_stopped()) {
+		fprintf(stderr, "Please stop all ports first\n");
+		return;
+	}
+
+	RTE_ETH_FOREACH_DEV(pid) {
+		if (parse_speed_lanes_cfg(pid, res->lanes))
+			return;
+	}
+
+	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
+				 "config");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
+	.f = cmd_config_speed_lanes_all_parsed,
+	.data = NULL,
+	.help_str = "port config all speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_all_port,
+		(void *)&cmd_config_speed_lanes_all_keyword,
+		(void *)&cmd_config_speed_lanes_all_all,
+		(void *)&cmd_config_speed_lanes_all_item,
+		(void *)&cmd_config_speed_lanes_all_lanes,
+		NULL,
+	},
+};
+
+/* *** configure speed_lanes for specific port *** */
+struct cmd_config_speed_lanes_specific {
+	cmdline_fixed_string_t port;
+	cmdline_fixed_string_t keyword;
+	uint16_t port_id;
+	cmdline_fixed_string_t item;
+	uint32_t lanes;
+};
+
+static void
+cmd_config_speed_lanes_specific_parsed(void *parsed_result,
+				       __rte_unused struct cmdline *cl,
+				       __rte_unused void *data)
+{
+	struct cmd_config_speed_lanes_specific *res = parsed_result;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	if (!port_is_stopped(res->port_id)) {
+		fprintf(stderr, "Please stop port %u first\n", res->port_id);
+		return;
+	}
+
+	if (parse_speed_lanes_cfg(res->port_id, res->lanes))
+		return;
+
+	cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
+				 "port");
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
+				 "config");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
+			      RTE_UINT16);
+static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
+	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
+				 "speed_lanes");
+static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
+	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
+			      RTE_UINT32);
+
+static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
+	.f = cmd_config_speed_lanes_specific_parsed,
+	.data = NULL,
+	.help_str = "port config <port_id> speed_lanes <value>",
+	.tokens = {
+		(void *)&cmd_config_speed_lanes_specific_port,
+		(void *)&cmd_config_speed_lanes_specific_keyword,
+		(void *)&cmd_config_speed_lanes_specific_id,
+		(void *)&cmd_config_speed_lanes_specific_item,
+		(void *)&cmd_config_speed_lanes_specific_lanes,
+		NULL,
+	},
+};
+
 /* *** configure txq/rxq, txd/rxd *** */
 struct cmd_config_rx_tx {
 	cmdline_fixed_string_t port;
@@ -13238,6 +13465,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_set_port_setup_on,
 	(cmdline_parse_inst_t *)&cmd_config_speed_all,
 	(cmdline_parse_inst_t *)&cmd_config_speed_specific,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
+	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
+	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,
 	(cmdline_parse_inst_t *)&cmd_config_loopback_all,
 	(cmdline_parse_inst_t *)&cmd_config_loopback_specific,
 	(cmdline_parse_inst_t *)&cmd_config_rx_tx,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 66c3a68c1d..498a7db467 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -207,6 +207,32 @@ static const struct {
 	{"gtpu", RTE_ETH_FLOW_GTPU},
 };
 
+static const struct {
+	enum rte_eth_speed_lanes lane;
+	const uint32_t value;
+} speed_lane_name[] = {
+	{
+		.lane = RTE_ETH_SPEED_LANE_UNKNOWN,
+		.value = 0,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_1,
+		.value = 1,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_2,
+		.value = 2,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_4,
+		.value = 4,
+	},
+	{
+		.lane = RTE_ETH_SPEED_LANE_8,
+		.value = 8,
+	},
+};
+
 static void
 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
 {
@@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
 	char name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 	char fw_version[ETHDEV_FWVERS_LEN];
+	uint32_t lanes;
 
 	if (port_id_is_invalid(port_id, ENABLED_WARN)) {
 		print_valid_ports();
@@ -828,6 +855,12 @@ port_infos_display(portid_t port_id)
 
 	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
 	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
+	if (rte_eth_speed_lanes_get(port_id, &lanes) == 0) {
+		if (lanes > 0)
+			printf("Active Lanes: %d\n", lanes);
+		else
+			printf("Active Lanes: %s\n", "Unknown");
+	}
 	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
 	       ("full-duplex") : ("half-duplex"));
 	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
@@ -962,7 +995,7 @@ port_summary_header_display(void)
 
 	port_number = rte_eth_dev_count_avail();
 	printf("Number of available ports: %i\n", port_number);
-	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
+	printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
 			"Driver", "Status", "Link");
 }
 
@@ -993,7 +1026,7 @@ port_summary_display(portid_t port_id)
 	if (ret != 0)
 		return;
 
-	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
+	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
 		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
 		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
 		rte_eth_link_speed_to_str(link.link_speed));
@@ -7244,3 +7277,35 @@ show_mcast_macs(portid_t port_id)
 		printf("  %s\n", buf);
 	}
 }
+
+int
+parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
+{
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
+		if (speed_lane_name[i].value == lane) {
+			*speed_lane = lane;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+void
+show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
+{
+	unsigned int i, j;
+
+	printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
+	printf("\n-----------------------------------\n");
+	for (i = 0; i < num; i++) {
+		printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
+
+		for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
+			if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
+				printf("%-2d ", speed_lane_name[j].value);
+		}
+		printf("\n");
+	}
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9facd7f281..fb9ef05cc5 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1253,6 +1253,10 @@ extern int flow_parse(const char *src, void *result, unsigned int size,
 		      struct rte_flow_item **pattern,
 		      struct rte_flow_action **actions);
 
+void show_speed_lanes_capability(uint32_t num,
+				 struct rte_eth_speed_lanes_capa *speed_lanes_capa);
+int parse_speed_lanes(uint32_t lane, uint32_t *speed_lane);
+
 uint64_t str_to_rsstypes(const char *str);
 const char *rsstypes_to_str(uint64_t rss_type);
 
diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
index 883e59a927..0f10aec3a1 100644
--- a/lib/ethdev/ethdev_driver.h
+++ b/lib/ethdev/ethdev_driver.h
@@ -1179,6 +1179,79 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
 					uint16_t queue_id, uint16_t offset,
 					uint16_t num, FILE *file);
 
+/**
+ * @internal
+ * Get number of current active lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes
+ *   Number of active lanes that the link is trained up.
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, get speed_lanes data success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
+
+/**
+ * @internal
+ * Set speed lanes
+ *
+ * @param dev
+ *   ethdev handle of port.
+ * @param speed_lanes
+ *   Non-negative number of lanes
+ *
+ * @return
+ *   Negative errno value on error, 0 on success.
+ *
+ * @retval 0
+ *   Success, set lanes success.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EINVAL
+ *   Unsupported mode requested.
+ * @retval -EIO
+ *   Device is removed.
+ */
+typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
+
+/**
+ * @internal
+ * Get supported link speed lanes capability
+ *
+ * @param speed_lanes_capa
+ *   speed_lanes_capa is out only with per-speed capabilities.
+ * @param num
+ *   a number of elements in an speed_speed_lanes_capa array.
+ *
+ * @return
+ *   Negative errno value on error, positive value on success.
+ *
+ * @retval positive value
+ *   A non-negative value lower or equal to num: success. The return value
+ *   is the number of entries filled in the speed lanes array.
+ *   A non-negative value higher than num: error, the given speed lanes capa array
+ *   is too small. The return value corresponds to the num that should
+ *   be given to succeed. The entries in the speed lanes capa array are not valid
+ *   and shall not be used by the caller.
+ * @retval -ENOTSUP
+ *   Operation is not supported.
+ * @retval -EIO
+ *   Device is removed.
+ * @retval -EINVAL
+ *   *num* or *speed_lanes_capa* invalid.
+ */
+typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
+						struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+						unsigned int num);
+
 /**
  * @internal
  * Dump Tx descriptor info to a file.
@@ -1247,6 +1320,10 @@ struct eth_dev_ops {
 	eth_dev_close_t            dev_close;     /**< Close device */
 	eth_dev_reset_t		   dev_reset;	  /**< Reset device */
 	eth_link_update_t          link_update;   /**< Get device link state */
+	eth_speed_lanes_get_t	   speed_lanes_get;	  /**<Get link speed active lanes */
+	eth_speed_lanes_set_t      speed_lanes_set;	  /**<set the link speeds supported lanes */
+	/** Get link speed lanes capability */
+	eth_speed_lanes_get_capability_t speed_lanes_get_capa;
 	/** Check if the device was physically removed */
 	eth_is_removed_t           is_removed;
 
diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index f1c658f49e..07cefea307 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -7008,4 +7008,55 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
 	return ret;
 }
 
+int
+rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_get == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
+}
+
+int
+rte_eth_speed_lanes_get_capability(uint16_t port_id,
+				   struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+				   unsigned int num)
+{
+	struct rte_eth_dev *dev;
+	int ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (speed_lanes_capa == NULL && num > 0) {
+		RTE_ETHDEV_LOG_LINE(ERR,
+				    "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
+				    port_id);
+		return -EINVAL;
+	}
+
+	if (*dev->dev_ops->speed_lanes_get_capa == NULL)
+		return -ENOTSUP;
+	ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
+
+	return ret;
+}
+
+int
+rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
+{
+	struct rte_eth_dev *dev;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	dev = &rte_eth_devices[port_id];
+
+	if (*dev->dev_ops->speed_lanes_set == NULL)
+		return -ENOTSUP;
+	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
+}
+
 RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
index 548fada1c7..35d0b81452 100644
--- a/lib/ethdev/rte_ethdev.h
+++ b/lib/ethdev/rte_ethdev.h
@@ -357,6 +357,30 @@ struct rte_eth_link {
 #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
 /**@}*/
 
+/**
+ * This enum indicates the possible link speed lanes of an ethdev port.
+ */
+enum rte_eth_speed_lanes {
+	RTE_ETH_SPEED_LANE_UNKNOWN = 0,  /**< speed lanes unsupported mode or default */
+	RTE_ETH_SPEED_LANE_1 = 1,        /**< Link speed lane  1 */
+	RTE_ETH_SPEED_LANE_2 = 2,        /**< Link speed lanes 2 */
+	RTE_ETH_SPEED_LANE_4 = 4,        /**< Link speed lanes 4 */
+	RTE_ETH_SPEED_LANE_8 = 8,        /**< Link speed lanes 8 */
+	RTE_ETH_SPEED_LANE_MAX,
+};
+
+/* Translate from link speed lanes to speed lanes capa */
+#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
+
+/* This macro indicates link speed lanes capa mask */
+#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
+
+/* A structure used to get and set lanes capabilities per link speed */
+struct rte_eth_speed_lanes_capa {
+	uint32_t speed;
+	uint32_t capa;
+};
+
 /**
  * A structure used to configure the ring threshold registers of an Rx/Tx
  * queue for an Ethernet port.
@@ -6922,6 +6946,74 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
 	return rc;
 }
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get Active lanes.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param lanes
+ *   driver populates a active lanes value whether link is Autonegotiated or Fixed speed.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes
+ *   speed_lanes a non-zero value of number lanes for this speeds.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ */
+__rte_experimental
+int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get speed lanes supported by the NIC.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param speed_lanes_capa
+ *   speed_lanes_capa int array with valid lanes per speed.
+ * @param num
+ *   size of the speed_lanes_capa array.
+ *
+ * @return
+ *   - (0) if successful.
+ *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
+ *     that operation.
+ *   - (-EIO) if device is removed.
+ *   - (-ENODEV)  if *port_id* invalid.
+ *   - (-EINVAL)  if *speed_lanes* invalid
+ */
+__rte_experimental
+int rte_eth_speed_lanes_get_capability(uint16_t port_id,
+				       struct rte_eth_speed_lanes_capa *speed_lanes_capa,
+				       unsigned int num);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 79f6f5293b..db9261946f 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -325,6 +325,11 @@ EXPERIMENTAL {
 	rte_flow_template_table_resizable;
 	rte_flow_template_table_resize;
 	rte_flow_template_table_resize_complete;
+
+	# added in 24.07
+	rte_eth_speed_lanes_get;
+	rte_eth_speed_lanes_get_capability;
+	rte_eth_speed_lanes_set;
 };
 
 INTERNAL {
-- 
2.43.5


-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v4] ethdev: Add link_speed lanes support
  2024-07-08 23:22                         ` [PATCH v4] " Damodharam Ammepalli
@ 2024-07-08 23:34                           ` Ajit Khaparde
  2024-07-09 11:10                           ` Ferruh Yigit
  1 sibling, 0 replies; 33+ messages in thread
From: Ajit Khaparde @ 2024-07-08 23:34 UTC (permalink / raw)
  To: Damodharam Ammepalli
  Cc: dev, ferruh.yigit, huangdengdui, kalesh-anakkur.purayil

[-- Attachment #1: Type: text/plain, Size: 1720 bytes --]

On Mon, Jul 8, 2024 at 4:30 PM Damodharam Ammepalli
<damodharam.ammepalli@broadcom.com> wrote:
>
> Update the eth_dev_ops structure with new function vectors
> to get, get capabilities and set ethernet link speed lanes.
> Update the testpmd to provide required config and information
> display infrastructure.
>
> The supporting ethernet controller driver will register callbacks
> to avail link speed lanes config and get services. This lanes
> configuration is applicable only when the nic is forced to fixed
> speeds. In Autonegiation mode, the hardware automatically
> negotiates the number of lanes.
>
> These are the new commands.
>
> testpmd> show port 0 speed_lanes capabilities
>
>  Supported speeds         Valid lanes
> -----------------------------------
>  10 Gbps                  1
>  25 Gbps                  1
>  40 Gbps                  4
>  50 Gbps                  1 2
>  100 Gbps                 1 2 4
>  200 Gbps                 2 4
>  400 Gbps                 4 8
> testpmd>
>
> testpmd>
> testpmd> port stop 0
> testpmd> port config 0 speed_lanes 4
> testpmd> port config 0 speed 200000 duplex full
> testpmd> port start 0
> testpmd>
> testpmd> show port info 0
>
> ********************* Infos for port 0  *********************
> MAC address: 14:23:F2:C3:BA:D2
> Device name: 0000:b1:00.0
> Driver name: net_bnxt
> Firmware-version: 228.9.115.0
> Connect to socket: 2
> memory allocation on the socket: 2
> Link status: up
> Link speed: 200 Gbps
> Active Lanes: 4
> Link duplex: full-duplex
> Autoneg status: Off
>
> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4218 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v4] ethdev: Add link_speed lanes support
  2024-07-08 23:22                         ` [PATCH v4] " Damodharam Ammepalli
  2024-07-08 23:34                           ` Ajit Khaparde
@ 2024-07-09 11:10                           ` Ferruh Yigit
  2024-07-09 21:20                             ` Damodharam Ammepalli
  1 sibling, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-07-09 11:10 UTC (permalink / raw)
  To: Damodharam Ammepalli
  Cc: ajit.khaparde, dev, huangdengdui, kalesh-anakkur.purayil

On 7/9/2024 12:22 AM, Damodharam Ammepalli wrote:
> Update the eth_dev_ops structure with new function vectors
> to get, get capabilities and set ethernet link speed lanes.
> Update the testpmd to provide required config and information
> display infrastructure.
> 
> The supporting ethernet controller driver will register callbacks
> to avail link speed lanes config and get services. This lanes
> configuration is applicable only when the nic is forced to fixed
> speeds. In Autonegiation mode, the hardware automatically
> negotiates the number of lanes.
> 
> These are the new commands.
> 
> testpmd> show port 0 speed_lanes capabilities
> 
>  Supported speeds         Valid lanes
> -----------------------------------
>  10 Gbps                  1
>  25 Gbps                  1
>  40 Gbps                  4
>  50 Gbps                  1 2
>  100 Gbps                 1 2 4
>  200 Gbps                 2 4
>  400 Gbps                 4 8
> testpmd>
> 
> testpmd>
> testpmd> port stop 0
> testpmd> port config 0 speed_lanes 4
> testpmd> port config 0 speed 200000 duplex full
>

Is there a requirement to set speed before speed_lane?
Because I expect driver will verify if a speed_lane value is valid or
not for a specific speed value. In above usage, driver will verify based
on existing speed, whatever it is, later chaning speed may cause invalid
speed_lane configuration.


> testpmd> port start 0
> testpmd>
> testpmd> show port info 0
> 
> ********************* Infos for port 0  *********************
> MAC address: 14:23:F2:C3:BA:D2
> Device name: 0000:b1:00.0
> Driver name: net_bnxt
> Firmware-version: 228.9.115.0
> Connect to socket: 2
> memory allocation on the socket: 2
> Link status: up
> Link speed: 200 Gbps
> Active Lanes: 4
> Link duplex: full-duplex
> Autoneg status: Off
> 
> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> ---
> v2->v3 Consolidating the testpmd and rtelib patches into a single patch
> as requested.
> v3->v4 Addressed comments and fix help string and documentation.
> 
>  app/test-pmd/cmdline.c     | 230 +++++++++++++++++++++++++++++++++++++
>  app/test-pmd/config.c      |  69 ++++++++++-
>  app/test-pmd/testpmd.h     |   4 +
>  lib/ethdev/ethdev_driver.h |  77 +++++++++++++
>  lib/ethdev/rte_ethdev.c    |  51 ++++++++
>  lib/ethdev/rte_ethdev.h    |  92 +++++++++++++++
>  lib/ethdev/version.map     |   5 +
>  7 files changed, 526 insertions(+), 2 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index b7759e38a8..a507df31d8 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>  
>  			"dump_log_types\n"
>  			"    Dumps the log level for all the dpdk modules\n\n"
> +
> +			"show port (port_id) speed_lanes capabilities"
> +			"	Show speed lanes capabilities of a port.\n\n"
>  		);
>  	}
>  
> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>  			"port config (port_id) txq (queue_id) affinity (value)\n"
>  			"    Map a Tx queue with an aggregated port "
>  			"of the DPDK port\n\n"
> +
> +			"port config (port_id|all) speed_lanes (0|1|4|8)\n"
> +			"    Set number of lanes for all ports or port_id for a forced speed\n\n"
>  		);
>  	}
>  
> @@ -1560,6 +1566,110 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
>  	},
>  };
>  
> +static int
> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
> +{
> +	int ret;
> +	uint32_t lanes_capa;
> +
> +	ret = parse_speed_lanes(lanes, &lanes_capa);
> +	if (ret < 0) {
> +		fprintf(stderr, "Unknown speed lane value: %d for port %d\n", lanes, pid);
> +		return -1;
> +	}
> +
> +	ret = rte_eth_speed_lanes_set(pid, lanes_capa);
> +	if (ret == -ENOTSUP) {
> +		fprintf(stderr, "Function not implemented\n");
> +		return -1;
> +	} else if (ret < 0) {
> +		fprintf(stderr, "Set speed lanes failed\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +/* *** display speed lanes per port capabilities *** */
> +struct cmd_show_speed_lanes_result {
> +	cmdline_fixed_string_t cmd_show;
> +	cmdline_fixed_string_t cmd_port;
> +	cmdline_fixed_string_t cmd_keyword;
> +	portid_t cmd_pid;
> +};
> +
> +static void
> +cmd_show_speed_lanes_parsed(void *parsed_result,
> +			    __rte_unused struct cmdline *cl,
> +			    __rte_unused void *data)
> +{
> +	struct cmd_show_speed_lanes_result *res = parsed_result;
> +	struct rte_eth_speed_lanes_capa *speed_lanes_capa;
> +	unsigned int num;
> +	int ret;
> +
> +	if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> +		fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
> +		return;
> +	}
> +
> +	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
> +	if (ret == -ENOTSUP) {
> +		fprintf(stderr, "Function not implemented\n");
> +		return;
> +	} else if (ret < 0) {
> +		fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
> +		return;
> +	}
> +
> +	num = (unsigned int)ret;
> +	speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
> +	if (speed_lanes_capa == NULL) {
> +		fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
> +		return;
> +	}
> +
> +	ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
> +	if (ret < 0) {
> +		fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
> +		goto out;
> +	}
> +
> +	show_speed_lanes_capability(num, speed_lanes_capa);
> +out:
> +	free(speed_lanes_capa);
> +}
> +
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_show, "show");
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_port, "port");
> +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
> +	TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
> +			      cmd_pid, RTE_UINT16);
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_keyword, "speed_lanes");
> +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> +				 cmd_keyword, "capabilities");
> +
> +static cmdline_parse_inst_t cmd_show_speed_lanes = {
> +	.f = cmd_show_speed_lanes_parsed,
> +	.data = NULL,
> +	.help_str = "show port <port_id> speed_lanes capabilities",
> +	.tokens = {
> +		(void *)&cmd_show_speed_lanes_show,
> +		(void *)&cmd_show_speed_lanes_port,
> +		(void *)&cmd_show_speed_lanes_pid,
> +		(void *)&cmd_show_speed_lanes_keyword,
> +		(void *)&cmd_show_speed_lanes_cap_keyword,
> +		NULL,
> +	},
> +};
> +
>  /* *** configure loopback for all ports *** */
>  struct cmd_config_loopback_all {
>  	cmdline_fixed_string_t port;
> @@ -1676,6 +1786,123 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
>  	},
>  };
>  
> +/* *** configure speed_lanes for all ports *** */
> +struct cmd_config_speed_lanes_all {
> +	cmdline_fixed_string_t port;
> +	cmdline_fixed_string_t keyword;
> +	cmdline_fixed_string_t all;
> +	cmdline_fixed_string_t item;
> +	uint32_t lanes;
> +};
> +
> +static void
> +cmd_config_speed_lanes_all_parsed(void *parsed_result,
> +				  __rte_unused struct cmdline *cl,
> +				  __rte_unused void *data)
> +{
> +	struct cmd_config_speed_lanes_all *res = parsed_result;
> +	portid_t pid;
> +
> +	if (!all_ports_stopped()) {
> +		fprintf(stderr, "Please stop all ports first\n");
> +		return;
> +	}
> +
> +	RTE_ETH_FOREACH_DEV(pid) {
> +		if (parse_speed_lanes_cfg(pid, res->lanes))
> +			return;
> +	}
> +
> +	cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
> +}
> +
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
> +				 "config");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
> +				 "speed_lanes");
> +static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
> +	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
> +
> +static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
> +	.f = cmd_config_speed_lanes_all_parsed,
> +	.data = NULL,
> +	.help_str = "port config all speed_lanes <value>",
> +	.tokens = {
> +		(void *)&cmd_config_speed_lanes_all_port,
> +		(void *)&cmd_config_speed_lanes_all_keyword,
> +		(void *)&cmd_config_speed_lanes_all_all,
> +		(void *)&cmd_config_speed_lanes_all_item,
> +		(void *)&cmd_config_speed_lanes_all_lanes,
> +		NULL,
> +	},
> +};
> +
> +/* *** configure speed_lanes for specific port *** */
> +struct cmd_config_speed_lanes_specific {
> +	cmdline_fixed_string_t port;
> +	cmdline_fixed_string_t keyword;
> +	uint16_t port_id;
> +	cmdline_fixed_string_t item;
> +	uint32_t lanes;
> +};
> +
> +static void
> +cmd_config_speed_lanes_specific_parsed(void *parsed_result,
> +				       __rte_unused struct cmdline *cl,
> +				       __rte_unused void *data)
> +{
> +	struct cmd_config_speed_lanes_specific *res = parsed_result;
> +
> +	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> +		return;
> +
> +	if (!port_is_stopped(res->port_id)) {
> +		fprintf(stderr, "Please stop port %u first\n", res->port_id);
> +		return;
> +	}
>

There is a requirement here, that port needs to be stopped before
calling the rte_eth_speed_lanes_set(),
is this requirement documented in the API documentation?


> +
> +	if (parse_speed_lanes_cfg(res->port_id, res->lanes))
> +		return;
> +
> +	cmd_reconfig_device_queue(res->port_id, 1, 1);
> +}
> +
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
> +				 "port");
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
> +				 "config");
> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
> +	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
> +			      RTE_UINT16);
> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
> +	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
> +				 "speed_lanes");
> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
> +	TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
> +			      RTE_UINT32);
> +
> +static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
> +	.f = cmd_config_speed_lanes_specific_parsed,
> +	.data = NULL,
> +	.help_str = "port config <port_id> speed_lanes <value>",
> +	.tokens = {
> +		(void *)&cmd_config_speed_lanes_specific_port,
> +		(void *)&cmd_config_speed_lanes_specific_keyword,
> +		(void *)&cmd_config_speed_lanes_specific_id,
> +		(void *)&cmd_config_speed_lanes_specific_item,
> +		(void *)&cmd_config_speed_lanes_specific_lanes,
> +		NULL,
> +	},
> +};
> +
>  /* *** configure txq/rxq, txd/rxd *** */
>  struct cmd_config_rx_tx {
>  	cmdline_fixed_string_t port;
> @@ -13238,6 +13465,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>  	(cmdline_parse_inst_t *)&cmd_set_port_setup_on,
>  	(cmdline_parse_inst_t *)&cmd_config_speed_all,
>  	(cmdline_parse_inst_t *)&cmd_config_speed_specific,
> +	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> +	(cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> +	(cmdline_parse_inst_t *)&cmd_show_speed_lanes,
>  	(cmdline_parse_inst_t *)&cmd_config_loopback_all,
>  	(cmdline_parse_inst_t *)&cmd_config_loopback_specific,
>  	(cmdline_parse_inst_t *)&cmd_config_rx_tx,
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 66c3a68c1d..498a7db467 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -207,6 +207,32 @@ static const struct {
>  	{"gtpu", RTE_ETH_FLOW_GTPU},
>  };
>  
> +static const struct {
> +	enum rte_eth_speed_lanes lane;
> +	const uint32_t value;
> +} speed_lane_name[] = {
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_UNKNOWN,
> +		.value = 0,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_1,
> +		.value = 1,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_2,
> +		.value = 2,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_4,
> +		.value = 4,
> +	},
> +	{
> +		.lane = RTE_ETH_SPEED_LANE_8,
> +		.value = 8,
> +	},
> +};
> +
>  static void
>  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
>  {
> @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
>  	char name[RTE_ETH_NAME_MAX_LEN];
>  	int ret;
>  	char fw_version[ETHDEV_FWVERS_LEN];
> +	uint32_t lanes;
>  
>  	if (port_id_is_invalid(port_id, ENABLED_WARN)) {
>  		print_valid_ports();
> @@ -828,6 +855,12 @@ port_infos_display(portid_t port_id)
>  
>  	printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
>  	printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
> +	if (rte_eth_speed_lanes_get(port_id, &lanes) == 0) {
> +		if (lanes > 0)
> +			printf("Active Lanes: %d\n", lanes);
> +		else
> +			printf("Active Lanes: %s\n", "Unknown");
>

What can be the 'else' case?
As 'lanes' is unsigned, only option is it being zero. Is API allowed to
return zero as lane number?


> +	}
>  	printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
>  	       ("full-duplex") : ("half-duplex"));
>  	printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
> @@ -962,7 +995,7 @@ port_summary_header_display(void)
>  
>  	port_number = rte_eth_dev_count_avail();
>  	printf("Number of available ports: %i\n", port_number);
> -	printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
> +	printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
>  			"Driver", "Status", "Link");
>  }
>  
> @@ -993,7 +1026,7 @@ port_summary_display(portid_t port_id)
>  	if (ret != 0)
>  		return;
>  
> -	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> +	printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
>

Summary updates are irrelevant in the patch, can you please drop them.


>  		port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
>  		dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
>  		rte_eth_link_speed_to_str(link.link_speed));
> @@ -7244,3 +7277,35 @@ show_mcast_macs(portid_t port_id)
>  		printf("  %s\n", buf);
>  	}
>  }
> +
> +int
> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
> +{
> +	uint8_t i;
> +
> +	for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
> +		if (speed_lane_name[i].value == lane) {
> +			*speed_lane = lane;
>

This converts from 8 -> 8, 4 -> 4 ....

Why not completely eliminate this fucntion? See below.

> +			return 0;
> +		}
> +	}
> +	return -1;
> +}
> +
> +void
> +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
> +{
> +	unsigned int i, j;
> +
> +	printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
> +	printf("\n-----------------------------------\n");
> +	for (i = 0; i < num; i++) {
> +		printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
> +
> +		for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
> +			if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
> +				printf("%-2d ", speed_lane_name[j].value);
> +		}

To eliminate both RTE_ETH_SPEED_LANE_MAX & speed_lane_name, what do you
think about:

capa = speed_lanes_capa[i].capa;
int s = 0;
while (capa) {
    if (capa & 0x1)
        printf("%-2d ", 1 << s);
    s++;
    capa = capa >> 1;
}

> +		printf("\n");
> +	}
> +}
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index 9facd7f281..fb9ef05cc5 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -1253,6 +1253,10 @@ extern int flow_parse(const char *src, void *result, unsigned int size,
>  		      struct rte_flow_item **pattern,
>  		      struct rte_flow_action **actions);
>  
> +void show_speed_lanes_capability(uint32_t num,
> +				 struct rte_eth_speed_lanes_capa *speed_lanes_capa);
> +int parse_speed_lanes(uint32_t lane, uint32_t *speed_lane);
> +
>

These functions only called in 'test-pmd/cmdline.c', what do you think
move functions to that file and make them static?


>  uint64_t str_to_rsstypes(const char *str);
>  const char *rsstypes_to_str(uint64_t rss_type);
>  
> diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> index 883e59a927..0f10aec3a1 100644
> --- a/lib/ethdev/ethdev_driver.h
> +++ b/lib/ethdev/ethdev_driver.h
> @@ -1179,6 +1179,79 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
>  					uint16_t queue_id, uint16_t offset,
>  					uint16_t num, FILE *file);
>  
> +/**
> + * @internal
> + * Get number of current active lanes
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes
> + *   Number of active lanes that the link is trained up.
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, get speed_lanes data success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
>

Is above '-ENOTSUP' & '-EIO' return values are valid?
Normally we expect those two from ethdev API, not from dev_ops.
In which case a dev_ops expected to return these?

Same comment for all three new APIs.


> + */
> +typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
> +
> +/**
> + * @internal
> + * Set speed lanes
> + *
> + * @param dev
> + *   ethdev handle of port.
> + * @param speed_lanes
> + *   Non-negative number of lanes
> + *
> + * @return
> + *   Negative errno value on error, 0 on success.
> + *
> + * @retval 0
> + *   Success, set lanes success.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EINVAL
> + *   Unsupported mode requested.
> + * @retval -EIO
> + *   Device is removed.
> + */
> +typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
> +
> +/**
> + * @internal
> + * Get supported link speed lanes capability
> + *
> + * @param speed_lanes_capa
> + *   speed_lanes_capa is out only with per-speed capabilities.
>

I can understand what above says but I think it can be clarified more,
what do you think?

> + * @param num
> + *   a number of elements in an speed_speed_lanes_capa array.
>

'a number of elements' or 'number of elements' ?

> + *
> + * @return
> + *   Negative errno value on error, positive value on success.
> + *
> + * @retval positive value
> + *   A non-negative value lower or equal to num: success. The return value
> + *   is the number of entries filled in the speed lanes array.
> + *   A non-negative value higher than num: error, the given speed lanes capa array
> + *   is too small. The return value corresponds to the num that should
> + *   be given to succeed. The entries in the speed lanes capa array are not valid
> + *   and shall not be used by the caller.
> + * @retval -ENOTSUP
> + *   Operation is not supported.
> + * @retval -EIO
> + *   Device is removed.
> + * @retval -EINVAL
> + *   *num* or *speed_lanes_capa* invalid.
> + */
> +typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
> +						struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> +						unsigned int num);
> +
>

These new dev_ops placed just in between existing dev_ops
'eth_rx_descriptor_dump_t' and 'eth_tx_descriptor_dump_t',
if you were looking this header file as whole, what would you think
about quality of it?

Please group new dev_ops below link related ones.


>  /**
>   * @internal
>   * Dump Tx descriptor info to a file.
> @@ -1247,6 +1320,10 @@ struct eth_dev_ops {
>  	eth_dev_close_t            dev_close;     /**< Close device */
>  	eth_dev_reset_t		   dev_reset;	  /**< Reset device */
>  	eth_link_update_t          link_update;   /**< Get device link state */
> +	eth_speed_lanes_get_t	   speed_lanes_get;	  /**<Get link speed active lanes */
> +	eth_speed_lanes_set_t      speed_lanes_set;	  /**<set the link speeds supported lanes */
> +	/** Get link speed lanes capability */
> +	eth_speed_lanes_get_capability_t speed_lanes_get_capa;
>  	/** Check if the device was physically removed */
>  	eth_is_removed_t           is_removed;
>  
> diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> index f1c658f49e..07cefea307 100644
> --- a/lib/ethdev/rte_ethdev.c
> +++ b/lib/ethdev/rte_ethdev.c
> @@ -7008,4 +7008,55 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
>  	return ret;
>  }
>  
> +int
> +rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->speed_lanes_get == NULL)
> +		return -ENOTSUP;
> +	return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
> +}
> +
> +int
> +rte_eth_speed_lanes_get_capability(uint16_t port_id,
> +				   struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> +				   unsigned int num)
> +{
> +	struct rte_eth_dev *dev;
> +	int ret;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (speed_lanes_capa == NULL && num > 0) {
> +		RTE_ETHDEV_LOG_LINE(ERR,
> +				    "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
> +				    port_id);
> +		return -EINVAL;
> +	}
>

According above check, "speed_lanes_capa == NULL && num == 0" is a valid
input, I assume this is useful to get expected size of the
'speed_lanes_capa' array, but this is not mentioned in the API
documentation, can you please update API doxygen comment to cover this case.


> +
> +	if (*dev->dev_ops->speed_lanes_get_capa == NULL)
> +		return -ENOTSUP;
>

About the order or the checks, should we first check if the dev_ops
exist than validating the input arguments?
If dev_ops is not available, input variables doesn't matter anyway.

> +	ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
> +
> +	return ret;
>

API returns -EIO only if it is returned with 'eth_err()', that is to
cover the hot remove case. It is missing in this function.


> +}
> +
> +int
> +rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> +{
> +	struct rte_eth_dev *dev;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +	dev = &rte_eth_devices[port_id];
> +
> +	if (*dev->dev_ops->speed_lanes_set == NULL)
> +		return -ENOTSUP;
> +	return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
> +}
>

Simiar location comment with the header one, instead of adding new APIs
to the very bottom of the file, can you please group them just below the
link related APIs?

> +
>  RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
> diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> index 548fada1c7..35d0b81452 100644
> --- a/lib/ethdev/rte_ethdev.h
> +++ b/lib/ethdev/rte_ethdev.h
> @@ -357,6 +357,30 @@ struct rte_eth_link {
>  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
>  /**@}*/
>  
> +/**
> + * This enum indicates the possible link speed lanes of an ethdev port.
> + */
> +enum rte_eth_speed_lanes {
> +	RTE_ETH_SPEED_LANE_UNKNOWN = 0,  /**< speed lanes unsupported mode or default */
> +	RTE_ETH_SPEED_LANE_1 = 1,        /**< Link speed lane  1 */
> +	RTE_ETH_SPEED_LANE_2 = 2,        /**< Link speed lanes 2 */
> +	RTE_ETH_SPEED_LANE_4 = 4,        /**< Link speed lanes 4 */
> +	RTE_ETH_SPEED_LANE_8 = 8,        /**< Link speed lanes 8 */
>

Do we really need enum for the lane number? Why not use it as just number?
As far as I can see APIs get "uint32 lanes" parameter anyway.


> +	RTE_ETH_SPEED_LANE_MAX,
>

This kind of MAX enum usage is causing trouble when we want to extend
the support in the future.
Like when 16 lane is required, adding it changes the value of MAX and as
this is a public structure, change is causing ABI break, making us wait
until next ABI break realease.
So better if we can prevent MAX enum usage.

> +};
> +
> +/* Translate from link speed lanes to speed lanes capa */
> +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> +
> +/* This macro indicates link speed lanes capa mask */
> +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
>

Why is above macro needed?


> +
> +/* A structure used to get and set lanes capabilities per link speed */
> +struct rte_eth_speed_lanes_capa {
> +	uint32_t speed;
> +	uint32_t capa;
> +};
> +
>  /**
>   * A structure used to configure the ring threshold registers of an Rx/Tx
>   * queue for an Ethernet port.
> @@ -6922,6 +6946,74 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
>  	return rc;
>  }
>  
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get Active lanes.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param lanes
> + *   driver populates a active lanes value whether link is Autonegotiated or Fixed speed.
>

As these doxygen comments are API docummentation, can you please form
them as proper sentences, like start with uppercase, end with '.', etc...
Same comment for all APIs.

> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Set speed lanes supported by the NIC.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes
> + *   speed_lanes a non-zero value of number lanes for this speeds.
>

'this speeds' ?


> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> + *
> + * Get speed lanes supported by the NIC.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param speed_lanes_capa
> + *   speed_lanes_capa int array with valid lanes per speed.
> + * @param num
> + *   size of the speed_lanes_capa array.
> + *
> + * @return
> + *   - (0) if successful.
> + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> + *     that operation.
> + *   - (-EIO) if device is removed.
> + *   - (-ENODEV)  if *port_id* invalid.
> + *   - (-EINVAL)  if *speed_lanes* invalid
> + */
> +__rte_experimental
> +int rte_eth_speed_lanes_get_capability(uint16_t port_id,
> +				       struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> +				       unsigned int num);
> +
>

The bottom of the header file is for static inline functions.
Instead of adding these new APIs at the very bottom of the header, can
you please group them just below the link speed related APIs?


>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> index 79f6f5293b..db9261946f 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -325,6 +325,11 @@ EXPERIMENTAL {
>  	rte_flow_template_table_resizable;
>  	rte_flow_template_table_resize;
>  	rte_flow_template_table_resize_complete;
> +
> +	# added in 24.07
> +	rte_eth_speed_lanes_get;
> +	rte_eth_speed_lanes_get_capability;
> +	rte_eth_speed_lanes_set;
>  };
>  
>  INTERNAL {


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v4] ethdev: Add link_speed lanes support
  2024-07-09 11:10                           ` Ferruh Yigit
@ 2024-07-09 21:20                             ` Damodharam Ammepalli
  2024-07-10  9:05                               ` Ferruh Yigit
  0 siblings, 1 reply; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-07-09 21:20 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: ajit.khaparde, dev, huangdengdui, kalesh-anakkur.purayil

On Tue, Jul 9, 2024 at 4:10 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 7/9/2024 12:22 AM, Damodharam Ammepalli wrote:
> > Update the eth_dev_ops structure with new function vectors
> > to get, get capabilities and set ethernet link speed lanes.
> > Update the testpmd to provide required config and information
> > display infrastructure.
> >
> > The supporting ethernet controller driver will register callbacks
> > to avail link speed lanes config and get services. This lanes
> > configuration is applicable only when the nic is forced to fixed
> > speeds. In Autonegiation mode, the hardware automatically
> > negotiates the number of lanes.
> >
> > These are the new commands.
> >
> > testpmd> show port 0 speed_lanes capabilities
> >
> >  Supported speeds         Valid lanes
> > -----------------------------------
> >  10 Gbps                  1
> >  25 Gbps                  1
> >  40 Gbps                  4
> >  50 Gbps                  1 2
> >  100 Gbps                 1 2 4
> >  200 Gbps                 2 4
> >  400 Gbps                 4 8
> > testpmd>
> >
> > testpmd>
> > testpmd> port stop 0
> > testpmd> port config 0 speed_lanes 4
> > testpmd> port config 0 speed 200000 duplex full
> >
>
> Is there a requirement to set speed before speed_lane?
> Because I expect driver will verify if a speed_lane value is valid or
> not for a specific speed value. In above usage, driver will verify based
> on existing speed, whatever it is, later chaning speed may cause invalid
> speed_lane configuration.
>
>
There is no requirement to set  speed before speed_lane.
If the controller supports lanes configuration capability, if no lanes
are given (which is 0)
the driver will pick up the lowest speed (eg: 200 gbps with NRZ mode),
if a fixed speed
already exists or is configured in tandem with speed_lanes. If speed
is already Auto,
test-pmd's speed_lane config is ignored.

> > testpmd> port start 0
> > testpmd>
> > testpmd> show port info 0
> >
> > ********************* Infos for port 0  *********************
> > MAC address: 14:23:F2:C3:BA:D2
> > Device name: 0000:b1:00.0
> > Driver name: net_bnxt
> > Firmware-version: 228.9.115.0
> > Connect to socket: 2
> > memory allocation on the socket: 2
> > Link status: up
> > Link speed: 200 Gbps
> > Active Lanes: 4
> > Link duplex: full-duplex
> > Autoneg status: Off
> >
> > Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> > ---
> > v2->v3 Consolidating the testpmd and rtelib patches into a single patch
> > as requested.
> > v3->v4 Addressed comments and fix help string and documentation.
> >
> >  app/test-pmd/cmdline.c     | 230 +++++++++++++++++++++++++++++++++++++
> >  app/test-pmd/config.c      |  69 ++++++++++-
> >  app/test-pmd/testpmd.h     |   4 +
> >  lib/ethdev/ethdev_driver.h |  77 +++++++++++++
> >  lib/ethdev/rte_ethdev.c    |  51 ++++++++
> >  lib/ethdev/rte_ethdev.h    |  92 +++++++++++++++
> >  lib/ethdev/version.map     |   5 +
> >  7 files changed, 526 insertions(+), 2 deletions(-)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> > index b7759e38a8..a507df31d8 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> >
> >                       "dump_log_types\n"
> >                       "    Dumps the log level for all the dpdk modules\n\n"
> > +
> > +                     "show port (port_id) speed_lanes capabilities"
> > +                     "       Show speed lanes capabilities of a port.\n\n"
> >               );
> >       }
> >
> > @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> >                       "port config (port_id) txq (queue_id) affinity (value)\n"
> >                       "    Map a Tx queue with an aggregated port "
> >                       "of the DPDK port\n\n"
> > +
> > +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
> > +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
> >               );
> >       }
> >
> > @@ -1560,6 +1566,110 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
> >       },
> >  };
> >
> > +static int
> > +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
> > +{
> > +     int ret;
> > +     uint32_t lanes_capa;
> > +
> > +     ret = parse_speed_lanes(lanes, &lanes_capa);
> > +     if (ret < 0) {
> > +             fprintf(stderr, "Unknown speed lane value: %d for port %d\n", lanes, pid);
> > +             return -1;
> > +     }
> > +
> > +     ret = rte_eth_speed_lanes_set(pid, lanes_capa);
> > +     if (ret == -ENOTSUP) {
> > +             fprintf(stderr, "Function not implemented\n");
> > +             return -1;
> > +     } else if (ret < 0) {
> > +             fprintf(stderr, "Set speed lanes failed\n");
> > +             return -1;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +/* *** display speed lanes per port capabilities *** */
> > +struct cmd_show_speed_lanes_result {
> > +     cmdline_fixed_string_t cmd_show;
> > +     cmdline_fixed_string_t cmd_port;
> > +     cmdline_fixed_string_t cmd_keyword;
> > +     portid_t cmd_pid;
> > +};
> > +
> > +static void
> > +cmd_show_speed_lanes_parsed(void *parsed_result,
> > +                         __rte_unused struct cmdline *cl,
> > +                         __rte_unused void *data)
> > +{
> > +     struct cmd_show_speed_lanes_result *res = parsed_result;
> > +     struct rte_eth_speed_lanes_capa *speed_lanes_capa;
> > +     unsigned int num;
> > +     int ret;
> > +
> > +     if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> > +             fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
> > +             return;
> > +     }
> > +
> > +     ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
> > +     if (ret == -ENOTSUP) {
> > +             fprintf(stderr, "Function not implemented\n");
> > +             return;
> > +     } else if (ret < 0) {
> > +             fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
> > +             return;
> > +     }
> > +
> > +     num = (unsigned int)ret;
> > +     speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
> > +     if (speed_lanes_capa == NULL) {
> > +             fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
> > +             return;
> > +     }
> > +
> > +     ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
> > +     if (ret < 0) {
> > +             fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
> > +             goto out;
> > +     }
> > +
> > +     show_speed_lanes_capability(num, speed_lanes_capa);
> > +out:
> > +     free(speed_lanes_capa);
> > +}
> > +
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_show, "show");
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_port, "port");
> > +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
> > +     TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                           cmd_pid, RTE_UINT16);
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_keyword, "speed_lanes");
> > +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> > +                              cmd_keyword, "capabilities");
> > +
> > +static cmdline_parse_inst_t cmd_show_speed_lanes = {
> > +     .f = cmd_show_speed_lanes_parsed,
> > +     .data = NULL,
> > +     .help_str = "show port <port_id> speed_lanes capabilities",
> > +     .tokens = {
> > +             (void *)&cmd_show_speed_lanes_show,
> > +             (void *)&cmd_show_speed_lanes_port,
> > +             (void *)&cmd_show_speed_lanes_pid,
> > +             (void *)&cmd_show_speed_lanes_keyword,
> > +             (void *)&cmd_show_speed_lanes_cap_keyword,
> > +             NULL,
> > +     },
> > +};
> > +
> >  /* *** configure loopback for all ports *** */
> >  struct cmd_config_loopback_all {
> >       cmdline_fixed_string_t port;
> > @@ -1676,6 +1786,123 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
> >       },
> >  };
> >
> > +/* *** configure speed_lanes for all ports *** */
> > +struct cmd_config_speed_lanes_all {
> > +     cmdline_fixed_string_t port;
> > +     cmdline_fixed_string_t keyword;
> > +     cmdline_fixed_string_t all;
> > +     cmdline_fixed_string_t item;
> > +     uint32_t lanes;
> > +};
> > +
> > +static void
> > +cmd_config_speed_lanes_all_parsed(void *parsed_result,
> > +                               __rte_unused struct cmdline *cl,
> > +                               __rte_unused void *data)
> > +{
> > +     struct cmd_config_speed_lanes_all *res = parsed_result;
> > +     portid_t pid;
> > +
> > +     if (!all_ports_stopped()) {
> > +             fprintf(stderr, "Please stop all ports first\n");
> > +             return;
> > +     }
> > +
> > +     RTE_ETH_FOREACH_DEV(pid) {
> > +             if (parse_speed_lanes_cfg(pid, res->lanes))
> > +                     return;
> > +     }
> > +
> > +     cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
> > +}
> > +
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
> > +                              "config");
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
> > +                              "speed_lanes");
> > +static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
> > +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
> > +
> > +static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
> > +     .f = cmd_config_speed_lanes_all_parsed,
> > +     .data = NULL,
> > +     .help_str = "port config all speed_lanes <value>",
> > +     .tokens = {
> > +             (void *)&cmd_config_speed_lanes_all_port,
> > +             (void *)&cmd_config_speed_lanes_all_keyword,
> > +             (void *)&cmd_config_speed_lanes_all_all,
> > +             (void *)&cmd_config_speed_lanes_all_item,
> > +             (void *)&cmd_config_speed_lanes_all_lanes,
> > +             NULL,
> > +     },
> > +};
> > +
> > +/* *** configure speed_lanes for specific port *** */
> > +struct cmd_config_speed_lanes_specific {
> > +     cmdline_fixed_string_t port;
> > +     cmdline_fixed_string_t keyword;
> > +     uint16_t port_id;
> > +     cmdline_fixed_string_t item;
> > +     uint32_t lanes;
> > +};
> > +
> > +static void
> > +cmd_config_speed_lanes_specific_parsed(void *parsed_result,
> > +                                    __rte_unused struct cmdline *cl,
> > +                                    __rte_unused void *data)
> > +{
> > +     struct cmd_config_speed_lanes_specific *res = parsed_result;
> > +
> > +     if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> > +             return;
> > +
> > +     if (!port_is_stopped(res->port_id)) {
> > +             fprintf(stderr, "Please stop port %u first\n", res->port_id);
> > +             return;
> > +     }
> >
>
> There is a requirement here, that port needs to be stopped before
> calling the rte_eth_speed_lanes_set(),
> is this requirement documented in the API documentation?
>
>
Speed link mode needs a phy reset, hence port stop is a requirement.
I will update this in the documentation in the next patch.

> > +
> > +     if (parse_speed_lanes_cfg(res->port_id, res->lanes))
> > +             return;
> > +
> > +     cmd_reconfig_device_queue(res->port_id, 1, 1);
> > +}
> > +
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
> > +                              "port");
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
> > +                              "config");
> > +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
> > +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
> > +                           RTE_UINT16);
> > +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
> > +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
> > +                              "speed_lanes");
> > +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
> > +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
> > +                           RTE_UINT32);
> > +
> > +static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
> > +     .f = cmd_config_speed_lanes_specific_parsed,
> > +     .data = NULL,
> > +     .help_str = "port config <port_id> speed_lanes <value>",
> > +     .tokens = {
> > +             (void *)&cmd_config_speed_lanes_specific_port,
> > +             (void *)&cmd_config_speed_lanes_specific_keyword,
> > +             (void *)&cmd_config_speed_lanes_specific_id,
> > +             (void *)&cmd_config_speed_lanes_specific_item,
> > +             (void *)&cmd_config_speed_lanes_specific_lanes,
> > +             NULL,
> > +     },
> > +};
> > +
> >  /* *** configure txq/rxq, txd/rxd *** */
> >  struct cmd_config_rx_tx {
> >       cmdline_fixed_string_t port;
> > @@ -13238,6 +13465,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
> >       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
> >       (cmdline_parse_inst_t *)&cmd_config_speed_all,
> >       (cmdline_parse_inst_t *)&cmd_config_speed_specific,
> > +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> > +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> > +     (cmdline_parse_inst_t *)&cmd_show_speed_lanes,
> >       (cmdline_parse_inst_t *)&cmd_config_loopback_all,
> >       (cmdline_parse_inst_t *)&cmd_config_loopback_specific,
> >       (cmdline_parse_inst_t *)&cmd_config_rx_tx,
> > diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> > index 66c3a68c1d..498a7db467 100644
> > --- a/app/test-pmd/config.c
> > +++ b/app/test-pmd/config.c
> > @@ -207,6 +207,32 @@ static const struct {
> >       {"gtpu", RTE_ETH_FLOW_GTPU},
> >  };
> >
> > +static const struct {
> > +     enum rte_eth_speed_lanes lane;
> > +     const uint32_t value;
> > +} speed_lane_name[] = {
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_UNKNOWN,
> > +             .value = 0,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_1,
> > +             .value = 1,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_2,
> > +             .value = 2,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_4,
> > +             .value = 4,
> > +     },
> > +     {
> > +             .lane = RTE_ETH_SPEED_LANE_8,
> > +             .value = 8,
> > +     },
> > +};
> > +
> >  static void
> >  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
> >  {
> > @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
> >       char name[RTE_ETH_NAME_MAX_LEN];
> >       int ret;
> >       char fw_version[ETHDEV_FWVERS_LEN];
> > +     uint32_t lanes;
> >
> >       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
> >               print_valid_ports();
> > @@ -828,6 +855,12 @@ port_infos_display(portid_t port_id)
> >
> >       printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
> >       printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
> > +     if (rte_eth_speed_lanes_get(port_id, &lanes) == 0) {
> > +             if (lanes > 0)
> > +                     printf("Active Lanes: %d\n", lanes);
> > +             else
> > +                     printf("Active Lanes: %s\n", "Unknown");
> >
>
> What can be the 'else' case?
> As 'lanes' is unsigned, only option is it being zero. Is API allowed to
> return zero as lane number?
>
>
Yes. link is down, but controller supports speed_lanes capability,
then we can show "unknown"
Other cases from brcm spec.
1gb 1Gb link speed < no lane info > (theoretically it can't be zero,
but we need to show what controller provides in the query).
10Gb (NRZ: 10G per lane, 1 lane) link speed

> > +     }
> >       printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
> >              ("full-duplex") : ("half-duplex"));
> >       printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
> > @@ -962,7 +995,7 @@ port_summary_header_display(void)
> >
> >       port_number = rte_eth_dev_count_avail();
> >       printf("Number of available ports: %i\n", port_number);
> > -     printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
> > +     printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
> >                       "Driver", "Status", "Link");
> >  }
> >
> > @@ -993,7 +1026,7 @@ port_summary_display(portid_t port_id)
> >       if (ret != 0)
> >               return;
> >
> > -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> > +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
> >
>
> Summary updates are irrelevant in the patch, can you please drop them.
>
>
Sure I will.

> >               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
> >               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
> >               rte_eth_link_speed_to_str(link.link_speed));
> > @@ -7244,3 +7277,35 @@ show_mcast_macs(portid_t port_id)
> >               printf("  %s\n", buf);
> >       }
> >  }
> > +
> > +int
> > +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
> > +{
> > +     uint8_t i;
> > +
> > +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
> > +             if (speed_lane_name[i].value == lane) {
> > +                     *speed_lane = lane;
> >
>
> This converts from 8 -> 8, 4 -> 4 ....
>
> Why not completely eliminate this fucntion? See below.
>
Sure, will evaluate and do the needful.

> > +                     return 0;
> > +             }
> > +     }
> > +     return -1;
> > +}
> > +
> > +void
> > +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
> > +{
> > +     unsigned int i, j;
> > +
> > +     printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
> > +     printf("\n-----------------------------------\n");
> > +     for (i = 0; i < num; i++) {
> > +             printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
> > +
> > +             for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
> > +                     if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
> > +                             printf("%-2d ", speed_lane_name[j].value);
> > +             }
>
> To eliminate both RTE_ETH_SPEED_LANE_MAX & speed_lane_name, what do you
> think about:
>
> capa = speed_lanes_capa[i].capa;
> int s = 0;
> while (capa) {
>     if (capa & 0x1)
>         printf("%-2d ", 1 << s);
>     s++;
>     capa = capa >> 1;
> }
>
Am new to the DPDK world.
Followed the FEC driver conventions for consistency.
Will update it as you suggested and it makes sense.

> > +             printf("\n");
> > +     }
> > +}
> > diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> > index 9facd7f281..fb9ef05cc5 100644
> > --- a/app/test-pmd/testpmd.h
> > +++ b/app/test-pmd/testpmd.h
> > @@ -1253,6 +1253,10 @@ extern int flow_parse(const char *src, void *result, unsigned int size,
> >                     struct rte_flow_item **pattern,
> >                     struct rte_flow_action **actions);
> >
> > +void show_speed_lanes_capability(uint32_t num,
> > +                              struct rte_eth_speed_lanes_capa *speed_lanes_capa);
> > +int parse_speed_lanes(uint32_t lane, uint32_t *speed_lane);
> > +
> >
>
> These functions only called in 'test-pmd/cmdline.c', what do you think
> move functions to that file and make them static?
>
>
Ack

> >  uint64_t str_to_rsstypes(const char *str);
> >  const char *rsstypes_to_str(uint64_t rss_type);
> >
> > diff --git a/lib/ethdev/ethdev_driver.h b/lib/ethdev/ethdev_driver.h
> > index 883e59a927..0f10aec3a1 100644
> > --- a/lib/ethdev/ethdev_driver.h
> > +++ b/lib/ethdev/ethdev_driver.h
> > @@ -1179,6 +1179,79 @@ typedef int (*eth_rx_descriptor_dump_t)(const struct rte_eth_dev *dev,
> >                                       uint16_t queue_id, uint16_t offset,
> >                                       uint16_t num, FILE *file);
> >
> > +/**
> > + * @internal
> > + * Get number of current active lanes
> > + *
> > + * @param dev
> > + *   ethdev handle of port.
> > + * @param speed_lanes
> > + *   Number of active lanes that the link is trained up.
> > + * @return
> > + *   Negative errno value on error, 0 on success.
> > + *
> > + * @retval 0
> > + *   Success, get speed_lanes data success.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EIO
> > + *   Device is removed.
> >
>
> Is above '-ENOTSUP' & '-EIO' return values are valid?
> Normally we expect those two from ethdev API, not from dev_ops.
> In which case a dev_ops expected to return these?
>
> Same comment for all three new APIs.
>
>
code snippet from our driver
.speed_lanes_get = bnxt_speed_lanes_get,
The ethdev dev_ops returns -ENOTSUP if capability is not supported. Is this ok?
static int bnxt_speed_lanes_get(struct rte_eth_dev *dev,
                                 uint32_t *speed_lanes)
{
        struct bnxt *bp = dev->data->dev_private;

        if (!BNXT_LINK_SPEEDS_V2(bp))
                return -ENOTSUP;

-EIO - will remove
I will check and update other functions also.

> > + */
> > +typedef int (*eth_speed_lanes_get_t)(struct rte_eth_dev *dev, uint32_t *speed_lanes);
> > +
> > +/**
> > + * @internal
> > + * Set speed lanes
> > + *
> > + * @param dev
> > + *   ethdev handle of port.
> > + * @param speed_lanes
> > + *   Non-negative number of lanes
> > + *
> > + * @return
> > + *   Negative errno value on error, 0 on success.
> > + *
> > + * @retval 0
> > + *   Success, set lanes success.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EINVAL
> > + *   Unsupported mode requested.
> > + * @retval -EIO
> > + *   Device is removed.
> > + */
> > +typedef int (*eth_speed_lanes_set_t)(struct rte_eth_dev *dev, uint32_t speed_lanes);
> > +
> > +/**
> > + * @internal
> > + * Get supported link speed lanes capability
> > + *
> > + * @param speed_lanes_capa
> > + *   speed_lanes_capa is out only with per-speed capabilities.
> >
>
> I can understand what above says but I think it can be clarified more,
> what do you think?
>
Ack

> > + * @param num
> > + *   a number of elements in an speed_speed_lanes_capa array.
> >
>
> 'a number of elements' or 'number of elements' ?
>
Ack

> > + *
> > + * @return
> > + *   Negative errno value on error, positive value on success.
> > + *
> > + * @retval positive value
> > + *   A non-negative value lower or equal to num: success. The return value
> > + *   is the number of entries filled in the speed lanes array.
> > + *   A non-negative value higher than num: error, the given speed lanes capa array
> > + *   is too small. The return value corresponds to the num that should
> > + *   be given to succeed. The entries in the speed lanes capa array are not valid
> > + *   and shall not be used by the caller.
> > + * @retval -ENOTSUP
> > + *   Operation is not supported.
> > + * @retval -EIO
> > + *   Device is removed.
> > + * @retval -EINVAL
> > + *   *num* or *speed_lanes_capa* invalid.
> > + */
> > +typedef int (*eth_speed_lanes_get_capability_t)(struct rte_eth_dev *dev,
> > +                                             struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> > +                                             unsigned int num);
> > +
> >
>
> These new dev_ops placed just in between existing dev_ops
> 'eth_rx_descriptor_dump_t' and 'eth_tx_descriptor_dump_t',
> if you were looking this header file as whole, what would you think
> about quality of it?
>
> Please group new dev_ops below link related ones.
>
>
Ack

> >  /**
> >   * @internal
> >   * Dump Tx descriptor info to a file.
> > @@ -1247,6 +1320,10 @@ struct eth_dev_ops {
> >       eth_dev_close_t            dev_close;     /**< Close device */
> >       eth_dev_reset_t            dev_reset;     /**< Reset device */
> >       eth_link_update_t          link_update;   /**< Get device link state */
> > +     eth_speed_lanes_get_t      speed_lanes_get;       /**<Get link speed active lanes */
> > +     eth_speed_lanes_set_t      speed_lanes_set;       /**<set the link speeds supported lanes */
> > +     /** Get link speed lanes capability */
> > +     eth_speed_lanes_get_capability_t speed_lanes_get_capa;
> >       /** Check if the device was physically removed */
> >       eth_is_removed_t           is_removed;
> >
> > diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> > index f1c658f49e..07cefea307 100644
> > --- a/lib/ethdev/rte_ethdev.c
> > +++ b/lib/ethdev/rte_ethdev.c
> > @@ -7008,4 +7008,55 @@ int rte_eth_dev_map_aggr_tx_affinity(uint16_t port_id, uint16_t tx_queue_id,
> >       return ret;
> >  }
> >
> > +int
> > +rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lane)
> > +{
> > +     struct rte_eth_dev *dev;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (*dev->dev_ops->speed_lanes_get == NULL)
> > +             return -ENOTSUP;
> > +     return eth_err(port_id, (*dev->dev_ops->speed_lanes_get)(dev, lane));
> > +}
> > +
> > +int
> > +rte_eth_speed_lanes_get_capability(uint16_t port_id,
> > +                                struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> > +                                unsigned int num)
> > +{
> > +     struct rte_eth_dev *dev;
> > +     int ret;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (speed_lanes_capa == NULL && num > 0) {
> > +             RTE_ETHDEV_LOG_LINE(ERR,
> > +                                 "Cannot get ethdev port %u speed lanes capability to NULL when array size is non zero",
> > +                                 port_id);
> > +             return -EINVAL;
> > +     }
> >
>
> According above check, "speed_lanes_capa == NULL && num == 0" is a valid
> input, I assume this is useful to get expected size of the
> 'speed_lanes_capa' array, but this is not mentioned in the API
> documentation, can you please update API doxygen comment to cover this case.
>
>
Ack

> > +
> > +     if (*dev->dev_ops->speed_lanes_get_capa == NULL)
> > +             return -ENOTSUP;
> >
>
> About the order or the checks, should we first check if the dev_ops
> exist than validating the input arguments?
> If dev_ops is not available, input variables doesn't matter anyway.
>
Ack

> > +     ret = (*dev->dev_ops->speed_lanes_get_capa)(dev, speed_lanes_capa, num);
> > +
> > +     return ret;
> >
>
> API returns -EIO only if it is returned with 'eth_err()', that is to
> cover the hot remove case. It is missing in this function.
>
>
Ack

> > +}
> > +
> > +int
> > +rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes_capa)
> > +{
> > +     struct rte_eth_dev *dev;
> > +
> > +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +     dev = &rte_eth_devices[port_id];
> > +
> > +     if (*dev->dev_ops->speed_lanes_set == NULL)
> > +             return -ENOTSUP;
> > +     return eth_err(port_id, (*dev->dev_ops->speed_lanes_set)(dev, speed_lanes_capa));
> > +}
> >
>
> Simiar location comment with the header one, instead of adding new APIs
> to the very bottom of the file, can you please group them just below the
> link related APIs?
>
Ack

> > +
> >  RTE_LOG_REGISTER_DEFAULT(rte_eth_dev_logtype, INFO);
> > diff --git a/lib/ethdev/rte_ethdev.h b/lib/ethdev/rte_ethdev.h
> > index 548fada1c7..35d0b81452 100644
> > --- a/lib/ethdev/rte_ethdev.h
> > +++ b/lib/ethdev/rte_ethdev.h
> > @@ -357,6 +357,30 @@ struct rte_eth_link {
> >  #define RTE_ETH_LINK_MAX_STR_LEN 40 /**< Max length of default link string. */
> >  /**@}*/
> >
> > +/**
> > + * This enum indicates the possible link speed lanes of an ethdev port.
> > + */
> > +enum rte_eth_speed_lanes {
> > +     RTE_ETH_SPEED_LANE_UNKNOWN = 0,  /**< speed lanes unsupported mode or default */
> > +     RTE_ETH_SPEED_LANE_1 = 1,        /**< Link speed lane  1 */
> > +     RTE_ETH_SPEED_LANE_2 = 2,        /**< Link speed lanes 2 */
> > +     RTE_ETH_SPEED_LANE_4 = 4,        /**< Link speed lanes 4 */
> > +     RTE_ETH_SPEED_LANE_8 = 8,        /**< Link speed lanes 8 */
> >
>
> Do we really need enum for the lane number? Why not use it as just number?
> As far as I can see APIs get "uint32 lanes" parameter anyway.
>
>
Ack

> > +     RTE_ETH_SPEED_LANE_MAX,
> >
>
Will take care in the upcoming new patch

> This kind of MAX enum usage is causing trouble when we want to extend
> the support in the future.
> Like when 16 lane is required, adding it changes the value of MAX and as
> this is a public structure, change is causing ABI break, making us wait
> until next ABI break realease.
> So better if we can prevent MAX enum usage.
>
Make sense. Ack

> > +};
> > +
> > +/* Translate from link speed lanes to speed lanes capa */
> > +#define RTE_ETH_SPEED_LANES_TO_CAPA(x) RTE_BIT32(x)
> > +
> > +/* This macro indicates link speed lanes capa mask */
> > +#define RTE_ETH_SPEED_LANES_CAPA_MASK(x) RTE_BIT32(RTE_ETH_SPEED_ ## x)
> >
>
> Why is above macro needed?
>
>
To use in parse_speed_lanes to validate user input. It's not used any
more in new patches. will remove it.

> > +
> > +/* A structure used to get and set lanes capabilities per link speed */
> > +struct rte_eth_speed_lanes_capa {
> > +     uint32_t speed;
> > +     uint32_t capa;
> > +};
> > +
> >  /**
> >   * A structure used to configure the ring threshold registers of an Rx/Tx
> >   * queue for an Ethernet port.
> > @@ -6922,6 +6946,74 @@ rte_eth_tx_queue_count(uint16_t port_id, uint16_t queue_id)
> >       return rc;
> >  }
> >
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get Active lanes.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param lanes
> > + *   driver populates a active lanes value whether link is Autonegotiated or Fixed speed.
> >
>
> As these doxygen comments are API docummentation, can you please form
> them as proper sentences, like start with uppercase, end with '.', etc...
> Same comment for all APIs.
>
Ack

> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_get(uint16_t port_id, uint32_t *lanes);
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Set speed lanes supported by the NIC.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes
> > + *   speed_lanes a non-zero value of number lanes for this speeds.
> >
>
> 'this speeds' ?
>
>
Ack. "number of lanes for current speed"

> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_set(uint16_t port_id, uint32_t speed_lanes);
> > +
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
> > + *
> > + * Get speed lanes supported by the NIC.
> > + *
> > + * @param port_id
> > + *   The port identifier of the Ethernet device.
> > + * @param speed_lanes_capa
> > + *   speed_lanes_capa int array with valid lanes per speed.
> > + * @param num
> > + *   size of the speed_lanes_capa array.
> > + *
> > + * @return
> > + *   - (0) if successful.
> > + *   - (-ENOTSUP) if underlying hardware OR driver doesn't support.
> > + *     that operation.
> > + *   - (-EIO) if device is removed.
> > + *   - (-ENODEV)  if *port_id* invalid.
> > + *   - (-EINVAL)  if *speed_lanes* invalid
> > + */
> > +__rte_experimental
> > +int rte_eth_speed_lanes_get_capability(uint16_t port_id,
> > +                                    struct rte_eth_speed_lanes_capa *speed_lanes_capa,
> > +                                    unsigned int num);
> > +
> >
>
> The bottom of the header file is for static inline functions.
> Instead of adding these new APIs at the very bottom of the header, can
> you please group them just below the link speed related APIs?
>
>
Ack

> >  #ifdef __cplusplus
> >  }
> >  #endif
> > diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> > index 79f6f5293b..db9261946f 100644
> > --- a/lib/ethdev/version.map
> > +++ b/lib/ethdev/version.map
> > @@ -325,6 +325,11 @@ EXPERIMENTAL {
> >       rte_flow_template_table_resizable;
> >       rte_flow_template_table_resize;
> >       rte_flow_template_table_resize_complete;
> > +
> > +     # added in 24.07
> > +     rte_eth_speed_lanes_get;
> > +     rte_eth_speed_lanes_get_capability;
> > +     rte_eth_speed_lanes_set;
> >  };
> >
> >  INTERNAL {
>

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v4] ethdev: Add link_speed lanes support
  2024-07-09 21:20                             ` Damodharam Ammepalli
@ 2024-07-10  9:05                               ` Ferruh Yigit
  2024-09-04  2:43                                 ` Damodharam Ammepalli
  0 siblings, 1 reply; 33+ messages in thread
From: Ferruh Yigit @ 2024-07-10  9:05 UTC (permalink / raw)
  To: Damodharam Ammepalli
  Cc: ajit.khaparde, dev, huangdengdui, kalesh-anakkur.purayil

On 7/9/2024 10:20 PM, Damodharam Ammepalli wrote:
> On Tue, Jul 9, 2024 at 4:10 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>>
>> On 7/9/2024 12:22 AM, Damodharam Ammepalli wrote:
>>> Update the eth_dev_ops structure with new function vectors
>>> to get, get capabilities and set ethernet link speed lanes.
>>> Update the testpmd to provide required config and information
>>> display infrastructure.
>>>
>>> The supporting ethernet controller driver will register callbacks
>>> to avail link speed lanes config and get services. This lanes
>>> configuration is applicable only when the nic is forced to fixed
>>> speeds. In Autonegiation mode, the hardware automatically
>>> negotiates the number of lanes.
>>>
>>> These are the new commands.
>>>
>>> testpmd> show port 0 speed_lanes capabilities
>>>
>>>  Supported speeds         Valid lanes
>>> -----------------------------------
>>>  10 Gbps                  1
>>>  25 Gbps                  1
>>>  40 Gbps                  4
>>>  50 Gbps                  1 2
>>>  100 Gbps                 1 2 4
>>>  200 Gbps                 2 4
>>>  400 Gbps                 4 8
>>> testpmd>
>>>
>>> testpmd>
>>> testpmd> port stop 0
>>> testpmd> port config 0 speed_lanes 4
>>> testpmd> port config 0 speed 200000 duplex full
>>>
>>
>> Is there a requirement to set speed before speed_lane?
>> Because I expect driver will verify if a speed_lane value is valid or
>> not for a specific speed value. In above usage, driver will verify based
>> on existing speed, whatever it is, later chaning speed may cause invalid
>> speed_lane configuration.
>>
>>
> There is no requirement to set  speed before speed_lane.
> If the controller supports lanes configuration capability, if no lanes
> are given (which is 0)
> the driver will pick up the lowest speed (eg: 200 gbps with NRZ mode),
> if a fixed speed
> already exists or is configured in tandem with speed_lanes. If speed
> is already Auto,
> test-pmd's speed_lane config is ignored.
> 

We don't see your driver code yet, so it is hard to know the intention,
but for your case will it work if first speed is set, later lane is set?
(Btw, in the context of lanes, I am always assuming it is fixed speed
configuration.)

Assume that default speed is 10G, when speed_lane is set first, is it
expected that driver verify the lane for that speed? If so, perhaps that
specific lane config is not valid for the default speed and fails to
set, do you think is this a valid case?

Overall, the issue I am trying to clarify is the reason why Dengdui went
with having different desing to couple speed and lanes. We said we will
go with this separated design, but lets clarify relation/order in user
perspective, since this is something that impacts driver implementation.
And not clarifying this enough for sure will cause confusion and
inconsistency in different driver implemntations.

>>> testpmd> port start 0
>>> testpmd>
>>> testpmd> show port info 0
>>>
>>> ********************* Infos for port 0  *********************
>>> MAC address: 14:23:F2:C3:BA:D2
>>> Device name: 0000:b1:00.0
>>> Driver name: net_bnxt
>>> Firmware-version: 228.9.115.0
>>> Connect to socket: 2
>>> memory allocation on the socket: 2
>>> Link status: up
>>> Link speed: 200 Gbps
>>> Active Lanes: 4
>>> Link duplex: full-duplex
>>> Autoneg status: Off
>>>
>>> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
>>> ---
>>> v2->v3 Consolidating the testpmd and rtelib patches into a single patch
>>> as requested.
>>> v3->v4 Addressed comments and fix help string and documentation.
>>>
>>>  app/test-pmd/cmdline.c     | 230 +++++++++++++++++++++++++++++++++++++
>>>  app/test-pmd/config.c      |  69 ++++++++++-
>>>  app/test-pmd/testpmd.h     |   4 +
>>>  lib/ethdev/ethdev_driver.h |  77 +++++++++++++
>>>  lib/ethdev/rte_ethdev.c    |  51 ++++++++
>>>  lib/ethdev/rte_ethdev.h    |  92 +++++++++++++++
>>>  lib/ethdev/version.map     |   5 +
>>>  7 files changed, 526 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
>>> index b7759e38a8..a507df31d8 100644
>>> --- a/app/test-pmd/cmdline.c
>>> +++ b/app/test-pmd/cmdline.c
>>> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>>>
>>>                       "dump_log_types\n"
>>>                       "    Dumps the log level for all the dpdk modules\n\n"
>>> +
>>> +                     "show port (port_id) speed_lanes capabilities"
>>> +                     "       Show speed lanes capabilities of a port.\n\n"
>>>               );
>>>       }
>>>
>>> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
>>>                       "port config (port_id) txq (queue_id) affinity (value)\n"
>>>                       "    Map a Tx queue with an aggregated port "
>>>                       "of the DPDK port\n\n"
>>> +
>>> +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
>>> +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
>>>               );
>>>       }
>>>
>>> @@ -1560,6 +1566,110 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
>>>       },
>>>  };
>>>
>>> +static int
>>> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
>>> +{
>>> +     int ret;
>>> +     uint32_t lanes_capa;
>>> +
>>> +     ret = parse_speed_lanes(lanes, &lanes_capa);
>>> +     if (ret < 0) {
>>> +             fprintf(stderr, "Unknown speed lane value: %d for port %d\n", lanes, pid);
>>> +             return -1;
>>> +     }
>>> +
>>> +     ret = rte_eth_speed_lanes_set(pid, lanes_capa);
>>> +     if (ret == -ENOTSUP) {
>>> +             fprintf(stderr, "Function not implemented\n");
>>> +             return -1;
>>> +     } else if (ret < 0) {
>>> +             fprintf(stderr, "Set speed lanes failed\n");
>>> +             return -1;
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +/* *** display speed lanes per port capabilities *** */
>>> +struct cmd_show_speed_lanes_result {
>>> +     cmdline_fixed_string_t cmd_show;
>>> +     cmdline_fixed_string_t cmd_port;
>>> +     cmdline_fixed_string_t cmd_keyword;
>>> +     portid_t cmd_pid;
>>> +};
>>> +
>>> +static void
>>> +cmd_show_speed_lanes_parsed(void *parsed_result,
>>> +                         __rte_unused struct cmdline *cl,
>>> +                         __rte_unused void *data)
>>> +{
>>> +     struct cmd_show_speed_lanes_result *res = parsed_result;
>>> +     struct rte_eth_speed_lanes_capa *speed_lanes_capa;
>>> +     unsigned int num;
>>> +     int ret;
>>> +
>>> +     if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
>>> +             fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
>>> +             return;
>>> +     }
>>> +
>>> +     ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
>>> +     if (ret == -ENOTSUP) {
>>> +             fprintf(stderr, "Function not implemented\n");
>>> +             return;
>>> +     } else if (ret < 0) {
>>> +             fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
>>> +             return;
>>> +     }
>>> +
>>> +     num = (unsigned int)ret;
>>> +     speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
>>> +     if (speed_lanes_capa == NULL) {
>>> +             fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
>>> +             return;
>>> +     }
>>> +
>>> +     ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
>>> +     if (ret < 0) {
>>> +             fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
>>> +             goto out;
>>> +     }
>>> +
>>> +     show_speed_lanes_capability(num, speed_lanes_capa);
>>> +out:
>>> +     free(speed_lanes_capa);
>>> +}
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
>>> +                              cmd_show, "show");
>>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
>>> +                              cmd_port, "port");
>>> +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
>>> +     TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
>>> +                           cmd_pid, RTE_UINT16);
>>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
>>> +                              cmd_keyword, "speed_lanes");
>>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
>>> +                              cmd_keyword, "capabilities");
>>> +
>>> +static cmdline_parse_inst_t cmd_show_speed_lanes = {
>>> +     .f = cmd_show_speed_lanes_parsed,
>>> +     .data = NULL,
>>> +     .help_str = "show port <port_id> speed_lanes capabilities",
>>> +     .tokens = {
>>> +             (void *)&cmd_show_speed_lanes_show,
>>> +             (void *)&cmd_show_speed_lanes_port,
>>> +             (void *)&cmd_show_speed_lanes_pid,
>>> +             (void *)&cmd_show_speed_lanes_keyword,
>>> +             (void *)&cmd_show_speed_lanes_cap_keyword,
>>> +             NULL,
>>> +     },
>>> +};
>>> +
>>>  /* *** configure loopback for all ports *** */
>>>  struct cmd_config_loopback_all {
>>>       cmdline_fixed_string_t port;
>>> @@ -1676,6 +1786,123 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
>>>       },
>>>  };
>>>
>>> +/* *** configure speed_lanes for all ports *** */
>>> +struct cmd_config_speed_lanes_all {
>>> +     cmdline_fixed_string_t port;
>>> +     cmdline_fixed_string_t keyword;
>>> +     cmdline_fixed_string_t all;
>>> +     cmdline_fixed_string_t item;
>>> +     uint32_t lanes;
>>> +};
>>> +
>>> +static void
>>> +cmd_config_speed_lanes_all_parsed(void *parsed_result,
>>> +                               __rte_unused struct cmdline *cl,
>>> +                               __rte_unused void *data)
>>> +{
>>> +     struct cmd_config_speed_lanes_all *res = parsed_result;
>>> +     portid_t pid;
>>> +
>>> +     if (!all_ports_stopped()) {
>>> +             fprintf(stderr, "Please stop all ports first\n");
>>> +             return;
>>> +     }
>>> +
>>> +     RTE_ETH_FOREACH_DEV(pid) {
>>> +             if (parse_speed_lanes_cfg(pid, res->lanes))
>>> +                     return;
>>> +     }
>>> +
>>> +     cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
>>> +}
>>> +
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
>>> +                              "config");
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
>>> +                              "speed_lanes");
>>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
>>> +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
>>> +
>>> +static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
>>> +     .f = cmd_config_speed_lanes_all_parsed,
>>> +     .data = NULL,
>>> +     .help_str = "port config all speed_lanes <value>",
>>> +     .tokens = {
>>> +             (void *)&cmd_config_speed_lanes_all_port,
>>> +             (void *)&cmd_config_speed_lanes_all_keyword,
>>> +             (void *)&cmd_config_speed_lanes_all_all,
>>> +             (void *)&cmd_config_speed_lanes_all_item,
>>> +             (void *)&cmd_config_speed_lanes_all_lanes,
>>> +             NULL,
>>> +     },
>>> +};
>>> +
>>> +/* *** configure speed_lanes for specific port *** */
>>> +struct cmd_config_speed_lanes_specific {
>>> +     cmdline_fixed_string_t port;
>>> +     cmdline_fixed_string_t keyword;
>>> +     uint16_t port_id;
>>> +     cmdline_fixed_string_t item;
>>> +     uint32_t lanes;
>>> +};
>>> +
>>> +static void
>>> +cmd_config_speed_lanes_specific_parsed(void *parsed_result,
>>> +                                    __rte_unused struct cmdline *cl,
>>> +                                    __rte_unused void *data)
>>> +{
>>> +     struct cmd_config_speed_lanes_specific *res = parsed_result;
>>> +
>>> +     if (port_id_is_invalid(res->port_id, ENABLED_WARN))
>>> +             return;
>>> +
>>> +     if (!port_is_stopped(res->port_id)) {
>>> +             fprintf(stderr, "Please stop port %u first\n", res->port_id);
>>> +             return;
>>> +     }
>>>
>>
>> There is a requirement here, that port needs to be stopped before
>> calling the rte_eth_speed_lanes_set(),
>> is this requirement documented in the API documentation?
>>
>>
> Speed link mode needs a phy reset, hence port stop is a requirement.
> I will update this in the documentation in the next patch.
> 

That is OK to have the stop requirement, only it needs to be clear.
And addition to document this in the API documentation, what do you
think to add this check in the API, so it guarantees in coding level
that this requirement is satified.
So this check in application level can be dropped.

>>> +
>>> +     if (parse_speed_lanes_cfg(res->port_id, res->lanes))
>>> +             return;
>>> +
>>> +     cmd_reconfig_device_queue(res->port_id, 1, 1);
>>> +}
>>> +
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
>>> +                              "port");
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
>>> +                              "config");
>>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
>>> +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
>>> +                           RTE_UINT16);
>>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
>>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
>>> +                              "speed_lanes");
>>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
>>> +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
>>> +                           RTE_UINT32);
>>> +
>>> +static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
>>> +     .f = cmd_config_speed_lanes_specific_parsed,
>>> +     .data = NULL,
>>> +     .help_str = "port config <port_id> speed_lanes <value>",
>>> +     .tokens = {
>>> +             (void *)&cmd_config_speed_lanes_specific_port,
>>> +             (void *)&cmd_config_speed_lanes_specific_keyword,
>>> +             (void *)&cmd_config_speed_lanes_specific_id,
>>> +             (void *)&cmd_config_speed_lanes_specific_item,
>>> +             (void *)&cmd_config_speed_lanes_specific_lanes,
>>> +             NULL,
>>> +     },
>>> +};
>>> +
>>>  /* *** configure txq/rxq, txd/rxd *** */
>>>  struct cmd_config_rx_tx {
>>>       cmdline_fixed_string_t port;
>>> @@ -13238,6 +13465,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>>>       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
>>>       (cmdline_parse_inst_t *)&cmd_config_speed_all,
>>>       (cmdline_parse_inst_t *)&cmd_config_speed_specific,
>>> +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
>>> +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
>>> +     (cmdline_parse_inst_t *)&cmd_show_speed_lanes,
>>>       (cmdline_parse_inst_t *)&cmd_config_loopback_all,
>>>       (cmdline_parse_inst_t *)&cmd_config_loopback_specific,
>>>       (cmdline_parse_inst_t *)&cmd_config_rx_tx,
>>> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
>>> index 66c3a68c1d..498a7db467 100644
>>> --- a/app/test-pmd/config.c
>>> +++ b/app/test-pmd/config.c
>>> @@ -207,6 +207,32 @@ static const struct {
>>>       {"gtpu", RTE_ETH_FLOW_GTPU},
>>>  };
>>>
>>> +static const struct {
>>> +     enum rte_eth_speed_lanes lane;
>>> +     const uint32_t value;
>>> +} speed_lane_name[] = {
>>> +     {
>>> +             .lane = RTE_ETH_SPEED_LANE_UNKNOWN,
>>> +             .value = 0,
>>> +     },
>>> +     {
>>> +             .lane = RTE_ETH_SPEED_LANE_1,
>>> +             .value = 1,
>>> +     },
>>> +     {
>>> +             .lane = RTE_ETH_SPEED_LANE_2,
>>> +             .value = 2,
>>> +     },
>>> +     {
>>> +             .lane = RTE_ETH_SPEED_LANE_4,
>>> +             .value = 4,
>>> +     },
>>> +     {
>>> +             .lane = RTE_ETH_SPEED_LANE_8,
>>> +             .value = 8,
>>> +     },
>>> +};
>>> +
>>>  static void
>>>  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
>>>  {
>>> @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
>>>       char name[RTE_ETH_NAME_MAX_LEN];
>>>       int ret;
>>>       char fw_version[ETHDEV_FWVERS_LEN];
>>> +     uint32_t lanes;
>>>
>>>       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
>>>               print_valid_ports();
>>> @@ -828,6 +855,12 @@ port_infos_display(portid_t port_id)
>>>
>>>       printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
>>>       printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
>>> +     if (rte_eth_speed_lanes_get(port_id, &lanes) == 0) {
>>> +             if (lanes > 0)
>>> +                     printf("Active Lanes: %d\n", lanes);
>>> +             else
>>> +                     printf("Active Lanes: %s\n", "Unknown");
>>>
>>
>> What can be the 'else' case?
>> As 'lanes' is unsigned, only option is it being zero. Is API allowed to
>> return zero as lane number?
>>
>>
> Yes. link is down, but controller supports speed_lanes capability,
> then we can show "unknown"
> Other cases from brcm spec.
> 1gb 1Gb link speed < no lane info > (theoretically it can't be zero,
> but we need to show what controller provides in the query).
> 10Gb (NRZ: 10G per lane, 1 lane) link speed
> 

I don't understand how application proccess the information that
'rte_eth_speed_lanes_get()' returns success but lane is zero.

For the link down case, doesn't it make sense to return error for the
'rte_eth_speed_lanes_get()' API?

And for other cases, like 1G that doesn't support the lane
configuration, does it make sense to return 1?
And for these cases what is the capability value you are returning?


>>> +     }
>>>       printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
>>>              ("full-duplex") : ("half-duplex"));
>>>       printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
>>> @@ -962,7 +995,7 @@ port_summary_header_display(void)
>>>
>>>       port_number = rte_eth_dev_count_avail();
>>>       printf("Number of available ports: %i\n", port_number);
>>> -     printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
>>> +     printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
>>>                       "Driver", "Status", "Link");
>>>  }
>>>
>>> @@ -993,7 +1026,7 @@ port_summary_display(portid_t port_id)
>>>       if (ret != 0)
>>>               return;
>>>
>>> -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
>>> +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
>>>
>>
>> Summary updates are irrelevant in the patch, can you please drop them.
>>
>>
> Sure I will.
> 
>>>               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
>>>               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
>>>               rte_eth_link_speed_to_str(link.link_speed));
>>> @@ -7244,3 +7277,35 @@ show_mcast_macs(portid_t port_id)
>>>               printf("  %s\n", buf);
>>>       }
>>>  }
>>> +
>>> +int
>>> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
>>> +{
>>> +     uint8_t i;
>>> +
>>> +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
>>> +             if (speed_lane_name[i].value == lane) {
>>> +                     *speed_lane = lane;
>>>
>>
>> This converts from 8 -> 8, 4 -> 4 ....
>>
>> Why not completely eliminate this fucntion? See below.
>>
> Sure, will evaluate and do the needful.
> 
>>> +                     return 0;
>>> +             }
>>> +     }
>>> +     return -1;
>>> +}
>>> +
>>> +void
>>> +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
>>> +{
>>> +     unsigned int i, j;
>>> +
>>> +     printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
>>> +     printf("\n-----------------------------------\n");
>>> +     for (i = 0; i < num; i++) {
>>> +             printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
>>> +
>>> +             for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
>>> +                     if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
>>> +                             printf("%-2d ", speed_lane_name[j].value);
>>> +             }
>>
>> To eliminate both RTE_ETH_SPEED_LANE_MAX & speed_lane_name, what do you
>> think about:
>>
>> capa = speed_lanes_capa[i].capa;
>> int s = 0;
>> while (capa) {
>>     if (capa & 0x1)
>>         printf("%-2d ", 1 << s);
>>     s++;
>>     capa = capa >> 1;
>> }
>>
> Am new to the DPDK world.
> Followed the FEC driver conventions for consistency.
> Will update it as you suggested and it makes sense.
> 

FEC values goes sequential, but lane values in power of two, we can
benefit from this fact. (though if we have lane value not power of two
later, this logic may need to change.)

Btw, I can see some of the code copies existing FEC implementation,
which makes sense, but it seems FEC code could be improved as well but
we missed at that time.
Instead of copying FEC exactly, lets try to improve whatever we can for
first merge, otherwise less likely these things will be fixed later.

Thanks,
ferruh

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v4] ethdev: Add link_speed lanes support
  2024-07-10  9:05                               ` Ferruh Yigit
@ 2024-09-04  2:43                                 ` Damodharam Ammepalli
  0 siblings, 0 replies; 33+ messages in thread
From: Damodharam Ammepalli @ 2024-09-04  2:43 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: ajit.khaparde, dev, huangdengdui, kalesh-anakkur.purayil

[-- Attachment #1: Type: text/plain, Size: 25967 bytes --]

On Wed, Jul 10, 2024 at 2:06 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
>
> On 7/9/2024 10:20 PM, Damodharam Ammepalli wrote:
> > On Tue, Jul 9, 2024 at 4:10 AM Ferruh Yigit <ferruh.yigit@amd.com> wrote:
> >>
> >> On 7/9/2024 12:22 AM, Damodharam Ammepalli wrote:
> >>> Update the eth_dev_ops structure with new function vectors
> >>> to get, get capabilities and set ethernet link speed lanes.
> >>> Update the testpmd to provide required config and information
> >>> display infrastructure.
> >>>
> >>> The supporting ethernet controller driver will register callbacks
> >>> to avail link speed lanes config and get services. This lanes
> >>> configuration is applicable only when the nic is forced to fixed
> >>> speeds. In Autonegiation mode, the hardware automatically
> >>> negotiates the number of lanes.
> >>>
> >>> These are the new commands.
> >>>
> >>> testpmd> show port 0 speed_lanes capabilities
> >>>
> >>>  Supported speeds         Valid lanes
> >>> -----------------------------------
> >>>  10 Gbps                  1
> >>>  25 Gbps                  1
> >>>  40 Gbps                  4
> >>>  50 Gbps                  1 2
> >>>  100 Gbps                 1 2 4
> >>>  200 Gbps                 2 4
> >>>  400 Gbps                 4 8
> >>> testpmd>
> >>>
> >>> testpmd>
> >>> testpmd> port stop 0
> >>> testpmd> port config 0 speed_lanes 4
> >>> testpmd> port config 0 speed 200000 duplex full
> >>>
> >>
> >> Is there a requirement to set speed before speed_lane?
> >> Because I expect driver will verify if a speed_lane value is valid or
> >> not for a specific speed value. In above usage, driver will verify based
> >> on existing speed, whatever it is, later chaning speed may cause invalid
> >> speed_lane configuration.
> >>
> >>
> > There is no requirement to set  speed before speed_lane.
> > If the controller supports lanes configuration capability, if no lanes
> > are given (which is 0)
> > the driver will pick up the lowest speed (eg: 200 gbps with NRZ mode),
> > if a fixed speed
> > already exists or is configured in tandem with speed_lanes. If speed
> > is already Auto,
> > test-pmd's speed_lane config is ignored.
> >
>
> We don't see your driver code yet, so it is hard to know the intention,
> but for your case will it work if first speed is set, later lane is set?
> (Btw, in the context of lanes, I am always assuming it is fixed speed
> configuration.)
>

Ack. Follow up series will carry the patches.

> Assume that default speed is 10G, when speed_lane is set first, is it
> expected that driver verify the lane for that speed? If so, perhaps that
> specific lane config is not valid for the default speed and fails to
> set, do you think is this a valid case?
>

No, Let me take 100G as an example which has lanes capability.
If the link is Auto Negotiated, the driver will ignore the user's lane
configuration.
Lane configuration will only be applied if the existing linked up
speed(eg: 100G) is a fixed speed.
Driver will check the lane's validity and reject it if it doesn't
match the speed's capability.

> Overall, the issue I am trying to clarify is the reason why Dengdui went
> with having different desing to couple speed and lanes. We said we will
> go with this separated design, but lets clarify relation/order in user
> perspective, since this is something that impacts driver implementation.
> And not clarifying this enough for sure will cause confusion and
> inconsistency in different driver implemntations.
>

Ack. Since the port is stopped, order of configuration does not matter.
Once the port is started, the driver will pick up up test pmds lanes and speed
configuration and re-configures the phy in one shot. The recommended steps
are to stop the port, configure a fixed speed and lane count.

> >>> testpmd> port start 0
> >>> testpmd>
> >>> testpmd> show port info 0
> >>>
> >>> ********************* Infos for port 0  *********************
> >>> MAC address: 14:23:F2:C3:BA:D2
> >>> Device name: 0000:b1:00.0
> >>> Driver name: net_bnxt
> >>> Firmware-version: 228.9.115.0
> >>> Connect to socket: 2
> >>> memory allocation on the socket: 2
> >>> Link status: up
> >>> Link speed: 200 Gbps
> >>> Active Lanes: 4
> >>> Link duplex: full-duplex
> >>> Autoneg status: Off
> >>>
> >>> Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
> >>> ---
> >>> v2->v3 Consolidating the testpmd and rtelib patches into a single patch
> >>> as requested.
> >>> v3->v4 Addressed comments and fix help string and documentation.
> >>>
> >>>  app/test-pmd/cmdline.c     | 230 +++++++++++++++++++++++++++++++++++++
> >>>  app/test-pmd/config.c      |  69 ++++++++++-
> >>>  app/test-pmd/testpmd.h     |   4 +
> >>>  lib/ethdev/ethdev_driver.h |  77 +++++++++++++
> >>>  lib/ethdev/rte_ethdev.c    |  51 ++++++++
> >>>  lib/ethdev/rte_ethdev.h    |  92 +++++++++++++++
> >>>  lib/ethdev/version.map     |   5 +
> >>>  7 files changed, 526 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> >>> index b7759e38a8..a507df31d8 100644
> >>> --- a/app/test-pmd/cmdline.c
> >>> +++ b/app/test-pmd/cmdline.c
> >>> @@ -284,6 +284,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> >>>
> >>>                       "dump_log_types\n"
> >>>                       "    Dumps the log level for all the dpdk modules\n\n"
> >>> +
> >>> +                     "show port (port_id) speed_lanes capabilities"
> >>> +                     "       Show speed lanes capabilities of a port.\n\n"
> >>>               );
> >>>       }
> >>>
> >>> @@ -823,6 +826,9 @@ static void cmd_help_long_parsed(void *parsed_result,
> >>>                       "port config (port_id) txq (queue_id) affinity (value)\n"
> >>>                       "    Map a Tx queue with an aggregated port "
> >>>                       "of the DPDK port\n\n"
> >>> +
> >>> +                     "port config (port_id|all) speed_lanes (0|1|4|8)\n"
> >>> +                     "    Set number of lanes for all ports or port_id for a forced speed\n\n"
> >>>               );
> >>>       }
> >>>
> >>> @@ -1560,6 +1566,110 @@ static cmdline_parse_inst_t cmd_config_speed_specific = {
> >>>       },
> >>>  };
> >>>
> >>> +static int
> >>> +parse_speed_lanes_cfg(portid_t pid, uint32_t lanes)
> >>> +{
> >>> +     int ret;
> >>> +     uint32_t lanes_capa;
> >>> +
> >>> +     ret = parse_speed_lanes(lanes, &lanes_capa);
> >>> +     if (ret < 0) {
> >>> +             fprintf(stderr, "Unknown speed lane value: %d for port %d\n", lanes, pid);
> >>> +             return -1;
> >>> +     }
> >>> +
> >>> +     ret = rte_eth_speed_lanes_set(pid, lanes_capa);
> >>> +     if (ret == -ENOTSUP) {
> >>> +             fprintf(stderr, "Function not implemented\n");
> >>> +             return -1;
> >>> +     } else if (ret < 0) {
> >>> +             fprintf(stderr, "Set speed lanes failed\n");
> >>> +             return -1;
> >>> +     }
> >>> +
> >>> +     return 0;
> >>> +}
> >>> +
> >>> +/* *** display speed lanes per port capabilities *** */
> >>> +struct cmd_show_speed_lanes_result {
> >>> +     cmdline_fixed_string_t cmd_show;
> >>> +     cmdline_fixed_string_t cmd_port;
> >>> +     cmdline_fixed_string_t cmd_keyword;
> >>> +     portid_t cmd_pid;
> >>> +};
> >>> +
> >>> +static void
> >>> +cmd_show_speed_lanes_parsed(void *parsed_result,
> >>> +                         __rte_unused struct cmdline *cl,
> >>> +                         __rte_unused void *data)
> >>> +{
> >>> +     struct cmd_show_speed_lanes_result *res = parsed_result;
> >>> +     struct rte_eth_speed_lanes_capa *speed_lanes_capa;
> >>> +     unsigned int num;
> >>> +     int ret;
> >>> +
> >>> +     if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
> >>> +             fprintf(stderr, "Invalid port id %u\n", res->cmd_pid);
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, NULL, 0);
> >>> +     if (ret == -ENOTSUP) {
> >>> +             fprintf(stderr, "Function not implemented\n");
> >>> +             return;
> >>> +     } else if (ret < 0) {
> >>> +             fprintf(stderr, "Get speed lanes capability failed: %d\n", ret);
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     num = (unsigned int)ret;
> >>> +     speed_lanes_capa = calloc(num, sizeof(*speed_lanes_capa));
> >>> +     if (speed_lanes_capa == NULL) {
> >>> +             fprintf(stderr, "Failed to alloc speed lanes capability buffer\n");
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     ret = rte_eth_speed_lanes_get_capability(res->cmd_pid, speed_lanes_capa, num);
> >>> +     if (ret < 0) {
> >>> +             fprintf(stderr, "Error getting speed lanes capability: %d\n", ret);
> >>> +             goto out;
> >>> +     }
> >>> +
> >>> +     show_speed_lanes_capability(num, speed_lanes_capa);
> >>> +out:
> >>> +     free(speed_lanes_capa);
> >>> +}
> >>> +
> >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_show =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> >>> +                              cmd_show, "show");
> >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_port =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> >>> +                              cmd_port, "port");
> >>> +static cmdline_parse_token_num_t cmd_show_speed_lanes_pid =
> >>> +     TOKEN_NUM_INITIALIZER(struct cmd_show_speed_lanes_result,
> >>> +                           cmd_pid, RTE_UINT16);
> >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_keyword =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> >>> +                              cmd_keyword, "speed_lanes");
> >>> +static cmdline_parse_token_string_t cmd_show_speed_lanes_cap_keyword =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_show_speed_lanes_result,
> >>> +                              cmd_keyword, "capabilities");
> >>> +
> >>> +static cmdline_parse_inst_t cmd_show_speed_lanes = {
> >>> +     .f = cmd_show_speed_lanes_parsed,
> >>> +     .data = NULL,
> >>> +     .help_str = "show port <port_id> speed_lanes capabilities",
> >>> +     .tokens = {
> >>> +             (void *)&cmd_show_speed_lanes_show,
> >>> +             (void *)&cmd_show_speed_lanes_port,
> >>> +             (void *)&cmd_show_speed_lanes_pid,
> >>> +             (void *)&cmd_show_speed_lanes_keyword,
> >>> +             (void *)&cmd_show_speed_lanes_cap_keyword,
> >>> +             NULL,
> >>> +     },
> >>> +};
> >>> +
> >>>  /* *** configure loopback for all ports *** */
> >>>  struct cmd_config_loopback_all {
> >>>       cmdline_fixed_string_t port;
> >>> @@ -1676,6 +1786,123 @@ static cmdline_parse_inst_t cmd_config_loopback_specific = {
> >>>       },
> >>>  };
> >>>
> >>> +/* *** configure speed_lanes for all ports *** */
> >>> +struct cmd_config_speed_lanes_all {
> >>> +     cmdline_fixed_string_t port;
> >>> +     cmdline_fixed_string_t keyword;
> >>> +     cmdline_fixed_string_t all;
> >>> +     cmdline_fixed_string_t item;
> >>> +     uint32_t lanes;
> >>> +};
> >>> +
> >>> +static void
> >>> +cmd_config_speed_lanes_all_parsed(void *parsed_result,
> >>> +                               __rte_unused struct cmdline *cl,
> >>> +                               __rte_unused void *data)
> >>> +{
> >>> +     struct cmd_config_speed_lanes_all *res = parsed_result;
> >>> +     portid_t pid;
> >>> +
> >>> +     if (!all_ports_stopped()) {
> >>> +             fprintf(stderr, "Please stop all ports first\n");
> >>> +             return;
> >>> +     }
> >>> +
> >>> +     RTE_ETH_FOREACH_DEV(pid) {
> >>> +             if (parse_speed_lanes_cfg(pid, res->lanes))
> >>> +                     return;
> >>> +     }
> >>> +
> >>> +     cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
> >>> +}
> >>> +
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_port =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, port, "port");
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_keyword =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, keyword,
> >>> +                              "config");
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_all =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, all, "all");
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_all_item =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_all, item,
> >>> +                              "speed_lanes");
> >>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_all_lanes =
> >>> +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_all, lanes, RTE_UINT32);
> >>> +
> >>> +static cmdline_parse_inst_t cmd_config_speed_lanes_all = {
> >>> +     .f = cmd_config_speed_lanes_all_parsed,
> >>> +     .data = NULL,
> >>> +     .help_str = "port config all speed_lanes <value>",
> >>> +     .tokens = {
> >>> +             (void *)&cmd_config_speed_lanes_all_port,
> >>> +             (void *)&cmd_config_speed_lanes_all_keyword,
> >>> +             (void *)&cmd_config_speed_lanes_all_all,
> >>> +             (void *)&cmd_config_speed_lanes_all_item,
> >>> +             (void *)&cmd_config_speed_lanes_all_lanes,
> >>> +             NULL,
> >>> +     },
> >>> +};
> >>> +
> >>> +/* *** configure speed_lanes for specific port *** */
> >>> +struct cmd_config_speed_lanes_specific {
> >>> +     cmdline_fixed_string_t port;
> >>> +     cmdline_fixed_string_t keyword;
> >>> +     uint16_t port_id;
> >>> +     cmdline_fixed_string_t item;
> >>> +     uint32_t lanes;
> >>> +};
> >>> +
> >>> +static void
> >>> +cmd_config_speed_lanes_specific_parsed(void *parsed_result,
> >>> +                                    __rte_unused struct cmdline *cl,
> >>> +                                    __rte_unused void *data)
> >>> +{
> >>> +     struct cmd_config_speed_lanes_specific *res = parsed_result;
> >>> +
> >>> +     if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> >>> +             return;
> >>> +
> >>> +     if (!port_is_stopped(res->port_id)) {
> >>> +             fprintf(stderr, "Please stop port %u first\n", res->port_id);
> >>> +             return;
> >>> +     }
> >>>
> >>
> >> There is a requirement here, that port needs to be stopped before
> >> calling the rte_eth_speed_lanes_set(),
> >> is this requirement documented in the API documentation?
> >>
> >>
> > Speed link mode needs a phy reset, hence port stop is a requirement.
> > I will update this in the documentation in the next patch.
> >
>
> That is OK to have the stop requirement, only it needs to be clear.
> And addition to document this in the API documentation, what do you
> think to add this check in the API, so it guarantees in coding level
> that this requirement is satified.
> So this check in application level can be dropped.
>

Ack. updated the relevant comments section and also added check in the function.

> >>> +
> >>> +     if (parse_speed_lanes_cfg(res->port_id, res->lanes))
> >>> +             return;
> >>> +
> >>> +     cmd_reconfig_device_queue(res->port_id, 1, 1);
> >>> +}
> >>> +
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_port =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, port,
> >>> +                              "port");
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_keyword =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, keyword,
> >>> +                              "config");
> >>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_id =
> >>> +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, port_id,
> >>> +                           RTE_UINT16);
> >>> +static cmdline_parse_token_string_t cmd_config_speed_lanes_specific_item =
> >>> +     TOKEN_STRING_INITIALIZER(struct cmd_config_speed_lanes_specific, item,
> >>> +                              "speed_lanes");
> >>> +static cmdline_parse_token_num_t cmd_config_speed_lanes_specific_lanes =
> >>> +     TOKEN_NUM_INITIALIZER(struct cmd_config_speed_lanes_specific, lanes,
> >>> +                           RTE_UINT32);
> >>> +
> >>> +static cmdline_parse_inst_t cmd_config_speed_lanes_specific = {
> >>> +     .f = cmd_config_speed_lanes_specific_parsed,
> >>> +     .data = NULL,
> >>> +     .help_str = "port config <port_id> speed_lanes <value>",
> >>> +     .tokens = {
> >>> +             (void *)&cmd_config_speed_lanes_specific_port,
> >>> +             (void *)&cmd_config_speed_lanes_specific_keyword,
> >>> +             (void *)&cmd_config_speed_lanes_specific_id,
> >>> +             (void *)&cmd_config_speed_lanes_specific_item,
> >>> +             (void *)&cmd_config_speed_lanes_specific_lanes,
> >>> +             NULL,
> >>> +     },
> >>> +};
> >>> +
> >>>  /* *** configure txq/rxq, txd/rxd *** */
> >>>  struct cmd_config_rx_tx {
> >>>       cmdline_fixed_string_t port;
> >>> @@ -13238,6 +13465,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
> >>>       (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
> >>>       (cmdline_parse_inst_t *)&cmd_config_speed_all,
> >>>       (cmdline_parse_inst_t *)&cmd_config_speed_specific,
> >>> +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_all,
> >>> +     (cmdline_parse_inst_t *)&cmd_config_speed_lanes_specific,
> >>> +     (cmdline_parse_inst_t *)&cmd_show_speed_lanes,
> >>>       (cmdline_parse_inst_t *)&cmd_config_loopback_all,
> >>>       (cmdline_parse_inst_t *)&cmd_config_loopback_specific,
> >>>       (cmdline_parse_inst_t *)&cmd_config_rx_tx,
> >>> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> >>> index 66c3a68c1d..498a7db467 100644
> >>> --- a/app/test-pmd/config.c
> >>> +++ b/app/test-pmd/config.c
> >>> @@ -207,6 +207,32 @@ static const struct {
> >>>       {"gtpu", RTE_ETH_FLOW_GTPU},
> >>>  };
> >>>
> >>> +static const struct {
> >>> +     enum rte_eth_speed_lanes lane;
> >>> +     const uint32_t value;
> >>> +} speed_lane_name[] = {
> >>> +     {
> >>> +             .lane = RTE_ETH_SPEED_LANE_UNKNOWN,
> >>> +             .value = 0,
> >>> +     },
> >>> +     {
> >>> +             .lane = RTE_ETH_SPEED_LANE_1,
> >>> +             .value = 1,
> >>> +     },
> >>> +     {
> >>> +             .lane = RTE_ETH_SPEED_LANE_2,
> >>> +             .value = 2,
> >>> +     },
> >>> +     {
> >>> +             .lane = RTE_ETH_SPEED_LANE_4,
> >>> +             .value = 4,
> >>> +     },
> >>> +     {
> >>> +             .lane = RTE_ETH_SPEED_LANE_8,
> >>> +             .value = 8,
> >>> +     },
> >>> +};
> >>> +
> >>>  static void
> >>>  print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
> >>>  {
> >>> @@ -786,6 +812,7 @@ port_infos_display(portid_t port_id)
> >>>       char name[RTE_ETH_NAME_MAX_LEN];
> >>>       int ret;
> >>>       char fw_version[ETHDEV_FWVERS_LEN];
> >>> +     uint32_t lanes;
> >>>
> >>>       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
> >>>               print_valid_ports();
> >>> @@ -828,6 +855,12 @@ port_infos_display(portid_t port_id)
> >>>
> >>>       printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
> >>>       printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
> >>> +     if (rte_eth_speed_lanes_get(port_id, &lanes) == 0) {
> >>> +             if (lanes > 0)
> >>> +                     printf("Active Lanes: %d\n", lanes);
> >>> +             else
> >>> +                     printf("Active Lanes: %s\n", "Unknown");
> >>>
> >>
> >> What can be the 'else' case?
> >> As 'lanes' is unsigned, only option is it being zero. Is API allowed to
> >> return zero as lane number?
> >>

Ack, in the ensuing patch, removing the else case since as per your
next comment,
driver returns either error code or 0, with lanes count > 0.

> >>
> > Yes. link is down, but controller supports speed_lanes capability,
> > then we can show "unknown"
> > Other cases from brcm spec.
> > 1gb 1Gb link speed < no lane info > (theoretically it can't be zero,
> > but we need to show what controller provides in the query).
> > 10Gb (NRZ: 10G per lane, 1 lane) link speed
> >
>
> I don't understand how application proccess the information that
> 'rte_eth_speed_lanes_get()' returns success but lane is zero.
>

Ack. Answered in the next comment.

> For the link down case, doesn't it make sense to return error for the
> 'rte_eth_speed_lanes_get()' API?
>
Ack.

> And for other cases, like 1G that doesn't support the lane
> configuration, does it make sense to return 1?
> And for these cases what is the capability value you are returning?
>

Ack. For speeds like 1G, checking with firmware engineers confirmed, a lane = 1
would be appropriate and the driver will always return lanes > 0.

>
> >>> +     }
> >>>       printf("Link duplex: %s\n", (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
> >>>              ("full-duplex") : ("half-duplex"));
> >>>       printf("Autoneg status: %s\n", (link.link_autoneg == RTE_ETH_LINK_AUTONEG) ?
> >>> @@ -962,7 +995,7 @@ port_summary_header_display(void)
> >>>
> >>>       port_number = rte_eth_dev_count_avail();
> >>>       printf("Number of available ports: %i\n", port_number);
> >>> -     printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
> >>> +     printf("%-4s %-17s %-12s %-14s %-8s %-8s\n", "Port", "MAC Address", "Name",
> >>>                       "Driver", "Status", "Link");
> >>>  }
> >>>
> >>> @@ -993,7 +1026,7 @@ port_summary_display(portid_t port_id)
> >>>       if (ret != 0)
> >>>               return;
> >>>
> >>> -     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %s\n",
> >>> +     printf("%-4d " RTE_ETHER_ADDR_PRT_FMT " %-12s %-14s %-8s %-8s\n",
> >>>
> >>
> >> Summary updates are irrelevant in the patch, can you please drop them.
> >>
> >>
> > Sure I will.
> >
> >>>               port_id, RTE_ETHER_ADDR_BYTES(&mac_addr), name,
> >>>               dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
> >>>               rte_eth_link_speed_to_str(link.link_speed));
> >>> @@ -7244,3 +7277,35 @@ show_mcast_macs(portid_t port_id)
> >>>               printf("  %s\n", buf);
> >>>       }
> >>>  }
> >>> +
> >>> +int
> >>> +parse_speed_lanes(uint32_t lane, uint32_t *speed_lane)
> >>> +{
> >>> +     uint8_t i;
> >>> +
> >>> +     for (i = 0; i < RTE_DIM(speed_lane_name); i++) {
> >>> +             if (speed_lane_name[i].value == lane) {
> >>> +                     *speed_lane = lane;
> >>>
> >>
> >> This converts from 8 -> 8, 4 -> 4 ....
> >>
> >> Why not completely eliminate this fucntion? See below.
> >>
> > Sure, will evaluate and do the needful.
> >
> >>> +                     return 0;
> >>> +             }
> >>> +     }
> >>> +     return -1;
> >>> +}
> >>> +
> >>> +void
> >>> +show_speed_lanes_capability(unsigned int num, struct rte_eth_speed_lanes_capa *speed_lanes_capa)
> >>> +{
> >>> +     unsigned int i, j;
> >>> +
> >>> +     printf("\n%-15s %-10s", "Supported-speeds", "Valid-lanes");
> >>> +     printf("\n-----------------------------------\n");
> >>> +     for (i = 0; i < num; i++) {
> >>> +             printf("%-17s ", rte_eth_link_speed_to_str(speed_lanes_capa[i].speed));
> >>> +
> >>> +             for (j = 0; j < RTE_ETH_SPEED_LANE_MAX; j++) {
> >>> +                     if (RTE_ETH_SPEED_LANES_TO_CAPA(j) & speed_lanes_capa[i].capa)
> >>> +                             printf("%-2d ", speed_lane_name[j].value);
> >>> +             }
> >>
> >> To eliminate both RTE_ETH_SPEED_LANE_MAX & speed_lane_name, what do you
> >> think about:
> >>
> >> capa = speed_lanes_capa[i].capa;
> >> int s = 0;
> >> while (capa) {
> >>     if (capa & 0x1)
> >>         printf("%-2d ", 1 << s);
> >>     s++;
> >>     capa = capa >> 1;
> >> }
> >>
> > Am new to the DPDK world.
> > Followed the FEC driver conventions for consistency.
> > Will update it as you suggested and it makes sense.
> >
>
> FEC values goes sequential, but lane values in power of two, we can
> benefit from this fact. (though if we have lane value not power of two
> later, this logic may need to change.)
>
> Btw, I can see some of the code copies existing FEC implementation,
> which makes sense, but it seems FEC code could be improved as well but
> we missed at that time.
> Instead of copying FEC exactly, lets try to improve whatever we can for
> first merge, otherwise less likely these things will be fixed later.
>

Ack. Follow up patch will have comments addressed.
Thanks for the review and sorry for the delay, as other priorities
took the front seat.

> Thanks,
> ferruh

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5457 bytes --]

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2024-09-04  2:43 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-22 22:25 [RFC 0/2] Add support for link speed lanes Damodharam Ammepalli
2024-03-22 22:25 ` [RFC 1/2] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
2024-03-22 22:25 ` [RFC 2/2] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
2024-05-22 20:59 ` [RFC 0/2] Add support for link speed lanes Ferruh Yigit
2024-05-28 21:19   ` Damodharam Ammepalli
2024-06-02  2:45     ` [PATCH v2 0/4] " Damodharam Ammepalli
2024-06-02  2:45       ` [PATCH v2 1/4] lib/ethdev: Add link_speed lanes support into rte lib Damodharam Ammepalli
2024-06-11 23:39         ` Ferruh Yigit
2024-06-14 18:27           ` Damodharam Ammepalli
2024-06-17 20:34             ` [PATCH v3] ethdev: Add link_speed lanes support Damodharam Ammepalli
2024-06-20  3:23               ` huangdengdui
2024-06-25 21:07                 ` Damodharam Ammepalli
2024-06-26  2:19                   ` huangdengdui
2024-07-05 17:33                     ` Ferruh Yigit
2024-07-08 20:35                       ` Damodharam Ammepalli
2024-07-08 23:22                         ` [PATCH v4] " Damodharam Ammepalli
2024-07-08 23:34                           ` Ajit Khaparde
2024-07-09 11:10                           ` Ferruh Yigit
2024-07-09 21:20                             ` Damodharam Ammepalli
2024-07-10  9:05                               ` Ferruh Yigit
2024-09-04  2:43                                 ` Damodharam Ammepalli
2024-07-05 17:35               ` [PATCH v3] " Ferruh Yigit
2024-07-08 20:31                 ` Damodharam Ammepalli
2024-06-02  2:45       ` [PATCH v2 2/4] testpmd: Add speed lanes to testpmd config and show command Damodharam Ammepalli
2024-06-11 23:39         ` Ferruh Yigit
2024-06-02  2:45       ` [PATCH v2 3/4] lib/ethdev: add support for displaying lanes capability Damodharam Ammepalli
2024-06-11 23:39         ` Ferruh Yigit
2024-06-02  2:45       ` [PATCH v2 4/4] testpmd: " Damodharam Ammepalli
2024-06-11 23:39         ` Ferruh Yigit
2024-06-12 17:53           ` Damodharam Ammepalli
2024-06-12 20:57             ` Ferruh Yigit
2024-06-11 23:38       ` [PATCH v2 0/4] Add support for link speed lanes Ferruh Yigit
2024-06-12 17:46         ` Damodharam Ammepalli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).