summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@samsung.com>2018-11-01 19:04:59 +0300
committerFerruh Yigit <ferruh.yigit@intel.com>2018-11-05 15:01:25 +0100
commit0408f47ba4d67f0cb96f5e907bc9336b6cbff0dd (patch)
tree95207c586de8b8fcd3ce7239287b2ef1cefc239d /drivers
parent65c9d24170c9ec1db59d3472b7c4af3fd087d621 (diff)
downloaddpdk-0408f47ba4d67f0cb96f5e907bc9336b6cbff0dd.zip
dpdk-0408f47ba4d67f0cb96f5e907bc9336b6cbff0dd.tar.gz
dpdk-0408f47ba4d67f0cb96f5e907bc9336b6cbff0dd.tar.xz
net/ixgbe: fix busy polling while fiber link update
If the multispeed fiber link is in DOWN state, ixgbe_setup_link could take around a second of busy polling. This is highly inconvenient for the case where single thread periodically checks the link statuses. For example, OVS main thread periodically updates the link statuses and hangs for a really long time busy waiting on ixgbe_setup_link() for a DOWN fiber ports. For case with 3 down ports it hangs for a 3 seconds and unable to do anything including packet processing. Fix that by shifting that workaround to a separate thread by alarm handler that will try to set up link if it is DOWN. Fixes: c12d22f65b13 ("net/ixgbe: ensure link status is updated") Cc: stable@dpdk.org Signed-off-by: Ilya Maximets <i.maximets@samsung.com> Reviewed-by: Qi Zhang <qi.z.zhang@intel.com> Reviewed-by: Wei Zhao <wei.zhao1@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ixgbe/ixgbe_ethdev.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 5a2c351..c9e82d5 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -220,6 +220,8 @@ static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev);
static void ixgbe_dev_interrupt_handler(void *param);
static void ixgbe_dev_interrupt_delayed_handler(void *param);
+static void ixgbe_dev_setup_link_alarm_handler(void *param);
+
static int ixgbe_add_rar(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
uint32_t index, uint32_t pool);
static void ixgbe_remove_rar(struct rte_eth_dev *dev, uint32_t index);
@@ -2793,6 +2795,8 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
PMD_INIT_FUNC_TRACE();
+ rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
+
/* disable interrupts */
ixgbe_disable_intr(hw);
@@ -3971,6 +3975,25 @@ out:
return ret_val;
}
+static void
+ixgbe_dev_setup_link_alarm_handler(void *param)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+ struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct ixgbe_interrupt *intr =
+ IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
+ u32 speed;
+ bool autoneg = false;
+
+ speed = hw->phy.autoneg_advertised;
+ if (!speed)
+ ixgbe_get_link_capabilities(hw, &speed, &autoneg);
+
+ ixgbe_setup_link(hw, speed, true);
+
+ intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
+}
+
/* return 0 means link status changed, -1 means not changed */
int
ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
@@ -3983,9 +4006,7 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
int link_up;
int diag;
- u32 speed = 0;
int wait = 1;
- bool autoneg = false;
memset(&link, 0, sizeof(link));
link.link_status = ETH_LINK_DOWN;
@@ -3995,13 +4016,8 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
hw->mac.get_link_status = true;
- if ((intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG) &&
- ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {
- speed = hw->phy.autoneg_advertised;
- if (!speed)
- ixgbe_get_link_capabilities(hw, &speed, &autoneg);
- ixgbe_setup_link(hw, speed, true);
- }
+ if (intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG)
+ return rte_eth_linkstatus_set(dev, &link);
/* check if it needs to wait to complete, if lsc interrupt is enabled */
if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0)
@@ -4019,11 +4035,14 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
}
if (link_up == 0) {
- intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
+ if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {
+ intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
+ rte_eal_alarm_set(10,
+ ixgbe_dev_setup_link_alarm_handler, dev);
+ }
return rte_eth_linkstatus_set(dev, &link);
}
- intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
link.link_status = ETH_LINK_UP;
link.link_duplex = ETH_LINK_FULL_DUPLEX;
@@ -5128,6 +5147,8 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)
PMD_INIT_FUNC_TRACE();
+ rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
+
ixgbevf_intr_disable(dev);
hw->adapter_stopped = 1;