aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Bowling <kbowling@FreeBSD.org>2026-07-31 10:41:02 +0000
committerKevin Bowling <kbowling@FreeBSD.org>2026-07-31 10:50:30 +0000
commit2a678cfeb5838978ef3a1907c686142d03237e15 (patch)
treedf6b402dd7e6798a934d43bd36c541ef9917f7bd
parent409601911b327426a34a6f28b31fdd5d95d1d275 (diff)
ixgbe: fail fast on VF-held PF mailboxes
The active PF mailbox operations use the legacy helpers. The mailbox API import changed check_for_msg into a read-only probe and added up to 2,000 500-microsecond lock retries. If a VF leaves VFU set, the PF cannot acquire the lock, busy-waits for up to one second, and leaves VFREQ pending so the delay can repeat. Give the legacy checker its old consume-on-check behavior so a failed read does not leave VFREQ asserted. If VFU is already set, fail immediately instead of retrying, while preserving retries for PF-side contention. Do not force RVFU, which would discard peer transaction state. MFC after: 1 week
-rw-r--r--sys/dev/ixgbe/ixgbe_mbx.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/dev/ixgbe/ixgbe_mbx.c b/sys/dev/ixgbe/ixgbe_mbx.c
index eef30733b7b2..810b282bbd0e 100644
--- a/sys/dev/ixgbe/ixgbe_mbx.c
+++ b/sys/dev/ixgbe/ixgbe_mbx.c
@@ -789,6 +789,22 @@ static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_id)
return IXGBE_ERR_MBX;
}
+/*
+ * Legacy callers expect checking for a message to consume its interrupt
+ * cause before attempting to read the mailbox. This keeps a failed read
+ * from leaving VFREQ pending indefinitely.
+ */
+static s32 ixgbe_check_for_msg_pf_legacy(struct ixgbe_hw *hw, u16 vf_id)
+{
+ s32 ret_val;
+
+ ret_val = ixgbe_check_for_msg_pf(hw, vf_id);
+ if (ret_val == IXGBE_SUCCESS)
+ ixgbe_clear_msg_pf(hw, vf_id);
+
+ return ret_val;
+}
+
/**
* ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
* @hw: pointer to the HW structure
@@ -876,8 +892,12 @@ static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_id)
/* Reserve mailbox for PF use */
pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
- /* Check if the mailbox is already owned by the PF or VF */
- if (pf_mailbox & (IXGBE_PFMAILBOX_PFU | IXGBE_PFMAILBOX_VFU))
+ /* A peer-held mailbox cannot be recovered by retrying here. */
+ if (pf_mailbox & IXGBE_PFMAILBOX_VFU)
+ return IXGBE_ERR_MBX;
+
+ /* Retry transient contention with another PF-side caller. */
+ if (pf_mailbox & IXGBE_PFMAILBOX_PFU)
goto retry;
pf_mailbox |= IXGBE_PFMAILBOX_PFU;
@@ -1127,7 +1147,7 @@ void ixgbe_init_mbx_params_pf_id(struct ixgbe_hw *hw, u16 vf_id)
mbx->ops[vf_id].release = ixgbe_release_mbx_lock_dummy;
mbx->ops[vf_id].read = ixgbe_read_mbx_pf_legacy;
mbx->ops[vf_id].write = ixgbe_write_mbx_pf_legacy;
- mbx->ops[vf_id].check_for_msg = ixgbe_check_for_msg_pf;
+ mbx->ops[vf_id].check_for_msg = ixgbe_check_for_msg_pf_legacy;
mbx->ops[vf_id].check_for_ack = ixgbe_check_for_ack_pf;
mbx->ops[vf_id].check_for_rst = ixgbe_check_for_rst_pf;
mbx->ops[vf_id].clear = ixgbe_clear_mbx_pf;