Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 07 Aug 2026 12:45:48 +0000
From:      Kevin Bowling <kbowling@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 33fdcdb18eb6 - main - ixgbe: complete PF cleanup after VF FLR
Message-ID:  <6a75d37c.38b6f.2e1eec7d@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kbowling:

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

commit 33fdcdb18eb61f089b9a4786ef7aa9224ad0722c
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-01 06:03:17 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
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;


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a75d37c.38b6f.2e1eec7d>