Lijian.Zhang | 1690dcb | 2020-03-19 10:22:52 +0800 | [diff] [blame] | 1 | From 6033eeec2b029d99d4c0e46065f311fbbb2a1f1b Mon Sep 17 00:00:00 2001 |
| 2 | From: Lijian Zhang <Lijian.Zhang@arm.com> |
| 3 | Date: Wed, 18 Mar 2020 17:21:08 +0800 |
| 4 | Subject: [PATCH] ixgbe: fix false link down timing issue |
| 5 | MIME-Version: 1.0 |
| 6 | Content-Type: text/plain; charset=UTF-8 |
| 7 | Content-Transfer-Encoding: 8bit |
| 8 | |
| 9 | This issue is observed with X520-2 NICs on FD.io Taishan server. After |
| 10 | VPP booting up and bringing up the interfaces with command ‘set |
| 11 | interface state <interface> up’, it still shows link down status from |
| 12 | the command ‘show hardware-interfaces’. However, the hardware link |
| 13 | status is actually up. dpdk_process() cannot get the hardware link |
| 14 | status correctly via rte_eth_link_get_nowait(). |
| 15 | |
| 16 | In ixgbe_dev_link_update_share(), if the media type is fiber and the |
| 17 | link is down, a flag (IXGBE_FLAG_NEED_LINK_CONFIG) is set. A callback to |
| 18 | ixgbe_dev_setup_link_alarm_handler() is scheduled trying to set up the |
| 19 | link and clear the flag afterwards. |
| 20 | |
| 21 | If the device is started or stopped before the flag is cleared, the |
| 22 | scheduled callback is canceled. This causes the flag to remain set and |
| 23 | subsequent calls to ixgbe_dev_link_update_share() return without trying |
| 24 | to retrieve the link state because the flag is set. |
| 25 | |
| 26 | When the callback is canceled by either interface start or stop |
| 27 | operation, in ixgbe_dev_cancel_link_thread(), after cancelling the |
| 28 | callback/thread, unset the flag on the device to avoid this condition. |
| 29 | |
| 30 | Signed-off-by: Lijian Zhang <Lijian.Zhang@arm.com> |
| 31 | --- |
| 32 | drivers/net/ixgbe/ixgbe_ethdev.c | 5 ++++- |
| 33 | 1 file changed, 4 insertions(+), 1 deletion(-) |
| 34 | |
| 35 | diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c |
| 36 | index 23b3f5b0c..aa882cb8b 100644 |
| 37 | --- a/drivers/net/ixgbe/ixgbe_ethdev.c |
| 38 | +++ b/drivers/net/ixgbe/ixgbe_ethdev.c |
| 39 | @@ -4147,11 +4147,14 @@ static void |
| 40 | ixgbe_dev_cancel_link_thread(struct rte_eth_dev *dev) |
| 41 | { |
| 42 | struct ixgbe_adapter *ad = dev->data->dev_private; |
| 43 | + struct ixgbe_interrupt *intr = |
| 44 | + IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private); |
| 45 | void *retval; |
| 46 | |
| 47 | if (rte_atomic32_read(&ad->link_thread_running)) { |
| 48 | pthread_cancel(ad->link_thread_tid); |
| 49 | pthread_join(ad->link_thread_tid, &retval); |
| 50 | + intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; |
| 51 | rte_atomic32_clear(&ad->link_thread_running); |
| 52 | } |
| 53 | } |
| 54 | @@ -4262,8 +4265,8 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev, |
| 55 | |
| 56 | if (link_up == 0) { |
| 57 | if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) { |
| 58 | - intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; |
| 59 | if (rte_atomic32_test_and_set(&ad->link_thread_running)) { |
| 60 | + intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; |
| 61 | if (rte_ctrl_thread_create(&ad->link_thread_tid, |
| 62 | "ixgbe-link-handler", |
| 63 | NULL, |
| 64 | -- |
| 65 | 2.17.1 |
| 66 | |