Module Name:    src
Committed By:   martin
Date:           Mon Jan 31 17:38:36 UTC 2022

Modified Files:
        src/sys/dev/pci/ixgbe [netbsd-8]: if_sriov.c ixgbe.c ixgbe_82599.c
            ixgbe_mbx.c ixgbe_mbx.h ixgbe_type.h ixgbe_vf.c ixgbe_x540.c ixv.c

Log Message:
Pull up following revision(s) (requested by msaitoh in ticket #1730):

        sys/dev/pci/ixgbe/ixgbe_mbx.h: revision 1.19
        sys/dev/pci/ixgbe/ixgbe_vf.c: revision 1.31
        sys/dev/pci/ixgbe/ixgbe_x540.c: revision 1.23
        sys/dev/pci/ixgbe/if_sriov.c: revision 1.17
        sys/dev/pci/ixgbe/ixv.c: revision 1.172
        sys/dev/pci/ixgbe/ixv.c: revision 1.173
        sys/dev/pci/ixgbe/ixgbe.c: revision 1.301
        sys/dev/pci/ixgbe/ixgbe_type.h: revision 1.55
        sys/dev/pci/ixgbe/ixgbe_82599.c: revision 1.29
        sys/dev/pci/ixgbe/ixgbe_mbx.c: revision 1.16
        sys/dev/pci/ixgbe/ixgbe_mbx.c: revision 1.17
        sys/dev/pci/ixgbe/ixgbe_mbx.c: revision 1.18

Add code to support API version 1.5. No functional change.
   - This change adds almost all code to support API 1.5 except real negotiation
     and upgrade mailbox functions.
   - From ix-3.3.18, ix-3.3.22 and ixv-1.5.24.

Enable mailbox API 1.5 support. Tested on ESXi with ixgben 1.10.3.0.

Don't clear mailbox related counters in ixgbe_upgrade_mbx_params_vf().
Don't clear mailbox related counters in ixgbe_upgrade_mbx_params_pf().


To generate a diff of this commit:
cvs rdiff -u -r1.1.4.7 -r1.1.4.8 src/sys/dev/pci/ixgbe/if_sriov.c
cvs rdiff -u -r1.88.2.47 -r1.88.2.48 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.14.8.8 -r1.14.8.9 src/sys/dev/pci/ixgbe/ixgbe_82599.c
cvs rdiff -u -r1.6.8.5 -r1.6.8.6 src/sys/dev/pci/ixgbe/ixgbe_mbx.c
cvs rdiff -u -r1.10.8.4 -r1.10.8.5 src/sys/dev/pci/ixgbe/ixgbe_mbx.h
cvs rdiff -u -r1.22.2.15 -r1.22.2.16 src/sys/dev/pci/ixgbe/ixgbe_type.h
cvs rdiff -u -r1.12.8.8 -r1.12.8.9 src/sys/dev/pci/ixgbe/ixgbe_vf.c
cvs rdiff -u -r1.9.6.7 -r1.9.6.8 src/sys/dev/pci/ixgbe/ixgbe_x540.c
cvs rdiff -u -r1.56.2.35 -r1.56.2.36 src/sys/dev/pci/ixgbe/ixv.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ixgbe/if_sriov.c
diff -u src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.7 src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.8
--- src/sys/dev/pci/ixgbe/if_sriov.c:1.1.4.7	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/if_sriov.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: if_sriov.c,v 1.1.4.7 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: if_sriov.c,v 1.1.4.8 2022/01/31 17:38:36 martin Exp $ */
 /******************************************************************************
 
   Copyright (c) 2001-2017, Intel Corporation
@@ -34,7 +34,7 @@
 /*$FreeBSD: head/sys/dev/ixgbe/if_sriov.c 327031 2017-12-20 18:15:06Z erj $*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_sriov.c,v 1.1.4.7 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_sriov.c,v 1.1.4.8 2022/01/31 17:38:36 martin Exp $");
 
 #include "ixgbe.h"
 #include "ixgbe_sriov.h"
@@ -99,7 +99,7 @@ ixgbe_send_vf_msg(struct ixgbe_hw *hw, s
 	if (vf->flags & IXGBE_VF_CTS)
 		msg |= IXGBE_VT_MSGTYPE_CTS;
 
-	hw->mbx.ops.write(hw, &msg, 1, vf->pool);
+	hw->mbx.ops[vf->pool].write(hw, &msg, 1, vf->pool);
 }
 
 static inline void
@@ -594,7 +594,8 @@ ixgbe_process_vf_msg(struct adapter *ada
 
 	hw = &adapter->hw;
 
-	error = hw->mbx.ops.read(hw, msg, IXGBE_VFMAILBOX_SIZE, vf->pool);
+	error = hw->mbx.ops[vf->pool].read(hw, msg, IXGBE_VFMAILBOX_SIZE,
+	    vf->pool);
 
 	if (error != 0)
 		return;
@@ -654,16 +655,17 @@ ixgbe_handle_mbx(void *context)
 	for (i = 0; i < adapter->num_vfs; i++) {
 		vf = &adapter->vfs[i];
 
-		if (vf->flags & IXGBE_VF_ACTIVE) {
-			if (hw->mbx.ops.check_for_rst(hw, vf->pool) == 0)
-				ixgbe_process_vf_reset(adapter, vf);
-
-			if (hw->mbx.ops.check_for_msg(hw, vf->pool) == 0)
-				ixgbe_process_vf_msg(adapter, vf);
-
-			if (hw->mbx.ops.check_for_ack(hw, vf->pool) == 0)
-				ixgbe_process_vf_ack(adapter, vf);
-		}
+		if ((vf->flags & IXGBE_VF_ACTIVE) == 0)
+			continue;
+
+		if (hw->mbx.ops[vf->pool].check_for_rst(hw, vf->pool) == 0)
+			ixgbe_process_vf_reset(adapter, vf);
+
+		if (hw->mbx.ops[vf->pool].check_for_msg(hw, vf->pool) == 0)
+			ixgbe_process_vf_msg(adapter, vf);
+
+		if (hw->mbx.ops[vf->pool].check_for_ack(hw, vf->pool) == 0)
+			ixgbe_process_vf_ack(adapter, vf);
 	}
 	IXGBE_CORE_UNLOCK(adapter);
 } /* ixgbe_handle_mbx */

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.47 src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.48
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.47	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe.c,v 1.88.2.47 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe.c,v 1.88.2.48 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
 
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.88.2.47 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.88.2.48 2022/01/31 17:38:36 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -84,7 +84,7 @@ __KERNEL_RCSID(0, "$NetBSD: ixgbe.c,v 1.
  * Driver version
  ************************************************************************/
 static const char ixgbe_driver_version[] = "4.0.1-k";
-/* XXX NetBSD: + 3.3.10 */
+/* XXX NetBSD: + 3.3.24 */
 
 /************************************************************************
  * PCI Device ID Table

Index: src/sys/dev/pci/ixgbe/ixgbe_82599.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.8 src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.9
--- src/sys/dev/pci/ixgbe/ixgbe_82599.c:1.14.8.8	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe_82599.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_82599.c,v 1.14.8.8 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe_82599.c,v 1.14.8.9 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -36,7 +36,7 @@
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 331224 2018-03-19 20:55:05Z erj $*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixgbe_82599.c,v 1.14.8.8 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixgbe_82599.c,v 1.14.8.9 2022/01/31 17:38:36 martin Exp $");
 
 #include "ixgbe_type.h"
 #include "ixgbe_82599.h"
@@ -331,6 +331,7 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw
 	struct ixgbe_phy_info *phy = &hw->phy;
 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
 	s32 ret_val;
+	u16 i;
 
 	DEBUGFUNC("ixgbe_init_ops_82599");
 
@@ -392,7 +393,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw
 	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
 				      & IXGBE_FWSM_MODE_MASK);
 
-	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
+	for (i = 0; i < 64; i++)
+		hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_pf;
 
 	/* EEPROM */
 	eeprom->ops.read = ixgbe_read_eeprom_82599;

Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.5 src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.6
--- src/sys/dev/pci/ixgbe/ixgbe_mbx.c:1.6.8.5	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe_mbx.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_mbx.c,v 1.6.8.5 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe_mbx.c,v 1.6.8.6 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -36,11 +36,14 @@
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_mbx.c 326022 2017-11-20 19:36:21Z pfg $*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixgbe_mbx.c,v 1.6.8.5 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixgbe_mbx.c,v 1.6.8.6 2022/01/31 17:38:36 martin Exp $");
 
 #include "ixgbe_type.h"
 #include "ixgbe_mbx.h"
 
+static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id);
+static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id);
+
 /**
  * ixgbe_read_mbx - Reads a message from the mailbox
  * @hw: pointer to the HW structure
@@ -53,42 +56,91 @@ __KERNEL_RCSID(0, "$NetBSD: ixgbe_mbx.c,
 s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
 
 	DEBUGFUNC("ixgbe_read_mbx");
 
 	/* limit read to size of mailbox */
-	if (size > mbx->size)
+	if (size > mbx->size) {
+		ERROR_REPORT3(IXGBE_ERROR_ARGUMENT,
+			      "Invalid mailbox message size %u, changing to %u",
+			      size, mbx->size);
 		size = mbx->size;
+	}
+
+	if (mbx->ops[mbx_id].read)
+		return mbx->ops[mbx_id].read(hw, msg, size, mbx_id);
+
+	return IXGBE_ERR_CONFIG;
+}
+
+/**
+ * ixgbe_poll_mbx - Wait for message and read it from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
+ * returns SUCCESS if it successfully read message from buffer
+ **/
+s32 ixgbe_poll_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+{
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+	s32 ret_val;
+
+	DEBUGFUNC("ixgbe_poll_mbx");
 
-	if (mbx->ops.read)
-		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+	if (!mbx->ops[mbx_id].read || !mbx->ops[mbx_id].check_for_msg ||
+	    !mbx->timeout)
+		return IXGBE_ERR_CONFIG;
+
+	/* limit read to size of mailbox */
+	if (size > mbx->size) {
+		ERROR_REPORT3(IXGBE_ERROR_ARGUMENT,
+			      "Invalid mailbox message size %u, changing to %u",
+			      size, mbx->size);
+		size = mbx->size;
+	}
+
+	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
+	/* if ack received read message, otherwise we timed out */
+	if (!ret_val)
+		return mbx->ops[mbx_id].read(hw, msg, size, mbx_id);
 
 	return ret_val;
 }
 
 /**
- * ixgbe_write_mbx - Write a message to the mailbox
+ * ixgbe_write_mbx - Write a message to the mailbox and wait for ACK
  * @hw: pointer to the HW structure
  * @msg: The message buffer
  * @size: Length of buffer
  * @mbx_id: id of mailbox to write
  *
- * returns SUCCESS if it successfully copied message into the buffer
+ * returns SUCCESS if it successfully copied message into the buffer and
+ * received an ACK to that message within specified period
  **/
 s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_SUCCESS;
+	s32 ret_val = IXGBE_ERR_MBX;
 
 	DEBUGFUNC("ixgbe_write_mbx");
 
+	/*
+	 * exit if either we can't write, release
+	 * or there is no timeout defined
+	 */
+	if (!mbx->ops[mbx_id].write || !mbx->ops[mbx_id].check_for_ack ||
+	    !mbx->ops[mbx_id].release || !mbx->timeout)
+		return IXGBE_ERR_CONFIG;
+
 	if (size > mbx->size) {
-		ret_val = IXGBE_ERR_MBX;
+		ret_val = IXGBE_ERR_PARAM;
 		ERROR_REPORT2(IXGBE_ERROR_ARGUMENT,
-			     "Invalid mailbox message size %d", size);
-	} else if (mbx->ops.write)
-		ret_val = mbx->ops.write(hw, msg, size, mbx_id);
+			     "Invalid mailbox message size %u", size);
+	} else {
+		ret_val = mbx->ops[mbx_id].write(hw, msg, size, mbx_id);
+	}
 
 	return ret_val;
 }
@@ -103,12 +155,12 @@ s32 ixgbe_write_mbx(struct ixgbe_hw *hw,
 s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
+	s32 ret_val = IXGBE_ERR_CONFIG;
 
 	DEBUGFUNC("ixgbe_check_for_msg");
 
-	if (mbx->ops.check_for_msg)
-		ret_val = mbx->ops.check_for_msg(hw, mbx_id);
+	if (mbx->ops[mbx_id].check_for_msg)
+		ret_val = mbx->ops[mbx_id].check_for_msg(hw, mbx_id);
 
 	return ret_val;
 }
@@ -123,12 +175,12 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw 
 s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
+	s32 ret_val = IXGBE_ERR_CONFIG;
 
 	DEBUGFUNC("ixgbe_check_for_ack");
 
-	if (mbx->ops.check_for_ack)
-		ret_val = mbx->ops.check_for_ack(hw, mbx_id);
+	if (mbx->ops[mbx_id].check_for_ack)
+		ret_val = mbx->ops[mbx_id].check_for_ack(hw, mbx_id);
 
 	return ret_val;
 }
@@ -143,12 +195,12 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw 
 s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
+	s32 ret_val = IXGBE_ERR_CONFIG;
 
 	DEBUGFUNC("ixgbe_check_for_rst");
 
-	if (mbx->ops.check_for_rst)
-		ret_val = mbx->ops.check_for_rst(hw, mbx_id);
+	if (mbx->ops[mbx_id].check_for_rst)
+		ret_val = mbx->ops[mbx_id].check_for_rst(hw, mbx_id);
 
 	return ret_val;
 }
@@ -156,19 +208,19 @@ s32 ixgbe_check_for_rst(struct ixgbe_hw 
 /**
  * ixgbe_clear_mbx - Clear Mailbox Memory
  * @hw: pointer to the HW structure
- * @vf_number: id of mailbox to write
+ * @mbx_id: id of mailbox to write
  *
  * Set VFMBMEM of given VF to 0x0.
  **/
-s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 vf_number)
+s32 ixgbe_clear_mbx(struct ixgbe_hw *hw, u16 mbx_id)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_SUCCESS;
+	s32 ret_val = IXGBE_ERR_CONFIG;
 
 	DEBUGFUNC("ixgbe_clear_mbx");
 
-	if (mbx->ops.clear)
-		ret_val = mbx->ops.clear(hw, vf_number);
+	if (mbx->ops[mbx_id].clear)
+		ret_val = mbx->ops[mbx_id].clear(hw, mbx_id);
 
 	return ret_val;
 }
@@ -187,22 +239,23 @@ static s32 ixgbe_poll_for_msg(struct ixg
 
 	DEBUGFUNC("ixgbe_poll_for_msg");
 
-	if (!countdown || !mbx->ops.check_for_msg)
-		goto out;
+	if (!countdown || !mbx->ops[mbx_id].check_for_msg)
+		return IXGBE_ERR_CONFIG;
 
-	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
+	while (countdown && mbx->ops[mbx_id].check_for_msg(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
 			break;
 		usec_delay(mbx->usec_delay);
 	}
 
-	if (countdown == 0)
+	if (countdown == 0) {
 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
-			   "Polling for VF%d mailbox message timedout", mbx_id);
+			   "Polling for VF%u mailbox message timedout", mbx_id);
+		return IXGBE_ERR_TIMEOUT;
+	}
 
-out:
-	return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
+	return IXGBE_SUCCESS;
 }
 
 /**
@@ -219,114 +272,72 @@ static s32 ixgbe_poll_for_ack(struct ixg
 
 	DEBUGFUNC("ixgbe_poll_for_ack");
 
-	if (!countdown || !mbx->ops.check_for_ack)
-		goto out;
+	if (!countdown || !mbx->ops[mbx_id].check_for_ack)
+		return IXGBE_ERR_CONFIG;
 
-	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
+	while (countdown && mbx->ops[mbx_id].check_for_ack(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
 			break;
 		usec_delay(mbx->usec_delay);
 	}
 
-	if (countdown == 0)
+	if (countdown == 0) {
 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
-			     "Polling for VF%d mailbox ack timedout", mbx_id);
+			     "Polling for VF%u mailbox ack timedout", mbx_id);
+		return IXGBE_ERR_TIMEOUT;
+	}
 
-out:
-	return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
+	return IXGBE_SUCCESS;
 }
 
+
 /**
- * ixgbe_read_posted_mbx - Wait for message notification and receive message
+ * ixgbe_read_mailbox_vf - read VF's mailbox register
  * @hw: pointer to the HW structure
- * @msg: The message buffer
- * @size: Length of buffer
- * @mbx_id: id of mailbox to write
  *
- * returns SUCCESS if it successfully received a message notification and
- * copied it into the receive buffer.
+ * This function is used to read the mailbox register dedicated for VF without
+ * losing the read to clear status bits.
  **/
-s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+static u32 ixgbe_read_mailbox_vf(struct ixgbe_hw *hw)
 {
-	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
-
-	DEBUGFUNC("ixgbe_read_posted_mbx");
+	u32 vf_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
 
-	if (!mbx->ops.read)
-		goto out;
-
-	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
+	vf_mailbox |= hw->mbx.vf_mailbox;
+	hw->mbx.vf_mailbox |= vf_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
 
-	/* if ack received read message, otherwise we timed out */
-	if (!ret_val)
-		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
-out:
-	return ret_val;
+	return vf_mailbox;
 }
 
-/**
- * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
- * @hw: pointer to the HW structure
- * @msg: The message buffer
- * @size: Length of buffer
- * @mbx_id: id of mailbox to write
- *
- * returns SUCCESS if it successfully copied message into the buffer and
- * received an ack to that message within delay * timeout period
- **/
-s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
-			   u16 mbx_id)
+static void ixgbe_clear_msg_vf(struct ixgbe_hw *hw)
 {
-	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 ret_val = IXGBE_ERR_MBX;
-
-	DEBUGFUNC("ixgbe_write_posted_mbx");
+	u32 vf_mailbox = ixgbe_read_mailbox_vf(hw);
 
-	/* exit if either we can't write or there isn't a defined timeout */
-	if (!mbx->ops.write || !mbx->timeout)
-		goto out;
-
-	/* send msg */
-	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
-
-	/* if msg sent wait until we receive an ack */
-	if (!ret_val)
-		ret_val = ixgbe_poll_for_ack(hw, mbx_id);
-out:
-	return ret_val;
+	if (vf_mailbox & IXGBE_VFMAILBOX_PFSTS) {
+		hw->mbx.stats.reqs.ev_count++;
+		hw->mbx.vf_mailbox &= ~IXGBE_VFMAILBOX_PFSTS;
+	}
 }
 
-/**
- * ixgbe_init_mbx_ops_generic - Initialize MB function pointers
- * @hw: pointer to the HW structure
- *
- * Setups up the mailbox read and write message function pointers
- **/
-void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
+static void ixgbe_clear_ack_vf(struct ixgbe_hw *hw)
 {
-	struct ixgbe_mbx_info *mbx = &hw->mbx;
+	u32 vf_mailbox = ixgbe_read_mailbox_vf(hw);
 
-	mbx->ops.read_posted = ixgbe_read_posted_mbx;
-	mbx->ops.write_posted = ixgbe_write_posted_mbx;
+	if (vf_mailbox & IXGBE_VFMAILBOX_PFACK) {
+		hw->mbx.stats.acks.ev_count++;
+		hw->mbx.vf_mailbox &= ~IXGBE_VFMAILBOX_PFACK;
+	}
 }
 
-/**
- * ixgbe_read_v2p_mailbox - read v2p mailbox
- * @hw: pointer to the HW structure
- *
- * This function is used to read the v2p mailbox without losing the read to
- * clear status bits.
- **/
-static u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw)
+static void ixgbe_clear_rst_vf(struct ixgbe_hw *hw)
 {
-	u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
-
-	v2p_mailbox |= hw->mbx.v2p_mailbox;
-	hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
+	u32 vf_mailbox = ixgbe_read_mailbox_vf(hw);
 
-	return v2p_mailbox;
+	if (vf_mailbox & (IXGBE_VFMAILBOX_RSTI | IXGBE_VFMAILBOX_RSTD)) {
+		hw->mbx.stats.rsts.ev_count++;
+		hw->mbx.vf_mailbox &= ~(IXGBE_VFMAILBOX_RSTI |
+					IXGBE_VFMAILBOX_RSTD);
+	}
 }
 
 /**
@@ -339,15 +350,12 @@ static u32 ixgbe_read_v2p_mailbox(struct
  **/
 static s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask)
 {
-	u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw);
-	s32 ret_val = IXGBE_ERR_MBX;
-
-	if (v2p_mailbox & mask)
-		ret_val = IXGBE_SUCCESS;
+	u32 vf_mailbox = ixgbe_read_mailbox_vf(hw);
 
-	hw->mbx.v2p_mailbox &= ~mask;
+	if (vf_mailbox & mask)
+		return IXGBE_SUCCESS;
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -359,17 +367,15 @@ static s32 ixgbe_check_for_bit_vf(struct
  **/
 static s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
-
 	UNREFERENCED_1PARAMETER(mbx_id);
 	DEBUGFUNC("ixgbe_check_for_msg_vf");
 
 	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) {
-		ret_val = IXGBE_SUCCESS;
 		hw->mbx.stats.reqs.ev_count++;
+		return IXGBE_SUCCESS;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -381,17 +387,17 @@ static s32 ixgbe_check_for_msg_vf(struct
  **/
 static s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
-
 	UNREFERENCED_1PARAMETER(mbx_id);
 	DEBUGFUNC("ixgbe_check_for_ack_vf");
 
 	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) {
-		ret_val = IXGBE_SUCCESS;
+		/* TODO: should this be autocleared? */
+		ixgbe_clear_ack_vf(hw);
 		hw->mbx.stats.acks.ev_count++;
+		return IXGBE_SUCCESS;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -403,18 +409,18 @@ static s32 ixgbe_check_for_ack_vf(struct
  **/
 static s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
-
 	UNREFERENCED_1PARAMETER(mbx_id);
 	DEBUGFUNC("ixgbe_check_for_rst_vf");
 
-	if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD |
-	    IXGBE_VFMAILBOX_RSTI))) {
-		ret_val = IXGBE_SUCCESS;
+	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_RSTI |
+					  IXGBE_VFMAILBOX_RSTD)) {
+		/* TODO: should this be autocleared? */
+		ixgbe_clear_rst_vf(hw);
 		hw->mbx.stats.rsts.ev_count++;
+		return IXGBE_SUCCESS;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -425,21 +431,115 @@ static s32 ixgbe_check_for_rst_vf(struct
  **/
 static s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
 {
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+	int countdown = mbx->timeout;
 	s32 ret_val = IXGBE_ERR_MBX;
+	u32 vf_mailbox;
 
 	DEBUGFUNC("ixgbe_obtain_mbx_lock_vf");
 
-	/* Take ownership of the buffer */
-	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU);
+	if (!mbx->timeout)
+		return IXGBE_ERR_CONFIG;
 
-	/* reserve mailbox for vf use */
-	if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU)
-		ret_val = IXGBE_SUCCESS;
+	while (countdown--) {
+		/* Reserve mailbox for VF use */
+		vf_mailbox = ixgbe_read_mailbox_vf(hw);
+		vf_mailbox |= IXGBE_VFMAILBOX_VFU;
+		IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox);
+
+		/* Verify that VF is the owner of the lock */
+		if (ixgbe_read_mailbox_vf(hw) & IXGBE_VFMAILBOX_VFU) {
+			ret_val = IXGBE_SUCCESS;
+			break;
+		}
+
+		/* Wait a bit before trying again */
+		usec_delay(mbx->usec_delay);
+	}
+
+	if (ret_val != IXGBE_SUCCESS) {
+		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+				"Failed to obtain mailbox lock");
+		ret_val = IXGBE_ERR_TIMEOUT;
+	}
 
 	return ret_val;
 }
 
 /**
+ * ixgbe_release_mbx_lock_dummy - release mailbox lock
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to read
+ **/
+static void ixgbe_release_mbx_lock_dummy(struct ixgbe_hw *hw, u16 mbx_id)
+{
+	UNREFERENCED_2PARAMETER(hw, mbx_id);
+
+	DEBUGFUNC("ixgbe_release_mbx_lock_dummy");
+}
+
+/**
+ * ixgbe_release_mbx_lock_vf - release mailbox lock
+ * @hw: pointer to the HW structure
+ * @mbx_id: id of mailbox to read
+ **/
+static void ixgbe_release_mbx_lock_vf(struct ixgbe_hw *hw, u16 mbx_id)
+{
+	u32 vf_mailbox;
+
+	UNREFERENCED_1PARAMETER(mbx_id);
+
+	DEBUGFUNC("ixgbe_release_mbx_lock_vf");
+
+	/* Return ownership of the buffer */
+	vf_mailbox = ixgbe_read_mailbox_vf(hw);
+	vf_mailbox &= ~IXGBE_VFMAILBOX_VFU;
+	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox);
+}
+
+/**
+ * ixgbe_write_mbx_vf_legacy - Write a message to the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to write
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+static s32 ixgbe_write_mbx_vf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size,
+				     u16 mbx_id)
+{
+	s32 ret_val;
+	u16 i;
+
+	UNREFERENCED_1PARAMETER(mbx_id);
+	DEBUGFUNC("ixgbe_write_mbx_vf_legacy");
+
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
+	if (ret_val)
+		return ret_val;
+
+	/* flush msg and acks as we are overwriting the message buffer */
+	ixgbe_check_for_msg_vf(hw, 0);
+	ixgbe_clear_msg_vf(hw);
+	ixgbe_check_for_ack_vf(hw, 0);
+	ixgbe_clear_ack_vf(hw);
+
+	/* copy the caller specified message to the mailbox memory buffer */
+	for (i = 0; i < size; i++)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]);
+
+	/* update stats */
+	hw->mbx.stats.msgs_tx.ev_count++;
+
+	/* interrupt the PF to tell it a message has been sent */
+	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
+
+	return IXGBE_SUCCESS;
+}
+
+/**
  * ixgbe_write_mbx_vf - Write a message to the mailbox
  * @hw: pointer to the HW structure
  * @msg: The message buffer
@@ -451,6 +551,7 @@ static s32 ixgbe_obtain_mbx_lock_vf(stru
 static s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 			      u16 mbx_id)
 {
+	u32 vf_mailbox;
 	s32 ret_val;
 	u16 i;
 
@@ -461,11 +562,11 @@ static s32 ixgbe_write_mbx_vf(struct ixg
 	/* lock the mailbox to prevent pf/vf race condition */
 	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
 	if (ret_val)
-		goto out_no_write;
+		goto out;
 
 	/* flush msg and acks as we are overwriting the message buffer */
-	ixgbe_check_for_msg_vf(hw, 0);
-	ixgbe_check_for_ack_vf(hw, 0);
+	ixgbe_clear_msg_vf(hw);
+	ixgbe_clear_ack_vf(hw);
 
 	/* copy the caller specified message to the mailbox memory buffer */
 	for (i = 0; i < size; i++)
@@ -474,15 +575,22 @@ static s32 ixgbe_write_mbx_vf(struct ixg
 	/* update stats */
 	hw->mbx.stats.msgs_tx.ev_count++;
 
-	/* Drop VFU and interrupt the PF to tell it a message has been sent */
-	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
+	/* interrupt the PF to tell it a message has been sent */
+	vf_mailbox = ixgbe_read_mailbox_vf(hw);
+	vf_mailbox |= IXGBE_VFMAILBOX_REQ;
+	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox);
+
+	/* if msg sent wait until we receive an ack */
+	ixgbe_poll_for_ack(hw, mbx_id);
+
+out:
+	hw->mbx.ops[mbx_id].release(hw, mbx_id);
 
-out_no_write:
 	return ret_val;
 }
 
 /**
- * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
+ * ixgbe_read_mbx_vf_legacy - Reads a message from the inbox intended for vf
  * @hw: pointer to the HW structure
  * @msg: The message buffer
  * @size: Length of buffer
@@ -490,19 +598,19 @@ out_no_write:
  *
  * returns SUCCESS if it successfully read message from buffer
  **/
-static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
-			     u16 mbx_id)
+static s32 ixgbe_read_mbx_vf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size,
+				    u16 mbx_id)
 {
-	s32 ret_val = IXGBE_SUCCESS;
+	s32 ret_val;
 	u16 i;
 
-	DEBUGFUNC("ixgbe_read_mbx_vf");
+	DEBUGFUNC("ixgbe_read_mbx_vf_legacy");
 	UNREFERENCED_1PARAMETER(mbx_id);
 
 	/* lock the mailbox to prevent pf/vf race condition */
 	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
 	if (ret_val)
-		goto out_no_read;
+		return ret_val;
 
 	/* copy the message from the mailbox memory buffer */
 	for (i = 0; i < size; i++)
@@ -514,35 +622,74 @@ static s32 ixgbe_read_mbx_vf(struct ixgb
 	/* update stats */
 	hw->mbx.stats.msgs_rx.ev_count++;
 
-out_no_read:
-	return ret_val;
+	return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @mbx_id: id of mailbox to read
+ *
+ * returns SUCCESS if it successfully read message from buffer
+ **/
+static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
+			     u16 mbx_id)
+{
+	u32 vf_mailbox;
+	s32 ret_val;
+	u16 i;
+
+	DEBUGFUNC("ixgbe_read_mbx_vf");
+	UNREFERENCED_1PARAMETER(mbx_id);
+
+	/* check if there is a message from PF */
+	ret_val = ixgbe_check_for_msg_vf(hw, 0);
+	if (ret_val != IXGBE_SUCCESS)
+		return IXGBE_ERR_MBX_NOMSG;
+
+	ixgbe_clear_msg_vf(hw);
+
+	/* copy the message from the mailbox memory buffer */
+	for (i = 0; i < size; i++)
+		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i);
+
+	/* Acknowledge receipt */
+	vf_mailbox = ixgbe_read_mailbox_vf(hw);
+	vf_mailbox |= IXGBE_VFMAILBOX_ACK;
+	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox);
+
+	/* update stats */
+	hw->mbx.stats.msgs_rx.ev_count++;
+
+	return IXGBE_SUCCESS;
 }
 
 /**
  * ixgbe_init_mbx_params_vf - set initial values for vf mailbox
  * @hw: pointer to the HW structure
  *
- * Initializes the hw->mbx struct to correct values for vf mailbox
+ * Initializes single set the hw->mbx struct to correct values for vf mailbox
+ * Set of legacy functions is being used here
  */
 void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
-	/* start mailbox as timed out and let the reset_hw call set the timeout
-	 * value to begin communications */
-	mbx->timeout = 0;
+	mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT;
 	mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
 
 	mbx->size = IXGBE_VFMAILBOX_SIZE;
 
-	mbx->ops.read = ixgbe_read_mbx_vf;
-	mbx->ops.write = ixgbe_write_mbx_vf;
-	mbx->ops.read_posted = ixgbe_read_posted_mbx;
-	mbx->ops.write_posted = ixgbe_write_posted_mbx;
-	mbx->ops.check_for_msg = ixgbe_check_for_msg_vf;
-	mbx->ops.check_for_ack = ixgbe_check_for_ack_vf;
-	mbx->ops.check_for_rst = ixgbe_check_for_rst_vf;
-	mbx->ops.clear = NULL;
+	/* VF has only one mailbox connection, no need for more IDs */
+	mbx->ops[0].release = ixgbe_release_mbx_lock_dummy;
+	mbx->ops[0].read = ixgbe_read_mbx_vf_legacy;
+	mbx->ops[0].write = ixgbe_write_mbx_vf_legacy;
+	mbx->ops[0].check_for_msg = ixgbe_check_for_msg_vf;
+	mbx->ops[0].check_for_ack = ixgbe_check_for_ack_vf;
+	mbx->ops[0].check_for_rst = ixgbe_check_for_rst_vf;
+	mbx->ops[0].clear = NULL;
 
 	mbx->stats.msgs_tx.ev_count = 0;
 	mbx->stats.msgs_rx.ev_count = 0;
@@ -551,62 +698,112 @@ void ixgbe_init_mbx_params_vf(struct ixg
 	mbx->stats.rsts.ev_count = 0;
 }
 
+/**
+ * ixgbe_upgrade_mbx_params_vf - set initial values for vf mailbox
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+void ixgbe_upgrade_mbx_params_vf(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+	mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT;
+	mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
+
+	mbx->size = IXGBE_VFMAILBOX_SIZE;
+
+	/* VF has only one mailbox connection, no need for more IDs */
+	mbx->ops[0].release = ixgbe_release_mbx_lock_vf;
+	mbx->ops[0].read = ixgbe_read_mbx_vf;
+	mbx->ops[0].write = ixgbe_write_mbx_vf;
+	mbx->ops[0].check_for_msg = ixgbe_check_for_msg_vf;
+	mbx->ops[0].check_for_ack = ixgbe_check_for_ack_vf;
+	mbx->ops[0].check_for_rst = ixgbe_check_for_rst_vf;
+	mbx->ops[0].clear = NULL;
+}
+
+static void ixgbe_clear_msg_pf(struct ixgbe_hw *hw, u16 vf_id)
+{
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_id);
+	u32 pfmbicr;
+
+	pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index));
+
+	if (pfmbicr & (IXGBE_PFMBICR_VFREQ_VF1 << vf_shift))
+		hw->mbx.stats.reqs.ev_count++;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFMBICR(index),
+			IXGBE_PFMBICR_VFREQ_VF1 << vf_shift);
+}
+
+static void ixgbe_clear_ack_pf(struct ixgbe_hw *hw, u16 vf_id)
+{
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_id);
+	u32 pfmbicr;
+
+	pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index));
+
+	if (pfmbicr & (IXGBE_PFMBICR_VFACK_VF1 << vf_shift))
+		hw->mbx.stats.acks.ev_count++;
+
+	IXGBE_WRITE_REG(hw, IXGBE_PFMBICR(index),
+			IXGBE_PFMBICR_VFACK_VF1 << vf_shift);
+}
+
 static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
 {
-	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
-	s32 ret_val = IXGBE_ERR_MBX;
+	u32 pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index));
 
-	if (mbvficr & mask) {
-		ret_val = IXGBE_SUCCESS;
-		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
-	}
+	if (pfmbicr & mask)
+		return IXGBE_SUCCESS;
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
  * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
  * @hw: pointer to the HW structure
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
  **/
-static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
+static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_id)
 {
-	s32 ret_val = IXGBE_ERR_MBX;
-	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
-	u32 vf_bit = vf_number % 16;
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_id);
 
 	DEBUGFUNC("ixgbe_check_for_msg_pf");
 
-	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
-				    index)) {
-		ret_val = IXGBE_SUCCESS;
-		hw->mbx.stats.reqs.ev_count++;
-	}
+	if (!ixgbe_check_for_bit_pf(hw, IXGBE_PFMBICR_VFREQ_VF1 << vf_shift,
+				    index))
+		return IXGBE_SUCCESS;
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
  * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
  * @hw: pointer to the HW structure
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
  **/
-static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
+static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_id)
 {
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_id);
 	s32 ret_val = IXGBE_ERR_MBX;
-	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
-	u32 vf_bit = vf_number % 16;
 
 	DEBUGFUNC("ixgbe_check_for_ack_pf");
 
-	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
+	if (!ixgbe_check_for_bit_pf(hw, IXGBE_PFMBICR_VFACK_VF1 << vf_shift,
 				    index)) {
 		ret_val = IXGBE_SUCCESS;
-		hw->mbx.stats.acks.ev_count++;
+		/* TODO: should this be autocleared? */
+		ixgbe_clear_ack_pf(hw, vf_id);
 	}
 
 	return ret_val;
@@ -615,28 +812,28 @@ static s32 ixgbe_check_for_ack_pf(struct
 /**
  * ixgbe_check_for_rst_pf - checks to see if the VF has reset
  * @hw: pointer to the HW structure
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
  **/
-static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
+static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_id)
 {
-	u32 reg_offset = (vf_number < 32) ? 0 : 1;
-	u32 vf_shift = vf_number % 32;
-	u32 vflre = 0;
+	u32 vf_shift = IXGBE_PFVFLRE_SHIFT(vf_id);
+	u32 index = IXGBE_PFVFLRE_INDEX(vf_id);
 	s32 ret_val = IXGBE_ERR_MBX;
+	u32 vflre = 0;
 
 	DEBUGFUNC("ixgbe_check_for_rst_pf");
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82599EB:
-		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
+		vflre = IXGBE_READ_REG(hw, IXGBE_PFVFLRE(index));
 		break;
 	case ixgbe_mac_X550:
 	case ixgbe_mac_X550EM_x:
 	case ixgbe_mac_X550EM_a:
 	case ixgbe_mac_X540:
-		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
+		vflre = IXGBE_READ_REG(hw, IXGBE_PFVFLREC(index));
 		break;
 	default:
 		break;
@@ -644,7 +841,7 @@ static s32 ixgbe_check_for_rst_pf(struct
 
 	if (vflre & (1 << vf_shift)) {
 		ret_val = IXGBE_SUCCESS;
-		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
+		IXGBE_WRITE_REG(hw, IXGBE_PFVFLREC(index), (1 << vf_shift));
 		hw->mbx.stats.rsts.ev_count++;
 	}
 
@@ -654,142 +851,290 @@ static s32 ixgbe_check_for_rst_pf(struct
 /**
  * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
  * @hw: pointer to the HW structure
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * return SUCCESS if we obtained the mailbox lock
  **/
-static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
+static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_id)
 {
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+	int countdown = mbx->timeout;
 	s32 ret_val = IXGBE_ERR_MBX;
-	u32 p2v_mailbox;
+	u32 pf_mailbox;
 
 	DEBUGFUNC("ixgbe_obtain_mbx_lock_pf");
 
-	/* Take ownership of the buffer */
-	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
+	if (!mbx->timeout)
+		return IXGBE_ERR_CONFIG;
 
-	/* reserve mailbox for vf use */
-	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
-	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
-		ret_val = IXGBE_SUCCESS;
-	else
-		ERROR_REPORT2(IXGBE_ERROR_POLLING,
-			   "Failed to obtain mailbox lock for VF%d", vf_number);
+	while (countdown--) {
+		/* Reserve mailbox for PF use */
+		pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
+		pf_mailbox |= IXGBE_PFMAILBOX_PFU;
+		IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox);
+
+		/* Verify that PF is the owner of the lock */
+		pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
+		if (pf_mailbox & IXGBE_PFMAILBOX_PFU) {
+			ret_val = IXGBE_SUCCESS;
+			break;
+		}
 
+		/* Wait a bit before trying again */
+		usec_delay(mbx->usec_delay);
+	}
+
+	if (ret_val != IXGBE_SUCCESS) {
+		ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE,
+			      "Failed to obtain mailbox lock");
+		ret_val = IXGBE_ERR_TIMEOUT;
+	}
 
 	return ret_val;
 }
 
 /**
+ * ixgbe_release_mbx_lock_pf - release mailbox lock
+ * @hw: pointer to the HW structure
+ * @vf_id: the VF index
+ **/
+static void ixgbe_release_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_id)
+{
+	u32 pf_mailbox;
+
+	DEBUGFUNC("ixgbe_release_mbx_lock_pf");
+
+	/* Return ownership of the buffer */
+	pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
+	pf_mailbox &= ~IXGBE_PFMAILBOX_PFU;
+	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox);
+}
+
+/**
+ * ixgbe_write_mbx_pf_legacy - Places a message in the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_id: the VF index
+ *
+ * returns SUCCESS if it successfully copied message into the buffer
+ **/
+static s32 ixgbe_write_mbx_pf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size,
+				     u16 vf_id)
+{
+	s32 ret_val;
+	u16 i;
+
+	DEBUGFUNC("ixgbe_write_mbx_pf_legacy");
+
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id);
+	if (ret_val)
+		return ret_val;
+
+	/* flush msg and acks as we are overwriting the message buffer */
+	ixgbe_check_for_msg_pf(hw, vf_id);
+	ixgbe_clear_msg_pf(hw, vf_id);
+	ixgbe_check_for_ack_pf(hw, vf_id);
+	ixgbe_clear_ack_pf(hw, vf_id);
+
+	/* copy the caller specified message to the mailbox memory buffer */
+	for (i = 0; i < size; i++)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, msg[i]);
+
+	/* Interrupt VF to tell it a message has been sent and release buffer*/
+	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), IXGBE_PFMAILBOX_STS);
+
+	/* update stats */
+	hw->mbx.stats.msgs_tx.ev_count++;
+
+	return IXGBE_SUCCESS;
+}
+
+/**
  * ixgbe_write_mbx_pf - Places a message in the mailbox
  * @hw: pointer to the HW structure
  * @msg: The message buffer
  * @size: Length of buffer
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * returns SUCCESS if it successfully copied message into the buffer
  **/
 static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
-			      u16 vf_number)
+			      u16 vf_id)
 {
+	u32 pf_mailbox;
 	s32 ret_val;
 	u16 i;
 
 	DEBUGFUNC("ixgbe_write_mbx_pf");
 
 	/* lock the mailbox to prevent pf/vf race condition */
-	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
+	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id);
 	if (ret_val)
-		goto out_no_write;
+		goto out;
 
 	/* flush msg and acks as we are overwriting the message buffer */
-	ixgbe_check_for_msg_pf(hw, vf_number);
-	ixgbe_check_for_ack_pf(hw, vf_number);
+	ixgbe_clear_msg_pf(hw, vf_id);
+	ixgbe_clear_ack_pf(hw, vf_id);
 
 	/* copy the caller specified message to the mailbox memory buffer */
 	for (i = 0; i < size; i++)
-		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, msg[i]);
 
-	/* Interrupt VF to tell it a message has been sent and release buffer*/
-	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
+	/* Interrupt VF to tell it a message has been sent */
+	pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
+	pf_mailbox |= IXGBE_PFMAILBOX_STS;
+	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox);
+
+	/* if msg sent wait until we receive an ack */
+	ixgbe_poll_for_ack(hw, vf_id);
 
 	/* update stats */
 	hw->mbx.stats.msgs_tx.ev_count++;
 
-out_no_write:
+out:
+	hw->mbx.ops[vf_id].release(hw, vf_id);
+
 	return ret_val;
 
 }
 
 /**
+ * ixgbe_read_mbx_pf_legacy - Read a message from the mailbox
+ * @hw: pointer to the HW structure
+ * @msg: The message buffer
+ * @size: Length of buffer
+ * @vf_id: the VF index
+ *
+ * This function copies a message from the mailbox buffer to the caller's
+ * memory buffer.  The presumption is that the caller knows that there was
+ * a message due to a VF request so no polling for message is needed.
+ **/
+static s32 ixgbe_read_mbx_pf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size,
+				    u16 vf_id)
+{
+	s32 ret_val;
+	u16 i;
+
+	DEBUGFUNC("ixgbe_read_mbx_pf_legacy");
+
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_id);
+	if (ret_val != IXGBE_SUCCESS)
+		return ret_val;
+
+	/* copy the message to the mailbox memory buffer */
+	for (i = 0; i < size; i++)
+		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i);
+
+	/* Acknowledge the message and release buffer */
+	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), IXGBE_PFMAILBOX_ACK);
+
+	/* update stats */
+	hw->mbx.stats.msgs_rx.ev_count++;
+
+	return IXGBE_SUCCESS;
+}
+
+/**
  * ixgbe_read_mbx_pf - Read a message from the mailbox
  * @hw: pointer to the HW structure
  * @msg: The message buffer
  * @size: Length of buffer
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * This function copies a message from the mailbox buffer to the caller's
  * memory buffer.  The presumption is that the caller knows that there was
  * a message due to a VF request so no polling for message is needed.
  **/
 static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
-			     u16 vf_number)
+			     u16 vf_id)
 {
+	u32 pf_mailbox;
 	s32 ret_val;
 	u16 i;
 
 	DEBUGFUNC("ixgbe_read_mbx_pf");
 
-	/* lock the mailbox to prevent pf/vf race condition */
-	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
-	if (ret_val)
-		goto out_no_read;
+	/* check if there is a message from VF */
+	ret_val = ixgbe_check_for_msg_pf(hw, vf_id);
+	if (ret_val != IXGBE_SUCCESS)
+		return IXGBE_ERR_MBX_NOMSG;
+
+	ixgbe_clear_msg_pf(hw, vf_id);
 
 	/* copy the message to the mailbox memory buffer */
 	for (i = 0; i < size; i++)
-		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
+		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i);
 
 	/* Acknowledge the message and release buffer */
-	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
+	pf_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_id));
+	pf_mailbox |= IXGBE_PFMAILBOX_ACK;
+	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_id), pf_mailbox);
 
 	/* update stats */
 	hw->mbx.stats.msgs_rx.ev_count++;
 
-out_no_read:
-	return ret_val;
+	return IXGBE_SUCCESS;
 }
 
 /**
  * ixgbe_clear_mbx_pf - Clear Mailbox Memory
  * @hw: pointer to the HW structure
- * @vf_number: the VF index
+ * @vf_id: the VF index
  *
  * Set VFMBMEM of given VF to 0x0.
  **/
-static s32 ixgbe_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_number)
+static s32 ixgbe_clear_mbx_pf(struct ixgbe_hw *hw, u16 vf_id)
 {
 	u16 mbx_size = hw->mbx.size;
 	u16 i;
 
-	if (vf_number > 63)
+	if (vf_id > 63)
 		return IXGBE_ERR_PARAM;
 
 	for (i = 0; i < mbx_size; ++i)
-		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, 0x0);
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_id), i, 0x0);
 
 	return IXGBE_SUCCESS;
 }
 
 /**
+ * ixgbe_init_mbx_params_pf_id - set initial values for pf mailbox
+ * @hw: pointer to the HW structure
+ * @vf_id: the VF index
+ *
+ * Initializes single set of the hw->mbx struct to correct values for pf mailbox
+ * Set of legacy functions is being used here
+ */
+void ixgbe_init_mbx_params_pf_id(struct ixgbe_hw *hw, u16 vf_id)
+{
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+	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_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;
+}
+
+/**
  * ixgbe_init_mbx_params_pf - set initial values for pf mailbox
  * @hw: pointer to the HW structure
  *
- * Initializes the hw->mbx struct to correct values for pf mailbox
+ * Initializes all sets of the hw->mbx struct to correct values for pf
+ * mailbox. One set corresponds to single VF. It also initializes counters
+ * and general variables. A set of legacy functions is used by default.
  */
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
 {
+	u16 i;
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
+	/* Ensure we are not calling this function from VF */
 	if (hw->mac.type != ixgbe_mac_82599EB &&
 	    hw->mac.type != ixgbe_mac_X550 &&
 	    hw->mac.type != ixgbe_mac_X550EM_x &&
@@ -797,23 +1142,57 @@ void ixgbe_init_mbx_params_pf(struct ixg
 	    hw->mac.type != ixgbe_mac_X540)
 		return;
 
-	mbx->timeout = 0;
-	mbx->usec_delay = 0;
-
+	/* Initialize common mailbox settings */
+	mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT;
+	mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
 	mbx->size = IXGBE_VFMAILBOX_SIZE;
 
-	mbx->ops.read = ixgbe_read_mbx_pf;
-	mbx->ops.write = ixgbe_write_mbx_pf;
-	mbx->ops.read_posted = ixgbe_read_posted_mbx;
-	mbx->ops.write_posted = ixgbe_write_posted_mbx;
-	mbx->ops.check_for_msg = ixgbe_check_for_msg_pf;
-	mbx->ops.check_for_ack = ixgbe_check_for_ack_pf;
-	mbx->ops.check_for_rst = ixgbe_check_for_rst_pf;
-	mbx->ops.clear = ixgbe_clear_mbx_pf;
-
+	/* Initialize counters with zeroes */
 	mbx->stats.msgs_tx.ev_count = 0;
 	mbx->stats.msgs_rx.ev_count = 0;
 	mbx->stats.reqs.ev_count = 0;
 	mbx->stats.acks.ev_count = 0;
 	mbx->stats.rsts.ev_count = 0;
+
+	/* No matter of VF number, we initialize params for all 64 VFs. */
+	/* TODO: 1. Add a define for max VF and refactor SHARED to get rid
+	 * of magic number for that (63 or 64 depending on use case.)
+	 * 2. rewrite the code to dynamically allocate mbx->ops[vf_id] for
+	 * certain number of VFs instead of default maximum value of 64 (0..63)
+	 */
+	for (i = 0; i < 64; i++)
+		ixgbe_init_mbx_params_pf_id(hw, i);
+}
+
+/**
+ * ixgbe_upgrade_mbx_params_pf - Upgrade initial values for pf mailbox
+ * @hw: pointer to the HW structure
+ * @vf_id: the VF index
+ *
+ * Initializes the hw->mbx struct to new function set for improved
+ * stability and handling of messages.
+ */
+void ixgbe_upgrade_mbx_params_pf(struct ixgbe_hw *hw, u16 vf_id)
+{
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+
+   /* Ensure we are not calling this function from VF */
+	if (hw->mac.type != ixgbe_mac_82599EB &&
+	    hw->mac.type != ixgbe_mac_X550 &&
+	    hw->mac.type != ixgbe_mac_X550EM_x &&
+	    hw->mac.type != ixgbe_mac_X550EM_a &&
+	    hw->mac.type != ixgbe_mac_X540)
+		return;
+
+	mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT;
+	mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
+	mbx->size = IXGBE_VFMAILBOX_SIZE;
+
+	mbx->ops[vf_id].release = ixgbe_release_mbx_lock_pf;
+	mbx->ops[vf_id].read = ixgbe_read_mbx_pf;
+	mbx->ops[vf_id].write = ixgbe_write_mbx_pf;
+	mbx->ops[vf_id].check_for_msg = ixgbe_check_for_msg_pf;
+	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;
 }

Index: src/sys/dev/pci/ixgbe/ixgbe_mbx.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.4 src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.5
--- src/sys/dev/pci/ixgbe/ixgbe_mbx.h:1.10.8.4	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe_mbx.h	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_mbx.h,v 1.10.8.4 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe_mbx.h,v 1.10.8.5 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -42,13 +42,12 @@
 
 struct ixgbe_mbx_operations {
 	void (*init_params)(struct ixgbe_hw *hw);
-	s32  (*read)(struct ixgbe_hw *, u32 *, u16,  u16);
-	s32  (*write)(struct ixgbe_hw *, u32 *, u16, u16);
-	s32  (*read_posted)(struct ixgbe_hw *, u32 *, u16,  u16);
-	s32  (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16);
-	s32  (*check_for_msg)(struct ixgbe_hw *, u16);
-	s32  (*check_for_ack)(struct ixgbe_hw *, u16);
-	s32  (*check_for_rst)(struct ixgbe_hw *, u16);
+	void (*release)(struct ixgbe_hw *hw, u16 mbx_id);
+	s32  (*read)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+	s32  (*write)(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+	s32  (*check_for_msg)(struct ixgbe_hw *hw, u16 vf_number);
+	s32  (*check_for_ack)(struct ixgbe_hw *hw, u16 vf_number);
+	s32  (*check_for_rst)(struct ixgbe_hw *hw, u16 vf_number);
 	s32  (*clear)(struct ixgbe_hw *hw, u16 vf_number);
 };
 
@@ -62,11 +61,16 @@ struct ixgbe_mbx_stats {
 };
 
 struct ixgbe_mbx_info {
-	struct ixgbe_mbx_operations ops;
+	/*
+	 * PF: One set of operations for each VF to handle various API versions
+	 *     at the same time
+	 * VF: Only the very first (0) set should be used
+	 */
+	struct ixgbe_mbx_operations ops[64];
 	struct ixgbe_mbx_stats stats;
 	u32 timeout;
 	u32 usec_delay;
-	u32 v2p_mailbox;
+	u32 vf_mailbox;
 	u16 size;
 };
 
@@ -92,10 +96,10 @@ struct ixgbe_mbx_info {
 #define IXGBE_PFMAILBOX_PFU	0x00000008 /* PF owns the mailbox buffer */
 #define IXGBE_PFMAILBOX_RVFU	0x00000010 /* Reset VFU - used when VF stuck */
 
-#define IXGBE_MBVFICR_VFREQ_MASK	0x0000FFFF /* bits for VF messages */
-#define IXGBE_MBVFICR_VFREQ_VF1		0x00000001 /* bit for VF 1 message */
-#define IXGBE_MBVFICR_VFACK_MASK	0xFFFF0000 /* bits for VF acks */
-#define IXGBE_MBVFICR_VFACK_VF1		0x00010000 /* bit for VF 1 ack */
+#define IXGBE_PFMBICR_VFREQ_MASK	0x0000FFFF /* bits for VF messages */
+#define IXGBE_PFMBICR_VFREQ_VF1		0x00000001 /* bit for VF 1 message */
+#define IXGBE_PFMBICR_VFACK_MASK	0xFFFF0000 /* bits for VF acks */
+#define IXGBE_PFMBICR_VFACK_VF1		0x00010000 /* bit for VF 1 ack */
 
 
 /* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the
@@ -127,6 +131,9 @@ enum ixgbe_pfvf_api_rev {
 	ixgbe_mbox_api_11,	/* API version 1.1, linux/freebsd VF driver */
 	ixgbe_mbox_api_12,	/* API version 1.2, linux/freebsd VF driver */
 	ixgbe_mbox_api_13,	/* API version 1.3, linux/freebsd VF driver */
+	/* API 1.4 is being used in the upstream for IPsec */
+	ixgbe_mbox_api_14,	/* API version 1.4, linux/freebsd VF driver */
+	ixgbe_mbox_api_15,	/* API version 1.5, linux/freebsd VF driver */
 	/* This value should always be last */
 	ixgbe_mbox_api_unknown,	/* indicates that API version is not known */
 };
@@ -187,16 +194,17 @@ enum ixgbevf_xcast_modes {
 #define IXGBE_VF_MBX_INIT_TIMEOUT	2000 /* number of retries on mailbox */
 #define IXGBE_VF_MBX_INIT_DELAY		500  /* microseconds between retries */
 
-s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16);
-s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16);
-s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16);
-s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16);
+s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+s32 ixgbe_poll_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+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);
-void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw);
 void ixgbe_init_mbx_params_vf(struct ixgbe_hw *);
-void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
+void ixgbe_upgrade_mbx_params_vf(struct ixgbe_hw *hw);
+void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw);
+void ixgbe_init_mbx_params_pf_id(struct ixgbe_hw *hw, u16 vf_id);
+void ixgbe_upgrade_mbx_params_pf(struct ixgbe_hw *hw, u16 vf_id);
 
 #endif /* _IXGBE_MBX_H_ */

Index: src/sys/dev/pci/ixgbe/ixgbe_type.h
diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.15 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.16
--- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.15	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe_type.h	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_type.h,v 1.22.2.15 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe_type.h,v 1.22.2.16 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -480,8 +480,14 @@ struct ixgbe_nvm_version {
 #define IXGBE_PFMAILBOX(_i)	(0x04B00 + (4 * (_i))) /* 64 total */
 /* 64 Mailboxes, 16 DW each */
 #define IXGBE_PFMBMEM(_i)	(0x13000 + (64 * (_i)))
+#define IXGBE_PFMBICR_INDEX(_i)	((_i) >> 4)
+#define IXGBE_PFMBICR_SHIFT(_i)	((_i) % 16)
 #define IXGBE_PFMBICR(_i)	(0x00710 + (4 * (_i))) /* 4 total */
 #define IXGBE_PFMBIMR(_i)	(0x00720 + (4 * (_i))) /* 4 total */
+#define IXGBE_PFVFLRE(_i)	((((_i) & 1) ? 0x001C0 : 0x00600))
+#define IXGBE_PFVFLREC(_i)	(0x00700 + ((_i) * 4))
+#define IXGBE_PFVFLRE_INDEX(_i)	((_i) >> 5)
+#define IXGBE_PFVFLRE_SHIFT(_i)	((_i) % 32)
 #define IXGBE_VFRE(_i)		(0x051E0 + ((_i) * 4))
 #define IXGBE_VFTE(_i)		(0x08110 + ((_i) * 4))
 #define IXGBE_VMECM(_i)		(0x08790 + ((_i) * 4))
@@ -2411,6 +2417,7 @@ enum {
 #endif /* PREBOOT_SUPPORT || QV_RELEASE*/
 
 
+
 #define IXGBE_SAN_MAC_ADDR_PTR		0x28
 #define IXGBE_NVM_MAP_VER		0x29
 #define IXGBE_OEM_NVM_IMAGE_VER		0x2A
@@ -2922,12 +2929,6 @@ enum {
 #define IXGBE_RX_DESC_SPECIAL_PRI_MASK	0xE000 /* Priority in upper 3 bits */
 #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT	0x000D /* Priority in upper 3 of 16 */
 #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT	IXGBE_RX_DESC_SPECIAL_PRI_SHIFT
-
-/* SR-IOV specific macros */
-#define IXGBE_MBVFICR_INDEX(vf_number)	(vf_number >> 4)
-#define IXGBE_MBVFICR(_i)		(0x00710 + ((_i) * 4))
-#define IXGBE_VFLRE(_i)			(((_i & 1) ? 0x001C0 : 0x00600))
-#define IXGBE_VFLREC(_i)		 (0x00700 + ((_i) * 4))
 /* Translated register #defines */
 #define IXGBE_PVFCTRL(P)	(0x00300 + (4 * (P)))
 #define IXGBE_PVFSTATUS(P)	(0x00008 + (0 * (P)))
@@ -4295,7 +4296,9 @@ struct ixgbe_hw {
 #define IXGBE_ERR_FDIR_CMD_INCOMPLETE		-38
 #define IXGBE_ERR_FW_RESP_INVALID		-39
 #define IXGBE_ERR_TOKEN_RETRY			-40
-#define IXGBE_ERR_MBX				-100
+#define IXGBE_ERR_MBX				-41
+#define IXGBE_ERR_MBX_NOMSG			-42
+#define IXGBE_ERR_TIMEOUT			-43
 
 #define IXGBE_ERR_NOT_TRUSTED			-50 /* XXX NetBSD */
 #define IXGBE_ERR_NOT_IN_PROMISC		-51 /* XXX NetBSD */

Index: src/sys/dev/pci/ixgbe/ixgbe_vf.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.8 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.9
--- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.8	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe_vf.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_vf.c,v 1.12.8.8 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe_vf.c,v 1.12.8.9 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -36,7 +36,7 @@
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_vf.c 331224 2018-03-19 20:55:05Z erj $*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixgbe_vf.c,v 1.12.8.8 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixgbe_vf.c,v 1.12.8.9 2022/01/31 17:38:36 martin Exp $");
 
 #include "ixgbe_api.h"
 #include "ixgbe_type.h"
@@ -60,6 +60,8 @@ __KERNEL_RCSID(0, "$NetBSD: ixgbe_vf.c,v
  **/
 s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw)
 {
+	u16 i;
+
 	/* MAC */
 	hw->mac.ops.init_hw = ixgbe_init_hw_vf;
 	hw->mac.ops.reset_hw = ixgbe_reset_hw_vf;
@@ -92,7 +94,8 @@ s32 ixgbe_init_ops_vf(struct ixgbe_hw *h
 	hw->mac.max_tx_queues = 1;
 	hw->mac.max_rx_queues = 1;
 
-	hw->mbx.ops.init_params = ixgbe_init_mbx_params_vf;
+	for (i = 0; i < 64; i++)
+		hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_vf;
 
 	return IXGBE_SUCCESS;
 }
@@ -196,6 +199,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h
 
 	/* reset the api version */
 	hw->api_version = ixgbe_mbox_api_10;
+	ixgbe_init_mbx_params_vf(hw);
 
 	DEBUGOUT("Issuing a function level reset to MAC\n");
 
@@ -205,7 +209,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h
 	msec_delay(50);
 
 	/* we cannot reset while the RSTI / RSTD bits are asserted */
-	while (!mbx->ops.check_for_rst(hw, 0) && timeout) {
+	while (!mbx->ops[0].check_for_rst(hw, 0) && timeout) {
 		timeout--;
 		usec_delay(5);
 	}
@@ -220,7 +224,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h
 	mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT;
 
 	msgbuf[0] = IXGBE_VF_RESET;
-	mbx->ops.write_posted(hw, msgbuf, 1, 0);
+	ixgbe_write_mbx(hw, msgbuf, 1, 0);
 
 	msec_delay(10);
 
@@ -229,8 +233,8 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *h
 	 * also set up the mc_filter_type which is piggy backed
 	 * on the mac address in word 3
 	 */
-	ret_val = mbx->ops.read_posted(hw, msgbuf,
-			IXGBE_VF_PERMADDR_MSG_LEN, 0);
+	ret_val = ixgbe_poll_mbx(hw, msgbuf,
+				 IXGBE_VF_PERMADDR_MSG_LEN, 0);
 	if (ret_val)
 		return ret_val;
 
@@ -335,13 +339,12 @@ static s32 ixgbe_mta_vector(struct ixgbe
 static s32 ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw, u32 *msg,
 				      u32 *retmsg, u16 size)
 {
-	struct ixgbe_mbx_info *mbx = &hw->mbx;
-	s32 retval = mbx->ops.write_posted(hw, msg, size, 0);
+	s32 retval = ixgbe_write_mbx(hw, msg, size, 0);
 
 	if (retval)
 		return retval;
 
-	return mbx->ops.read_posted(hw, retmsg, size, 0);
+	return ixgbe_poll_mbx(hw, retmsg, size, 0);
 }
 
 /**
@@ -450,6 +453,7 @@ s32 ixgbevf_update_xcast_mode(struct ixg
 			return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
 		/* Fall through */
 	case ixgbe_mbox_api_13:
+	case ixgbe_mbox_api_15:
 		break;
 	default:
 		return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
@@ -621,11 +625,10 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe
 	struct ixgbe_mac_info *mac = &hw->mac;
 	s32 ret_val = IXGBE_SUCCESS;
 	u32 links_reg;
-	u32 in_msg = 0;
 	UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
 
 	/* If we were hit with a reset drop the link */
-	if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout)
+	if (!mbx->ops[0].check_for_rst(hw, 0) || !mbx->timeout)
 		mac->get_link_status = TRUE;
 
 	if (!mac->get_link_status)
@@ -654,7 +657,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe
 	switch (links_reg & IXGBE_LINKS_SPEED_82599) {
 	case IXGBE_LINKS_SPEED_10G_82599:
 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
-		if (hw->mac.type >= ixgbe_mac_X550) {
+		if (hw->mac.type >= ixgbe_mac_X550_vf) {
 			if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
 				*speed = IXGBE_LINK_SPEED_2_5GB_FULL;
 		}
@@ -664,7 +667,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe
 		break;
 	case IXGBE_LINKS_SPEED_100_82599:
 		*speed = IXGBE_LINK_SPEED_100_FULL;
-		if (hw->mac.type >= ixgbe_mac_X550) {
+		if (hw->mac.type >= ixgbe_mac_X550_vf) {
 			if (links_reg & IXGBE_LINKS_SPEED_NON_STD)
 				*speed = IXGBE_LINK_SPEED_5GB_FULL;
 		}
@@ -672,30 +675,34 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe
 	case IXGBE_LINKS_SPEED_10_X550EM_A:
 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
 		/* Since Reserved in older MAC's */
-		if (hw->mac.type >= ixgbe_mac_X550)
+		if (hw->mac.type >= ixgbe_mac_X550_vf)
 			*speed = IXGBE_LINK_SPEED_10_FULL;
 		break;
 	default:
 		*speed = IXGBE_LINK_SPEED_UNKNOWN;
 	}
 
-	/* if the read failed it could just be a mailbox collision, best wait
-	 * until we are called again and don't report an error
-	 */
-	if (mbx->ops.read(hw, &in_msg, 1, 0))
-		goto out;
+	if (hw->api_version < ixgbe_mbox_api_15) {
+		u32 in_msg = 0;
 
-	if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) {
-		/* msg is not CTS and is NACK we must have lost CTS status */
-		if (in_msg & IXGBE_VT_MSGTYPE_FAILURE)
-			ret_val = -1;
-		goto out;
-	}
+		/* if the read failed it could just be a mailbox collision, best wait
+		 * until we are called again and don't report an error
+		 */
+		if (ixgbe_read_mbx(hw, &in_msg, 1, 0))
+			goto out;
 
-	/* the pf is talking, if we timed out in the past we reinit */
-	if (!mbx->timeout) {
-		ret_val = -1;
-		goto out;
+		if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) {
+			/* msg is not CTS and is NACK we must have lost CTS status */
+			if (in_msg & IXGBE_VT_MSGTYPE_FAILURE)
+				ret_val = IXGBE_ERR_MBX;
+			goto out;
+		}
+
+		/* the pf is talking, if we timed out in the past we reinit */
+		if (!mbx->timeout) {
+			ret_val = IXGBE_ERR_TIMEOUT;
+			goto out;
+		}
 	}
 
 	/* if we passed all the tests above then the link is up and we no
@@ -773,6 +780,7 @@ int ixgbevf_get_queues(struct ixgbe_hw *
 	case ixgbe_mbox_api_11:
 	case ixgbe_mbox_api_12:
 	case ixgbe_mbox_api_13:
+	case ixgbe_mbox_api_15:
 		break;
 	default:
 		return 0;
@@ -787,7 +795,7 @@ int ixgbevf_get_queues(struct ixgbe_hw *
 		msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
 
 		/*
-		 * if we didn't get an ACK there must have been
+		 * if we didn't get a SUCCESS there must have been
 		 * some sort of mailbox error so we should treat it
 		 * as such
 		 */

Index: src/sys/dev/pci/ixgbe/ixgbe_x540.c
diff -u src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.9.6.7 src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.9.6.8
--- src/sys/dev/pci/ixgbe/ixgbe_x540.c:1.9.6.7	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixgbe_x540.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixgbe_x540.c,v 1.9.6.7 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixgbe_x540.c,v 1.9.6.8 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
   SPDX-License-Identifier: BSD-3-Clause
@@ -36,7 +36,7 @@
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe_x540.c 331224 2018-03-19 20:55:05Z erj $*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixgbe_x540.c,v 1.9.6.7 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixgbe_x540.c,v 1.9.6.8 2022/01/31 17:38:36 martin Exp $");
 
 #include "ixgbe_x540.h"
 #include "ixgbe_type.h"
@@ -68,6 +68,7 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw 
 	struct ixgbe_phy_info *phy = &hw->phy;
 	struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
 	s32 ret_val;
+	u16 i;
 
 	DEBUGFUNC("ixgbe_init_ops_X540");
 
@@ -151,7 +152,8 @@ s32 ixgbe_init_ops_X540(struct ixgbe_hw 
 	mac->arc_subsystem_valid = !!(IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw))
 				     & IXGBE_FWSM_MODE_MASK);
 
-	hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
+	for (i = 0; i < 64; i++)
+		hw->mbx.ops[i].init_params = ixgbe_init_mbx_params_pf;
 
 	/* LEDs */
 	mac->ops.blink_led_start = ixgbe_blink_led_start_X540;

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.56.2.35 src/sys/dev/pci/ixgbe/ixv.c:1.56.2.36
--- src/sys/dev/pci/ixgbe/ixv.c:1.56.2.35	Sun Jan 30 16:06:35 2022
+++ src/sys/dev/pci/ixgbe/ixv.c	Mon Jan 31 17:38:36 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: ixv.c,v 1.56.2.35 2022/01/30 16:06:35 martin Exp $ */
+/* $NetBSD: ixv.c,v 1.56.2.36 2022/01/31 17:38:36 martin Exp $ */
 
 /******************************************************************************
 
@@ -35,7 +35,7 @@
 /*$FreeBSD: head/sys/dev/ixgbe/if_ixv.c 331224 2018-03-19 20:55:05Z erj $*/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ixv.c,v 1.56.2.35 2022/01/30 16:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ixv.c,v 1.56.2.36 2022/01/31 17:38:36 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -466,6 +466,12 @@ ixv_attach(device_t parent, device_t dev
 	case ixgbe_mbox_api_13:
 		apivstr = "1.3";
 		break;
+	case ixgbe_mbox_api_14:
+		apivstr = "1.4";
+		break;
+	case ixgbe_mbox_api_15:
+		apivstr = "1.5";
+		break;
 	default:
 		apivstr = "unknown";
 		break;
@@ -1090,7 +1096,8 @@ static int
 ixv_negotiate_api(struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int		mbx_api[] = { ixgbe_mbox_api_13,
+	int		mbx_api[] = { ixgbe_mbox_api_15,
+				      ixgbe_mbox_api_13,
 				      ixgbe_mbox_api_12,
 				      ixgbe_mbox_api_11,
 				      ixgbe_mbox_api_10,
@@ -1098,8 +1105,11 @@ ixv_negotiate_api(struct adapter *adapte
 	int		i = 0;
 
 	while (mbx_api[i] != ixgbe_mbox_api_unknown) {
-		if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0)
+		if (ixgbevf_negotiate_api_version(hw, mbx_api[i]) == 0) {
+			if (hw->api_version >= ixgbe_mbox_api_15)
+				ixgbe_upgrade_mbx_params_vf(hw);
 			return (0);
+		}
 		i++;
 	}
 

Reply via email to