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