git: 505e6bb93f80 - main - igbv: Accept reset NACKs when no MAC is assigned

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Tue, 11 Aug 2026 20:59:57 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=505e6bb93f80fa3a7799cd88b0d0cafcaa468491

commit 505e6bb93f80fa3a7799cd88b0d0cafcaa468491
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-11 17:38:15 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-11 20:59:32 +0000

    igbv: Accept reset NACKs when no MAC is assigned
    
    A reset NACK from a Linux PF means that the reset completed but no
    permanent MAC address was assigned.  Treat that response as a
    successful reset with a zero permanent address so attach can generate
    a local address instead of retrying a live mailbox.
    
    FreeBSD PFs also use a one-dword reset NACK while retained queues are
    being sanitized.  Seed the otherwise unused request payload and accept
    only the three-dword, zero-filled NACK used by Linux, preserving the
    FreeBSD retry contract.
    
    MFC after:      2 weeks
---
 sys/dev/e1000/e1000_vf.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/sys/dev/e1000/e1000_vf.c b/sys/dev/e1000/e1000_vf.c
index 70c5f23fea0b..9528ab6009cb 100644
--- a/sys/dev/e1000/e1000_vf.c
+++ b/sys/dev/e1000/e1000_vf.c
@@ -260,7 +260,7 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
 	struct e1000_mbx_info *mbx = &hw->mbx;
 	u32 timeout = E1000_VF_INIT_TIMEOUT;
 	s32 ret_val = -E1000_ERR_MAC_INIT;
-	u32 ctrl, msgbuf[3];
+	u32 ctrl, msgbuf[3] = { E1000_VF_RESET, ~0U, ~0U };
 	u8 *addr = (u8 *)(&msgbuf[1]);
 
 	DEBUGFUNC("e1000_reset_hw_vf");
@@ -281,8 +281,13 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
 	/* mailbox timeout can now become active */
 	mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
 
-	msgbuf[0] = E1000_VF_RESET;
-	ret_val = mbx->ops.write_posted(hw, msgbuf, 1, 0);
+	/*
+	 * Linux PFs return a three-dword, zero-filled NACK when the reset
+	 * completed without an assigned MAC address.  FreeBSD PFs also use a
+	 * one-dword NACK while retained queues are still being sanitized.  Seed
+	 * the unused request payload so the two responses remain distinguishable.
+	 */
+	ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0);
 	if (ret_val)
 		return ret_val;
 
@@ -291,10 +296,20 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
 	/* set our "perm_addr" based on info provided by PF */
 	ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0);
 	if (!ret_val) {
-		if (msgbuf[0] == (E1000_VF_RESET | E1000_VT_MSGTYPE_ACK))
-			memcpy(hw->mac.perm_addr, addr, 6);
-		else
+		switch (msgbuf[0]) {
+		case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
+			memcpy(hw->mac.perm_addr, addr, ETHER_ADDR_LEN);
+			break;
+		case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
+			if (msgbuf[1] == 0 && msgbuf[2] == 0)
+				memset(hw->mac.perm_addr, 0, ETHER_ADDR_LEN);
+			else
+				ret_val = -E1000_ERR_MAC_INIT;
+			break;
+		default:
 			ret_val = -E1000_ERR_MAC_INIT;
+			break;
+		}
 	}
 
 	return ret_val;