The link update originally direct coded into the periodic service thread and is made separate in preparation for additional SFP handling code.
Signed-off-by: Jeff Daly <je...@silicom-usa.com> Inspired-by: Stephen Douthit <steph...@silicom-usa.com> --- drivers/net/ixgbe/ixgbe_ethdev.c | 99 ++++++++++++++++++++++---------- drivers/net/ixgbe/ixgbe_ethdev.h | 1 + 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 81b15ad28212..f1694ef76b14 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -4131,48 +4131,89 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, return ret_val; } -static void * -ixgbe_dev_setup_link_thread_handler(void *param) +static void +ixgbe_link_service(struct rte_eth_dev *dev) { - 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, start, ticks, service_ms; + bool link_up, autoneg = false, have_int = false; + u32 speed; s32 err; - bool link_up, autoneg = false; - pthread_detach(pthread_self()); + /* Test if we have a LSC interrupt for this platform, if not we need to + * manually check the link register since IXGBE_FLAG_NEED_LINK_CONFIG + * will never be set in the interrupt handler + */ +#ifndef RTE_EXEC_ENV_FREEBSD + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = pci_dev->intr_handle; + if (rte_intr_allow_others(intr_handle)) { + /* check if LSC interrupt is enabled */ + if (dev->data->dev_conf.intr_conf.lsc) + have_int = true; + } +#endif /* #ifdef RTE_EXEC_ENV_FREEBSD */ - while (1) { - service_ms = 100; - if (intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG) { - speed = hw->phy.autoneg_advertised; + /* Skip if we still need to setup an SFP, or if no link config requested + */ + if ((intr->flags & IXGBE_FLAG_NEED_SFP_SETUP) || + (!(intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG) && have_int)) + return; + + if (!have_int && !(intr->flags & IXGBE_FLAG_NEED_LINK_CONFIG)) { + err = ixgbe_check_link(hw, &speed, &link_up, 0); + if (!err && !link_up) { + intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG; + PMD_DRV_LOG(DEBUG, "Link down, no LSC, set NEED_LINK_CONFIG\n"); + } else { + return; + } + } + + speed = hw->phy.autoneg_advertised; + if (!speed) + ixgbe_get_link_capabilities(hw, &speed, &autoneg); - if (!speed) - ixgbe_get_link_capabilities(hw, &speed, &autoneg); + err = ixgbe_setup_link(hw, speed, true); + if (err) { + PMD_DRV_LOG(ERR, "ixgbe_setup_link failed %d\n", err); + return; + } - err = ixgbe_setup_link(hw, speed, true); + intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; +} - if (err == IXGBE_SUCCESS) - err = ixgbe_check_link(hw, &speed, &link_up, 0); +static void * +ixgbe_dev_setup_link_thread_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); + u32 speed, start, ticks, service_ms; + s32 err; + bool link_up = false; - /* Run the service thread handler more frequently when link is - * down to reduce link up latency (every 200ms vs 1s) - * - * Use a number of smaller sleeps to decrease exit latency when - * ixgbe_dev_stop() wants this thread to join - */ - if (err == IXGBE_SUCCESS && link_up) { - service_ms = 2000; - intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; - } + pthread_detach(pthread_self()); - if (!ixgbe_dev_link_update(dev, 0)) { - ixgbe_dev_link_status_print(dev); - rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); - } + while (1) { + ixgbe_link_service(dev); + + if (!ixgbe_dev_link_update(dev, 0)) { + ixgbe_dev_link_status_print(dev); + rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL); } + /* Run the service thread handler more frequently when link is + * down to reduce link up latency (every 200ms vs 1s) + * + * Use a number of smaller sleeps to decrease exit latency when + * ixgbe_dev_stop() wants this thread to join + */ + + err = ixgbe_check_link(hw, &speed, &link_up, 0); + if (err == IXGBE_SUCCESS && link_up) + service_ms = 2000; + else + service_ms = 100; /* Call msec_delay in a loop with several smaller sleeps to * provide periodic thread cancellation points diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h index 69e0e82a5b1a..f61706c9eae6 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.h +++ b/drivers/net/ixgbe/ixgbe_ethdev.h @@ -29,6 +29,7 @@ #define IXGBE_FLAG_PHY_INTERRUPT (uint32_t)(1 << 2) #define IXGBE_FLAG_MACSEC (uint32_t)(1 << 3) #define IXGBE_FLAG_NEED_LINK_CONFIG (uint32_t)(1 << 4) +#define IXGBE_FLAG_NEED_SFP_SETUP (uint32_t)(1 << 5) /* * Defines that were not part of ixgbe_type.h as they are not used by the -- 2.25.1