DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] i40e: support autoneg or force link speed
@ 2014-07-31 20:44 Cunming Liang
  2014-08-20  8:29 ` Liang, Cunming
  2014-08-25  3:18 ` [dpdk-dev] [PATCH v2] " Cunming Liang
  0 siblings, 2 replies; 4+ messages in thread
From: Cunming Liang @ 2014-07-31 20:44 UTC (permalink / raw)
  To: dev

- i40e force link up/down
- i40e autoneg/force speed

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
Acked-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
Tested-by: Xu HuilongX <huilongx.xu@intel.com>
---
 app/test-pmd/cmdline.c            |  17 +++--
 lib/librte_pmd_i40e/i40e_ethdev.c | 139 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 6 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 345be11..0abc233 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -527,7 +527,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port close (port_id|all)\n"
 			"    Close all ports or port_id.\n\n"
 
-			"port config (port_id|all) speed (10|100|1000|10000|auto)"
+			"port config (port_id|all)"
+			" speed (10|100|1000|10000|40000|auto)"
 			" duplex (half|full|auto)\n"
 			"    Set speed and duplex for all ports or port_id\n\n"
 
@@ -801,7 +802,9 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	else if (!strcmp(res->value1, "1000"))
 		link_speed = ETH_LINK_SPEED_1000;
 	else if (!strcmp(res->value1, "10000"))
-		link_speed = ETH_LINK_SPEED_10000;
+		link_speed = ETH_LINK_SPEED_10G;
+	else if (!strcmp(res->value1, "40000"))
+		link_speed = ETH_LINK_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
 		link_speed = ETH_LINK_SPEED_AUTONEG;
 	else {
@@ -839,7 +842,7 @@ cmdline_parse_token_string_t cmd_config_speed_all_item1 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1, "speed");
 cmdline_parse_token_string_t cmd_config_speed_all_value1 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
-						"10#100#1000#10000#auto");
+						"10#100#1000#10000#40000#auto");
 cmdline_parse_token_string_t cmd_config_speed_all_item2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
 cmdline_parse_token_string_t cmd_config_speed_all_value2 =
@@ -849,7 +852,7 @@ cmdline_parse_token_string_t cmd_config_speed_all_value2 =
 cmdline_parse_inst_t cmd_config_speed_all = {
 	.f = cmd_config_speed_all_parsed,
 	.data = NULL,
-	.help_str = "port config all speed 10|100|1000|10000|auto duplex "
+	.help_str = "port config all speed 10|100|1000|10000|40000|auto duplex "
 							"half|full|auto",
 	.tokens = {
 		(void *)&cmd_config_speed_all_port,
@@ -901,6 +904,8 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 		link_speed = ETH_LINK_SPEED_1000;
 	else if (!strcmp(res->value1, "10000"))
 		link_speed = ETH_LINK_SPEED_10000;
+	else if (!strcmp(res->value1, "40000"))
+		link_speed = ETH_LINK_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
 		link_speed = ETH_LINK_SPEED_AUTONEG;
 	else {
@@ -939,7 +944,7 @@ cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
 								"speed");
 cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
-						"10#100#1000#10000#auto");
+						"10#100#1000#10000#40000#auto");
 cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
 								"duplex");
@@ -950,7 +955,7 @@ cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
 cmdline_parse_inst_t cmd_config_speed_specific = {
 	.f = cmd_config_speed_specific_parsed,
 	.data = NULL,
-	.help_str = "port config X speed 10|100|1000|10000|auto duplex "
+	.help_str = "port config X speed 10|100|1000|10000|40000|auto duplex "
 							"half|full|auto",
 	.tokens = {
 		(void *)&cmd_config_speed_specific_port,
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index 9ed31b5..fe4c78e 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -128,6 +128,8 @@ static void i40e_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void i40e_dev_promiscuous_disable(struct rte_eth_dev *dev);
 static void i40e_dev_allmulticast_enable(struct rte_eth_dev *dev);
 static void i40e_dev_allmulticast_disable(struct rte_eth_dev *dev);
+static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
+static int i40e_dev_set_link_down(struct rte_eth_dev *dev);
 static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
@@ -222,6 +224,8 @@ static struct eth_dev_ops i40e_eth_dev_ops = {
 	.promiscuous_disable          = i40e_dev_promiscuous_disable,
 	.allmulticast_enable          = i40e_dev_allmulticast_enable,
 	.allmulticast_disable         = i40e_dev_allmulticast_disable,
+	.dev_set_link_up              = i40e_dev_set_link_up,
+	.dev_set_link_down            = i40e_dev_set_link_down,
 	.link_update                  = i40e_dev_link_update,
 	.stats_get                    = i40e_dev_stats_get,
 	.stats_reset                  = i40e_dev_stats_reset,
@@ -649,6 +653,100 @@ i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
 }
 
+static inline uint8_t
+i40e_parse_link_speed(uint16_t eth_link_speed)
+{
+	uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN;
+
+	switch (eth_link_speed) {
+	case ETH_LINK_SPEED_40G:
+		link_speed = I40E_LINK_SPEED_40GB;
+		break;
+	case ETH_LINK_SPEED_20G:
+		link_speed = I40E_LINK_SPEED_20GB;
+		break;
+	case ETH_LINK_SPEED_10G:
+		link_speed = I40E_LINK_SPEED_10GB;
+		break;
+	case ETH_LINK_SPEED_1000:
+		link_speed = I40E_LINK_SPEED_1GB;
+		break;
+	case ETH_LINK_SPEED_100:
+		link_speed = I40E_LINK_SPEED_100MB;
+		break;
+	}
+
+	return link_speed;
+}
+
+static int
+i40e_phy_conf_link(struct i40e_hw *hw, uint8_t abilities, uint8_t force_speed)
+{
+	enum i40e_status_code status;
+	struct i40e_aq_get_phy_abilities_resp phy_ab;
+	struct i40e_aq_set_phy_config phy_conf = {0};
+	const uint8_t mask = I40E_AQ_PHY_FLAG_PAUSE_TX |
+			I40E_AQ_PHY_FLAG_PAUSE_RX |
+			I40E_AQ_PHY_FLAG_LOW_POWER;
+	const uint8_t advt = I40E_LINK_SPEED_40GB |
+			I40E_LINK_SPEED_10GB |
+			I40E_LINK_SPEED_1GB |
+			I40E_LINK_SPEED_100MB;
+	int ret = -ENOTSUP;
+
+	status = i40e_aq_get_phy_capabilities(hw, false, false, &phy_ab,
+					      NULL);
+	if (status)
+		return ret;
+
+	/* bits 0-2 use the values from get_phy_abilities_resp */
+	abilities &= ~mask;
+	abilities |= phy_ab.abilities & mask;
+
+	/* update ablities and speed */
+	if (abilities & I40E_AQ_PHY_AN_ENABLED)
+		phy_conf.link_speed = advt;
+	else
+		phy_conf.link_speed = force_speed;
+
+	phy_conf.abilities = abilities;
+
+	/* use get_phy_abilities_resp value for the rest */
+	phy_conf.phy_type = phy_ab.phy_type;
+	phy_conf.eee_capability = phy_ab.eee_capability;
+	phy_conf.eeer = phy_ab.eeer_val;
+	phy_conf.low_power_ctrl = phy_ab.d3_lpan;
+
+	PMD_DRV_LOG(DEBUG, "\n\tCurrent: abilities %x, link_speed %x\n"
+		    "\tConfig:  abilities %x, link_speed %x",
+		    phy_ab.abilities, phy_ab.link_speed,
+		    phy_conf.abilities, phy_conf.link_speed);
+
+	status = i40e_aq_set_phy_config(hw, &phy_conf, NULL);
+	if (status)
+		return ret;
+
+	return I40E_SUCCESS;
+}
+
+static int
+i40e_apply_link_speed(struct rte_eth_dev *dev)
+{
+	uint8_t speed;
+	uint8_t abilities = 0;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_eth_conf *conf = &dev->data->dev_conf;
+
+	speed = i40e_parse_link_speed(conf->link_speed);
+	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+	if (conf->link_speed == ETH_LINK_SPEED_AUTONEG)
+		abilities |= I40E_AQ_PHY_AN_ENABLED;
+	else
+		abilities |= I40E_AQ_PHY_LINK_ENABLED;
+
+	return i40e_phy_conf_link(hw, abilities, speed);
+}
+
 static int
 i40e_dev_start(struct rte_eth_dev *dev)
 {
@@ -657,6 +755,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct i40e_vsi *vsi = pf->main_vsi;
 	int ret;
 
+	if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) &&
+		(dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) {
+		PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu\n",
+				dev->data->dev_conf.link_duplex,
+				dev->data->port_id);
+		return -EINVAL;
+	}
+
 	/* Initialize VSI */
 	ret = i40e_vsi_init(vsi);
 	if (ret != I40E_SUCCESS) {
@@ -682,6 +788,13 @@ i40e_dev_start(struct rte_eth_dev *dev)
 			PMD_DRV_LOG(INFO, "fail to set vsi broadcast\n");
 	}
 
+	/* Apply link configure */
+	ret = i40e_apply_link_speed(dev);
+	if (I40E_SUCCESS != ret) {
+		PMD_DRV_LOG(ERR, "Fail to apply link setting\n");
+		goto err_up;
+	}
+
 	return I40E_SUCCESS;
 
 err_up:
@@ -703,6 +816,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	/* Clear all queues and release memory */
 	i40e_dev_clear_queues(dev);
 
+	/* Set link down */
+	i40e_dev_set_link_down(dev);
+
 	/* un-map queues with interrupt registers */
 	i40e_vsi_disable_queues_intr(vsi);
 	i40e_vsi_queues_unbind_intr(vsi);
@@ -798,6 +914,29 @@ i40e_dev_allmulticast_disable(struct rte_eth_dev *dev)
 		PMD_DRV_LOG(ERR, "Failed to disable multicast promiscuous\n");
 }
 
+/*
+ * Set device link up.
+ */
+static int
+i40e_dev_set_link_up(struct rte_eth_dev *dev)
+{
+	/* re-apply link speed setting */
+	return i40e_apply_link_speed(dev);
+}
+
+/*
+ * Set device link down.
+ */
+static int
+i40e_dev_set_link_down(__rte_unused struct rte_eth_dev *dev)
+{
+	uint8_t speed = I40E_LINK_SPEED_UNKNOWN;
+	uint8_t abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	return i40e_phy_conf_link(hw, abilities, speed);
+}
+
 int
 i40e_dev_link_update(struct rte_eth_dev *dev,
 		     __rte_unused int wait_to_complete)
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH] i40e: support autoneg or force link speed
  2014-07-31 20:44 [dpdk-dev] [PATCH] i40e: support autoneg or force link speed Cunming Liang
@ 2014-08-20  8:29 ` Liang, Cunming
  2014-08-25  3:18 ` [dpdk-dev] [PATCH v2] " Cunming Liang
  1 sibling, 0 replies; 4+ messages in thread
From: Liang, Cunming @ 2014-08-20  8:29 UTC (permalink / raw)
  To: dev

Hi,

Any plan to merge this patch ?

BRs,
Steve

> -----Original Message-----
> From: Liang, Cunming
> Sent: Friday, August 01, 2014 4:44 AM
> To: dev@dpdk.org
> Cc: Liang, Cunming
> Subject: [PATCH] i40e: support autoneg or force link speed
> 
> - i40e force link up/down
> - i40e autoneg/force speed
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
> Acked-by: Helin Zhang <helin.zhang@intel.com>
> Acked-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
> Tested-by: Xu HuilongX <huilongx.xu@intel.com>
> ---
>  app/test-pmd/cmdline.c            |  17 +++--
>  lib/librte_pmd_i40e/i40e_ethdev.c | 139
> ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 150 insertions(+), 6 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 345be11..0abc233 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -527,7 +527,8 @@ static void cmd_help_long_parsed(void *parsed_result,
>  			"port close (port_id|all)\n"
>  			"    Close all ports or port_id.\n\n"
> 
> -			"port config (port_id|all) speed
> (10|100|1000|10000|auto)"
> +			"port config (port_id|all)"
> +			" speed (10|100|1000|10000|40000|auto)"
>  			" duplex (half|full|auto)\n"
>  			"    Set speed and duplex for all ports or port_id\n\n"
> 
> @@ -801,7 +802,9 @@ cmd_config_speed_all_parsed(void *parsed_result,
>  	else if (!strcmp(res->value1, "1000"))
>  		link_speed = ETH_LINK_SPEED_1000;
>  	else if (!strcmp(res->value1, "10000"))
> -		link_speed = ETH_LINK_SPEED_10000;
> +		link_speed = ETH_LINK_SPEED_10G;
> +	else if (!strcmp(res->value1, "40000"))
> +		link_speed = ETH_LINK_SPEED_40G;
>  	else if (!strcmp(res->value1, "auto"))
>  		link_speed = ETH_LINK_SPEED_AUTONEG;
>  	else {
> @@ -839,7 +842,7 @@ cmdline_parse_token_string_t
> cmd_config_speed_all_item1 =
>  	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1,
> "speed");
>  cmdline_parse_token_string_t cmd_config_speed_all_value1 =
>  	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
> -						"10#100#1000#10000#auto");
> +
> 	"10#100#1000#10000#40000#auto");
>  cmdline_parse_token_string_t cmd_config_speed_all_item2 =
>  	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2,
> "duplex");
>  cmdline_parse_token_string_t cmd_config_speed_all_value2 =
> @@ -849,7 +852,7 @@ cmdline_parse_token_string_t
> cmd_config_speed_all_value2 =
>  cmdline_parse_inst_t cmd_config_speed_all = {
>  	.f = cmd_config_speed_all_parsed,
>  	.data = NULL,
> -	.help_str = "port config all speed 10|100|1000|10000|auto duplex "
> +	.help_str = "port config all speed 10|100|1000|10000|40000|auto duplex
> "
>  							"half|full|auto",
>  	.tokens = {
>  		(void *)&cmd_config_speed_all_port,
> @@ -901,6 +904,8 @@ cmd_config_speed_specific_parsed(void *parsed_result,
>  		link_speed = ETH_LINK_SPEED_1000;
>  	else if (!strcmp(res->value1, "10000"))
>  		link_speed = ETH_LINK_SPEED_10000;
> +	else if (!strcmp(res->value1, "40000"))
> +		link_speed = ETH_LINK_SPEED_40G;
>  	else if (!strcmp(res->value1, "auto"))
>  		link_speed = ETH_LINK_SPEED_AUTONEG;
>  	else {
> @@ -939,7 +944,7 @@ cmdline_parse_token_string_t
> cmd_config_speed_specific_item1 =
>  								"speed");
>  cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
>  	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
> -						"10#100#1000#10000#auto");
> +
> 	"10#100#1000#10000#40000#auto");
>  cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
>  	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
>  								"duplex");
> @@ -950,7 +955,7 @@ cmdline_parse_token_string_t
> cmd_config_speed_specific_value2 =
>  cmdline_parse_inst_t cmd_config_speed_specific = {
>  	.f = cmd_config_speed_specific_parsed,
>  	.data = NULL,
> -	.help_str = "port config X speed 10|100|1000|10000|auto duplex "
> +	.help_str = "port config X speed 10|100|1000|10000|40000|auto duplex "
>  							"half|full|auto",
>  	.tokens = {
>  		(void *)&cmd_config_speed_specific_port,
> diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c
> b/lib/librte_pmd_i40e/i40e_ethdev.c
> index 9ed31b5..fe4c78e 100644
> --- a/lib/librte_pmd_i40e/i40e_ethdev.c
> +++ b/lib/librte_pmd_i40e/i40e_ethdev.c
> @@ -128,6 +128,8 @@ static void i40e_dev_promiscuous_enable(struct
> rte_eth_dev *dev);
>  static void i40e_dev_promiscuous_disable(struct rte_eth_dev *dev);
>  static void i40e_dev_allmulticast_enable(struct rte_eth_dev *dev);
>  static void i40e_dev_allmulticast_disable(struct rte_eth_dev *dev);
> +static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
> +static int i40e_dev_set_link_down(struct rte_eth_dev *dev);
>  static void i40e_dev_stats_get(struct rte_eth_dev *dev,
>  			       struct rte_eth_stats *stats);
>  static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
> @@ -222,6 +224,8 @@ static struct eth_dev_ops i40e_eth_dev_ops = {
>  	.promiscuous_disable          = i40e_dev_promiscuous_disable,
>  	.allmulticast_enable          = i40e_dev_allmulticast_enable,
>  	.allmulticast_disable         = i40e_dev_allmulticast_disable,
> +	.dev_set_link_up              = i40e_dev_set_link_up,
> +	.dev_set_link_down            = i40e_dev_set_link_down,
>  	.link_update                  = i40e_dev_link_update,
>  	.stats_get                    = i40e_dev_stats_get,
>  	.stats_reset                  = i40e_dev_stats_reset,
> @@ -649,6 +653,100 @@ i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
>  	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
>  }
> 
> +static inline uint8_t
> +i40e_parse_link_speed(uint16_t eth_link_speed)
> +{
> +	uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN;
> +
> +	switch (eth_link_speed) {
> +	case ETH_LINK_SPEED_40G:
> +		link_speed = I40E_LINK_SPEED_40GB;
> +		break;
> +	case ETH_LINK_SPEED_20G:
> +		link_speed = I40E_LINK_SPEED_20GB;
> +		break;
> +	case ETH_LINK_SPEED_10G:
> +		link_speed = I40E_LINK_SPEED_10GB;
> +		break;
> +	case ETH_LINK_SPEED_1000:
> +		link_speed = I40E_LINK_SPEED_1GB;
> +		break;
> +	case ETH_LINK_SPEED_100:
> +		link_speed = I40E_LINK_SPEED_100MB;
> +		break;
> +	}
> +
> +	return link_speed;
> +}
> +
> +static int
> +i40e_phy_conf_link(struct i40e_hw *hw, uint8_t abilities, uint8_t force_speed)
> +{
> +	enum i40e_status_code status;
> +	struct i40e_aq_get_phy_abilities_resp phy_ab;
> +	struct i40e_aq_set_phy_config phy_conf = {0};
> +	const uint8_t mask = I40E_AQ_PHY_FLAG_PAUSE_TX |
> +			I40E_AQ_PHY_FLAG_PAUSE_RX |
> +			I40E_AQ_PHY_FLAG_LOW_POWER;
> +	const uint8_t advt = I40E_LINK_SPEED_40GB |
> +			I40E_LINK_SPEED_10GB |
> +			I40E_LINK_SPEED_1GB |
> +			I40E_LINK_SPEED_100MB;
> +	int ret = -ENOTSUP;
> +
> +	status = i40e_aq_get_phy_capabilities(hw, false, false, &phy_ab,
> +					      NULL);
> +	if (status)
> +		return ret;
> +
> +	/* bits 0-2 use the values from get_phy_abilities_resp */
> +	abilities &= ~mask;
> +	abilities |= phy_ab.abilities & mask;
> +
> +	/* update ablities and speed */
> +	if (abilities & I40E_AQ_PHY_AN_ENABLED)
> +		phy_conf.link_speed = advt;
> +	else
> +		phy_conf.link_speed = force_speed;
> +
> +	phy_conf.abilities = abilities;
> +
> +	/* use get_phy_abilities_resp value for the rest */
> +	phy_conf.phy_type = phy_ab.phy_type;
> +	phy_conf.eee_capability = phy_ab.eee_capability;
> +	phy_conf.eeer = phy_ab.eeer_val;
> +	phy_conf.low_power_ctrl = phy_ab.d3_lpan;
> +
> +	PMD_DRV_LOG(DEBUG, "\n\tCurrent: abilities %x, link_speed %x\n"
> +		    "\tConfig:  abilities %x, link_speed %x",
> +		    phy_ab.abilities, phy_ab.link_speed,
> +		    phy_conf.abilities, phy_conf.link_speed);
> +
> +	status = i40e_aq_set_phy_config(hw, &phy_conf, NULL);
> +	if (status)
> +		return ret;
> +
> +	return I40E_SUCCESS;
> +}
> +
> +static int
> +i40e_apply_link_speed(struct rte_eth_dev *dev)
> +{
> +	uint8_t speed;
> +	uint8_t abilities = 0;
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +	struct rte_eth_conf *conf = &dev->data->dev_conf;
> +
> +	speed = i40e_parse_link_speed(conf->link_speed);
> +	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
> +	if (conf->link_speed == ETH_LINK_SPEED_AUTONEG)
> +		abilities |= I40E_AQ_PHY_AN_ENABLED;
> +	else
> +		abilities |= I40E_AQ_PHY_LINK_ENABLED;
> +
> +	return i40e_phy_conf_link(hw, abilities, speed);
> +}
> +
>  static int
>  i40e_dev_start(struct rte_eth_dev *dev)
>  {
> @@ -657,6 +755,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
>  	struct i40e_vsi *vsi = pf->main_vsi;
>  	int ret;
> 
> +	if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX)
> &&
> +		(dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX))
> {
> +		PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu\n",
> +				dev->data->dev_conf.link_duplex,
> +				dev->data->port_id);
> +		return -EINVAL;
> +	}
> +
>  	/* Initialize VSI */
>  	ret = i40e_vsi_init(vsi);
>  	if (ret != I40E_SUCCESS) {
> @@ -682,6 +788,13 @@ i40e_dev_start(struct rte_eth_dev *dev)
>  			PMD_DRV_LOG(INFO, "fail to set vsi broadcast\n");
>  	}
> 
> +	/* Apply link configure */
> +	ret = i40e_apply_link_speed(dev);
> +	if (I40E_SUCCESS != ret) {
> +		PMD_DRV_LOG(ERR, "Fail to apply link setting\n");
> +		goto err_up;
> +	}
> +
>  	return I40E_SUCCESS;
> 
>  err_up:
> @@ -703,6 +816,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
>  	/* Clear all queues and release memory */
>  	i40e_dev_clear_queues(dev);
> 
> +	/* Set link down */
> +	i40e_dev_set_link_down(dev);
> +
>  	/* un-map queues with interrupt registers */
>  	i40e_vsi_disable_queues_intr(vsi);
>  	i40e_vsi_queues_unbind_intr(vsi);
> @@ -798,6 +914,29 @@ i40e_dev_allmulticast_disable(struct rte_eth_dev *dev)
>  		PMD_DRV_LOG(ERR, "Failed to disable multicast
> promiscuous\n");
>  }
> 
> +/*
> + * Set device link up.
> + */
> +static int
> +i40e_dev_set_link_up(struct rte_eth_dev *dev)
> +{
> +	/* re-apply link speed setting */
> +	return i40e_apply_link_speed(dev);
> +}
> +
> +/*
> + * Set device link down.
> + */
> +static int
> +i40e_dev_set_link_down(__rte_unused struct rte_eth_dev *dev)
> +{
> +	uint8_t speed = I40E_LINK_SPEED_UNKNOWN;
> +	uint8_t abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +
> +	return i40e_phy_conf_link(hw, abilities, speed);
> +}
> +
>  int
>  i40e_dev_link_update(struct rte_eth_dev *dev,
>  		     __rte_unused int wait_to_complete)
> --
> 1.8.1.4

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

* [dpdk-dev] [PATCH v2] i40e: support autoneg or force link speed
  2014-07-31 20:44 [dpdk-dev] [PATCH] i40e: support autoneg or force link speed Cunming Liang
  2014-08-20  8:29 ` Liang, Cunming
@ 2014-08-25  3:18 ` Cunming Liang
  2014-08-25 14:11   ` Thomas Monjalon
  1 sibling, 1 reply; 4+ messages in thread
From: Cunming Liang @ 2014-08-25  3:18 UTC (permalink / raw)
  To: dev

  - i40e force link up/down
  - i40e autoneg/force speed

  v2, fix warnning complain on gcc 4.6.3

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
Acked-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
Tested-by: Xu HuilongX <huilongx.xu@intel.com>
---
 app/test-pmd/cmdline.c            |  17 +++--
 lib/librte_pmd_i40e/i40e_ethdev.c | 141 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+), 6 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 345be11..0abc233 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -527,7 +527,8 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port close (port_id|all)\n"
 			"    Close all ports or port_id.\n\n"
 
-			"port config (port_id|all) speed (10|100|1000|10000|auto)"
+			"port config (port_id|all)"
+			" speed (10|100|1000|10000|40000|auto)"
 			" duplex (half|full|auto)\n"
 			"    Set speed and duplex for all ports or port_id\n\n"
 
@@ -801,7 +802,9 @@ cmd_config_speed_all_parsed(void *parsed_result,
 	else if (!strcmp(res->value1, "1000"))
 		link_speed = ETH_LINK_SPEED_1000;
 	else if (!strcmp(res->value1, "10000"))
-		link_speed = ETH_LINK_SPEED_10000;
+		link_speed = ETH_LINK_SPEED_10G;
+	else if (!strcmp(res->value1, "40000"))
+		link_speed = ETH_LINK_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
 		link_speed = ETH_LINK_SPEED_AUTONEG;
 	else {
@@ -839,7 +842,7 @@ cmdline_parse_token_string_t cmd_config_speed_all_item1 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1, "speed");
 cmdline_parse_token_string_t cmd_config_speed_all_value1 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
-						"10#100#1000#10000#auto");
+						"10#100#1000#10000#40000#auto");
 cmdline_parse_token_string_t cmd_config_speed_all_item2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
 cmdline_parse_token_string_t cmd_config_speed_all_value2 =
@@ -849,7 +852,7 @@ cmdline_parse_token_string_t cmd_config_speed_all_value2 =
 cmdline_parse_inst_t cmd_config_speed_all = {
 	.f = cmd_config_speed_all_parsed,
 	.data = NULL,
-	.help_str = "port config all speed 10|100|1000|10000|auto duplex "
+	.help_str = "port config all speed 10|100|1000|10000|40000|auto duplex "
 							"half|full|auto",
 	.tokens = {
 		(void *)&cmd_config_speed_all_port,
@@ -901,6 +904,8 @@ cmd_config_speed_specific_parsed(void *parsed_result,
 		link_speed = ETH_LINK_SPEED_1000;
 	else if (!strcmp(res->value1, "10000"))
 		link_speed = ETH_LINK_SPEED_10000;
+	else if (!strcmp(res->value1, "40000"))
+		link_speed = ETH_LINK_SPEED_40G;
 	else if (!strcmp(res->value1, "auto"))
 		link_speed = ETH_LINK_SPEED_AUTONEG;
 	else {
@@ -939,7 +944,7 @@ cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
 								"speed");
 cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
-						"10#100#1000#10000#auto");
+						"10#100#1000#10000#40000#auto");
 cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
 	TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
 								"duplex");
@@ -950,7 +955,7 @@ cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
 cmdline_parse_inst_t cmd_config_speed_specific = {
 	.f = cmd_config_speed_specific_parsed,
 	.data = NULL,
-	.help_str = "port config X speed 10|100|1000|10000|auto duplex "
+	.help_str = "port config X speed 10|100|1000|10000|40000|auto duplex "
 							"half|full|auto",
 	.tokens = {
 		(void *)&cmd_config_speed_specific_port,
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index 9ed31b5..0fcb797 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -128,6 +128,8 @@ static void i40e_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static void i40e_dev_promiscuous_disable(struct rte_eth_dev *dev);
 static void i40e_dev_allmulticast_enable(struct rte_eth_dev *dev);
 static void i40e_dev_allmulticast_disable(struct rte_eth_dev *dev);
+static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
+static int i40e_dev_set_link_down(struct rte_eth_dev *dev);
 static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
@@ -222,6 +224,8 @@ static struct eth_dev_ops i40e_eth_dev_ops = {
 	.promiscuous_disable          = i40e_dev_promiscuous_disable,
 	.allmulticast_enable          = i40e_dev_allmulticast_enable,
 	.allmulticast_disable         = i40e_dev_allmulticast_disable,
+	.dev_set_link_up              = i40e_dev_set_link_up,
+	.dev_set_link_down            = i40e_dev_set_link_down,
 	.link_update                  = i40e_dev_link_update,
 	.stats_get                    = i40e_dev_stats_get,
 	.stats_reset                  = i40e_dev_stats_reset,
@@ -649,6 +653,102 @@ i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_REG(hw, I40E_PFINT_DYN_CTLN(vsi->msix_intr - 1), 0);
 }
 
+static inline uint8_t
+i40e_parse_link_speed(uint16_t eth_link_speed)
+{
+	uint8_t link_speed = I40E_LINK_SPEED_UNKNOWN;
+
+	switch (eth_link_speed) {
+	case ETH_LINK_SPEED_40G:
+		link_speed = I40E_LINK_SPEED_40GB;
+		break;
+	case ETH_LINK_SPEED_20G:
+		link_speed = I40E_LINK_SPEED_20GB;
+		break;
+	case ETH_LINK_SPEED_10G:
+		link_speed = I40E_LINK_SPEED_10GB;
+		break;
+	case ETH_LINK_SPEED_1000:
+		link_speed = I40E_LINK_SPEED_1GB;
+		break;
+	case ETH_LINK_SPEED_100:
+		link_speed = I40E_LINK_SPEED_100MB;
+		break;
+	}
+
+	return link_speed;
+}
+
+static int
+i40e_phy_conf_link(struct i40e_hw *hw, uint8_t abilities, uint8_t force_speed)
+{
+	enum i40e_status_code status;
+	struct i40e_aq_get_phy_abilities_resp phy_ab;
+	struct i40e_aq_set_phy_config phy_conf;
+	const uint8_t mask = I40E_AQ_PHY_FLAG_PAUSE_TX |
+			I40E_AQ_PHY_FLAG_PAUSE_RX |
+			I40E_AQ_PHY_FLAG_LOW_POWER;
+	const uint8_t advt = I40E_LINK_SPEED_40GB |
+			I40E_LINK_SPEED_10GB |
+			I40E_LINK_SPEED_1GB |
+			I40E_LINK_SPEED_100MB;
+	int ret = -ENOTSUP;
+
+	status = i40e_aq_get_phy_capabilities(hw, false, false, &phy_ab,
+					      NULL);
+	if (status)
+		return ret;
+
+	memset(&phy_conf, 0, sizeof(phy_conf));
+
+	/* bits 0-2 use the values from get_phy_abilities_resp */
+	abilities &= ~mask;
+	abilities |= phy_ab.abilities & mask;
+
+	/* update ablities and speed */
+	if (abilities & I40E_AQ_PHY_AN_ENABLED)
+		phy_conf.link_speed = advt;
+	else
+		phy_conf.link_speed = force_speed;
+
+	phy_conf.abilities = abilities;
+
+	/* use get_phy_abilities_resp value for the rest */
+	phy_conf.phy_type = phy_ab.phy_type;
+	phy_conf.eee_capability = phy_ab.eee_capability;
+	phy_conf.eeer = phy_ab.eeer_val;
+	phy_conf.low_power_ctrl = phy_ab.d3_lpan;
+
+	PMD_DRV_LOG(DEBUG, "\n\tCurrent: abilities %x, link_speed %x\n"
+		    "\tConfig:  abilities %x, link_speed %x",
+		    phy_ab.abilities, phy_ab.link_speed,
+		    phy_conf.abilities, phy_conf.link_speed);
+
+	status = i40e_aq_set_phy_config(hw, &phy_conf, NULL);
+	if (status)
+		return ret;
+
+	return I40E_SUCCESS;
+}
+
+static int
+i40e_apply_link_speed(struct rte_eth_dev *dev)
+{
+	uint8_t speed;
+	uint8_t abilities = 0;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_eth_conf *conf = &dev->data->dev_conf;
+
+	speed = i40e_parse_link_speed(conf->link_speed);
+	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+	if (conf->link_speed == ETH_LINK_SPEED_AUTONEG)
+		abilities |= I40E_AQ_PHY_AN_ENABLED;
+	else
+		abilities |= I40E_AQ_PHY_LINK_ENABLED;
+
+	return i40e_phy_conf_link(hw, abilities, speed);
+}
+
 static int
 i40e_dev_start(struct rte_eth_dev *dev)
 {
@@ -657,6 +757,14 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct i40e_vsi *vsi = pf->main_vsi;
 	int ret;
 
+	if ((dev->data->dev_conf.link_duplex != ETH_LINK_AUTONEG_DUPLEX) &&
+		(dev->data->dev_conf.link_duplex != ETH_LINK_FULL_DUPLEX)) {
+		PMD_INIT_LOG(ERR, "Invalid link_duplex (%hu) for port %hhu\n",
+				dev->data->dev_conf.link_duplex,
+				dev->data->port_id);
+		return -EINVAL;
+	}
+
 	/* Initialize VSI */
 	ret = i40e_vsi_init(vsi);
 	if (ret != I40E_SUCCESS) {
@@ -682,6 +790,13 @@ i40e_dev_start(struct rte_eth_dev *dev)
 			PMD_DRV_LOG(INFO, "fail to set vsi broadcast\n");
 	}
 
+	/* Apply link configure */
+	ret = i40e_apply_link_speed(dev);
+	if (I40E_SUCCESS != ret) {
+		PMD_DRV_LOG(ERR, "Fail to apply link setting\n");
+		goto err_up;
+	}
+
 	return I40E_SUCCESS;
 
 err_up:
@@ -703,6 +818,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	/* Clear all queues and release memory */
 	i40e_dev_clear_queues(dev);
 
+	/* Set link down */
+	i40e_dev_set_link_down(dev);
+
 	/* un-map queues with interrupt registers */
 	i40e_vsi_disable_queues_intr(vsi);
 	i40e_vsi_queues_unbind_intr(vsi);
@@ -798,6 +916,29 @@ i40e_dev_allmulticast_disable(struct rte_eth_dev *dev)
 		PMD_DRV_LOG(ERR, "Failed to disable multicast promiscuous\n");
 }
 
+/*
+ * Set device link up.
+ */
+static int
+i40e_dev_set_link_up(struct rte_eth_dev *dev)
+{
+	/* re-apply link speed setting */
+	return i40e_apply_link_speed(dev);
+}
+
+/*
+ * Set device link down.
+ */
+static int
+i40e_dev_set_link_down(__rte_unused struct rte_eth_dev *dev)
+{
+	uint8_t speed = I40E_LINK_SPEED_UNKNOWN;
+	uint8_t abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	return i40e_phy_conf_link(hw, abilities, speed);
+}
+
 int
 i40e_dev_link_update(struct rte_eth_dev *dev,
 		     __rte_unused int wait_to_complete)
-- 
1.8.1.4

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

* Re: [dpdk-dev] [PATCH v2] i40e: support autoneg or force link speed
  2014-08-25  3:18 ` [dpdk-dev] [PATCH v2] " Cunming Liang
@ 2014-08-25 14:11   ` Thomas Monjalon
  0 siblings, 0 replies; 4+ messages in thread
From: Thomas Monjalon @ 2014-08-25 14:11 UTC (permalink / raw)
  To: Cunming Liang; +Cc: dev

>   - i40e force link up/down
>   - i40e autoneg/force speed
> 
>   v2, fix warnning complain on gcc 4.6.3
> 
> Signed-off-by: Cunming Liang <cunming.liang@intel.com>
> Acked-by: Helin Zhang <helin.zhang@intel.com>
> Acked-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
> Tested-by: Xu HuilongX <huilongx.xu@intel.com>

Applied for version 1.7.1.

Thanks
-- 
Thomas

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

end of thread, other threads:[~2014-08-25 14:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-31 20:44 [dpdk-dev] [PATCH] i40e: support autoneg or force link speed Cunming Liang
2014-08-20  8:29 ` Liang, Cunming
2014-08-25  3:18 ` [dpdk-dev] [PATCH v2] " Cunming Liang
2014-08-25 14:11   ` Thomas Monjalon

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).