diff options
| author | Kevin Bowling <kbowling@FreeBSD.org> | 2026-07-31 10:41:02 +0000 |
|---|---|---|
| committer | Kevin Bowling <kbowling@FreeBSD.org> | 2026-07-31 10:50:30 +0000 |
| commit | 2a678cfeb5838978ef3a1907c686142d03237e15 (patch) | |
| tree | df6b402dd7e6798a934d43bd36c541ef9917f7bd | |
| parent | 409601911b327426a34a6f28b31fdd5d95d1d275 (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.c | 26 |
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; |
