| From 6033eeec2b029d99d4c0e46065f311fbbb2a1f1b Mon Sep 17 00:00:00 2001 |
| From: Lijian Zhang <Lijian.Zhang@arm.com> |
| Date: Wed, 18 Mar 2020 17:21:08 +0800 |
| Subject: [PATCH] ixgbe: fix false link down timing issue |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| This issue is observed with X520-2 NICs on FD.io Taishan server. After |
| VPP booting up and bringing up the interfaces with command ‘set |
| interface state <interface> up’, it still shows link down status from |
| the command ‘show hardware-interfaces’. However, the hardware link |
| status is actually up. dpdk_process() cannot get the hardware link |
| status correctly via rte_eth_link_get_nowait(). |
| |
| In ixgbe_dev_link_update_share(), if the media type is fiber and the |
| link is down, a flag (IXGBE_FLAG_NEED_LINK_CONFIG) is set. A callback to |
| ixgbe_dev_setup_link_alarm_handler() is scheduled trying to set up the |
| link and clear the flag afterwards. |
| |
| If the device is started or stopped before the flag is cleared, the |
| scheduled callback is canceled. This causes the flag to remain set and |
| subsequent calls to ixgbe_dev_link_update_share() return without trying |
| to retrieve the link state because the flag is set. |
| |
| When the callback is canceled by either interface start or stop |
| operation, in ixgbe_dev_cancel_link_thread(), after cancelling the |
| callback/thread, unset the flag on the device to avoid this condition. |
| |
| Signed-off-by: Lijian Zhang <Lijian.Zhang@arm.com> |
| --- |
| drivers/net/ixgbe/ixgbe_ethdev.c | 5 ++++- |
| 1 file changed, 4 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c |
| index 23b3f5b0c..aa882cb8b 100644 |
| --- a/drivers/net/ixgbe/ixgbe_ethdev.c |
| +++ b/drivers/net/ixgbe/ixgbe_ethdev.c |
| @@ -4147,11 +4147,14 @@ static void |
| ixgbe_dev_cancel_link_thread(struct rte_eth_dev *dev) |
| { |
| struct ixgbe_adapter *ad = dev->data->dev_private; |
| + struct ixgbe_interrupt *intr = |
| + IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); |
| void *retval; |
| |
| if (rte_atomic32_read(&ad->link_thread_running)) { |
| pthread_cancel(ad->link_thread_tid); |
| pthread_join(ad->link_thread_tid, &retval); |
| + intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; |
| rte_atomic32_clear(&ad->link_thread_running); |
| } |
| } |
| @@ -4262,8 +4265,8 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev, |
| |
| if (link_up == 0) { |
| if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) { |
| - intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; |
| if (rte_atomic32_test_and_set(&ad->link_thread_running)) { |
| + intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; |
| if (rte_ctrl_thread_create(&ad->link_thread_tid, |
| "ixgbe-link-handler", |
| NULL, |
| -- |
| 2.17.1 |
| |