The branch main has been updated by kbowling:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=33fdcdb18eb61f089b9a4786ef7aa9224ad0722c

commit 33fdcdb18eb61f089b9a4786ef7aa9224ad0722c
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-08-01 06:03:17 +0000
Commit:     Kevin Bowling <[email protected]>
CommitDate: 2026-08-07 12:45:43 +0000

    ixgbe: complete PF cleanup after VF FLR
    
    The 82599, X540, and X550 documentation identifies VF registers which
    retain state across VFLR and must be reconfigured before a VF is reused.
    The VF reset path already initializes its queue-owned registers, but the
    PF only cleared VF mailbox memory and transmit head write-back addresses
    after a cooperative mailbox reset.  A bare hardware VFLR therefore left
    both behind on affected devices.
    
    Move TDWBA cleanup into the common reset path.  Clear CTS when VFLR
    invalidates the mailbox session, and accept only VF_RESET during the
    reset pass before restoring VF traffic.
    
    Clear VFMBMEM through the PFU/VFU semaphore.  Recheck VFREQ while
    holding PFU so a reset event cannot erase a request posted between the
    initial mailbox check and the clear.  Dispatch an already-read message
    even if the residual clear fails, but keep cleanup pending until a
    synchronized clear succeeds.  Retry cleanup in the same admin pass
    after a failed message read or clear.
    
    The 82599 also retains VFMAILBOX.VFU across VFLR.  Leave a VF-owned
    mailbox intact initially so a live post-reset writer can finish.  Retry
    cleanup from the admin timer and, after a two-second grace period, use
    PFMAILBOX.RVFU only when VFU remains set and no request has been posted.
    Clear the mailbox under PFU afterward.  This recovers an abandoned
    pre-reset owner without sleeping under the iflib context lock or
    immediately stealing from a new reset request.
    
    Suppress mailbox dispatch once iflib has cleared IFF_DRV_RUNNING so a
    pending reset request cannot re-enable VF traffic inside the PF stop
    path.  Periodically sample aggregate VFREQ, VFACK, and VFLR registers,
    masked to active VFs, so work suppressed across a stop/restart and a
    bare 82599 VFLR without EICR_MAILBOX are both discovered without another
    interrupt edge.
    
    MFC after:      2 weeks
---
 sys/dev/ixgbe/if_ix.c       |   9 ++-
 sys/dev/ixgbe/if_sriov.c    | 190 +++++++++++++++++++++++++++++++++++++-------
 sys/dev/ixgbe/ixgbe.h       |   2 +
 sys/dev/ixgbe/ixgbe_mbx.c   |  66 +++++++++++++--
 sys/dev/ixgbe/ixgbe_mbx.h   |   1 +
 sys/dev/ixgbe/ixgbe_sriov.h |   2 +
 sys/dev/ixgbe/ixgbe_vf.c    |   4 +-
 7 files changed, 237 insertions(+), 37 deletions(-)

diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index f800be109fc3..d18f60984b8f 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -4831,7 +4831,14 @@ ixgbe_if_update_admin_status(if_ctx_t ctx)
                ixgbe_handle_mod(ctx);
        if (sc->task_requests & IXGBE_REQUEST_TASK_MSF)
                ixgbe_handle_msf(ctx);
-       if (sc->task_requests & IXGBE_REQUEST_TASK_MBX)
+       /*
+        * A reset request re-enables VF traffic, so do not service mailboxes
+        * while the PF is stopped.  VFREQ, VFACK, and VFLR are hardware-latched
+        * and ixgbe_mbx_pending() resamples them after the PF is running again.
+        */
+       if ((if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0 &&
+           ((sc->task_requests & IXGBE_REQUEST_TASK_MBX) != 0 ||
+           sc->iov_mbx_cleanup_pending || ixgbe_mbx_pending(sc)))
                ixgbe_handle_mbx(ctx);
        if (sc->task_requests & IXGBE_REQUEST_TASK_FDIR)
                ixgbe_reinit_fdir(ctx);
diff --git a/sys/dev/ixgbe/if_sriov.c b/sys/dev/ixgbe/if_sriov.c
index b2325046d5e8..848a53df290c 100644
--- a/sys/dev/ixgbe/if_sriov.c
+++ b/sys/dev/ixgbe/if_sriov.c
@@ -41,6 +41,8 @@
 
 MALLOC_DEFINE(M_IXGBE_SRIOV, "ix_sriov", "ix SR-IOV allocations");
 
+#define IXGBE_VF_MBX_CLEANUP_GRACE     (2 * SBT_1S)
+
 /************************************************************************
  * ixgbe_define_iov_schemas
  ************************************************************************/
@@ -521,9 +523,13 @@ ixgbe_vf_frame_size_compatible(struct ixgbe_softc *sc, 
struct ixgbe_vf *vf)
 static void
 ixgbe_process_vf_reset(struct ixgbe_softc *sc, struct ixgbe_vf *vf)
 {
+       struct ixgbe_hw *hw;
        bool rebuild_mta;
        s32 error;
+       int i, queue_count;
 
+       hw = &sc->hw;
+       vf->flags &= ~IXGBE_VF_CTS;
        rebuild_mta = vf->num_mc_hashes != 0;
        vf->xcast_mode = IXGBEVF_XCAST_MODE_NONE;
        vf->num_mc_hashes = 0;
@@ -537,9 +543,18 @@ ixgbe_process_vf_reset(struct ixgbe_softc *sc, struct 
ixgbe_vf *vf)
                ixgbe_iov_rebuild_mta(sc);
 
        ixgbe_vf_clear_mac_filters(sc, vf, true);
-       ixgbe_clear_rar(&sc->hw, vf->rar_index);
+       ixgbe_clear_rar(hw, vf->rar_index);
        ixgbe_vf_set_anti_spoof(sc, vf);
-       ixgbe_toggle_txdctl(&sc->hw, vf->pool);
+       ixgbe_toggle_txdctl(hw, vf->pool);
+
+       /* VFLR does not clear transmit head write-back state. */
+       queue_count = ixgbe_vf_queues(sc->iov_mode);
+       for (i = 0; i < queue_count; i++) {
+               IXGBE_WRITE_REG(hw,
+                   IXGBE_PVFTDWBAHn(queue_count, vf->pool, i), 0);
+               IXGBE_WRITE_REG(hw,
+                   IXGBE_PVFTDWBALn(queue_count, vf->pool, i), 0);
+       }
 
        vf->api_ver = IXGBE_API_VER_UNKNOWN;
 } /* ixgbe_process_vf_reset */
@@ -584,28 +599,10 @@ ixgbe_vf_reset_msg(struct ixgbe_softc *sc, struct 
ixgbe_vf *vf, uint32_t *msg)
        struct ixgbe_hw *hw;
        uint32_t ack;
        uint32_t resp[IXGBE_VF_PERMADDR_MSG_LEN];
-       int i, queue_count;
 
        hw = &sc->hw;
 
        ixgbe_process_vf_reset(sc, vf);
-       /*
-        * The reset request was consumed by ixgbe_process_vf_msg(), so it is
-        * now safe to clear this VF's mailbox.
-        */
-       ixgbe_clear_mbx(hw, vf->pool);
-
-       /*
-        * VF reset does not clear the transmit head write-back addresses.
-        * The queues were disabled by ixgbe_process_vf_reset().
-        */
-       queue_count = ixgbe_vf_queues(sc->iov_mode);
-       for (i = 0; i < queue_count; i++) {
-               IXGBE_WRITE_REG(hw,
-                   IXGBE_PVFTDWBAHn(queue_count, vf->pool, i), 0);
-               IXGBE_WRITE_REG(hw,
-                   IXGBE_PVFTDWBALn(queue_count, vf->pool, i), 0);
-       }
 
        if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) {
                ixgbe_set_rar(&sc->hw, vf->rar_index, vf->ether_addr,
@@ -936,8 +933,8 @@ ixgbe_vf_get_queues(struct ixgbe_softc *sc, struct ixgbe_vf 
*vf,
 } /* ixgbe_vf_get_queues */
 
 
-static void
-ixgbe_process_vf_msg(if_ctx_t ctx, struct ixgbe_vf *vf)
+static bool
+ixgbe_process_vf_msg(if_ctx_t ctx, struct ixgbe_vf *vf, bool reset_pending)
 {
        struct ixgbe_softc *sc = iflib_get_softc(ctx);
 #ifdef KTR
@@ -945,25 +942,39 @@ ixgbe_process_vf_msg(if_ctx_t ctx, struct ixgbe_vf *vf)
 #endif
        struct ixgbe_hw *hw;
        uint32_t msg[IXGBE_VFMAILBOX_SIZE];
+       bool cleanup_complete;
        int error;
 
        hw = &sc->hw;
+       cleanup_complete = true;
 
        error = ixgbe_read_mbx(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool);
 
        if (error != 0)
-               return;
+               return (false);
+       /*
+        * Some devices do not clear VFMBMEM on VFLR.  Copy a pending request
+        * first because the VF posts its mailbox reset request after raising
+        * the reset event.
+        */
+       if (reset_pending || msg[0] == IXGBE_VF_RESET)
+               cleanup_complete =
+                   ixgbe_clear_mbx(hw, vf->pool) == IXGBE_SUCCESS;
+       /* The successful read ACKed the request; dispatch it even if not 
clear. */
 
        CTR3(KTR_MALLOC, "%s: received msg %x from %d", if_name(ifp),
            msg[0], vf->pool);
        if (msg[0] == IXGBE_VF_RESET) {
                ixgbe_vf_reset_msg(sc, vf, msg);
-               return;
+               return (cleanup_complete);
        }
+       /* Discard requests from the mailbox session invalidated by VFLR. */
+       if (reset_pending)
+               return (cleanup_complete);
 
        if (!(vf->flags & IXGBE_VF_CTS)) {
                ixgbe_send_vf_failure(sc, vf, msg[0]);
-               return;
+               return (true);
        }
 
        switch (msg[0] & IXGBE_VT_MSG_MASK) {
@@ -994,8 +1005,39 @@ ixgbe_process_vf_msg(if_ctx_t ctx, struct ixgbe_vf *vf)
        default:
                ixgbe_send_vf_failure(sc, vf, msg[0]);
        }
+       return (true);
 } /* ixgbe_process_vf_msg */
 
+static void
+ixgbe_cleanup_vf_mbx(struct ixgbe_softc *sc, struct ixgbe_vf *vf)
+{
+       struct ixgbe_hw *hw;
+       sbintime_t now;
+
+       hw = &sc->hw;
+       if (ixgbe_clear_mbx(hw, vf->pool) == IXGBE_SUCCESS) {
+               vf->flags &= ~IXGBE_VF_MBX_CLEANUP;
+               return;
+       }
+
+       now = getsbinuptime();
+       if (now < vf->mbx_cleanup_deadline)
+               return;
+
+       /*
+        * A functioning VF posts VFREQ within the grace interval.  Ownership
+        * still held after that interval is residue from the old reset epoch.
+        * The force-clear helper rechecks VFREQ before asserting RVFU.
+        */
+       if (ixgbe_force_clear_mbx_pf(hw, vf->pool) == IXGBE_SUCCESS) {
+               vf->flags &= ~IXGBE_VF_MBX_CLEANUP;
+               return;
+       }
+
+       /* A request raced the force-clear attempt; give it another interval. */
+       vf->mbx_cleanup_deadline = now + IXGBE_VF_MBX_CLEANUP_GRACE;
+}
+
 /* Tasklet for handling VF -> PF mailbox messages */
 void
 ixgbe_handle_mbx(void *context)
@@ -1004,29 +1046,109 @@ ixgbe_handle_mbx(void *context)
        struct ixgbe_softc *sc = iflib_get_softc(ctx);
        struct ixgbe_hw *hw;
        struct ixgbe_vf *vf;
+       bool cleanup_pending, reset_pending, reset_seen;
        int i;
 
        hw = &sc->hw;
+       cleanup_pending = false;
 
        for (i = 0; i < sc->num_vfs; i++) {
                vf = &sc->vfs[i];
 
                if (vf->flags & IXGBE_VF_ACTIVE) {
-                       if (hw->mbx.ops[vf->pool].check_for_rst(hw,
-                           vf->pool) == 0)
+                       reset_seen = hw->mbx.ops[vf->pool].check_for_rst(hw,
+                           vf->pool) == 0;
+                       if (reset_seen) {
+                               vf->flags |= IXGBE_VF_MBX_CLEANUP;
+                               vf->mbx_cleanup_deadline = getsbinuptime() +
+                                   IXGBE_VF_MBX_CLEANUP_GRACE;
                                ixgbe_process_vf_reset(sc, vf);
+                       }
+                       reset_pending =
+                           (vf->flags & IXGBE_VF_MBX_CLEANUP) != 0;
 
                        if (hw->mbx.ops[vf->pool].check_for_msg(hw,
-                           vf->pool) == 0)
-                               ixgbe_process_vf_msg(ctx, vf);
+                           vf->pool) == 0) {
+                               if (ixgbe_process_vf_msg(ctx, vf, 
reset_pending))
+                                       vf->flags &= ~IXGBE_VF_MBX_CLEANUP;
+                       }
+                       if (reset_pending &&
+                           (vf->flags & IXGBE_VF_MBX_CLEANUP) != 0)
+                               ixgbe_cleanup_vf_mbx(sc, vf);
 
                        if (hw->mbx.ops[vf->pool].check_for_ack(hw,
                            vf->pool) == 0)
                                ixgbe_process_vf_ack(sc, vf);
+
+                       if (vf->flags & IXGBE_VF_MBX_CLEANUP)
+                               cleanup_pending = true;
                }
        }
+       sc->iov_mbx_cleanup_pending = cleanup_pending;
 } /* ixgbe_handle_mbx */
 
+/*
+ * VFREQ, VFACK, and a bare VFLR can remain latched without a usable shared
+ * mailbox interrupt across a PF stop/restart.  Sample their aggregate
+ * registers from the periodic admin pass so work does not depend on another
+ * edge.
+ */
+bool
+ixgbe_mbx_pending(struct ixgbe_softc *sc)
+{
+       struct ixgbe_hw *hw;
+       uint32_t active_mbx[4], active_rst[2], events;
+       int i, index;
+
+       if (sc->num_vfs == 0)
+               return (false);
+
+       bzero(active_mbx, sizeof(active_mbx));
+       bzero(active_rst, sizeof(active_rst));
+       for (i = 0; i < sc->num_vfs; i++) {
+               if ((sc->vfs[i].flags & IXGBE_VF_ACTIVE) == 0)
+                       continue;
+               index = IXGBE_PFMBICR_INDEX(sc->vfs[i].pool);
+               active_mbx[index] |=
+                   IXGBE_PFMBICR_VFREQ_VF1 <<
+                   IXGBE_PFMBICR_SHIFT(sc->vfs[i].pool);
+               active_mbx[index] |=
+                   IXGBE_PFMBICR_VFACK_VF1 <<
+                   IXGBE_PFMBICR_SHIFT(sc->vfs[i].pool);
+               index = IXGBE_PFVFLRE_INDEX(sc->vfs[i].pool);
+               active_rst[index] |=
+                   1U << IXGBE_PFVFLRE_SHIFT(sc->vfs[i].pool);
+       }
+
+       hw = &sc->hw;
+       for (index = 0; index < nitems(active_mbx); index++) {
+               if (active_mbx[index] != 0 &&
+                   (IXGBE_READ_REG(hw, IXGBE_PFMBICR(index)) &
+                   active_mbx[index]) != 0)
+                       return (true);
+       }
+       for (index = 0; index < nitems(active_rst); index++) {
+               if (active_rst[index] == 0)
+                       continue;
+               switch (hw->mac.type) {
+               case ixgbe_mac_82599EB:
+                       events = IXGBE_READ_REG(hw, IXGBE_PFVFLRE(index));
+                       break;
+               case ixgbe_mac_X540:
+               case ixgbe_mac_X550:
+               case ixgbe_mac_X550EM_x:
+               case ixgbe_mac_X550EM_a:
+                       events = IXGBE_READ_REG(hw, IXGBE_PFVFLREC(index));
+                       break;
+               default:
+                       return (false);
+               }
+               if ((events & active_rst[index]) != 0)
+                       return (true);
+       }
+       return (false);
+}
+
 int
 ixgbe_iov_validate(struct ixgbe_softc *sc, u16 num_vfs)
 {
@@ -1114,6 +1236,7 @@ ixgbe_if_iov_init(if_ctx_t ctx, u16 num_vfs, const 
nvlist_t *config)
        }
 
        sc->num_vfs = num_vfs;
+       sc->iov_mbx_cleanup_pending = false;
        ixgbe_init_mbx_params_pf(&sc->hw);
 
        sc->feat_en |= IXGBE_FEATURE_SRIOV;
@@ -1129,6 +1252,7 @@ err_init_iov:
        sc->num_vfs = 0;
        sc->pool = 0;
        sc->iov_mode = IXGBE_NO_VM;
+       sc->iov_mbx_cleanup_pending = false;
 
        return (retval);
 } /* ixgbe_if_iov_init */
@@ -1204,6 +1328,7 @@ ixgbe_if_iov_uninit(if_ctx_t ctx)
        ixgbe_align_all_queue_indices(sc);
        sc->iov_vfta_valid = false;
        sc->iov_vlan_promisc = false;
+       sc->iov_mbx_cleanup_pending = false;
        (void)ixgbe_clear_vfta(hw);
        ixgbe_setup_vlan_hw_support(ctx);
 } /* ixgbe_if_iov_uninit */
@@ -1405,4 +1530,11 @@ ixgbe_handle_mbx(void *context)
        UNREFERENCED_PARAMETER(context);
 } /* ixgbe_handle_mbx */
 
+bool
+ixgbe_mbx_pending(struct ixgbe_softc *sc)
+{
+       UNREFERENCED_PARAMETER(sc);
+       return (false);
+}
+
 #endif
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index 003021e928a9..20f8fce8f04b 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -366,6 +366,7 @@ struct ixgbe_vf {
        uint16_t        default_vlan;
        uint16_t        api_ver;
        uint8_t         xcast_mode;
+       sbintime_t      mbx_cleanup_deadline;
 };
 
 /* Our softc structure */
@@ -461,6 +462,7 @@ struct ixgbe_softc {
        bool                    iov_mta_valid;
        bool                    iov_vfta_valid;
        bool                    iov_vlan_promisc;
+       bool                    iov_mbx_cleanup_pending;
 
        /* Bypass */
        struct ixgbe_bp_data    bypass;
diff --git a/sys/dev/ixgbe/ixgbe_mbx.c b/sys/dev/ixgbe/ixgbe_mbx.c
index 810b282bbd0e..eefe4543f3fe 100644
--- a/sys/dev/ixgbe/ixgbe_mbx.c
+++ b/sys/dev/ixgbe/ixgbe_mbx.c
@@ -207,7 +207,8 @@ s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
  * @hw: pointer to the HW structure
  * @mbx_id: id of mailbox to write
  *
- * Set VFMBMEM of given VF to 0x0.
+ * Set VFMBMEM of given VF to 0x0.  A peer-owned or newly posted mailbox is
+ * left intact.
  **/
 s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 mbx_id)
 {
@@ -1112,24 +1113,79 @@ static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 
*msg, u16 size,
 }
 
 /**
- * ixgbe_clear_mbx_pf - Clear Mailbox Memory
+ * ixgbe_clear_mbx_pf - Clear idle Mailbox Memory
  * @hw: pointer to the HW structure
  * @vf_id: the VF index
  *
- * Set VFMBMEM of given VF to 0x0.
+ * Set VFMBMEM of given VF to 0x0 unless the VF owns it or has posted a new
+ * request.
  **/
 static s32 ixgbe_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_id)
 {
-       u16 mbx_size = hw->mbx.size;
+       s32 ret_val;
+       u16 mbx_size;
        u16 i;
 
        if (vf_id > 63)
                return IXGBE_ERR_PARAM;
 
+       /*
+        * Serialize against a VF composing a request.  After acquiring PFU,
+        * recheck VFREQ to close the window between the caller's mailbox check
+        * and this clear.  Leave a newly posted request intact for the normal
+        * mailbox path to consume.
+        */
+       ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id);
+       if (ret_val != IXGBE_SUCCESS)
+               return ret_val;
+       if (ixgbe_check_for_msg_pf(hw, vf_id) == IXGBE_SUCCESS) {
+               ret_val = IXGBE_ERR_MBX;
+               goto out;
+       }
+
+       mbx_size = hw->mbx.size;
        for (i = 0; i < mbx_size; ++i)
                IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, 0x0);
+       ret_val = IXGBE_SUCCESS;
 
-       return IXGBE_SUCCESS;
+out:
+       ixgbe_release_mbx_lock_pf(hw, vf_id);
+       return ret_val;
+}
+
+/**
+ * ixgbe_force_clear_mbx_pf - Revoke stale VF ownership and clear its mailbox
+ * @hw: pointer to the HW structure
+ * @vf_id: the VF index
+ *
+ * VFLR does not clear VFMAILBOX.VFU on some devices.  The caller must allow a
+ * live VF a bounded interval to finish posting its reset request before using
+ * this function.  Refuse to revoke ownership if a request is already posted,
+ * then use RVFU and the normal synchronized clear path.
+ **/
+s32 ixgbe_force_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_id)
+{
+       u32 pf_mailbox;
+
+       if (vf_id > 63)
+               return IXGBE_ERR_PARAM;
+
+       pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
+       if ((pf_mailbox & IXGBE_PFMAILBOX_VFU) == 0)
+               return ixgbe_clear_mbx_pf(hw, vf_id);
+       if (ixgbe_check_for_msg_pf(hw, vf_id) == IXGBE_SUCCESS)
+               return IXGBE_ERR_MBX;
+
+       /*
+        * Hardware has no atomic revoke-if-idle operation.  A VF that starts a
+        * request after the grace interval can race RVFU; the synchronized 
clear
+        * below detects a request that has reached VFREQ, and its failure makes
+        * the caller retain cleanup state for another interval.
+        */
+       IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), IXGBE_PFMAILBOX_RVFU);
+       IXGBE_WRITE_FLUSH(hw);
+
+       return ixgbe_clear_mbx_pf(hw, vf_id);
 }
 
 /**
diff --git a/sys/dev/ixgbe/ixgbe_mbx.h b/sys/dev/ixgbe/ixgbe_mbx.h
index e6519963242e..fc6831f67b34 100644
--- a/sys/dev/ixgbe/ixgbe_mbx.h
+++ b/sys/dev/ixgbe/ixgbe_mbx.h
@@ -196,6 +196,7 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id);
 s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id);
 s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id);
 s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 vf_number);
+s32 ixgbe_force_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_number);
 void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw);
 void ixgbe_upgrade_mbx_params_vf(struct ixgbe_hw *hw);
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw);
diff --git a/sys/dev/ixgbe/ixgbe_sriov.h b/sys/dev/ixgbe/ixgbe_sriov.h
index 443bf78e9a1d..1ae54863befc 100644
--- a/sys/dev/ixgbe/ixgbe_sriov.h
+++ b/sys/dev/ixgbe/ixgbe_sriov.h
@@ -49,6 +49,7 @@
 #define IXGBE_VF_ACTIVE         (1 << 3) /* VF is active. */
 #define IXGBE_VF_ANTI_SPOOF     (1 << 4) /* Enforce source identity. */
 #define IXGBE_VF_ALLOW_PROMISC  (1 << 5) /* VF may request promiscuity. */
+#define IXGBE_VF_MBX_CLEANUP    (1 << 6) /* Reset mailbox cleanup pending. */
 #define IXGBE_VF_INDEX(vmdq)    ((vmdq) / 32)
 #define IXGBE_VF_BIT(vmdq)      (1 << ((vmdq) % 32))
 
@@ -106,5 +107,6 @@ u32  ixgbe_get_mrqc(int);
 
 void ixgbe_if_init(if_ctx_t ctx);
 void ixgbe_handle_mbx(void *);
+bool ixgbe_mbx_pending(struct ixgbe_softc *);
 
 #endif
diff --git a/sys/dev/ixgbe/ixgbe_vf.c b/sys/dev/ixgbe/ixgbe_vf.c
index 5f65ee038753..00f0cb131cbf 100644
--- a/sys/dev/ixgbe/ixgbe_vf.c
+++ b/sys/dev/ixgbe/ixgbe_vf.c
@@ -210,8 +210,8 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
        ixgbe_virt_clr_reg(hw);
 
        /*
-        * VFLR does not clear VFMAILBOX.VFU. Drop stale ownership and
-        * cached read-to-clear status.
+        * Some devices do not clear VFMAILBOX.VFU on VFLR.  Drop stale
+        * ownership and cached read-to-clear status.
         */
        IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, 0);
        hw->mbx.vf_mailbox = 0;

Reply via email to