txgbe_dev_set_link_down() clears hw->dev_start, but the Amber-Lite
AN73 watchdog treats a down link as a recovery condition and can start
negotiation again. The setup-link alarm handler can likewise configure
the PHY after a link update or a previous setup retry.
As a result, a port brought down through rte_eth_dev_set_link_down()
can link up again without a matching rte_eth_dev_set_link_up() call.
Use hw->dev_start as the administrative link gate, and skip link
recovery while the port is administratively down.
The gate alone is not enough. A setup-link run that started before
link-down keeps going and rewrites the PMD transmit and receive
enables, so the port reports down while the peer still sees a signal.
Stop the AN73 watchdog and the setup-link alarm, wait for a running
link thread to finish, and only then drop the transmitter.
Arm the watchdog again on link-up so that monitoring resumes, and
cancel it first. The alarm list keeps every entry registered for the
same callback, and each entry re-arms itself, so arming without
cancelling would leave two watchdog chains running.
This keeps the link down until rte_eth_dev_set_link_up() explicitly
re-enables it. The link-up path then restores the required PHY
configuration.
Fixes: 234ce0d1fa9d ("net/txgbe: fix link stability for Amber-Lite backplane
mode")
Fixes: 6104fd11086e ("net/txgbe: fix link stability for 25G NIC")
Cc: [email protected]
Signed-off-by: Zaiyu Wang <[email protected]>
---
drivers/net/txgbe/txgbe_ethdev.c | 34 +++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 043c96b747..fc3c5539c2 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -2227,12 +2227,33 @@ txgbe_dev_set_link_up(struct rte_eth_dev *dev)
}
hw->dev_start = true;
+ if (hw->mac.type == txgbe_mac_aml ||
+ hw->mac.type == txgbe_mac_aml40) {
+ rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev);
+ rte_eal_alarm_set(hw->bp_event_interval,
+ txgbe_dev_e56_check_bp_event, dev);
+ }
txgbe_dev_link_update(dev, 0);
}
return 0;
}
+static void
+txgbe_stop_link_handlers(struct rte_eth_dev *dev)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+
+ if (hw->mac.type != txgbe_mac_aml &&
+ hw->mac.type != txgbe_mac_aml40)
+ return;
+
+ rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev);
+ rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw);
+ txgbe_dev_wait_setup_link_complete(dev, 0);
+ rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw);
+}
+
/*
* Set device link down: disable tx.
*/
@@ -2245,9 +2266,11 @@ txgbe_dev_set_link_down(struct rte_eth_dev *dev)
/* Turn off the copper */
hw->phy.set_phy_power(hw, false);
} else {
+ hw->dev_start = false;
+ txgbe_stop_link_handlers(dev);
+
/* Turn off the laser */
hw->mac.disable_tx_laser(hw);
- hw->dev_start = false;
txgbe_dev_link_update(dev, 0);
}
@@ -3073,8 +3096,8 @@ void txgbe_dev_e56_check_bp_event(void *param)
if (!hw->devarg.auto_neg)
return;
- /* only continue if link is down */
- if (dev->data->dev_link.link_status)
+ /* Continue only for an administratively up port with link down. */
+ if (!hw->dev_start || dev->data->dev_link.link_status)
goto out;
value = rd32_epcs(hw, VR_AN_INTR);
@@ -3412,6 +3435,11 @@ txgbe_dev_setup_link_alarm_handler_aml(void *param)
bool autoneg = false;
u32 gssr = hw->phy.phy_semaphore_mask;
+ if (!hw->dev_start) {
+ intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG;
+ return;
+ }
+
speed = hw->phy.autoneg_advertised;
if (!speed)
hw->mac.get_link_capabilities(hw, &speed, &autoneg);
--
2.55.0.windows.2