@@ -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;
@@ -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)
@@ -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;
@@ -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 /* 16 32 bit words - 64 bytes */
-#define IXGBE_ERR_MBX -100
#define IXGBE_VFMAILBOX 0x002FC
#define IXGBE_VFMBMEM 0x00200
@@ -65,6 +98,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 */
};
@@ -125,15 +161,16 @@ 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);
-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 *);
+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);
+void ixgbe_init_mbx_params_vf(struct ixgbe_hw *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_ */
@@ -4141,35 +4141,6 @@ struct ixgbe_phy_info {
#include "ixgbe_mbx.h"
-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);
-};
-
-struct ixgbe_mbx_stats {
- u32 msgs_tx;
- u32 msgs_rx;
-
- u32 acks;
- u32 reqs;
- u32 rsts;
-};
-
-struct ixgbe_mbx_info {
- struct ixgbe_mbx_operations ops;
- struct ixgbe_mbx_stats stats;
- u32 timeout;
- u32 usec_delay;
- u32 v2p_mailbox;
- u16 size;
-};
-
struct ixgbe_hw {
u8 IOMEM *hw_addr;
void *back;
@@ -4239,6 +4210,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 -41
+#define IXGBE_ERR_MBX_NOMSG -42
+#define IXGBE_ERR_TIMEOUT -43
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
@@ -21,6 +21,8 @@
**/
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;
@@ -53,7 +55,8 @@ s32 ixgbe_init_ops_vf(struct ixgbe_hw *hw)
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;
}
@@ -156,6 +159,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
/* 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");
@@ -165,7 +169,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
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);
}
@@ -180,7 +184,7 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
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);
@@ -189,8 +193,8 @@ s32 ixgbe_reset_hw_vf(struct ixgbe_hw *hw)
* 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;
@@ -295,13 +299,12 @@ STATIC s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr)
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);
}
/**
@@ -351,7 +354,6 @@ s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, ixgbe_mc_addr_itr next,
bool clear)
{
- struct ixgbe_mbx_info *mbx = &hw->mbx;
u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
u16 *vector_list = (u16 *)&msgbuf[1];
u32 vector;
@@ -383,7 +385,7 @@ s32 ixgbe_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list,
vector_list[i] = (u16)vector;
}
- return mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE, 0);
+ return ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, IXGBE_VFMAILBOX_SIZE);
}
/**
@@ -405,6 +407,7 @@ s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, int xcast_mode)
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;
@@ -551,12 +554,13 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
struct ixgbe_mbx_info *mbx = &hw->mbx;
struct ixgbe_mac_info *mac = &hw->mac;
s32 ret_val = IXGBE_SUCCESS;
- u32 links_reg;
u32 in_msg = 0;
+ u32 links_reg;
+
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)
@@ -613,21 +617,22 @@ s32 ixgbe_check_mac_link_vf(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
/* 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))
+ if (ixgbe_read_mbx(hw, &in_msg, 1, 0)) {
+ if (hw->api_version >= ixgbe_mbox_api_15)
+ mac->get_link_status = false;
goto out;
+ }
if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) {
- /* msg is not CTS and is FAILURE,
- * we must have lost CTS status.
- */
+ /* msg is not CTS and is FAILURE we must have lost CTS status */
if (in_msg & IXGBE_VT_MSGTYPE_FAILURE)
- ret_val = -1;
+ 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 = -1;
+ ret_val = IXGBE_ERR_TIMEOUT;
goto out;
}
@@ -706,6 +711,7 @@ int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
case ixgbe_mbox_api_11:
case ixgbe_mbox_api_12:
case ixgbe_mbox_api_13:
+ case ixgbe_mbox_api_15:
break;
default:
return 0;
@@ -32,6 +32,7 @@ s32 ixgbe_init_ops_X540(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_X540");
@@ -111,7 +112,8 @@ s32 ixgbe_init_ops_X540(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;
/* LEDs */
mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
@@ -1663,7 +1663,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
}
/* init_mailbox_params */
- hw->mbx.ops.init_params(hw);
+ hw->mbx.ops[0].init_params(hw);
/* Reset the hw statistics */
ixgbevf_dev_stats_reset(eth_dev);
@@ -4099,7 +4099,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
int ret_val = 0;
/* 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)
@@ -4165,7 +4165,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
/* 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))
+ if (mbx->ops[0].read(hw, &in_msg, 1, 0))
goto out;
if (!(in_msg & IXGBE_VT_MSGTYPE_CTS)) {
@@ -77,6 +77,7 @@ int ixgbe_pf_host_init(struct rte_eth_dev *eth_dev)
uint16_t vf_num;
uint8_t nb_queue;
int ret = 0;
+ size_t i;
PMD_INIT_FUNC_TRACE();
@@ -122,7 +123,8 @@ int ixgbe_pf_host_init(struct rte_eth_dev *eth_dev)
ixgbe_vf_perm_addr_gen(eth_dev, vf_num);
/* init_mailbox_params */
- hw->mbx.ops.init_params(hw);
+ for (i = 0; i < vf_num; i++)
+ hw->mbx.ops[i].init_params(hw);
/* set mb interrupt mask */
ixgbe_mb_intr_setup(eth_dev);