169b5a878SDan McDonald /******************************************************************************
2*48ed61a7SRobert Mustacchi   SPDX-License-Identifier: BSD-3-Clause
369b5a878SDan McDonald 
4*48ed61a7SRobert Mustacchi   Copyright (c) 2001-2017, Intel Corporation
569b5a878SDan McDonald   All rights reserved.
6*48ed61a7SRobert Mustacchi 
7*48ed61a7SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
869b5a878SDan McDonald   modification, are permitted provided that the following conditions are met:
9*48ed61a7SRobert Mustacchi 
10*48ed61a7SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1169b5a878SDan McDonald       this list of conditions and the following disclaimer.
12*48ed61a7SRobert Mustacchi 
13*48ed61a7SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
14*48ed61a7SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1569b5a878SDan McDonald       documentation and/or other materials provided with the distribution.
16*48ed61a7SRobert Mustacchi 
17*48ed61a7SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
18*48ed61a7SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1969b5a878SDan McDonald       this software without specific prior written permission.
20*48ed61a7SRobert Mustacchi 
2169b5a878SDan McDonald   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*48ed61a7SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*48ed61a7SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*48ed61a7SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*48ed61a7SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*48ed61a7SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*48ed61a7SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*48ed61a7SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*48ed61a7SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3069b5a878SDan McDonald   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3169b5a878SDan McDonald   POSSIBILITY OF SUCH DAMAGE.
3269b5a878SDan McDonald 
3369b5a878SDan McDonald ******************************************************************************/
3469b5a878SDan McDonald /*$FreeBSD$*/
3569b5a878SDan McDonald 
3669b5a878SDan McDonald #include "ixgbe_type.h"
3769b5a878SDan McDonald #include "ixgbe_mbx.h"
3869b5a878SDan McDonald 
3969b5a878SDan McDonald /**
4069b5a878SDan McDonald  *  ixgbe_poll_for_msg - Wait for message notification
4169b5a878SDan McDonald  *  @hw: pointer to the HW structure
4269b5a878SDan McDonald  *  @mbx_id: id of mailbox to write
4369b5a878SDan McDonald  *
4469b5a878SDan McDonald  *  returns SUCCESS if it successfully received a message notification
4569b5a878SDan McDonald  **/
ixgbe_poll_for_msg(struct ixgbe_hw * hw,u16 mbx_id)4669b5a878SDan McDonald static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
4769b5a878SDan McDonald {
4869b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
4969b5a878SDan McDonald 	int countdown = mbx->timeout;
5069b5a878SDan McDonald 
5169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_poll_for_msg");
5269b5a878SDan McDonald 
5369b5a878SDan McDonald 	if (!countdown || !mbx->ops.check_for_msg)
5469b5a878SDan McDonald 		goto out;
5569b5a878SDan McDonald 
5669b5a878SDan McDonald 	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
5769b5a878SDan McDonald 		countdown--;
5869b5a878SDan McDonald 		if (!countdown)
5969b5a878SDan McDonald 			break;
6069b5a878SDan McDonald 		usec_delay(mbx->usec_delay);
6169b5a878SDan McDonald 	}
6269b5a878SDan McDonald 
63dc0cb1cdSDale Ghent 	if (countdown == 0)
64dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
65dc0cb1cdSDale Ghent 			   "Polling for VF%d mailbox message timedout", mbx_id);
66dc0cb1cdSDale Ghent 
6769b5a878SDan McDonald out:
6869b5a878SDan McDonald 	return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
6969b5a878SDan McDonald }
7069b5a878SDan McDonald 
7169b5a878SDan McDonald /**
7269b5a878SDan McDonald  *  ixgbe_poll_for_ack - Wait for message acknowledgement
7369b5a878SDan McDonald  *  @hw: pointer to the HW structure
7469b5a878SDan McDonald  *  @mbx_id: id of mailbox to write
7569b5a878SDan McDonald  *
7669b5a878SDan McDonald  *  returns SUCCESS if it successfully received a message acknowledgement
7769b5a878SDan McDonald  **/
ixgbe_poll_for_ack(struct ixgbe_hw * hw,u16 mbx_id)7869b5a878SDan McDonald static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
7969b5a878SDan McDonald {
8069b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
8169b5a878SDan McDonald 	int countdown = mbx->timeout;
8269b5a878SDan McDonald 
8369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_poll_for_ack");
8469b5a878SDan McDonald 
8569b5a878SDan McDonald 	if (!countdown || !mbx->ops.check_for_ack)
8669b5a878SDan McDonald 		goto out;
8769b5a878SDan McDonald 
8869b5a878SDan McDonald 	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
8969b5a878SDan McDonald 		countdown--;
9069b5a878SDan McDonald 		if (!countdown)
9169b5a878SDan McDonald 			break;
9269b5a878SDan McDonald 		usec_delay(mbx->usec_delay);
9369b5a878SDan McDonald 	}
9469b5a878SDan McDonald 
95dc0cb1cdSDale Ghent 	if (countdown == 0)
96dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
97dc0cb1cdSDale Ghent 			     "Polling for VF%d mailbox ack timedout", mbx_id);
98dc0cb1cdSDale Ghent 
9969b5a878SDan McDonald out:
10069b5a878SDan McDonald 	return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
10169b5a878SDan McDonald }
10269b5a878SDan McDonald 
10369b5a878SDan McDonald /**
10469b5a878SDan McDonald  *  ixgbe_read_posted_mbx - Wait for message notification and receive message
10569b5a878SDan McDonald  *  @hw: pointer to the HW structure
10669b5a878SDan McDonald  *  @msg: The message buffer
10769b5a878SDan McDonald  *  @size: Length of buffer
10869b5a878SDan McDonald  *  @mbx_id: id of mailbox to write
10969b5a878SDan McDonald  *
11069b5a878SDan McDonald  *  returns SUCCESS if it successfully received a message notification and
11169b5a878SDan McDonald  *  copied it into the receive buffer.
11269b5a878SDan McDonald  **/
ixgbe_read_posted_mbx(struct ixgbe_hw * hw,u32 * msg,u16 size,u16 mbx_id)113*48ed61a7SRobert Mustacchi static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
114*48ed61a7SRobert Mustacchi 				 u16 mbx_id)
11569b5a878SDan McDonald {
11669b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
11769b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
11869b5a878SDan McDonald 
11969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_posted_mbx");
12069b5a878SDan McDonald 
12169b5a878SDan McDonald 	if (!mbx->ops.read)
12269b5a878SDan McDonald 		goto out;
12369b5a878SDan McDonald 
12469b5a878SDan McDonald 	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
12569b5a878SDan McDonald 
12669b5a878SDan McDonald 	/* if ack received read message, otherwise we timed out */
12769b5a878SDan McDonald 	if (!ret_val)
12869b5a878SDan McDonald 		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
12969b5a878SDan McDonald out:
13069b5a878SDan McDonald 	return ret_val;
13169b5a878SDan McDonald }
13269b5a878SDan McDonald 
13369b5a878SDan McDonald /**
13469b5a878SDan McDonald  *  ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
13569b5a878SDan McDonald  *  @hw: pointer to the HW structure
13669b5a878SDan McDonald  *  @msg: The message buffer
13769b5a878SDan McDonald  *  @size: Length of buffer
13869b5a878SDan McDonald  *  @mbx_id: id of mailbox to write
13969b5a878SDan McDonald  *
14069b5a878SDan McDonald  *  returns SUCCESS if it successfully copied message into the buffer and
14169b5a878SDan McDonald  *  received an ack to that message within delay * timeout period
14269b5a878SDan McDonald  **/
ixgbe_write_posted_mbx(struct ixgbe_hw * hw,u32 * msg,u16 size,u16 mbx_id)143*48ed61a7SRobert Mustacchi static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
144*48ed61a7SRobert Mustacchi 				  u16 mbx_id)
14569b5a878SDan McDonald {
14669b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
14769b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
14869b5a878SDan McDonald 
14969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_posted_mbx");
15069b5a878SDan McDonald 
15169b5a878SDan McDonald 	/* exit if either we can't write or there isn't a defined timeout */
15269b5a878SDan McDonald 	if (!mbx->ops.write || !mbx->timeout)
15369b5a878SDan McDonald 		goto out;
15469b5a878SDan McDonald 
15569b5a878SDan McDonald 	/* send msg */
15669b5a878SDan McDonald 	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
15769b5a878SDan McDonald 
15869b5a878SDan McDonald 	/* if msg sent wait until we receive an ack */
15969b5a878SDan McDonald 	if (!ret_val)
16069b5a878SDan McDonald 		ret_val = ixgbe_poll_for_ack(hw, mbx_id);
16169b5a878SDan McDonald out:
16269b5a878SDan McDonald 	return ret_val;
16369b5a878SDan McDonald }
16469b5a878SDan McDonald 
16569b5a878SDan McDonald /**
16669b5a878SDan McDonald  *  ixgbe_init_mbx_ops_generic - Initialize MB function pointers
16769b5a878SDan McDonald  *  @hw: pointer to the HW structure
16869b5a878SDan McDonald  *
16969b5a878SDan McDonald  *  Setups up the mailbox read and write message function pointers
17069b5a878SDan McDonald  **/
ixgbe_init_mbx_ops_generic(struct ixgbe_hw * hw)17169b5a878SDan McDonald void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
17269b5a878SDan McDonald {
17369b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
17469b5a878SDan McDonald 
17569b5a878SDan McDonald 	mbx->ops.read_posted = ixgbe_read_posted_mbx;
17669b5a878SDan McDonald 	mbx->ops.write_posted = ixgbe_write_posted_mbx;
17769b5a878SDan McDonald }
17869b5a878SDan McDonald 
17969b5a878SDan McDonald /**
18069b5a878SDan McDonald  *  ixgbe_read_v2p_mailbox - read v2p mailbox
18169b5a878SDan McDonald  *  @hw: pointer to the HW structure
18269b5a878SDan McDonald  *
18369b5a878SDan McDonald  *  This function is used to read the v2p mailbox without losing the read to
18469b5a878SDan McDonald  *  clear status bits.
18569b5a878SDan McDonald  **/
ixgbe_read_v2p_mailbox(struct ixgbe_hw * hw)18669b5a878SDan McDonald static u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw)
18769b5a878SDan McDonald {
18869b5a878SDan McDonald 	u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
18969b5a878SDan McDonald 
19069b5a878SDan McDonald 	v2p_mailbox |= hw->mbx.v2p_mailbox;
19169b5a878SDan McDonald 	hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
19269b5a878SDan McDonald 
19369b5a878SDan McDonald 	return v2p_mailbox;
19469b5a878SDan McDonald }
19569b5a878SDan McDonald 
19669b5a878SDan McDonald /**
19769b5a878SDan McDonald  *  ixgbe_check_for_bit_vf - Determine if a status bit was set
19869b5a878SDan McDonald  *  @hw: pointer to the HW structure
19969b5a878SDan McDonald  *  @mask: bitmask for bits to be tested and cleared
20069b5a878SDan McDonald  *
20169b5a878SDan McDonald  *  This function is used to check for the read to clear bits within
20269b5a878SDan McDonald  *  the V2P mailbox.
20369b5a878SDan McDonald  **/
ixgbe_check_for_bit_vf(struct ixgbe_hw * hw,u32 mask)20469b5a878SDan McDonald static s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask)
20569b5a878SDan McDonald {
20669b5a878SDan McDonald 	u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw);
20769b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
20869b5a878SDan McDonald 
20969b5a878SDan McDonald 	if (v2p_mailbox & mask)
21069b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
21169b5a878SDan McDonald 
21269b5a878SDan McDonald 	hw->mbx.v2p_mailbox &= ~mask;
21369b5a878SDan McDonald 
21469b5a878SDan McDonald 	return ret_val;
21569b5a878SDan McDonald }
21669b5a878SDan McDonald 
21769b5a878SDan McDonald /**
21869b5a878SDan McDonald  *  ixgbe_check_for_msg_vf - checks to see if the PF has sent mail
21969b5a878SDan McDonald  *  @hw: pointer to the HW structure
22069b5a878SDan McDonald  *  @mbx_id: id of mailbox to check
22169b5a878SDan McDonald  *
22269b5a878SDan McDonald  *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
22369b5a878SDan McDonald  **/
ixgbe_check_for_msg_vf(struct ixgbe_hw * hw,u16 mbx_id)22469b5a878SDan McDonald static s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id)
22569b5a878SDan McDonald {
22669b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
22769b5a878SDan McDonald 
22869b5a878SDan McDonald 	UNREFERENCED_1PARAMETER(mbx_id);
22969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_check_for_msg_vf");
23069b5a878SDan McDonald 
23169b5a878SDan McDonald 	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) {
23269b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
23369b5a878SDan McDonald 		hw->mbx.stats.reqs++;
23469b5a878SDan McDonald 	}
23569b5a878SDan McDonald 
23669b5a878SDan McDonald 	return ret_val;
23769b5a878SDan McDonald }
23869b5a878SDan McDonald 
23969b5a878SDan McDonald /**
24069b5a878SDan McDonald  *  ixgbe_check_for_ack_vf - checks to see if the PF has ACK'd
24169b5a878SDan McDonald  *  @hw: pointer to the HW structure
24269b5a878SDan McDonald  *  @mbx_id: id of mailbox to check
24369b5a878SDan McDonald  *
24469b5a878SDan McDonald  *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
24569b5a878SDan McDonald  **/
ixgbe_check_for_ack_vf(struct ixgbe_hw * hw,u16 mbx_id)24669b5a878SDan McDonald static s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id)
24769b5a878SDan McDonald {
24869b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
24969b5a878SDan McDonald 
25069b5a878SDan McDonald 	UNREFERENCED_1PARAMETER(mbx_id);
25169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_check_for_ack_vf");
25269b5a878SDan McDonald 
25369b5a878SDan McDonald 	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) {
25469b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
25569b5a878SDan McDonald 		hw->mbx.stats.acks++;
25669b5a878SDan McDonald 	}
25769b5a878SDan McDonald 
25869b5a878SDan McDonald 	return ret_val;
25969b5a878SDan McDonald }
26069b5a878SDan McDonald 
26169b5a878SDan McDonald /**
26269b5a878SDan McDonald  *  ixgbe_check_for_rst_vf - checks to see if the PF has reset
26369b5a878SDan McDonald  *  @hw: pointer to the HW structure
26469b5a878SDan McDonald  *  @mbx_id: id of mailbox to check
26569b5a878SDan McDonald  *
26669b5a878SDan McDonald  *  returns TRUE if the PF has set the reset done bit or else FALSE
26769b5a878SDan McDonald  **/
ixgbe_check_for_rst_vf(struct ixgbe_hw * hw,u16 mbx_id)26869b5a878SDan McDonald static s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id)
26969b5a878SDan McDonald {
27069b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
27169b5a878SDan McDonald 
27269b5a878SDan McDonald 	UNREFERENCED_1PARAMETER(mbx_id);
27369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_check_for_rst_vf");
27469b5a878SDan McDonald 
27569b5a878SDan McDonald 	if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD |
27669b5a878SDan McDonald 	    IXGBE_VFMAILBOX_RSTI))) {
27769b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
27869b5a878SDan McDonald 		hw->mbx.stats.rsts++;
27969b5a878SDan McDonald 	}
28069b5a878SDan McDonald 
28169b5a878SDan McDonald 	return ret_val;
28269b5a878SDan McDonald }
28369b5a878SDan McDonald 
28469b5a878SDan McDonald /**
28569b5a878SDan McDonald  *  ixgbe_obtain_mbx_lock_vf - obtain mailbox lock
28669b5a878SDan McDonald  *  @hw: pointer to the HW structure
28769b5a878SDan McDonald  *
28869b5a878SDan McDonald  *  return SUCCESS if we obtained the mailbox lock
28969b5a878SDan McDonald  **/
ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw * hw)29069b5a878SDan McDonald static s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
29169b5a878SDan McDonald {
29269b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
29369b5a878SDan McDonald 
29469b5a878SDan McDonald 	DEBUGFUNC("ixgbe_obtain_mbx_lock_vf");
29569b5a878SDan McDonald 
29669b5a878SDan McDonald 	/* Take ownership of the buffer */
29769b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU);
29869b5a878SDan McDonald 
29969b5a878SDan McDonald 	/* reserve mailbox for vf use */
30069b5a878SDan McDonald 	if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU)
30169b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
30269b5a878SDan McDonald 
30369b5a878SDan McDonald 	return ret_val;
30469b5a878SDan McDonald }
30569b5a878SDan McDonald 
30669b5a878SDan McDonald /**
30769b5a878SDan McDonald  *  ixgbe_write_mbx_vf - Write a message to the mailbox
30869b5a878SDan McDonald  *  @hw: pointer to the HW structure
30969b5a878SDan McDonald  *  @msg: The message buffer
31069b5a878SDan McDonald  *  @size: Length of buffer
31169b5a878SDan McDonald  *  @mbx_id: id of mailbox to write
31269b5a878SDan McDonald  *
31369b5a878SDan McDonald  *  returns SUCCESS if it successfully copied message into the buffer
31469b5a878SDan McDonald  **/
ixgbe_write_mbx_vf(struct ixgbe_hw * hw,u32 * msg,u16 size,u16 mbx_id)31569b5a878SDan McDonald static s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
31669b5a878SDan McDonald 			      u16 mbx_id)
31769b5a878SDan McDonald {
31869b5a878SDan McDonald 	s32 ret_val;
31969b5a878SDan McDonald 	u16 i;
32069b5a878SDan McDonald 
32169b5a878SDan McDonald 	UNREFERENCED_1PARAMETER(mbx_id);
32269b5a878SDan McDonald 
32369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_mbx_vf");
32469b5a878SDan McDonald 
32569b5a878SDan McDonald 	/* lock the mailbox to prevent pf/vf race condition */
32669b5a878SDan McDonald 	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
32769b5a878SDan McDonald 	if (ret_val)
32869b5a878SDan McDonald 		goto out_no_write;
32969b5a878SDan McDonald 
33069b5a878SDan McDonald 	/* flush msg and acks as we are overwriting the message buffer */
331dc0cb1cdSDale Ghent 	ixgbe_check_for_msg_vf(hw, 0);
332dc0cb1cdSDale Ghent 	ixgbe_check_for_ack_vf(hw, 0);
33369b5a878SDan McDonald 
33469b5a878SDan McDonald 	/* copy the caller specified message to the mailbox memory buffer */
33569b5a878SDan McDonald 	for (i = 0; i < size; i++)
33669b5a878SDan McDonald 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]);
33769b5a878SDan McDonald 
33869b5a878SDan McDonald 	/* update stats */
33969b5a878SDan McDonald 	hw->mbx.stats.msgs_tx++;
34069b5a878SDan McDonald 
34169b5a878SDan McDonald 	/* Drop VFU and interrupt the PF to tell it a message has been sent */
34269b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
34369b5a878SDan McDonald 
34469b5a878SDan McDonald out_no_write:
34569b5a878SDan McDonald 	return ret_val;
34669b5a878SDan McDonald }
34769b5a878SDan McDonald 
34869b5a878SDan McDonald /**
34969b5a878SDan McDonald  *  ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
35069b5a878SDan McDonald  *  @hw: pointer to the HW structure
35169b5a878SDan McDonald  *  @msg: The message buffer
35269b5a878SDan McDonald  *  @size: Length of buffer
35369b5a878SDan McDonald  *  @mbx_id: id of mailbox to read
35469b5a878SDan McDonald  *
355dc0cb1cdSDale Ghent  *  returns SUCCESS if it successfully read message from buffer
35669b5a878SDan McDonald  **/
ixgbe_read_mbx_vf(struct ixgbe_hw * hw,u32 * msg,u16 size,u16 mbx_id)35769b5a878SDan McDonald static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
35869b5a878SDan McDonald 			     u16 mbx_id)
35969b5a878SDan McDonald {
36069b5a878SDan McDonald 	s32 ret_val = IXGBE_SUCCESS;
36169b5a878SDan McDonald 	u16 i;
36269b5a878SDan McDonald 
36369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_mbx_vf");
36469b5a878SDan McDonald 	UNREFERENCED_1PARAMETER(mbx_id);
36569b5a878SDan McDonald 
36669b5a878SDan McDonald 	/* lock the mailbox to prevent pf/vf race condition */
36769b5a878SDan McDonald 	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
36869b5a878SDan McDonald 	if (ret_val)
36969b5a878SDan McDonald 		goto out_no_read;
37069b5a878SDan McDonald 
37169b5a878SDan McDonald 	/* copy the message from the mailbox memory buffer */
37269b5a878SDan McDonald 	for (i = 0; i < size; i++)
37369b5a878SDan McDonald 		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i);
37469b5a878SDan McDonald 
37569b5a878SDan McDonald 	/* Acknowledge receipt and release mailbox, then we're done */
37669b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
37769b5a878SDan McDonald 
37869b5a878SDan McDonald 	/* update stats */
37969b5a878SDan McDonald 	hw->mbx.stats.msgs_rx++;
38069b5a878SDan McDonald 
38169b5a878SDan McDonald out_no_read:
38269b5a878SDan McDonald 	return ret_val;
38369b5a878SDan McDonald }
38469b5a878SDan McDonald 
38569b5a878SDan McDonald /**
38669b5a878SDan McDonald  *  ixgbe_init_mbx_params_vf - set initial values for vf mailbox
38769b5a878SDan McDonald  *  @hw: pointer to the HW structure
38869b5a878SDan McDonald  *
38969b5a878SDan McDonald  *  Initializes the hw->mbx struct to correct values for vf mailbox
39069b5a878SDan McDonald  */
ixgbe_init_mbx_params_vf(struct ixgbe_hw * hw)39169b5a878SDan McDonald void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
39269b5a878SDan McDonald {
39369b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
39469b5a878SDan McDonald 
39569b5a878SDan McDonald 	/* start mailbox as timed out and let the reset_hw call set the timeout
39669b5a878SDan McDonald 	 * value to begin communications */
39769b5a878SDan McDonald 	mbx->timeout = 0;
39869b5a878SDan McDonald 	mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
39969b5a878SDan McDonald 
40069b5a878SDan McDonald 	mbx->size = IXGBE_VFMAILBOX_SIZE;
40169b5a878SDan McDonald 
40269b5a878SDan McDonald 	mbx->ops.read = ixgbe_read_mbx_vf;
40369b5a878SDan McDonald 	mbx->ops.write = ixgbe_write_mbx_vf;
40469b5a878SDan McDonald 	mbx->ops.read_posted = ixgbe_read_posted_mbx;
40569b5a878SDan McDonald 	mbx->ops.write_posted = ixgbe_write_posted_mbx;
40669b5a878SDan McDonald 	mbx->ops.check_for_msg = ixgbe_check_for_msg_vf;
40769b5a878SDan McDonald 	mbx->ops.check_for_ack = ixgbe_check_for_ack_vf;
40869b5a878SDan McDonald 	mbx->ops.check_for_rst = ixgbe_check_for_rst_vf;
40969b5a878SDan McDonald 
41069b5a878SDan McDonald 	mbx->stats.msgs_tx = 0;
41169b5a878SDan McDonald 	mbx->stats.msgs_rx = 0;
41269b5a878SDan McDonald 	mbx->stats.reqs = 0;
41369b5a878SDan McDonald 	mbx->stats.acks = 0;
41469b5a878SDan McDonald 	mbx->stats.rsts = 0;
41569b5a878SDan McDonald }
41669b5a878SDan McDonald 
ixgbe_check_for_bit_pf(struct ixgbe_hw * hw,u32 mask,s32 index)41769b5a878SDan McDonald static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
41869b5a878SDan McDonald {
41969b5a878SDan McDonald 	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
42069b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
42169b5a878SDan McDonald 
42269b5a878SDan McDonald 	if (mbvficr & mask) {
42369b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
42469b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
42569b5a878SDan McDonald 	}
42669b5a878SDan McDonald 
42769b5a878SDan McDonald 	return ret_val;
42869b5a878SDan McDonald }
42969b5a878SDan McDonald 
43069b5a878SDan McDonald /**
43169b5a878SDan McDonald  *  ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
43269b5a878SDan McDonald  *  @hw: pointer to the HW structure
43369b5a878SDan McDonald  *  @vf_number: the VF index
43469b5a878SDan McDonald  *
43569b5a878SDan McDonald  *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
43669b5a878SDan McDonald  **/
ixgbe_check_for_msg_pf(struct ixgbe_hw * hw,u16 vf_number)43769b5a878SDan McDonald static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
43869b5a878SDan McDonald {
43969b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
44069b5a878SDan McDonald 	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
44169b5a878SDan McDonald 	u32 vf_bit = vf_number % 16;
44269b5a878SDan McDonald 
44369b5a878SDan McDonald 	DEBUGFUNC("ixgbe_check_for_msg_pf");
44469b5a878SDan McDonald 
44569b5a878SDan McDonald 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
44669b5a878SDan McDonald 				    index)) {
44769b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
44869b5a878SDan McDonald 		hw->mbx.stats.reqs++;
44969b5a878SDan McDonald 	}
45069b5a878SDan McDonald 
45169b5a878SDan McDonald 	return ret_val;
45269b5a878SDan McDonald }
45369b5a878SDan McDonald 
45469b5a878SDan McDonald /**
45569b5a878SDan McDonald  *  ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
45669b5a878SDan McDonald  *  @hw: pointer to the HW structure
45769b5a878SDan McDonald  *  @vf_number: the VF index
45869b5a878SDan McDonald  *
45969b5a878SDan McDonald  *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
46069b5a878SDan McDonald  **/
ixgbe_check_for_ack_pf(struct ixgbe_hw * hw,u16 vf_number)46169b5a878SDan McDonald static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
46269b5a878SDan McDonald {
46369b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
46469b5a878SDan McDonald 	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
46569b5a878SDan McDonald 	u32 vf_bit = vf_number % 16;
46669b5a878SDan McDonald 
46769b5a878SDan McDonald 	DEBUGFUNC("ixgbe_check_for_ack_pf");
46869b5a878SDan McDonald 
46969b5a878SDan McDonald 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
47069b5a878SDan McDonald 				    index)) {
47169b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
47269b5a878SDan McDonald 		hw->mbx.stats.acks++;
47369b5a878SDan McDonald 	}
47469b5a878SDan McDonald 
47569b5a878SDan McDonald 	return ret_val;
47669b5a878SDan McDonald }
47769b5a878SDan McDonald 
47869b5a878SDan McDonald /**
47969b5a878SDan McDonald  *  ixgbe_check_for_rst_pf - checks to see if the VF has reset
48069b5a878SDan McDonald  *  @hw: pointer to the HW structure
48169b5a878SDan McDonald  *  @vf_number: the VF index
48269b5a878SDan McDonald  *
48369b5a878SDan McDonald  *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
48469b5a878SDan McDonald  **/
ixgbe_check_for_rst_pf(struct ixgbe_hw * hw,u16 vf_number)48569b5a878SDan McDonald static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
48669b5a878SDan McDonald {
48769b5a878SDan McDonald 	u32 reg_offset = (vf_number < 32) ? 0 : 1;
48869b5a878SDan McDonald 	u32 vf_shift = vf_number % 32;
48969b5a878SDan McDonald 	u32 vflre = 0;
49069b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
49169b5a878SDan McDonald 
49269b5a878SDan McDonald 	DEBUGFUNC("ixgbe_check_for_rst_pf");
49369b5a878SDan McDonald 
49469b5a878SDan McDonald 	switch (hw->mac.type) {
49569b5a878SDan McDonald 	case ixgbe_mac_82599EB:
49669b5a878SDan McDonald 		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
49769b5a878SDan McDonald 		break;
498dc0cb1cdSDale Ghent 	case ixgbe_mac_X550:
499dc0cb1cdSDale Ghent 	case ixgbe_mac_X550EM_x:
500*48ed61a7SRobert Mustacchi 	case ixgbe_mac_X550EM_a:
50169b5a878SDan McDonald 	case ixgbe_mac_X540:
50269b5a878SDan McDonald 		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
50369b5a878SDan McDonald 		break;
50469b5a878SDan McDonald 	default:
50569b5a878SDan McDonald 		break;
50669b5a878SDan McDonald 	}
50769b5a878SDan McDonald 
50869b5a878SDan McDonald 	if (vflre & (1 << vf_shift)) {
50969b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
51069b5a878SDan McDonald 		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
51169b5a878SDan McDonald 		hw->mbx.stats.rsts++;
51269b5a878SDan McDonald 	}
51369b5a878SDan McDonald 
51469b5a878SDan McDonald 	return ret_val;
51569b5a878SDan McDonald }
51669b5a878SDan McDonald 
51769b5a878SDan McDonald /**
51869b5a878SDan McDonald  *  ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
51969b5a878SDan McDonald  *  @hw: pointer to the HW structure
52069b5a878SDan McDonald  *  @vf_number: the VF index
52169b5a878SDan McDonald  *
52269b5a878SDan McDonald  *  return SUCCESS if we obtained the mailbox lock
52369b5a878SDan McDonald  **/
ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw * hw,u16 vf_number)52469b5a878SDan McDonald static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
52569b5a878SDan McDonald {
52669b5a878SDan McDonald 	s32 ret_val = IXGBE_ERR_MBX;
52769b5a878SDan McDonald 	u32 p2v_mailbox;
52869b5a878SDan McDonald 
52969b5a878SDan McDonald 	DEBUGFUNC("ixgbe_obtain_mbx_lock_pf");
53069b5a878SDan McDonald 
53169b5a878SDan McDonald 	/* Take ownership of the buffer */
53269b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
53369b5a878SDan McDonald 
53469b5a878SDan McDonald 	/* reserve mailbox for vf use */
53569b5a878SDan McDonald 	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
53669b5a878SDan McDonald 	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
53769b5a878SDan McDonald 		ret_val = IXGBE_SUCCESS;
538dc0cb1cdSDale Ghent 	else
539dc0cb1cdSDale Ghent 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
540dc0cb1cdSDale Ghent 			   "Failed to obtain mailbox lock for VF%d", vf_number);
541dc0cb1cdSDale Ghent 
54269b5a878SDan McDonald 
54369b5a878SDan McDonald 	return ret_val;
54469b5a878SDan McDonald }
54569b5a878SDan McDonald 
54669b5a878SDan McDonald /**
54769b5a878SDan McDonald  *  ixgbe_write_mbx_pf - Places a message in the mailbox
54869b5a878SDan McDonald  *  @hw: pointer to the HW structure
54969b5a878SDan McDonald  *  @msg: The message buffer
55069b5a878SDan McDonald  *  @size: Length of buffer
55169b5a878SDan McDonald  *  @vf_number: the VF index
55269b5a878SDan McDonald  *
55369b5a878SDan McDonald  *  returns SUCCESS if it successfully copied message into the buffer
55469b5a878SDan McDonald  **/
ixgbe_write_mbx_pf(struct ixgbe_hw * hw,u32 * msg,u16 size,u16 vf_number)55569b5a878SDan McDonald static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
55669b5a878SDan McDonald 			      u16 vf_number)
55769b5a878SDan McDonald {
55869b5a878SDan McDonald 	s32 ret_val;
55969b5a878SDan McDonald 	u16 i;
56069b5a878SDan McDonald 
56169b5a878SDan McDonald 	DEBUGFUNC("ixgbe_write_mbx_pf");
56269b5a878SDan McDonald 
56369b5a878SDan McDonald 	/* lock the mailbox to prevent pf/vf race condition */
56469b5a878SDan McDonald 	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
56569b5a878SDan McDonald 	if (ret_val)
56669b5a878SDan McDonald 		goto out_no_write;
56769b5a878SDan McDonald 
56869b5a878SDan McDonald 	/* flush msg and acks as we are overwriting the message buffer */
569dc0cb1cdSDale Ghent 	ixgbe_check_for_msg_pf(hw, vf_number);
570dc0cb1cdSDale Ghent 	ixgbe_check_for_ack_pf(hw, vf_number);
57169b5a878SDan McDonald 
57269b5a878SDan McDonald 	/* copy the caller specified message to the mailbox memory buffer */
57369b5a878SDan McDonald 	for (i = 0; i < size; i++)
57469b5a878SDan McDonald 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
57569b5a878SDan McDonald 
57669b5a878SDan McDonald 	/* Interrupt VF to tell it a message has been sent and release buffer*/
57769b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
57869b5a878SDan McDonald 
57969b5a878SDan McDonald 	/* update stats */
58069b5a878SDan McDonald 	hw->mbx.stats.msgs_tx++;
58169b5a878SDan McDonald 
58269b5a878SDan McDonald out_no_write:
58369b5a878SDan McDonald 	return ret_val;
58469b5a878SDan McDonald 
58569b5a878SDan McDonald }
58669b5a878SDan McDonald 
58769b5a878SDan McDonald /**
58869b5a878SDan McDonald  *  ixgbe_read_mbx_pf - Read a message from the mailbox
58969b5a878SDan McDonald  *  @hw: pointer to the HW structure
59069b5a878SDan McDonald  *  @msg: The message buffer
59169b5a878SDan McDonald  *  @size: Length of buffer
59269b5a878SDan McDonald  *  @vf_number: the VF index
59369b5a878SDan McDonald  *
59469b5a878SDan McDonald  *  This function copies a message from the mailbox buffer to the caller's
59569b5a878SDan McDonald  *  memory buffer.  The presumption is that the caller knows that there was
59669b5a878SDan McDonald  *  a message due to a VF request so no polling for message is needed.
59769b5a878SDan McDonald  **/
ixgbe_read_mbx_pf(struct ixgbe_hw * hw,u32 * msg,u16 size,u16 vf_number)59869b5a878SDan McDonald static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
59969b5a878SDan McDonald 			     u16 vf_number)
60069b5a878SDan McDonald {
60169b5a878SDan McDonald 	s32 ret_val;
60269b5a878SDan McDonald 	u16 i;
60369b5a878SDan McDonald 
60469b5a878SDan McDonald 	DEBUGFUNC("ixgbe_read_mbx_pf");
60569b5a878SDan McDonald 
60669b5a878SDan McDonald 	/* lock the mailbox to prevent pf/vf race condition */
60769b5a878SDan McDonald 	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
60869b5a878SDan McDonald 	if (ret_val)
60969b5a878SDan McDonald 		goto out_no_read;
61069b5a878SDan McDonald 
61169b5a878SDan McDonald 	/* copy the message to the mailbox memory buffer */
61269b5a878SDan McDonald 	for (i = 0; i < size; i++)
61369b5a878SDan McDonald 		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
61469b5a878SDan McDonald 
61569b5a878SDan McDonald 	/* Acknowledge the message and release buffer */
61669b5a878SDan McDonald 	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
61769b5a878SDan McDonald 
61869b5a878SDan McDonald 	/* update stats */
61969b5a878SDan McDonald 	hw->mbx.stats.msgs_rx++;
62069b5a878SDan McDonald 
62169b5a878SDan McDonald out_no_read:
62269b5a878SDan McDonald 	return ret_val;
62369b5a878SDan McDonald }
62469b5a878SDan McDonald 
62569b5a878SDan McDonald /**
62669b5a878SDan McDonald  *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
62769b5a878SDan McDonald  *  @hw: pointer to the HW structure
62869b5a878SDan McDonald  *
62969b5a878SDan McDonald  *  Initializes the hw->mbx struct to correct values for pf mailbox
63069b5a878SDan McDonald  */
ixgbe_init_mbx_params_pf(struct ixgbe_hw * hw)63169b5a878SDan McDonald void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
63269b5a878SDan McDonald {
63369b5a878SDan McDonald 	struct ixgbe_mbx_info *mbx = &hw->mbx;
63469b5a878SDan McDonald 
63569b5a878SDan McDonald 	if (hw->mac.type != ixgbe_mac_82599EB &&
636dc0cb1cdSDale Ghent 	    hw->mac.type != ixgbe_mac_X550 &&
637dc0cb1cdSDale Ghent 	    hw->mac.type != ixgbe_mac_X550EM_x &&
638*48ed61a7SRobert Mustacchi 	    hw->mac.type != ixgbe_mac_X550EM_a &&
63969b5a878SDan McDonald 	    hw->mac.type != ixgbe_mac_X540)
64069b5a878SDan McDonald 		return;
64169b5a878SDan McDonald 
64269b5a878SDan McDonald 	mbx->timeout = 0;
64369b5a878SDan McDonald 	mbx->usec_delay = 0;
64469b5a878SDan McDonald 
64569b5a878SDan McDonald 	mbx->size = IXGBE_VFMAILBOX_SIZE;
64669b5a878SDan McDonald 
64769b5a878SDan McDonald 	mbx->ops.read = ixgbe_read_mbx_pf;
64869b5a878SDan McDonald 	mbx->ops.write = ixgbe_write_mbx_pf;
64969b5a878SDan McDonald 	mbx->ops.read_posted = ixgbe_read_posted_mbx;
65069b5a878SDan McDonald 	mbx->ops.write_posted = ixgbe_write_posted_mbx;
65169b5a878SDan McDonald 	mbx->ops.check_for_msg = ixgbe_check_for_msg_pf;
65269b5a878SDan McDonald 	mbx->ops.check_for_ack = ixgbe_check_for_ack_pf;
65369b5a878SDan McDonald 	mbx->ops.check_for_rst = ixgbe_check_for_rst_pf;
65469b5a878SDan McDonald 
65569b5a878SDan McDonald 	mbx->stats.msgs_tx = 0;
65669b5a878SDan McDonald 	mbx->stats.msgs_rx = 0;
65769b5a878SDan McDonald 	mbx->stats.reqs = 0;
65869b5a878SDan McDonald 	mbx->stats.acks = 0;
65969b5a878SDan McDonald 	mbx->stats.rsts = 0;
66069b5a878SDan McDonald }
661