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. Detect PF ifconfig down when
TXGBE_VT_MSGTYPE_SPEC is present in mailbox commands. Detect PF ifconfig
up when mailbox commands lack TXGBE_VT_MSGTYPE_CTS. Upon detection PF
up, the VF needs to reset; the driver sets a reset callback to prompt
users to reset the VF.

Additionally, hw->rx_loaded and hw->offset_loaded must be reset after
PF ifconfig up; otherwise, because hardware counter registers are cleared
during PF reset, the VF's software counters will overflow to 0xFFFFFFFF.

Signed-off-by: Zaiyu Wang <[email protected]>
---
 drivers/net/txgbe/base/txgbe_type.h |  1 +
 drivers/net/txgbe/txgbe_ethdev.c    |  3 +-
 drivers/net/txgbe/txgbe_ethdev_vf.c | 58 +++++++++++++++++++++++++----
 3 files changed, 54 insertions(+), 8 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..7ec1e009ed 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,8 +1406,18 @@ 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_up = false;
+               link_speed = TXGBE_LINK_SPEED_UNKNOWN;
+               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;
 
@@ -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[TXGBE_VF_PERMADDR_MSG_LEN] = {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[0] = 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

Reply via email to