162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/pci.h>
562306a36Sopenharmony_ci#include <linux/delay.h>
662306a36Sopenharmony_ci#include "ixgbe.h"
762306a36Sopenharmony_ci#include "ixgbe_mbx.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/**
1062306a36Sopenharmony_ci *  ixgbe_read_mbx - Reads a message from the mailbox
1162306a36Sopenharmony_ci *  @hw: pointer to the HW structure
1262306a36Sopenharmony_ci *  @msg: The message buffer
1362306a36Sopenharmony_ci *  @size: Length of buffer
1462306a36Sopenharmony_ci *  @mbx_id: id of mailbox to read
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *  returns SUCCESS if it successfully read message from buffer
1762306a36Sopenharmony_ci **/
1862306a36Sopenharmony_cis32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	/* limit read to size of mailbox */
2362306a36Sopenharmony_ci	if (size > mbx->size)
2462306a36Sopenharmony_ci		size = mbx->size;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (!mbx->ops)
2762306a36Sopenharmony_ci		return -EIO;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	return mbx->ops->read(hw, msg, size, mbx_id);
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/**
3362306a36Sopenharmony_ci *  ixgbe_write_mbx - Write a message to the mailbox
3462306a36Sopenharmony_ci *  @hw: pointer to the HW structure
3562306a36Sopenharmony_ci *  @msg: The message buffer
3662306a36Sopenharmony_ci *  @size: Length of buffer
3762306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer
4062306a36Sopenharmony_ci **/
4162306a36Sopenharmony_cis32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	if (size > mbx->size)
4662306a36Sopenharmony_ci		return -EINVAL;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (!mbx->ops)
4962306a36Sopenharmony_ci		return -EIO;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	return mbx->ops->write(hw, msg, size, mbx_id);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/**
5562306a36Sopenharmony_ci *  ixgbe_check_for_msg - checks to see if someone sent us mail
5662306a36Sopenharmony_ci *  @hw: pointer to the HW structure
5762306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
6062306a36Sopenharmony_ci **/
6162306a36Sopenharmony_cis32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (!mbx->ops)
6662306a36Sopenharmony_ci		return -EIO;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	return mbx->ops->check_for_msg(hw, mbx_id);
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/**
7262306a36Sopenharmony_ci *  ixgbe_check_for_ack - checks to see if someone sent us ACK
7362306a36Sopenharmony_ci *  @hw: pointer to the HW structure
7462306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
7762306a36Sopenharmony_ci **/
7862306a36Sopenharmony_cis32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (!mbx->ops)
8362306a36Sopenharmony_ci		return -EIO;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	return mbx->ops->check_for_ack(hw, mbx_id);
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/**
8962306a36Sopenharmony_ci *  ixgbe_check_for_rst - checks to see if other side has reset
9062306a36Sopenharmony_ci *  @hw: pointer to the HW structure
9162306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
9462306a36Sopenharmony_ci **/
9562306a36Sopenharmony_cis32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	if (!mbx->ops)
10062306a36Sopenharmony_ci		return -EIO;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	return mbx->ops->check_for_rst(hw, mbx_id);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/**
10662306a36Sopenharmony_ci *  ixgbe_poll_for_msg - Wait for message notification
10762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
10862306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
10962306a36Sopenharmony_ci *
11062306a36Sopenharmony_ci *  returns SUCCESS if it successfully received a message notification
11162306a36Sopenharmony_ci **/
11262306a36Sopenharmony_cistatic s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
11562306a36Sopenharmony_ci	int countdown = mbx->timeout;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (!countdown || !mbx->ops)
11862306a36Sopenharmony_ci		return -EIO;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	while (mbx->ops->check_for_msg(hw, mbx_id)) {
12162306a36Sopenharmony_ci		countdown--;
12262306a36Sopenharmony_ci		if (!countdown)
12362306a36Sopenharmony_ci			return -EIO;
12462306a36Sopenharmony_ci		udelay(mbx->usec_delay);
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return 0;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/**
13162306a36Sopenharmony_ci *  ixgbe_poll_for_ack - Wait for message acknowledgement
13262306a36Sopenharmony_ci *  @hw: pointer to the HW structure
13362306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci *  returns SUCCESS if it successfully received a message acknowledgement
13662306a36Sopenharmony_ci **/
13762306a36Sopenharmony_cistatic s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
14062306a36Sopenharmony_ci	int countdown = mbx->timeout;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	if (!countdown || !mbx->ops)
14362306a36Sopenharmony_ci		return -EIO;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	while (mbx->ops->check_for_ack(hw, mbx_id)) {
14662306a36Sopenharmony_ci		countdown--;
14762306a36Sopenharmony_ci		if (!countdown)
14862306a36Sopenharmony_ci			return -EIO;
14962306a36Sopenharmony_ci		udelay(mbx->usec_delay);
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return 0;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/**
15662306a36Sopenharmony_ci *  ixgbe_read_posted_mbx - Wait for message notification and receive message
15762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
15862306a36Sopenharmony_ci *  @msg: The message buffer
15962306a36Sopenharmony_ci *  @size: Length of buffer
16062306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
16162306a36Sopenharmony_ci *
16262306a36Sopenharmony_ci *  returns SUCCESS if it successfully received a message notification and
16362306a36Sopenharmony_ci *  copied it into the receive buffer.
16462306a36Sopenharmony_ci **/
16562306a36Sopenharmony_cistatic s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
16662306a36Sopenharmony_ci				 u16 mbx_id)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
16962306a36Sopenharmony_ci	s32 ret_val;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	if (!mbx->ops)
17262306a36Sopenharmony_ci		return -EIO;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
17562306a36Sopenharmony_ci	if (ret_val)
17662306a36Sopenharmony_ci		return ret_val;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/* if ack received read message */
17962306a36Sopenharmony_ci	return mbx->ops->read(hw, msg, size, mbx_id);
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci/**
18362306a36Sopenharmony_ci *  ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
18462306a36Sopenharmony_ci *  @hw: pointer to the HW structure
18562306a36Sopenharmony_ci *  @msg: The message buffer
18662306a36Sopenharmony_ci *  @size: Length of buffer
18762306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
18862306a36Sopenharmony_ci *
18962306a36Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer and
19062306a36Sopenharmony_ci *  received an ack to that message within delay * timeout period
19162306a36Sopenharmony_ci **/
19262306a36Sopenharmony_cistatic s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
19362306a36Sopenharmony_ci			   u16 mbx_id)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
19662306a36Sopenharmony_ci	s32 ret_val;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	/* exit if either we can't write or there isn't a defined timeout */
19962306a36Sopenharmony_ci	if (!mbx->ops || !mbx->timeout)
20062306a36Sopenharmony_ci		return -EIO;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	/* send msg */
20362306a36Sopenharmony_ci	ret_val = mbx->ops->write(hw, msg, size, mbx_id);
20462306a36Sopenharmony_ci	if (ret_val)
20562306a36Sopenharmony_ci		return ret_val;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	/* if msg sent wait until we receive an ack */
20862306a36Sopenharmony_ci	return ixgbe_poll_for_ack(hw, mbx_id);
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (mbvficr & mask) {
21662306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
21762306a36Sopenharmony_ci		return 0;
21862306a36Sopenharmony_ci	}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	return -EIO;
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci/**
22462306a36Sopenharmony_ci *  ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
22562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
22662306a36Sopenharmony_ci *  @vf_number: the VF index
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
22962306a36Sopenharmony_ci **/
23062306a36Sopenharmony_cistatic s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
23362306a36Sopenharmony_ci	u32 vf_bit = vf_number % 16;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
23662306a36Sopenharmony_ci				    index)) {
23762306a36Sopenharmony_ci		hw->mbx.stats.reqs++;
23862306a36Sopenharmony_ci		return 0;
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	return -EIO;
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci/**
24562306a36Sopenharmony_ci *  ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
24662306a36Sopenharmony_ci *  @hw: pointer to the HW structure
24762306a36Sopenharmony_ci *  @vf_number: the VF index
24862306a36Sopenharmony_ci *
24962306a36Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
25062306a36Sopenharmony_ci **/
25162306a36Sopenharmony_cistatic s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
25462306a36Sopenharmony_ci	u32 vf_bit = vf_number % 16;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
25762306a36Sopenharmony_ci				    index)) {
25862306a36Sopenharmony_ci		hw->mbx.stats.acks++;
25962306a36Sopenharmony_ci		return 0;
26062306a36Sopenharmony_ci	}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return -EIO;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci/**
26662306a36Sopenharmony_ci *  ixgbe_check_for_rst_pf - checks to see if the VF has reset
26762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
26862306a36Sopenharmony_ci *  @vf_number: the VF index
26962306a36Sopenharmony_ci *
27062306a36Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
27162306a36Sopenharmony_ci **/
27262306a36Sopenharmony_cistatic s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	u32 reg_offset = (vf_number < 32) ? 0 : 1;
27562306a36Sopenharmony_ci	u32 vf_shift = vf_number % 32;
27662306a36Sopenharmony_ci	u32 vflre = 0;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	switch (hw->mac.type) {
27962306a36Sopenharmony_ci	case ixgbe_mac_82599EB:
28062306a36Sopenharmony_ci		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
28162306a36Sopenharmony_ci		break;
28262306a36Sopenharmony_ci	case ixgbe_mac_X540:
28362306a36Sopenharmony_ci	case ixgbe_mac_X550:
28462306a36Sopenharmony_ci	case ixgbe_mac_X550EM_x:
28562306a36Sopenharmony_ci	case ixgbe_mac_x550em_a:
28662306a36Sopenharmony_ci		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
28762306a36Sopenharmony_ci		break;
28862306a36Sopenharmony_ci	default:
28962306a36Sopenharmony_ci		break;
29062306a36Sopenharmony_ci	}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	if (vflre & BIT(vf_shift)) {
29362306a36Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), BIT(vf_shift));
29462306a36Sopenharmony_ci		hw->mbx.stats.rsts++;
29562306a36Sopenharmony_ci		return 0;
29662306a36Sopenharmony_ci	}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	return -EIO;
29962306a36Sopenharmony_ci}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci/**
30262306a36Sopenharmony_ci *  ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
30362306a36Sopenharmony_ci *  @hw: pointer to the HW structure
30462306a36Sopenharmony_ci *  @vf_number: the VF index
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci *  return SUCCESS if we obtained the mailbox lock
30762306a36Sopenharmony_ci **/
30862306a36Sopenharmony_cistatic s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	u32 p2v_mailbox;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* Take ownership of the buffer */
31362306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	/* reserve mailbox for vf use */
31662306a36Sopenharmony_ci	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
31762306a36Sopenharmony_ci	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
31862306a36Sopenharmony_ci		return 0;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	return -EIO;
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci/**
32462306a36Sopenharmony_ci *  ixgbe_write_mbx_pf - Places a message in the mailbox
32562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
32662306a36Sopenharmony_ci *  @msg: The message buffer
32762306a36Sopenharmony_ci *  @size: Length of buffer
32862306a36Sopenharmony_ci *  @vf_number: the VF index
32962306a36Sopenharmony_ci *
33062306a36Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer
33162306a36Sopenharmony_ci **/
33262306a36Sopenharmony_cistatic s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
33362306a36Sopenharmony_ci			      u16 vf_number)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	s32 ret_val;
33662306a36Sopenharmony_ci	u16 i;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	/* lock the mailbox to prevent pf/vf race condition */
33962306a36Sopenharmony_ci	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
34062306a36Sopenharmony_ci	if (ret_val)
34162306a36Sopenharmony_ci		return ret_val;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	/* flush msg and acks as we are overwriting the message buffer */
34462306a36Sopenharmony_ci	ixgbe_check_for_msg_pf(hw, vf_number);
34562306a36Sopenharmony_ci	ixgbe_check_for_ack_pf(hw, vf_number);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* copy the caller specified message to the mailbox memory buffer */
34862306a36Sopenharmony_ci	for (i = 0; i < size; i++)
34962306a36Sopenharmony_ci		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/* Interrupt VF to tell it a message has been sent and release buffer*/
35262306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* update stats */
35562306a36Sopenharmony_ci	hw->mbx.stats.msgs_tx++;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	return 0;
35862306a36Sopenharmony_ci}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci/**
36162306a36Sopenharmony_ci *  ixgbe_read_mbx_pf - Read a message from the mailbox
36262306a36Sopenharmony_ci *  @hw: pointer to the HW structure
36362306a36Sopenharmony_ci *  @msg: The message buffer
36462306a36Sopenharmony_ci *  @size: Length of buffer
36562306a36Sopenharmony_ci *  @vf_number: the VF index
36662306a36Sopenharmony_ci *
36762306a36Sopenharmony_ci *  This function copies a message from the mailbox buffer to the caller's
36862306a36Sopenharmony_ci *  memory buffer.  The presumption is that the caller knows that there was
36962306a36Sopenharmony_ci *  a message due to a VF request so no polling for message is needed.
37062306a36Sopenharmony_ci **/
37162306a36Sopenharmony_cistatic s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
37262306a36Sopenharmony_ci			     u16 vf_number)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	s32 ret_val;
37562306a36Sopenharmony_ci	u16 i;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* lock the mailbox to prevent pf/vf race condition */
37862306a36Sopenharmony_ci	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
37962306a36Sopenharmony_ci	if (ret_val)
38062306a36Sopenharmony_ci		return ret_val;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	/* copy the message to the mailbox memory buffer */
38362306a36Sopenharmony_ci	for (i = 0; i < size; i++)
38462306a36Sopenharmony_ci		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* Acknowledge the message and release buffer */
38762306a36Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	/* update stats */
39062306a36Sopenharmony_ci	hw->mbx.stats.msgs_rx++;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	return 0;
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV
39662306a36Sopenharmony_ci/**
39762306a36Sopenharmony_ci *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
39862306a36Sopenharmony_ci *  @hw: pointer to the HW structure
39962306a36Sopenharmony_ci *
40062306a36Sopenharmony_ci *  Initializes the hw->mbx struct to correct values for pf mailbox
40162306a36Sopenharmony_ci */
40262306a36Sopenharmony_civoid ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (hw->mac.type != ixgbe_mac_82599EB &&
40762306a36Sopenharmony_ci	    hw->mac.type != ixgbe_mac_X550 &&
40862306a36Sopenharmony_ci	    hw->mac.type != ixgbe_mac_X550EM_x &&
40962306a36Sopenharmony_ci	    hw->mac.type != ixgbe_mac_x550em_a &&
41062306a36Sopenharmony_ci	    hw->mac.type != ixgbe_mac_X540)
41162306a36Sopenharmony_ci		return;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	mbx->timeout = 0;
41462306a36Sopenharmony_ci	mbx->usec_delay = 0;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	mbx->stats.msgs_tx = 0;
41762306a36Sopenharmony_ci	mbx->stats.msgs_rx = 0;
41862306a36Sopenharmony_ci	mbx->stats.reqs = 0;
41962306a36Sopenharmony_ci	mbx->stats.acks = 0;
42062306a36Sopenharmony_ci	mbx->stats.rsts = 0;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	mbx->size = IXGBE_VFMAILBOX_SIZE;
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci#endif /* CONFIG_PCI_IOV */
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ciconst struct ixgbe_mbx_operations mbx_ops_generic = {
42762306a36Sopenharmony_ci	.read                   = ixgbe_read_mbx_pf,
42862306a36Sopenharmony_ci	.write                  = ixgbe_write_mbx_pf,
42962306a36Sopenharmony_ci	.read_posted            = ixgbe_read_posted_mbx,
43062306a36Sopenharmony_ci	.write_posted           = ixgbe_write_posted_mbx,
43162306a36Sopenharmony_ci	.check_for_msg          = ixgbe_check_for_msg_pf,
43262306a36Sopenharmony_ci	.check_for_ack          = ixgbe_check_for_ack_pf,
43362306a36Sopenharmony_ci	.check_for_rst          = ixgbe_check_for_rst_pf,
43462306a36Sopenharmony_ci};
43562306a36Sopenharmony_ci
436