DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v1 00/22] Update IXGBE base driver
@ 2024-04-24 13:21 Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 01/22] net/ixgbe/base: revert remove default advertising for x550 2.5G/5G Anatoly Burakov
                   ` (22 more replies)
  0 siblings, 23 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev; +Cc: vladimir.medvedkin, bruce.richardson

This patchset updates IXGBE base driver to latest shared code snapshot,
fixing a few issues as well as adding support for new hardware.

Barbara Skobiej (3):
  net/ixgbe/base: remove circular header dependency
  net/ixgbe/base: add missing QV defines
  net/ixgbe/base: improve SWFW semaphore acquisition

Chinh T Cao (1):
  net/ixgbe/base: remove prototypes of unimplemented functions

Dawid Zielinski (1):
  net/ixgbe/base: prevent untrusted loop bound

Jakub Chylkowski (3):
  net/ixgbe/base: rename message type macros
  net/ixgbe/base: correct registers names to match datasheet
  net/ixgbe/base: introduce new mailbox API

Krzysztof Galazka (1):
  net/ixgbe/base: filter out spurious link up indication

Marcin Jurczak (1):
  net/ixgbe/base: remove non-inclusive language

Mical MarekX (1):
  net/ixgbe/base: replace HIC with direct register access

Milosz Szymonek (1):
  net/ixgbe/base: add IXGBE_ADVTXD_MACLEN_MASK macro

Piotr Pietruszewski (1):
  net/ixgbe/base: revert remove default advertising for x550 2.5G/5G

Piotr Skajewski (2):
  net/ixgbe/base: fix wrong 5G link speed reported on VF
  net/ixgbe/base: handle -Wimplicit-fallthrough

Radoslaw Tyl (4):
  net/ixgbe/base: fix PHY ID for X550
  net/ixgbe/base: increase DCB BW calculation for MTU from 4088 to 9128
  net/ixgbe/base: improve function comments
  net/ixgbe/base: add fw_rst_cnt field to ixgbe_hw struct

Slawomir Mrozowicz (2):
  net/ixgbe/base: fix crash while loading driver
  net/ixgbe/base: added link state handling

Stefan Wegrzyn (1):
  net/ixgbe/base: add support for E610 device

 drivers/net/ixgbe/base/README            |    6 +-
 drivers/net/ixgbe/base/ixgbe_82599.c     |   18 +-
 drivers/net/ixgbe/base/ixgbe_api.c       |   62 +-
 drivers/net/ixgbe/base/ixgbe_api.h       |    6 +-
 drivers/net/ixgbe/base/ixgbe_common.c    |  103 +-
 drivers/net/ixgbe/base/ixgbe_common.h    |    2 +-
 drivers/net/ixgbe/base/ixgbe_dcb.c       |    2 +-
 drivers/net/ixgbe/base/ixgbe_dcb.h       |    4 +-
 drivers/net/ixgbe/base/ixgbe_e610.c      | 4982 ++++++++++++++++++++++
 drivers/net/ixgbe/base/ixgbe_e610.h      |  163 +
 drivers/net/ixgbe/base/ixgbe_hv_vf.c     |   15 +-
 drivers/net/ixgbe/base/ixgbe_mbx.c       |  860 +++-
 drivers/net/ixgbe/base/ixgbe_mbx.h       |   87 +-
 drivers/net/ixgbe/base/ixgbe_osdep.c     |   43 +
 drivers/net/ixgbe/base/ixgbe_osdep.h     |   17 +
 drivers/net/ixgbe/base/ixgbe_phy.c       |   13 +-
 drivers/net/ixgbe/base/ixgbe_type.h      |  128 +-
 drivers/net/ixgbe/base/ixgbe_type_e610.h | 2181 ++++++++++
 drivers/net/ixgbe/base/ixgbe_vf.c        |  103 +-
 drivers/net/ixgbe/base/ixgbe_vf.h        |    1 +
 drivers/net/ixgbe/base/ixgbe_x540.c      |    4 +-
 drivers/net/ixgbe/base/ixgbe_x550.c      |  140 +-
 drivers/net/ixgbe/base/ixgbe_x550.h      |    6 -
 drivers/net/ixgbe/base/meson.build       |    2 +
 drivers/net/ixgbe/ixgbe_ethdev.c         |   12 +-
 drivers/net/ixgbe/ixgbe_pf.c             |   16 +-
 26 files changed, 8454 insertions(+), 522 deletions(-)
 create mode 100644 drivers/net/ixgbe/base/ixgbe_e610.c
 create mode 100644 drivers/net/ixgbe/base/ixgbe_e610.h
 create mode 100644 drivers/net/ixgbe/base/ixgbe_osdep.c
 create mode 100644 drivers/net/ixgbe/base/ixgbe_type_e610.h

-- 
2.43.0


^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH v1 01/22] net/ixgbe/base: revert remove default advertising for x550 2.5G/5G
  2024-04-24 13:21 [PATCH v1 00/22] Update IXGBE base driver Anatoly Burakov
@ 2024-04-24 13:21 ` Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 02/22] net/ixgbe/base: fix wrong 5G link speed reported on VF Anatoly Burakov
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev
  Cc: Piotr Pietruszewski, vladimir.medvedkin, bruce.richardson,
	stable, Skajewski, PiotrX, Marek Mical, Kirsher, Jeffrey T,
	Michael, Alice

From: Piotr Pietruszewski <piotr.pietruszewski@intel.com>

This reverts the following commit:

    13de2444449e ("net/ixgbe/base: remove default advertising for x550 2.5G/5G")

The commit removing advertising 2.5G and 5G speeds from
ixgbe_get_copper_speeds_supported() was supposed to disable 2.5G and 5G
during the autonegotiation with default settings. However, that change
prevented OS-specific part of the driver from forcing these speeds at
user request.

This change reverts the commit and adds 2.5G and 5G as speeds supported
by the X550.

Cc: stable@dpdk.org

Signed-off-by: Piotr Pietruszewski <piotr.pietruszewski@intel.com>
Reviewed-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
Reviewed-by: Marek Mical <marekx.mical@intel.com>
Reviewed-by: Kirsher, Jeffrey T <jeffrey.t.kirsher@intel.com>
Reviewed-by: Michael, Alice <alice.michael@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_phy.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ixgbe/base/ixgbe_phy.c b/drivers/net/ixgbe/base/ixgbe_phy.c
index 74c5db16fa..3a8e603472 100644
--- a/drivers/net/ixgbe/base/ixgbe_phy.c
+++ b/drivers/net/ixgbe/base/ixgbe_phy.c
@@ -915,6 +915,10 @@ static s32 ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
 
 	switch (hw->mac.type) {
+	case ixgbe_mac_X550:
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
+		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
+		break;
 	case ixgbe_mac_X550EM_x:
 	case ixgbe_mac_X550EM_a:
 		hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH v1 02/22] net/ixgbe/base: fix wrong 5G link speed reported on VF
  2024-04-24 13:21 [PATCH v1 00/22] Update IXGBE base driver Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 01/22] net/ixgbe/base: revert remove default advertising for x550 2.5G/5G Anatoly Burakov
@ 2024-04-24 13:21 ` Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 03/22] net/ixgbe/base: fix PHY ID for X550 Anatoly Burakov
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev, Wei Dai
  Cc: Piotr Skajewski, vladimir.medvedkin, bruce.richardson, stable,
	Tyl, RadoslawX, Mrozowicz, SlawomirX, Michael, Alice

From: Piotr Skajewski <piotrx.skajewski@intel.com>

When 5000 Base-T was set on PF the VF reported 100 Base-T.
This patch change ixgbe_check_mac_link_vf function
where was incorrect conditional which points to PF mac types,
now it is pointing correctly to VF mac types.

Fixes: 12e20906905c ("net/ixgbe/base: include new speeds in VFLINK interpretation")
Cc: stable@dpdk.org

Signed-off-by: Piotr Skajewski <piotrx.skajewski@intel.com>
Reviewed-by: Tyl, RadoslawX <radoslawx.tyl@intel.com>
Reviewed-by: Mrozowicz, SlawomirX <slawomirx.mrozowicz@intel.com>
Reviewed-by: Michael, Alice <alice.michael@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_vf.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_vf.c b/drivers/net/ixgbe/base/ixgbe_vf.c
index 5e3ae1b519..11dbbe2a86 100644
--- a/drivers/net/ixgbe/base/ixgbe_vf.c
+++ b/drivers/net/ixgbe/base/ixgbe_vf.c
@@ -585,7 +585,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 	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;
 		}
@@ -595,7 +595,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 		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;
 		}
@@ -603,7 +603,7 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 	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:
-- 
2.43.0


^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH v1 03/22] net/ixgbe/base: fix PHY ID for X550
  2024-04-24 13:21 [PATCH v1 00/22] Update IXGBE base driver Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 01/22] net/ixgbe/base: revert remove default advertising for x550 2.5G/5G Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 02/22] net/ixgbe/base: fix wrong 5G link speed reported on VF Anatoly Burakov
@ 2024-04-24 13:21 ` Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 04/22] net/ixgbe/base: rename message type macros Anatoly Burakov
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev, Wenzhuo Lu, Helin Zhang
  Cc: Radoslaw Tyl, vladimir.medvedkin, bruce.richardson, stable,
	Skajewski, PiotrX, Michael, Alice

From: Radoslaw Tyl <radoslawx.tyl@intel.com>

Function ixgbe_get_phy_type_from_id() for X550_PHY_ID2 and
X550_PHY_ID3 always return ixgbe_phy_unknown instead of ixgbe_phy_aq
because phy ID's last 4 bits are always masked, and should not be
taken into account when selecting phy type.

This patch adds default PHY ID for X550 devices with mask on last 4
bits (0xFFFFFFF0), and fixes the switch statement to use it.

Fixes: 58ddc803e412 ("ixgbe/base: add new X550 PHY ids")
Cc: stable@dpdk.org

Signed-off-by: Radoslaw Tyl <radoslawx.tyl@intel.com>
Reviewed-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
Reviewed-by: Michael, Alice <alice.michael@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_phy.c  | 3 +--
 drivers/net/ixgbe/base/ixgbe_type.h | 1 +
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_phy.c b/drivers/net/ixgbe/base/ixgbe_phy.c
index 3a8e603472..56267bb00d 100644
--- a/drivers/net/ixgbe/base/ixgbe_phy.c
+++ b/drivers/net/ixgbe/base/ixgbe_phy.c
@@ -432,8 +432,7 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
 	case TN1010_PHY_ID:
 		phy_type = ixgbe_phy_tn;
 		break;
-	case X550_PHY_ID2:
-	case X550_PHY_ID3:
+	case X550_PHY_ID:
 	case X540_PHY_ID:
 		phy_type = ixgbe_phy_aq;
 		break;
diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h
index 35212a561b..f709681df2 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -1664,6 +1664,7 @@ struct ixgbe_dmac_config {
 #define TN1010_PHY_ID	0x00A19410
 #define TNX_FW_REV	0xB
 #define X540_PHY_ID	0x01540200
+#define X550_PHY_ID	0x01540220
 #define X550_PHY_ID2	0x01540223
 #define X550_PHY_ID3	0x01540221
 #define X557_PHY_ID	0x01540240
-- 
2.43.0


^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH v1 04/22] net/ixgbe/base: rename message type macros
  2024-04-24 13:21 [PATCH v1 00/22] Update IXGBE base driver Anatoly Burakov
                   ` (2 preceding siblings ...)
  2024-04-24 13:21 ` [PATCH v1 03/22] net/ixgbe/base: fix PHY ID for X550 Anatoly Burakov
@ 2024-04-24 13:21 ` Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 05/22] net/ixgbe/base: correct registers names to match datasheet Anatoly Burakov
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev
  Cc: Jakub Chylkowski, vladimir.medvedkin, bruce.richardson,
	Zalfresso-jundzillo, MarekX, Michael, Alice, Skajewski, PiotrX,
	Mrozowicz, SlawomirX

From: Jakub Chylkowski <jakubx.chylkowski@intel.com>

There is name similarity within IXGBE_VT_MSGTYPE_ACK and
PFMAILBOX.ACK / VFMAILBOX.ACK which may cause confusion. Rename MSGTYPE
macros to SUCCESS and FAILURE as they are not specified in datasheet and
now will be easily distinguishable.

Signed-off-by: Jakub Chylkowski <jakubx.chylkowski@intel.com>
Reviewed-by: Zalfresso-jundzillo, MarekX <marekx.zalfresso-jundzillo@intel.com>
Reviewed-by: Michael, Alice <alice.michael@intel.com>
Reviewed-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
Tested-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
Reviewed-by: Mrozowicz, SlawomirX <slawomirx.mrozowicz@intel.com>
Tested-by: Michael, Alice <alice.michael@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_mbx.h | 17 +++++++++-------
 drivers/net/ixgbe/base/ixgbe_vf.c  | 32 ++++++++++++++++--------------
 drivers/net/ixgbe/ixgbe_ethdev.c   |  4 ++--
 drivers/net/ixgbe/ixgbe_pf.c       | 12 +++++------
 4 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_mbx.h b/drivers/net/ixgbe/base/ixgbe_mbx.h
index 1a45e49c2f..28a2d94d02 100644
--- a/drivers/net/ixgbe/base/ixgbe_mbx.h
+++ b/drivers/net/ixgbe/base/ixgbe_mbx.h
@@ -38,14 +38,17 @@
 
 /* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the
  * PF.  The reverse is true if it is IXGBE_PF_*.
- * Message ACK's are the value or'd with 0xF0000000
+ * Message results are the value or'd with 0xF0000000
  */
-#define IXGBE_VT_MSGTYPE_ACK	0x80000000 /* Messages below or'd with
-					    * this are the ACK */
-#define IXGBE_VT_MSGTYPE_NACK	0x40000000 /* Messages below or'd with
-					    * this are the NACK */
-#define IXGBE_VT_MSGTYPE_CTS	0x20000000 /* Indicates that VF is still
-					    * clear to send requests */
+#define IXGBE_VT_MSGTYPE_SUCCESS	0x80000000 /* Messages or'd with this
+						    * have succeeded
+						    */
+#define IXGBE_VT_MSGTYPE_FAILURE	0x40000000 /* Messages or'd with this
+						    * have failed
+						    */
+#define IXGBE_VT_MSGTYPE_CTS		0x20000000 /* Indicates that VF is still
+						    * clear to send requests
+						    */
 #define IXGBE_VT_MSGINFO_SHIFT	16
 /* bits 23:16 are used for extra info for certain messages */
 #define IXGBE_VT_MSGINFO_MASK	(0xFF << IXGBE_VT_MSGINFO_SHIFT)
diff --git a/drivers/net/ixgbe/base/ixgbe_vf.c b/drivers/net/ixgbe/base/ixgbe_vf.c
index 11dbbe2a86..d390b0d5e0 100644
--- a/drivers/net/ixgbe/base/ixgbe_vf.c
+++ b/drivers/net/ixgbe/base/ixgbe_vf.c
@@ -194,11 +194,11 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
 	if (ret_val)
 		return ret_val;
 
-	if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK) &&
-	    msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_NACK))
+	if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_SUCCESS) &&
+	    msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_FAILURE))
 		return IXGBE_ERR_INVALID_MAC_ADDR;
 
-	if (msgbuf[0] == (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK))
+	if (msgbuf[0] == (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_SUCCESS))
 		memcpy(hw->mac.perm_addr, addr, IXGBE_ETH_LENGTH_OF_ADDRESS);
 
 	hw->mac.mc_filter_type = msgbuf[IXGBE_VF_MC_TYPE_WORD];
@@ -327,9 +327,9 @@ s32 ixgbe_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
 
 	msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
 
-	/* if nacked the address was rejected, use "perm_addr" */
+	/* if we had failure, the address was rejected, use "perm_addr" */
 	if (!ret_val &&
-	    (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) {
+	    (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_FAILURE))) {
 		ixgbe_get_mac_addr_vf(hw, hw->mac.addr);
 		return IXGBE_ERR_MBX;
 	}
@@ -418,7 +418,7 @@ s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode)
 		return err;
 
 	msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
-	if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK))
+	if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_FAILURE))
 		return IXGBE_ERR_FEATURE_NOT_SUPPORTED;
 	return IXGBE_SUCCESS;
 }
@@ -446,10 +446,10 @@ s32 ixgbe_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
 	msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT;
 
 	ret_val = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2);
-	if (!ret_val && (msgbuf[0] & IXGBE_VT_MSGTYPE_ACK))
+	if (!ret_val && (msgbuf[0] & IXGBE_VT_MSGTYPE_SUCCESS))
 		return IXGBE_SUCCESS;
 
-	return ret_val | (msgbuf[0] & IXGBE_VT_MSGTYPE_NACK);
+	return ret_val | (msgbuf[0] & IXGBE_VT_MSGTYPE_FAILURE);
 }
 
 /**
@@ -514,7 +514,7 @@ s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
 	if (!ret_val) {
 		msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
 
-		if (msgbuf[0] == (msgbuf_chk | IXGBE_VT_MSGTYPE_NACK))
+		if (msgbuf[0] == (msgbuf_chk | IXGBE_VT_MSGTYPE_FAILURE))
 			return IXGBE_ERR_OUT_OF_MEM;
 	}
 
@@ -617,8 +617,10 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 		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_NACK)
+		/* msg is not CTS and is FAILURE,
+		 * we must have lost CTS status.
+		 */
+		if (in_msg & IXGBE_VT_MSGTYPE_FAILURE)
 			ret_val = -1;
 		goto out;
 	}
@@ -656,7 +658,7 @@ s32 ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size)
 	if (retval)
 		return retval;
 	if ((msgbuf[0] & IXGBE_VF_SET_LPE) &&
-	    (msgbuf[0] & IXGBE_VT_MSGTYPE_NACK))
+	    (msgbuf[0] & IXGBE_VT_MSGTYPE_FAILURE))
 		return IXGBE_ERR_MBX;
 
 	return 0;
@@ -682,7 +684,7 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
 		msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
 
 		/* Store value and return 0 on success */
-		if (msg[0] == (IXGBE_VF_API_NEGOTIATE | IXGBE_VT_MSGTYPE_ACK)) {
+		if (msg[0] == (IXGBE_VF_API_NEGOTIATE | IXGBE_VT_MSGTYPE_SUCCESS)) {
 			hw->api_version = api;
 			return 0;
 		}
@@ -718,11 +720,11 @@ int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
 		msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
 
 		/*
-		 * if we 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
 		 */
-		if (msg[0] != (IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_ACK))
+		if (msg[0] != (IXGBE_VF_GET_QUEUES | IXGBE_VT_MSGTYPE_SUCCESS))
 			return IXGBE_ERR_MBX;
 
 		/* record and validate values from message */
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c61c52b296..8c60351636 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -4169,8 +4169,8 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 		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_NACK)
+		/* msg is not CTS and is FAILURE we must have lost CTS status */
+		if (in_msg & IXGBE_VT_MSGTYPE_FAILURE)
 			mac->get_link_status = false;
 		goto out;
 	}
diff --git a/drivers/net/ixgbe/ixgbe_pf.c b/drivers/net/ixgbe/ixgbe_pf.c
index 0a0f639e39..71104247da 100644
--- a/drivers/net/ixgbe/ixgbe_pf.c
+++ b/drivers/net/ixgbe/ixgbe_pf.c
@@ -448,8 +448,8 @@ ixgbe_vf_reset(struct rte_eth_dev *dev, uint16_t vf, uint32_t *msgbuf)
 	/* Disable multicast promiscuous at reset */
 	ixgbe_disable_vf_mc_promisc(dev, vf);
 
-	/* reply to reset with ack and vf mac address */
-	msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
+	/* reply to reset with success and vf mac address */
+	msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_SUCCESS;
 	rte_memcpy(new_mac, vf_mac, RTE_ETHER_ADDR_LEN);
 	/*
 	 * Piggyback the multicast filter type so VF can compute the
@@ -840,7 +840,7 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 	}
 
 	/* do nothing with the message already been processed */
-	if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK))
+	if (msgbuf[0] & (IXGBE_VT_MSGTYPE_SUCCESS | IXGBE_VT_MSGTYPE_FAILURE))
 		return retval;
 
 	/* flush the ack before we write any messages back */
@@ -919,9 +919,9 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 
 	/* response the VF according to the message process result */
 	if (retval)
-		msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
+		msgbuf[0] |= IXGBE_VT_MSGTYPE_FAILURE;
 	else
-		msgbuf[0] |= IXGBE_VT_MSGTYPE_ACK;
+		msgbuf[0] |= IXGBE_VT_MSGTYPE_SUCCESS;
 
 	msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS;
 
@@ -933,7 +933,7 @@ ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 static inline void
 ixgbe_rcv_ack_from_vf(struct rte_eth_dev *dev, uint16_t vf)
 {
-	uint32_t msg = IXGBE_VT_MSGTYPE_NACK;
+	uint32_t msg = IXGBE_VT_MSGTYPE_FAILURE;
 	struct ixgbe_hw *hw =
 		IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_vf_info *vfinfo =
-- 
2.43.0


^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH v1 05/22] net/ixgbe/base: correct registers names to match datasheet
  2024-04-24 13:21 [PATCH v1 00/22] Update IXGBE base driver Anatoly Burakov
                   ` (3 preceding siblings ...)
  2024-04-24 13:21 ` [PATCH v1 04/22] net/ixgbe/base: rename message type macros Anatoly Burakov
@ 2024-04-24 13:21 ` Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 06/22] net/ixgbe/base: introduce new mailbox API Anatoly Burakov
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev
  Cc: Jakub Chylkowski, vladimir.medvedkin, bruce.richardson,
	Zalfresso-jundzillo, MarekX, Michael, Alice, Skajewski, PiotrX,
	Mrozowicz, SlawomirX

From: Jakub Chylkowski <jakubx.chylkowski@intel.com>

Some of mailbox-related registers have different names than it is
specified in datasheet. Correct these names to correspond to their
datasheet counterparts. Additionally, several calculations are changed
to no longer use magic numbers but dedicated macros instead.

Signed-off-by: Jakub Chylkowski <jakubx.chylkowski@intel.com>
Reviewed-by: Zalfresso-jundzillo, MarekX <marekx.zalfresso-jundzillo@intel.com>
Reviewed-by: Michael, Alice <alice.michael@intel.com>
Reviewed-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
Tested-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
Reviewed-by: Mrozowicz, SlawomirX <slawomirx.mrozowicz@intel.com>
Tested-by: Michael, Alice <alice.michael@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_mbx.c  | 30 ++++++++++++++---------------
 drivers/net/ixgbe/base/ixgbe_mbx.h  |  8 ++++----
 drivers/net/ixgbe/base/ixgbe_type.h | 12 ++++++------
 3 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_mbx.c b/drivers/net/ixgbe/base/ixgbe_mbx.c
index 4dddff2c58..d645dcf827 100644
--- a/drivers/net/ixgbe/base/ixgbe_mbx.c
+++ b/drivers/net/ixgbe/base/ixgbe_mbx.c
@@ -496,12 +496,12 @@ void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
 
 STATIC s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
 {
-	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
+	u32 pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index));
 	s32 ret_val = IXGBE_ERR_MBX;
 
-	if (mbvficr & mask) {
+	if (pfmbicr & mask) {
 		ret_val = IXGBE_SUCCESS;
-		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
+		IXGBE_WRITE_REG(hw, IXGBE_PFMBICR(index), mask);
 	}
 
 	return ret_val;
@@ -516,13 +516,13 @@ STATIC s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
  **/
 STATIC s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
 {
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_number);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_number);
 	s32 ret_val = IXGBE_ERR_MBX;
-	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
-	u32 vf_bit = vf_number % 16;
 
 	DEBUGFUNC("ixgbe_check_for_msg_pf");
 
-	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
+	if (!ixgbe_check_for_bit_pf(hw, IXGBE_PFMBICR_VFREQ_VF1 << vf_shift,
 				    index)) {
 		ret_val = IXGBE_SUCCESS;
 		hw->mbx.stats.reqs++;
@@ -540,13 +540,13 @@ STATIC s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
  **/
 STATIC s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
 {
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_number);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_number);
 	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++;
@@ -564,22 +564,22 @@ STATIC s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
  **/
 STATIC s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
 {
-	u32 reg_offset = (vf_number < 32) ? 0 : 1;
-	u32 vf_shift = vf_number % 32;
+	u32 vf_shift = IXGBE_PFVFLRE_SHIFT(vf_number);
+	u32 index = IXGBE_PFVFLRE_INDEX(vf_number);
+	s32 ret_val = IXGBE_ERR_MBX;
 	u32 vflre = 0;
-	s32 ret_val = IXGBE_ERR_MBX;
 
 	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;
@@ -587,7 +587,7 @@ STATIC s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
 
 	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++;
 	}
 
diff --git a/drivers/net/ixgbe/base/ixgbe_mbx.h b/drivers/net/ixgbe/base/ixgbe_mbx.h
index 28a2d94d02..f7861e6bde 100644
--- a/drivers/net/ixgbe/base/ixgbe_mbx.h
+++ b/drivers/net/ixgbe/base/ixgbe_mbx.h
@@ -30,10 +30,10 @@
 #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
diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h
index f709681df2..5036b2a907 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -451,8 +451,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))
@@ -2866,12 +2872,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)))
-- 
2.43.0


^ permalink raw reply	[flat|nested] 85+ messages in thread

* [PATCH v1 06/22] net/ixgbe/base: introduce new mailbox API
  2024-04-24 13:21 [PATCH v1 00/22] Update IXGBE base driver Anatoly Burakov
                   ` (4 preceding siblings ...)
  2024-04-24 13:21 ` [PATCH v1 05/22] net/ixgbe/base: correct registers names to match datasheet Anatoly Burakov
@ 2024-04-24 13:21 ` Anatoly Burakov
  2024-04-24 13:21 ` [PATCH v1 07/22] net/ixgbe/base: increase DCB BW calculation for MTU from 4088 to 9128 Anatoly Burakov
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 85+ messages in thread
From: Anatoly Burakov @ 2024-04-24 13:21 UTC (permalink / raw)
  To: dev
  Cc: Jakub Chylkowski, vladimir.medvedkin, bruce.richardson, Michael,
	Alice, Pietruszewski, Piotr, Skajewski, PiotrX

From: Jakub Chylkowski <jakubx.chylkowski@intel.com>

Current mailbox API does not work as described in documentation and
is prone to errors (for example, it is doing locks on read). Introduce
new mailbox API and provide compatibility functions with old API.

New error codes have been introduced:
- IXGBE_ERR_CONFIG - ixgbe_mbx_operations is not correctly set
- IXGBE_ERR_TIMEOUT - mailbox operation, e.g. poll for message, timedout
- IXGBE_ERR_MBX_NOMSG - no message available on read

In addition, some refactoring has been done: mailbox structures were
defined twice: in ixgbe_type.h and ixgbe_vf.h. Move them into
ixgbe_mbx.h as this header is dedicated for mailbox.

Signed-off-by: Jakub Chylkowski <jakubx.chylkowski@intel.com>
Reviewed-by: Michael, Alice <alice.michael@intel.com>
Reviewed-by: Pietruszewski, Piotr <piotr.pietruszewski@intel.com>
Tested-by: Michael, Alice <alice.michael@intel.com>
Tested-by: Skajewski, PiotrX <piotrx.skajewski@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_82599.c |   4 +-
 drivers/net/ixgbe/base/ixgbe_hv_vf.c |   2 +-
 drivers/net/ixgbe/base/ixgbe_mbx.c   | 843 +++++++++++++++++++--------
 drivers/net/ixgbe/base/ixgbe_mbx.h   |  59 +-
 drivers/net/ixgbe/base/ixgbe_type.h  |  32 +-
 drivers/net/ixgbe/base/ixgbe_vf.c    |  42 +-
 drivers/net/ixgbe/base/ixgbe_x540.c  |   4 +-
 drivers/net/ixgbe/ixgbe_ethdev.c     |   6 +-
 drivers/net/ixgbe/ixgbe_pf.c         |   4 +-
 9 files changed, 702 insertions(+), 294 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_82599.c b/drivers/net/ixgbe/base/ixgbe_82599.c
index c6e8b7e976..7d2938b253 100644
--- a/drivers/net/ixgbe/base/ixgbe_82599.c
+++ b/drivers/net/ixgbe/base/ixgbe_82599.c
@@ -291,6 +291,7 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *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");
 
@@ -352,7 +353,8 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *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;
diff --git a/drivers/net/ixgbe/base/ixgbe_hv_vf.c b/drivers/net/ixgbe/base/ixgbe_hv_vf.c
index 4572411d39..34add03e8b 100644
--- a/drivers/net/ixgbe/base/ixgbe_hv_vf.c
+++ b/drivers/net/ixgbe/base/ixgbe_hv_vf.c
@@ -97,7 +97,7 @@ static s32 ixgbevf_hv_check_mac_link_vf(struct ixgbe_hw *hw,
 	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)
diff --git a/drivers/net/ixgbe/base/ixgbe_mbx.c b/drivers/net/ixgbe/base/ixgbe_mbx.c
index d645dcf827..2dab347396 100644
--- a/drivers/net/ixgbe/base/ixgbe_mbx.c
+++ b/drivers/net/ixgbe/base/ixgbe_mbx.c
@@ -5,6 +5,9 @@
 #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
@@ -17,42 +20,91 @@
 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.read)
-		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
+	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[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;
 }
@@ -67,12 +119,12 @@ 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)
 {
 	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;
 }
@@ -87,12 +139,12 @@ s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
 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;
 }
@@ -107,12 +159,12 @@ s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
 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;
 }
@@ -131,22 +183,23 @@ STATIC s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
 
 	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;
 }
 
 /**
@@ -163,114 +216,71 @@ STATIC s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
 
 	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;
+	u32 vf_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
 
-	DEBUGFUNC("ixgbe_read_posted_mbx");
+	vf_mailbox |= hw->mbx.vf_mailbox;
+	hw->mbx.vf_mailbox |= vf_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
 
-	if (!mbx->ops.read)
-		goto out;
-
-	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
-
-	/* 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");
-
-	/* 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);
+	u32 vf_mailbox = ixgbe_read_mailbox_vf(hw);
 
-	/* 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++;
+		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++;
+		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++;
+		hw->mbx.vf_mailbox &= ~(IXGBE_VFMAILBOX_RSTI |
+					IXGBE_VFMAILBOX_RSTD);
+	}
 }
 
 /**
@@ -283,15 +293,12 @@ STATIC u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw)
  **/
 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;
+	u32 vf_mailbox = ixgbe_read_mailbox_vf(hw);
 
-	if (v2p_mailbox & mask)
-		ret_val = IXGBE_SUCCESS;
+	if (vf_mailbox & mask)
+		return IXGBE_SUCCESS;
 
-	hw->mbx.v2p_mailbox &= ~mask;
-
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -303,17 +310,13 @@ STATIC s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask)
  **/
 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++;
-	}
+	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS))
+		return IXGBE_SUCCESS;
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -325,17 +328,16 @@ STATIC s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id)
  **/
 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;
-		hw->mbx.stats.acks++;
+		/* TODO: should this be autocleared? */
+		ixgbe_clear_ack_vf(hw);
+		return IXGBE_SUCCESS;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -347,18 +349,17 @@ STATIC s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id)
  **/
 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;
-		hw->mbx.stats.rsts++;
+	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_RSTI |
+					  IXGBE_VFMAILBOX_RSTD)) {
+		/* TODO: should this be autocleared? */
+		ixgbe_clear_rst_vf(hw);
+		return IXGBE_SUCCESS;
 	}
 
-	return ret_val;
+	return IXGBE_ERR_MBX;
 }
 
 /**
@@ -369,20 +370,114 @@ STATIC s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id)
  **/
 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++;
+
+	/* 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
@@ -395,6 +490,7 @@ STATIC s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
 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;
 
@@ -405,11 +501,11 @@ STATIC s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 	/* 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++)
@@ -418,13 +514,56 @@ STATIC s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 	/* update stats */
 	hw->mbx.stats.msgs_tx++;
 
-	/* 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_legacy - 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_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size,
+				    u16 mbx_id)
+{
+	s32 ret_val;
+	u16 i;
+
+	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)
+		return ret_val;
+
+	/* 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 and release mailbox, then we're done */
+	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
+
+	/* update stats */
+	hw->mbx.stats.msgs_rx++;
+
+	return IXGBE_SUCCESS;
+}
+
 /**
  * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
  * @hw: pointer to the HW structure
@@ -437,55 +576,58 @@ STATIC s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 STATIC s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
 			     u16 mbx_id)
 {
-	s32 ret_val = IXGBE_SUCCESS;
+	u32 vf_mailbox;
+	s32 ret_val;
 	u16 i;
 
 	DEBUGFUNC("ixgbe_read_mbx_vf");
 	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;
+	/* 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 and release mailbox, then we're done */
-	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
+	/* 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++;
 
-out_no_read:
-	return ret_val;
+	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;
+	/* 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->stats.msgs_tx = 0;
 	mbx->stats.msgs_rx = 0;
@@ -494,54 +636,109 @@ void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
 	mbx->stats.rsts = 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;
+
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 0;
+}
+
+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++;
+
+	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++;
+
+	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 pfmbicr = IXGBE_READ_REG(hw, IXGBE_PFMBICR(index));
-	s32 ret_val = IXGBE_ERR_MBX;
 
-	if (pfmbicr & mask) {
-		ret_val = IXGBE_SUCCESS;
-		IXGBE_WRITE_REG(hw, IXGBE_PFMBICR(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)
 {
-	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_number);
-	s32 index = IXGBE_PFMBICR_INDEX(vf_number);
-	s32 ret_val = IXGBE_ERR_MBX;
+	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_PFMBICR_VFREQ_VF1 << vf_shift,
-				    index)) {
-		ret_val = IXGBE_SUCCESS;
-		hw->mbx.stats.reqs++;
-	}
+				    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_number);
-	s32 index = IXGBE_PFMBICR_INDEX(vf_number);
+	u32 vf_shift = IXGBE_PFMBICR_SHIFT(vf_id);
+	s32 index = IXGBE_PFMBICR_INDEX(vf_id);
 	s32 ret_val = IXGBE_ERR_MBX;
 
 	DEBUGFUNC("ixgbe_check_for_ack_pf");
@@ -549,7 +746,8 @@ STATIC s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_PFMBICR_VFACK_VF1 << vf_shift,
 				    index)) {
 		ret_val = IXGBE_SUCCESS;
-		hw->mbx.stats.acks++;
+		/* TODO: should this be autocleared? */
+		ixgbe_clear_ack_pf(hw, vf_id);
 	}
 
 	return ret_val;
@@ -558,14 +756,14 @@ STATIC s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
 /**
  * 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 vf_shift = IXGBE_PFVFLRE_SHIFT(vf_number);
-	u32 index = IXGBE_PFVFLRE_INDEX(vf_number);
+	u32 vf_shift = IXGBE_PFVFLRE_SHIFT(vf_id);
+	u32 index = IXGBE_PFVFLRE_INDEX(vf_id);
 	s32 ret_val = IXGBE_ERR_MBX;
 	u32 vflre = 0;
 
@@ -597,121 +795,268 @@ STATIC s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
 /**
  * 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++;
+
+	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++;
 
-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++;
+
+	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++;
 
-out_no_read:
-	return ret_val;
+	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;
 }
 
 /**
  * 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 &&
@@ -719,18 +1064,58 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
 	    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;
+
+	/* Initialize counters with zeroes */
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 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.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[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->stats.msgs_tx = 0;
 	mbx->stats.msgs_rx = 0;
diff --git a/drivers/net/ixgbe/base/ixgbe_mbx.h b/drivers/net/ixgbe/base/ixgbe_mbx.h
index f7861e6bde..fadfccaabb 100644
--- a/drivers/net/ixgbe/base/ixgbe_mbx.h
+++ b/drivers/net/ixgbe/base/ixgbe_mbx.h
@@ -7,8 +7,41 @@
 
 #include "ixgbe_type.h"
 
+struct ixgbe_mbx_operations {
+	void (*init_params)(struct ixgbe_hw *hw);
+	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);
+};
+
+struct ixgbe_mbx_stats {
+	u32 msgs_tx;
+	u32 msgs_rx;
+
+	u32 acks;
+	u32 reqs;
+	u32 rsts;
+};
+
+struct ixgbe_mbx_info {
+	/*
+	 * 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 vf_mailbox;
+	u16 size;
+};
+
 #define IXGBE_VFMAILBOX_SIZE	16 /*