aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Bowling <kbowling@FreeBSD.org>2026-08-11 17:38:15 +0000
committerKevin Bowling <kbowling@FreeBSD.org>2026-08-11 20:59:32 +0000
commit505e6bb93f80fa3a7799cd88b0d0cafcaa468491 (patch)
tree3b225efe2bfad77abfcfedb8c036345accb80f42
parentbb8d0944b5d53863f00492b69b7bf13d2618fc95 (diff)
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
-rw-r--r--sys/dev/e1000/e1000_vf.c27
1 files 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;