* [PATCH] drivers/i40e: fix link update no wait
@ 2018-03-08 11:55 Fan Zhang
2018-03-08 12:17 ` [PATCH v2] " Fan Zhang
0 siblings, 1 reply; 5+ messages in thread
From: Fan Zhang @ 2018-03-08 11:55 UTC (permalink / raw)
To: dev; +Cc: michael.j.glynn, roy.fan.zhang, stable, helin.zhang, Andrey Chilikin
Fixes: 263333bbb7a9 ("i40e: fix link status timeout")
In i40e_dev_link_update() the driver obtains the link status
info via admin queue command despite of "no_wait" flag. This
requires relatively long time and may be a problem to some
application such as ovs-dpdk
(https://bugzilla.redhat.com/show_bug.cgi?id=1551761).
This patch aims to fix the problem by using a different
approach of obtaining link status for i40e NIC without waiting.
Instead of getting the link status via admin queue command,
this patch reads the link status registers to accelerate the
procedure.
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 128 ++++++++++++++++++++++++++++++-----------
1 file changed, 95 insertions(+), 33 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 508b4171c..968249ed1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2437,77 +2437,139 @@ i40e_dev_set_link_down(struct rte_eth_dev *dev)
return i40e_phy_conf_link(hw, abilities, speed, false);
}
-int
-i40e_dev_link_update(struct rte_eth_dev *dev,
- int wait_to_complete)
+static __rte_always_inline void
+update_link_no_wait(struct i40e_hw *hw, struct rte_eth_link *link)
+{
+/* Link status registers and values*/
+#define I40E_PRTMAC_LINKSTA 0x001E2420
+#define I40E_REG_LINK_UP 0x40000080
+#define I40E_PRTMAC_MACC 0x001E24E0
+#define I40E_REG_MACC_25GB 0x00020000
+#define I40E_REG_SPEED_MASK 0x38000000
+#define I40E_REG_SPEED_100MB 0x00000000
+#define I40E_REG_SPEED_1GB 0x08000000
+#define I40E_REG_SPEED_10GB 0x10000000
+#define I40E_REG_SPEED_20GB 0x20000000
+#define I40E_REG_SPEED_25_40GB 0x18000000
+ uint32_t link_speed;
+ uint32_t reg_val;
+
+ reg_val = I40E_READ_REG(hw, I40E_PRTMAC_LINKSTA);
+ link_speed = reg_val & I40E_REG_SPEED_MASK;
+ reg_val &= I40E_REG_LINK_UP;
+ link->link_status = (reg_val == I40E_REG_LINK_UP) ? 1 : 0;
+
+ if (unlikely(link->link_status != 0))
+ return;
+
+ /* Parse the link status */
+ switch (link_speed) {
+ case I40E_REG_SPEED_100MB:
+ link->link_speed = ETH_SPEED_NUM_100M;
+ break;
+ case I40E_REG_SPEED_1GB:
+ link->link_speed = ETH_SPEED_NUM_1G;
+ break;
+ case I40E_REG_SPEED_10GB:
+ link->link_speed = ETH_SPEED_NUM_10G;
+ break;
+ case I40E_REG_SPEED_20GB:
+ link->link_speed = ETH_SPEED_NUM_20G;
+ break;
+ case I40E_REG_SPEED_25_40GB:
+ reg_val = I40E_READ_REG(hw, I40E_PRTMAC_MACC);
+
+ if (reg_val & I40E_REG_MACC_25GB)
+ link->link_speed = ETH_SPEED_NUM_25G;
+ else
+ link->link_speed = ETH_SPEED_NUM_40G;
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unknown link speed info %u", link_speed);
+ break;
+ }
+}
+
+static __rte_always_inline void
+update_link_wait(struct i40e_hw *hw, struct rte_eth_link *link,
+ bool enable_lse)
{
-#define CHECK_INTERVAL 100 /* 100ms */
-#define MAX_REPEAT_TIME 10 /* 1s (10 * 100ms) in total */
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_REPEAT_TIME 10 /* 1s (10 * 100ms) in total */
+ uint32_t rep_cnt = MAX_REPEAT_TIME;
struct i40e_link_status link_status;
- struct rte_eth_link link, old;
int status;
- unsigned rep_cnt = MAX_REPEAT_TIME;
- bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
- memset(&link, 0, sizeof(link));
- memset(&old, 0, sizeof(old));
memset(&link_status, 0, sizeof(link_status));
- rte_i40e_dev_atomic_read_link_status(dev, &old);
do {
/* Get link status information from hardware */
status = i40e_aq_get_link_info(hw, enable_lse,
&link_status, NULL);
- if (status != I40E_SUCCESS) {
- link.link_speed = ETH_SPEED_NUM_100M;
- link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ if (unlikely(status != I40E_SUCCESS)) {
+ link->link_speed = ETH_SPEED_NUM_100M;
+ link->link_duplex = ETH_LINK_FULL_DUPLEX;
PMD_DRV_LOG(ERR, "Failed to get link info");
- goto out;
+ return;
}
- link.link_status = link_status.link_info & I40E_AQ_LINK_UP;
- if (!wait_to_complete || link.link_status)
- break;
+ link->link_status = link_status.link_info & I40E_AQ_LINK_UP;
+ if (unlikely(link->link_status != 0))
+ return;
rte_delay_ms(CHECK_INTERVAL);
} while (--rep_cnt);
- if (!link.link_status)
- goto out;
-
- /* i40e uses full duplex only */
- link.link_duplex = ETH_LINK_FULL_DUPLEX;
-
/* Parse the link status */
switch (link_status.link_speed) {
case I40E_LINK_SPEED_100MB:
- link.link_speed = ETH_SPEED_NUM_100M;
+ link->link_speed = ETH_SPEED_NUM_100M;
break;
case I40E_LINK_SPEED_1GB:
- link.link_speed = ETH_SPEED_NUM_1G;
+ link->link_speed = ETH_SPEED_NUM_1G;
break;
case I40E_LINK_SPEED_10GB:
- link.link_speed = ETH_SPEED_NUM_10G;
+ link->link_speed = ETH_SPEED_NUM_10G;
break;
case I40E_LINK_SPEED_20GB:
- link.link_speed = ETH_SPEED_NUM_20G;
+ link->link_speed = ETH_SPEED_NUM_20G;
break;
case I40E_LINK_SPEED_25GB:
- link.link_speed = ETH_SPEED_NUM_25G;
+ link->link_speed = ETH_SPEED_NUM_25G;
break;
case I40E_LINK_SPEED_40GB:
- link.link_speed = ETH_SPEED_NUM_40G;
+ link->link_speed = ETH_SPEED_NUM_40G;
break;
default:
- link.link_speed = ETH_SPEED_NUM_100M;
+ link->link_speed = ETH_SPEED_NUM_100M;
break;
}
+}
+
+int
+i40e_dev_link_update(struct rte_eth_dev *dev,
+ int wait_to_complete)
+{
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_eth_link link, old;
+ bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
+ memset(&link, 0, sizeof(link));
+ memset(&old, 0, sizeof(old));
+
+ rte_i40e_dev_atomic_read_link_status(dev, &old);
+
+ /* i40e uses full duplex only */
+ link.link_duplex = ETH_LINK_FULL_DUPLEX;
link.link_autoneg = !(dev->data->dev_conf.link_speeds &
ETH_LINK_SPEED_FIXED);
-out:
+ if (!wait_to_complete)
+ update_link_no_wait(hw, &link);
+ else
+ update_link_wait(hw, &link, enable_lse);
+
rte_i40e_dev_atomic_write_link_status(dev, &link);
if (link.link_status == old.link_status)
return -1;
--
2.13.6
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2] drivers/i40e: fix link update no wait
2018-03-08 11:55 [PATCH] drivers/i40e: fix link update no wait Fan Zhang
@ 2018-03-08 12:17 ` Fan Zhang
2018-03-08 13:01 ` Eelco Chaudron
2018-03-09 8:45 ` Lu, Wenzhuo
0 siblings, 2 replies; 5+ messages in thread
From: Fan Zhang @ 2018-03-08 12:17 UTC (permalink / raw)
To: dev
Cc: michael.j.glynn, roy.fan.zhang, stable, helin.zhang,
cunming.liang, Andrey Chilikin
Fixes: 263333bbb7a9 ("i40e: fix link status timeout")
Cc: cunming.liang@intel.com
Cc: stable@dpdk.org
In i40e_dev_link_update() the driver obtains the link status
info via admin queue command despite of "no_wait" flag. This
requires relatively long time and may be a problem to some
application such as ovs-dpdk
(https://bugzilla.redhat.com/show_bug.cgi?id=1551761).
This patch aims to fix the problem by using a different
approach of obtaining link status for i40e NIC without waiting.
Instead of getting the link status via admin queue command,
this patch reads the link status registers to accelerate the
procedure.
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
---
v2:
- add ccs after fixline
drivers/net/i40e/i40e_ethdev.c | 128 ++++++++++++++++++++++++++++++-----------
1 file changed, 95 insertions(+), 33 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 508b4171c..968249ed1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2437,77 +2437,139 @@ i40e_dev_set_link_down(struct rte_eth_dev *dev)
return i40e_phy_conf_link(hw, abilities, speed, false);
}
-int
-i40e_dev_link_update(struct rte_eth_dev *dev,
- int wait_to_complete)
+static __rte_always_inline void
+update_link_no_wait(struct i40e_hw *hw, struct rte_eth_link *link)
+{
+/* Link status registers and values*/
+#define I40E_PRTMAC_LINKSTA 0x001E2420
+#define I40E_REG_LINK_UP 0x40000080
+#define I40E_PRTMAC_MACC 0x001E24E0
+#define I40E_REG_MACC_25GB 0x00020000
+#define I40E_REG_SPEED_MASK 0x38000000
+#define I40E_REG_SPEED_100MB 0x00000000
+#define I40E_REG_SPEED_1GB 0x08000000
+#define I40E_REG_SPEED_10GB 0x10000000
+#define I40E_REG_SPEED_20GB 0x20000000
+#define I40E_REG_SPEED_25_40GB 0x18000000
+ uint32_t link_speed;
+ uint32_t reg_val;
+
+ reg_val = I40E_READ_REG(hw, I40E_PRTMAC_LINKSTA);
+ link_speed = reg_val & I40E_REG_SPEED_MASK;
+ reg_val &= I40E_REG_LINK_UP;
+ link->link_status = (reg_val == I40E_REG_LINK_UP) ? 1 : 0;
+
+ if (unlikely(link->link_status != 0))
+ return;
+
+ /* Parse the link status */
+ switch (link_speed) {
+ case I40E_REG_SPEED_100MB:
+ link->link_speed = ETH_SPEED_NUM_100M;
+ break;
+ case I40E_REG_SPEED_1GB:
+ link->link_speed = ETH_SPEED_NUM_1G;
+ break;
+ case I40E_REG_SPEED_10GB:
+ link->link_speed = ETH_SPEED_NUM_10G;
+ break;
+ case I40E_REG_SPEED_20GB:
+ link->link_speed = ETH_SPEED_NUM_20G;
+ break;
+ case I40E_REG_SPEED_25_40GB:
+ reg_val = I40E_READ_REG(hw, I40E_PRTMAC_MACC);
+
+ if (reg_val & I40E_REG_MACC_25GB)
+ link->link_speed = ETH_SPEED_NUM_25G;
+ else
+ link->link_speed = ETH_SPEED_NUM_40G;
+
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "Unknown link speed info %u", link_speed);
+ break;
+ }
+}
+
+static __rte_always_inline void
+update_link_wait(struct i40e_hw *hw, struct rte_eth_link *link,
+ bool enable_lse)
{
-#define CHECK_INTERVAL 100 /* 100ms */
-#define MAX_REPEAT_TIME 10 /* 1s (10 * 100ms) in total */
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_REPEAT_TIME 10 /* 1s (10 * 100ms) in total */
+ uint32_t rep_cnt = MAX_REPEAT_TIME;
struct i40e_link_status link_status;
- struct rte_eth_link link, old;
int status;
- unsigned rep_cnt = MAX_REPEAT_TIME;
- bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
- memset(&link, 0, sizeof(link));
- memset(&old, 0, sizeof(old));
memset(&link_status, 0, sizeof(link_status));
- rte_i40e_dev_atomic_read_link_status(dev, &old);
do {
/* Get link status information from hardware */
status = i40e_aq_get_link_info(hw, enable_lse,
&link_status, NULL);
- if (status != I40E_SUCCESS) {
- link.link_speed = ETH_SPEED_NUM_100M;
- link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ if (unlikely(status != I40E_SUCCESS)) {
+ link->link_speed = ETH_SPEED_NUM_100M;
+ link->link_duplex = ETH_LINK_FULL_DUPLEX;
PMD_DRV_LOG(ERR, "Failed to get link info");
- goto out;
+ return;
}
- link.link_status = link_status.link_info & I40E_AQ_LINK_UP;
- if (!wait_to_complete || link.link_status)
- break;
+ link->link_status = link_status.link_info & I40E_AQ_LINK_UP;
+ if (unlikely(link->link_status != 0))
+ return;
rte_delay_ms(CHECK_INTERVAL);
} while (--rep_cnt);
- if (!link.link_status)
- goto out;
-
- /* i40e uses full duplex only */
- link.link_duplex = ETH_LINK_FULL_DUPLEX;
-
/* Parse the link status */
switch (link_status.link_speed) {
case I40E_LINK_SPEED_100MB:
- link.link_speed = ETH_SPEED_NUM_100M;
+ link->link_speed = ETH_SPEED_NUM_100M;
break;
case I40E_LINK_SPEED_1GB:
- link.link_speed = ETH_SPEED_NUM_1G;
+ link->link_speed = ETH_SPEED_NUM_1G;
break;
case I40E_LINK_SPEED_10GB:
- link.link_speed = ETH_SPEED_NUM_10G;
+ link->link_speed = ETH_SPEED_NUM_10G;
break;
case I40E_LINK_SPEED_20GB:
- link.link_speed = ETH_SPEED_NUM_20G;
+ link->link_speed = ETH_SPEED_NUM_20G;
break;
case I40E_LINK_SPEED_25GB:
- link.link_speed = ETH_SPEED_NUM_25G;
+ link->link_speed = ETH_SPEED_NUM_25G;
break;
case I40E_LINK_SPEED_40GB:
- link.link_speed = ETH_SPEED_NUM_40G;
+ link->link_speed = ETH_SPEED_NUM_40G;
break;
default:
- link.link_speed = ETH_SPEED_NUM_100M;
+ link->link_speed = ETH_SPEED_NUM_100M;
break;
}
+}
+
+int
+i40e_dev_link_update(struct rte_eth_dev *dev,
+ int wait_to_complete)
+{
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_eth_link link, old;
+ bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
+ memset(&link, 0, sizeof(link));
+ memset(&old, 0, sizeof(old));
+
+ rte_i40e_dev_atomic_read_link_status(dev, &old);
+
+ /* i40e uses full duplex only */
+ link.link_duplex = ETH_LINK_FULL_DUPLEX;
link.link_autoneg = !(dev->data->dev_conf.link_speeds &
ETH_LINK_SPEED_FIXED);
-out:
+ if (!wait_to_complete)
+ update_link_no_wait(hw, &link);
+ else
+ update_link_wait(hw, &link, enable_lse);
+
rte_i40e_dev_atomic_write_link_status(dev, &link);
if (link.link_status == old.link_status)
return -1;
--
2.13.6
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] drivers/i40e: fix link update no wait
2018-03-08 12:17 ` [PATCH v2] " Fan Zhang
@ 2018-03-08 13:01 ` Eelco Chaudron
2018-03-09 8:45 ` Lu, Wenzhuo
1 sibling, 0 replies; 5+ messages in thread
From: Eelco Chaudron @ 2018-03-08 13:01 UTC (permalink / raw)
To: Fan Zhang, dev
Cc: michael.j.glynn, stable, helin.zhang, cunming.liang,
Andrey Chilikin, Flavio Leitner
On 08/03/18 13:17, Fan Zhang wrote:
> Fixes: 263333bbb7a9 ("i40e: fix link status timeout")
> Cc: cunming.liang@intel.com
> Cc: stable@dpdk.org
>
> In i40e_dev_link_update() the driver obtains the link status
> info via admin queue command despite of "no_wait" flag. This
> requires relatively long time and may be a problem to some
> application such as ovs-dpdk
> (https://bugzilla.redhat.com/show_bug.cgi?id=1551761).
>
> This patch aims to fix the problem by using a different
> approach of obtaining link status for i40e NIC without waiting.
> Instead of getting the link status via admin queue command,
> this patch reads the link status registers to accelerate the
> procedure.
Reviewed the changes, and tested them in combination with Open vSwitch
bonds/direct interfaces through various VMs and found no problems. Also
tested basic link flapping.
Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
Tested-by: Eelco Chaudron <echaudro@redhat.com>
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
> ---
> v2:
> - add ccs after fixline
>
> <SNIP>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] drivers/i40e: fix link update no wait
2018-03-08 12:17 ` [PATCH v2] " Fan Zhang
2018-03-08 13:01 ` Eelco Chaudron
@ 2018-03-09 8:45 ` Lu, Wenzhuo
2018-03-09 13:22 ` Zhang, Helin
1 sibling, 1 reply; 5+ messages in thread
From: Lu, Wenzhuo @ 2018-03-09 8:45 UTC (permalink / raw)
To: Zhang, Roy Fan, dev
Cc: Glynn, Michael J, Zhang, Roy Fan, stable, Zhang, Helin, Liang,
Cunming, Chilikin, Andrey
Hi,
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Fan Zhang
> Sent: Thursday, March 8, 2018 8:18 PM
> To: dev@dpdk.org
> Cc: Glynn, Michael J <michael.j.glynn@intel.com>; Zhang, Roy Fan
> <roy.fan.zhang@intel.com>; stable@dpdk.org; Zhang, Helin
> <helin.zhang@intel.com>; Liang, Cunming <cunming.liang@intel.com>;
> Chilikin, Andrey <andrey.chilikin@intel.com>
> Subject: [dpdk-dev] [PATCH v2] drivers/i40e: fix link update no wait
>
> Fixes: 263333bbb7a9 ("i40e: fix link status timeout")
> Cc: cunming.liang@intel.com
> Cc: stable@dpdk.org
>
> In i40e_dev_link_update() the driver obtains the link status info via admin
> queue command despite of "no_wait" flag. This requires relatively long time
> and may be a problem to some application such as ovs-dpdk
> (https://bugzilla.redhat.com/show_bug.cgi?id=1551761).
>
> This patch aims to fix the problem by using a different approach of obtaining
> link status for i40e NIC without waiting.
> Instead of getting the link status via admin queue command, this patch
> reads the link status registers to accelerate the procedure.
>
> Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] drivers/i40e: fix link update no wait
2018-03-09 8:45 ` Lu, Wenzhuo
@ 2018-03-09 13:22 ` Zhang, Helin
0 siblings, 0 replies; 5+ messages in thread
From: Zhang, Helin @ 2018-03-09 13:22 UTC (permalink / raw)
To: Lu, Wenzhuo, Zhang, Roy Fan, dev
> -----Original Message-----
> From: Lu, Wenzhuo
> Sent: Friday, March 9, 2018 4:45 PM
> To: Zhang, Roy Fan; dev@dpdk.org
> Cc: Glynn, Michael J; Zhang, Roy Fan; stable@dpdk.org; Zhang, Helin; Liang,
> Cunming; Chilikin, Andrey
> Subject: RE: [dpdk-dev] [PATCH v2] drivers/i40e: fix link update no wait
>
> Hi,
>
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Fan Zhang
> > Sent: Thursday, March 8, 2018 8:18 PM
> > To: dev@dpdk.org
> > Cc: Glynn, Michael J <michael.j.glynn@intel.com>; Zhang, Roy Fan
> > <roy.fan.zhang@intel.com>; stable@dpdk.org; Zhang, Helin
> > <helin.zhang@intel.com>; Liang, Cunming <cunming.liang@intel.com>;
> > Chilikin, Andrey <andrey.chilikin@intel.com>
> > Subject: [dpdk-dev] [PATCH v2] drivers/i40e: fix link update no wait
> >
> > Fixes: 263333bbb7a9 ("i40e: fix link status timeout")
> > Cc: cunming.liang@intel.com
> > Cc: stable@dpdk.org
> >
> > In i40e_dev_link_update() the driver obtains the link status info via
> > admin queue command despite of "no_wait" flag. This requires
> > relatively long time and may be a problem to some application such as
> > ovs-dpdk (https://bugzilla.redhat.com/show_bug.cgi?id=1551761).
> >
> > This patch aims to fix the problem by using a different approach of
> > obtaining link status for i40e NIC without waiting.
> > Instead of getting the link status via admin queue command, this patch
> > reads the link status registers to accelerate the procedure.
> >
> > Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
> > Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
> Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Applied to dpdk-next-net-intel, with minor commit log changes. Thanks!
/Helin
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-03-09 13:22 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-08 11:55 [PATCH] drivers/i40e: fix link update no wait Fan Zhang
2018-03-08 12:17 ` [PATCH v2] " Fan Zhang
2018-03-08 13:01 ` Eelco Chaudron
2018-03-09 8:45 ` Lu, Wenzhuo
2018-03-09 13:22 ` Zhang, Helin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.