[2/3] ixgbe: move periodic link service work into separate function
Checks
Commit Message
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 <jeffd@silicom-usa.com>
Inspired-by: Stephen Douthit <stephend@silicom-usa.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 99 ++++++++++++++++++++++----------
drivers/net/ixgbe/ixgbe_ethdev.h | 1 +
2 files changed, 71 insertions(+), 29 deletions(-)
@@ -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
@@ -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