[PATCH v3 3/4] net/txgbe: add support for VF sensing PF down
Zaiyu Wang
zaiyuwang at trustnetic.com
Tue Jun 23 13:38:03 CEST 2026
VFs should continue normal packet Rx/Tx after PF ifconfig down/up.
To achieve this, cooperate with mailbox commands added in our Linux
kernel driver txgbe-2.2.0. When mailbox messages lack the
TXGBE_VT_MSGTYPE_CTS flag, the PF is considered down. In this state,
the VF reports link down and stops transmitting. Upon detecting the
loss of CTS, the VF sends a reset request to the PF. If the request
succeeds (indicating PF recovery), the VF triggers an
RTE_ETH_EVENT_INTR_RESET event to notify the application or users to
reset the VF.
Additionally, hw->rx_loaded and hw->offset_loaded must be reset when
PF ifconfig down; otherwise, because hardware counter registers are
cleared during PF reset, the VF's software counters will overflow to
0xFFFFFFFF.
Signed-off-by: Zaiyu Wang <zaiyuwang at trustnetic.com>
---
drivers/net/txgbe/base/txgbe_type.h | 1 +
drivers/net/txgbe/txgbe_ethdev.c | 3 +-
drivers/net/txgbe/txgbe_ethdev_vf.c | 60 +++++++++++++++++++++++++----
3 files changed, 55 insertions(+), 9 deletions(-)
diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h
index ede780321f..956080c702 100644
--- a/drivers/net/txgbe/base/txgbe_type.h
+++ b/drivers/net/txgbe/base/txgbe_type.h
@@ -883,6 +883,7 @@ struct txgbe_hw {
rte_atomic32_t swfw_busy;
u32 fec_mode;
u32 cur_fec_link;
+ bool pf_running;
};
struct txgbe_backplane_ability {
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 0f484dfe91..003a24141c 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -3150,7 +3150,8 @@ txgbe_dev_link_update_share(struct rte_eth_dev *dev,
hw->mac.get_link_status = true;
- if (intr->flags & TXGBE_FLAG_NEED_LINK_CONFIG)
+ if (intr->flags & TXGBE_FLAG_NEED_LINK_CONFIG ||
+ (txgbe_is_vf(hw) && !hw->pf_running))
return rte_eth_linkstatus_set(dev, &link);
/* check if it needs to wait to complete, if lsc interrupt is enabled */
diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c
index 7a50c7a855..e3832c0173 100644
--- a/drivers/net/txgbe/txgbe_ethdev_vf.c
+++ b/drivers/net/txgbe/txgbe_ethdev_vf.c
@@ -281,6 +281,7 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
hw->subsystem_device_id = pci_dev->id.subsystem_device_id;
hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
+ hw->pf_running = true;
/* initialize the vfta */
memset(shadow_vfta, 0, sizeof(*shadow_vfta));
@@ -1405,10 +1406,20 @@ static s32 txgbevf_get_pf_link_status(struct rte_eth_dev *dev)
if (retval)
return 0;
+ if (!(msgbuf[0] & TXGBE_NOFITY_VF_LINK_STATUS))
+ return 0;
+
rte_eth_linkstatus_get(dev, &link);
+ if (!hw->pf_running) {
+ link.link_status = RTE_ETH_LINK_DOWN;
+ link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+ link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+ return rte_eth_linkstatus_set(dev, &link);
+ }
+
link_up = msgbuf[1] & TXGBE_VFSTATUS_UP;
- link_speed = (msgbuf[1] & 0xFFF0) >> 1;
+ link_speed = (msgbuf[1] & 0x1FFFFE) >> 1;
if (link_up == link.link_status && link_speed == link.link_speed)
return 0;
@@ -1434,10 +1445,22 @@ static s32 txgbevf_get_pf_link_status(struct rte_eth_dev *dev)
static void txgbevf_check_link_for_intr(struct rte_eth_dev *dev)
{
struct rte_eth_link orig_link, new_link;
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
rte_eth_linkstatus_get(dev, &orig_link);
- txgbevf_dev_link_update(dev, 0);
- rte_eth_linkstatus_get(dev, &new_link);
+
+ if (hw->pf_running) {
+ txgbevf_dev_link_update(dev, 0);
+ rte_eth_linkstatus_get(dev, &new_link);
+ } else {
+ DEBUGOUT("PF ifconfig down, so VF link down");
+ new_link.link_status = RTE_ETH_LINK_DOWN;
+ new_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+ new_link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+ new_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+ RTE_ETH_LINK_SPEED_FIXED);
+ rte_eth_linkstatus_set(dev, &new_link);
+ }
PMD_DRV_LOG(INFO, "orig_link: %d, new_link: %d",
orig_link.link_status, new_link.link_status);
@@ -1450,6 +1473,8 @@ static void txgbevf_check_link_for_intr(struct rte_eth_dev *dev)
static void txgbevf_mbx_process(struct rte_eth_dev *dev)
{
struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+ struct txgbe_mbx_info *mbx = &hw->mbx;
+ u32 msgbuf = 0;
u32 in_msg = 0;
/* peek the message first */
@@ -1457,14 +1482,33 @@ static void txgbevf_mbx_process(struct rte_eth_dev *dev)
/* PF reset VF event */
if (in_msg & TXGBE_PF_CONTROL_MSG) {
- if (in_msg & TXGBE_NOFITY_VF_LINK_STATUS) {
+ /* msg is not CTS, we need to do reset */
+ if (!(in_msg & TXGBE_VT_MSGTYPE_CTS)) {
+ /* send reset to PF to reconfig CTS flag */
+ int err = 0;
+
+ msgbuf = TXGBE_VF_RESET;
+ err = mbx->write_posted(hw, &msgbuf, 1, 0);
+ if (err) {
+ hw->pf_running = false;
+ txgbevf_check_link_for_intr(dev);
+ } else {
+ hw->pf_running = true;
+ rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET,
+ NULL);
+ }
+ }
+
+ if (in_msg & TXGBE_NOFITY_VF_LINK_STATUS)
txgbevf_get_pf_link_status(dev);
- } else {
- /* dummy mbx read to ack pf */
- txgbe_read_mbx(hw, &in_msg, 1, 0);
+ else
/* check link status if pf ping vf */
txgbevf_check_link_for_intr(dev);
- }
+ }
+
+ if (!hw->pf_running) {
+ hw->rx_loaded = true;
+ hw->offset_loaded = true;
}
}
--
2.21.0.windows.1
More information about the dev
mailing list