162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2007 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "e1000_mbx.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/**
762306a36Sopenharmony_ci *  igb_read_mbx - Reads a message from the mailbox
862306a36Sopenharmony_ci *  @hw: pointer to the HW structure
962306a36Sopenharmony_ci *  @msg: The message buffer
1062306a36Sopenharmony_ci *  @size: Length of buffer
1162306a36Sopenharmony_ci *  @mbx_id: id of mailbox to read
1262306a36Sopenharmony_ci *  @unlock: skip locking or not
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  returns SUCCESS if it successfully read message from buffer
1562306a36Sopenharmony_ci **/
1662306a36Sopenharmony_cis32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
1762306a36Sopenharmony_ci		 bool unlock)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
2062306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_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.read)
2762306a36Sopenharmony_ci		ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	return ret_val;
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/**
3362306a36Sopenharmony_ci *  igb_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 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
4462306a36Sopenharmony_ci	s32 ret_val = 0;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	if (size > mbx->size)
4762306a36Sopenharmony_ci		ret_val = -E1000_ERR_MBX;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	else if (mbx->ops.write)
5062306a36Sopenharmony_ci		ret_val = mbx->ops.write(hw, msg, size, mbx_id);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	return ret_val;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/**
5662306a36Sopenharmony_ci *  igb_check_for_msg - checks to see if someone sent us mail
5762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
5862306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
6162306a36Sopenharmony_ci **/
6262306a36Sopenharmony_cis32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
6562306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	if (mbx->ops.check_for_msg)
6862306a36Sopenharmony_ci		ret_val = mbx->ops.check_for_msg(hw, mbx_id);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return ret_val;
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/**
7462306a36Sopenharmony_ci *  igb_check_for_ack - checks to see if someone sent us ACK
7562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
7662306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
7962306a36Sopenharmony_ci **/
8062306a36Sopenharmony_cis32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
8362306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (mbx->ops.check_for_ack)
8662306a36Sopenharmony_ci		ret_val = mbx->ops.check_for_ack(hw, mbx_id);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	return ret_val;
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/**
9262306a36Sopenharmony_ci *  igb_check_for_rst - checks to see if other side has reset
9362306a36Sopenharmony_ci *  @hw: pointer to the HW structure
9462306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
9562306a36Sopenharmony_ci *
9662306a36Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
9762306a36Sopenharmony_ci **/
9862306a36Sopenharmony_cis32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
10162306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (mbx->ops.check_for_rst)
10462306a36Sopenharmony_ci		ret_val = mbx->ops.check_for_rst(hw, mbx_id);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return ret_val;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/**
11062306a36Sopenharmony_ci *  igb_unlock_mbx - unlock the mailbox
11162306a36Sopenharmony_ci *  @hw: pointer to the HW structure
11262306a36Sopenharmony_ci *  @mbx_id: id of mailbox to check
11362306a36Sopenharmony_ci *
11462306a36Sopenharmony_ci *  returns SUCCESS if the mailbox was unlocked or else ERR_MBX
11562306a36Sopenharmony_ci **/
11662306a36Sopenharmony_cis32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
11962306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	if (mbx->ops.unlock)
12262306a36Sopenharmony_ci		ret_val = mbx->ops.unlock(hw, mbx_id);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return ret_val;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/**
12862306a36Sopenharmony_ci *  igb_poll_for_msg - Wait for message notification
12962306a36Sopenharmony_ci *  @hw: pointer to the HW structure
13062306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
13162306a36Sopenharmony_ci *
13262306a36Sopenharmony_ci *  returns SUCCESS if it successfully received a message notification
13362306a36Sopenharmony_ci **/
13462306a36Sopenharmony_cistatic s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
13762306a36Sopenharmony_ci	int countdown = mbx->timeout;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	if (!countdown || !mbx->ops.check_for_msg)
14062306a36Sopenharmony_ci		goto out;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
14362306a36Sopenharmony_ci		countdown--;
14462306a36Sopenharmony_ci		if (!countdown)
14562306a36Sopenharmony_ci			break;
14662306a36Sopenharmony_ci		udelay(mbx->usec_delay);
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* if we failed, all future posted messages fail until reset */
15062306a36Sopenharmony_ci	if (!countdown)
15162306a36Sopenharmony_ci		mbx->timeout = 0;
15262306a36Sopenharmony_ciout:
15362306a36Sopenharmony_ci	return countdown ? 0 : -E1000_ERR_MBX;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci/**
15762306a36Sopenharmony_ci *  igb_poll_for_ack - Wait for message acknowledgement
15862306a36Sopenharmony_ci *  @hw: pointer to the HW structure
15962306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
16062306a36Sopenharmony_ci *
16162306a36Sopenharmony_ci *  returns SUCCESS if it successfully received a message acknowledgement
16262306a36Sopenharmony_ci **/
16362306a36Sopenharmony_cistatic s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
16662306a36Sopenharmony_ci	int countdown = mbx->timeout;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (!countdown || !mbx->ops.check_for_ack)
16962306a36Sopenharmony_ci		goto out;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
17262306a36Sopenharmony_ci		countdown--;
17362306a36Sopenharmony_ci		if (!countdown)
17462306a36Sopenharmony_ci			break;
17562306a36Sopenharmony_ci		udelay(mbx->usec_delay);
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/* if we failed, all future posted messages fail until reset */
17962306a36Sopenharmony_ci	if (!countdown)
18062306a36Sopenharmony_ci		mbx->timeout = 0;
18162306a36Sopenharmony_ciout:
18262306a36Sopenharmony_ci	return countdown ? 0 : -E1000_ERR_MBX;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/**
18662306a36Sopenharmony_ci *  igb_read_posted_mbx - Wait for message notification and receive message
18762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
18862306a36Sopenharmony_ci *  @msg: The message buffer
18962306a36Sopenharmony_ci *  @size: Length of buffer
19062306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci *  returns SUCCESS if it successfully received a message notification and
19362306a36Sopenharmony_ci *  copied it into the receive buffer.
19462306a36Sopenharmony_ci **/
19562306a36Sopenharmony_cistatic s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
19662306a36Sopenharmony_ci			       u16 mbx_id)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
19962306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	if (!mbx->ops.read)
20262306a36Sopenharmony_ci		goto out;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	ret_val = igb_poll_for_msg(hw, mbx_id);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (!ret_val)
20762306a36Sopenharmony_ci		ret_val = mbx->ops.read(hw, msg, size, mbx_id, true);
20862306a36Sopenharmony_ciout:
20962306a36Sopenharmony_ci	return ret_val;
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/**
21362306a36Sopenharmony_ci *  igb_write_posted_mbx - Write a message to the mailbox, wait for ack
21462306a36Sopenharmony_ci *  @hw: pointer to the HW structure
21562306a36Sopenharmony_ci *  @msg: The message buffer
21662306a36Sopenharmony_ci *  @size: Length of buffer
21762306a36Sopenharmony_ci *  @mbx_id: id of mailbox to write
21862306a36Sopenharmony_ci *
21962306a36Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer and
22062306a36Sopenharmony_ci *  received an ack to that message within delay * timeout period
22162306a36Sopenharmony_ci **/
22262306a36Sopenharmony_cistatic s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size,
22362306a36Sopenharmony_ci				u16 mbx_id)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
22662306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	/* exit if either we can't write or there isn't a defined timeout */
22962306a36Sopenharmony_ci	if (!mbx->ops.write || !mbx->timeout)
23062306a36Sopenharmony_ci		goto out;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	/* send msg */
23362306a36Sopenharmony_ci	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	/* if msg sent wait until we receive an ack */
23662306a36Sopenharmony_ci	if (!ret_val)
23762306a36Sopenharmony_ci		ret_val = igb_poll_for_ack(hw, mbx_id);
23862306a36Sopenharmony_ciout:
23962306a36Sopenharmony_ci	return ret_val;
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	u32 mbvficr = rd32(E1000_MBVFICR);
24562306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	if (mbvficr & mask) {
24862306a36Sopenharmony_ci		ret_val = 0;
24962306a36Sopenharmony_ci		wr32(E1000_MBVFICR, mask);
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	return ret_val;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/**
25662306a36Sopenharmony_ci *  igb_check_for_msg_pf - checks to see if the VF has sent mail
25762306a36Sopenharmony_ci *  @hw: pointer to the HW structure
25862306a36Sopenharmony_ci *  @vf_number: the VF index
25962306a36Sopenharmony_ci *
26062306a36Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
26162306a36Sopenharmony_ci **/
26262306a36Sopenharmony_cistatic s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
26762306a36Sopenharmony_ci		ret_val = 0;
26862306a36Sopenharmony_ci		hw->mbx.stats.reqs++;
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	return ret_val;
27262306a36Sopenharmony_ci}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci/**
27562306a36Sopenharmony_ci *  igb_check_for_ack_pf - checks to see if the VF has ACKed
27662306a36Sopenharmony_ci *  @hw: pointer to the HW structure
27762306a36Sopenharmony_ci *  @vf_number: the VF index
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
28062306a36Sopenharmony_ci **/
28162306a36Sopenharmony_cistatic s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
28662306a36Sopenharmony_ci		ret_val = 0;
28762306a36Sopenharmony_ci		hw->mbx.stats.acks++;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return ret_val;
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci/**
29462306a36Sopenharmony_ci *  igb_check_for_rst_pf - checks to see if the VF has reset
29562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
29662306a36Sopenharmony_ci *  @vf_number: the VF index
29762306a36Sopenharmony_ci *
29862306a36Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
29962306a36Sopenharmony_ci **/
30062306a36Sopenharmony_cistatic s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	u32 vflre = rd32(E1000_VFLRE);
30362306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (vflre & BIT(vf_number)) {
30662306a36Sopenharmony_ci		ret_val = 0;
30762306a36Sopenharmony_ci		wr32(E1000_VFLRE, BIT(vf_number));
30862306a36Sopenharmony_ci		hw->mbx.stats.rsts++;
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	return ret_val;
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci/**
31562306a36Sopenharmony_ci *  igb_obtain_mbx_lock_pf - obtain mailbox lock
31662306a36Sopenharmony_ci *  @hw: pointer to the HW structure
31762306a36Sopenharmony_ci *  @vf_number: the VF index
31862306a36Sopenharmony_ci *
31962306a36Sopenharmony_ci *  return SUCCESS if we obtained the mailbox lock
32062306a36Sopenharmony_ci **/
32162306a36Sopenharmony_cistatic s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	s32 ret_val = -E1000_ERR_MBX;
32462306a36Sopenharmony_ci	u32 p2v_mailbox;
32562306a36Sopenharmony_ci	int count = 10;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	do {
32862306a36Sopenharmony_ci		/* Take ownership of the buffer */
32962306a36Sopenharmony_ci		wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci		/* reserve mailbox for vf use */
33262306a36Sopenharmony_ci		p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
33362306a36Sopenharmony_ci		if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
33462306a36Sopenharmony_ci			ret_val = 0;
33562306a36Sopenharmony_ci			break;
33662306a36Sopenharmony_ci		}
33762306a36Sopenharmony_ci		udelay(1000);
33862306a36Sopenharmony_ci	} while (count-- > 0);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return ret_val;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci/**
34462306a36Sopenharmony_ci *  igb_release_mbx_lock_pf - release mailbox lock
34562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
34662306a36Sopenharmony_ci *  @vf_number: the VF index
34762306a36Sopenharmony_ci *
34862306a36Sopenharmony_ci *  return SUCCESS if we released the mailbox lock
34962306a36Sopenharmony_ci **/
35062306a36Sopenharmony_cistatic s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	u32 p2v_mailbox;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* drop PF lock of mailbox, if set */
35562306a36Sopenharmony_ci	p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number));
35662306a36Sopenharmony_ci	if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
35762306a36Sopenharmony_ci		wr32(E1000_P2VMAILBOX(vf_number),
35862306a36Sopenharmony_ci		     p2v_mailbox & ~E1000_P2VMAILBOX_PFU);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return 0;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci/**
36462306a36Sopenharmony_ci *  igb_write_mbx_pf - Places a message in the mailbox
36562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
36662306a36Sopenharmony_ci *  @msg: The message buffer
36762306a36Sopenharmony_ci *  @size: Length of buffer
36862306a36Sopenharmony_ci *  @vf_number: the VF index
36962306a36Sopenharmony_ci *
37062306a36Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer
37162306a36Sopenharmony_ci **/
37262306a36Sopenharmony_cistatic s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
37362306a36Sopenharmony_ci			    u16 vf_number)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	s32 ret_val;
37662306a36Sopenharmony_ci	u16 i;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	/* lock the mailbox to prevent pf/vf race condition */
37962306a36Sopenharmony_ci	ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
38062306a36Sopenharmony_ci	if (ret_val)
38162306a36Sopenharmony_ci		goto out_no_write;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/* flush msg and acks as we are overwriting the message buffer */
38462306a36Sopenharmony_ci	igb_check_for_msg_pf(hw, vf_number);
38562306a36Sopenharmony_ci	igb_check_for_ack_pf(hw, vf_number);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	/* copy the caller specified message to the mailbox memory buffer */
38862306a36Sopenharmony_ci	for (i = 0; i < size; i++)
38962306a36Sopenharmony_ci		array_wr32(E1000_VMBMEM(vf_number), i, msg[i]);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	/* Interrupt VF to tell it a message has been sent and release buffer*/
39262306a36Sopenharmony_ci	wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/* update stats */
39562306a36Sopenharmony_ci	hw->mbx.stats.msgs_tx++;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ciout_no_write:
39862306a36Sopenharmony_ci	return ret_val;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci/**
40362306a36Sopenharmony_ci *  igb_read_mbx_pf - Read a message from the mailbox
40462306a36Sopenharmony_ci *  @hw: pointer to the HW structure
40562306a36Sopenharmony_ci *  @msg: The message buffer
40662306a36Sopenharmony_ci *  @size: Length of buffer
40762306a36Sopenharmony_ci *  @vf_number: the VF index
40862306a36Sopenharmony_ci *  @unlock: unlock the mailbox when done?
40962306a36Sopenharmony_ci *
41062306a36Sopenharmony_ci *  This function copies a message from the mailbox buffer to the caller's
41162306a36Sopenharmony_ci *  memory buffer.  The presumption is that the caller knows that there was
41262306a36Sopenharmony_ci *  a message due to a VF request so no polling for message is needed.
41362306a36Sopenharmony_ci **/
41462306a36Sopenharmony_cistatic s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
41562306a36Sopenharmony_ci			   u16 vf_number, bool unlock)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	s32 ret_val;
41862306a36Sopenharmony_ci	u16 i;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	/* lock the mailbox to prevent pf/vf race condition */
42162306a36Sopenharmony_ci	ret_val = igb_obtain_mbx_lock_pf(hw, vf_number);
42262306a36Sopenharmony_ci	if (ret_val)
42362306a36Sopenharmony_ci		goto out_no_read;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	/* copy the message to the mailbox memory buffer */
42662306a36Sopenharmony_ci	for (i = 0; i < size; i++)
42762306a36Sopenharmony_ci		msg[i] = array_rd32(E1000_VMBMEM(vf_number), i);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/* Acknowledge the message and release mailbox lock (or not) */
43062306a36Sopenharmony_ci	if (unlock)
43162306a36Sopenharmony_ci		wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
43262306a36Sopenharmony_ci	else
43362306a36Sopenharmony_ci		wr32(E1000_P2VMAILBOX(vf_number),
43462306a36Sopenharmony_ci		     E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	/* update stats */
43762306a36Sopenharmony_ci	hw->mbx.stats.msgs_rx++;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ciout_no_read:
44062306a36Sopenharmony_ci	return ret_val;
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci/**
44462306a36Sopenharmony_ci *  igb_init_mbx_params_pf - set initial values for pf mailbox
44562306a36Sopenharmony_ci *  @hw: pointer to the HW structure
44662306a36Sopenharmony_ci *
44762306a36Sopenharmony_ci *  Initializes the hw->mbx struct to correct values for pf mailbox
44862306a36Sopenharmony_ci */
44962306a36Sopenharmony_cis32 igb_init_mbx_params_pf(struct e1000_hw *hw)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	struct e1000_mbx_info *mbx = &hw->mbx;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	mbx->timeout = 0;
45462306a36Sopenharmony_ci	mbx->usec_delay = 0;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	mbx->size = E1000_VFMAILBOX_SIZE;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	mbx->ops.read = igb_read_mbx_pf;
45962306a36Sopenharmony_ci	mbx->ops.write = igb_write_mbx_pf;
46062306a36Sopenharmony_ci	mbx->ops.read_posted = igb_read_posted_mbx;
46162306a36Sopenharmony_ci	mbx->ops.write_posted = igb_write_posted_mbx;
46262306a36Sopenharmony_ci	mbx->ops.check_for_msg = igb_check_for_msg_pf;
46362306a36Sopenharmony_ci	mbx->ops.check_for_ack = igb_check_for_ack_pf;
46462306a36Sopenharmony_ci	mbx->ops.check_for_rst = igb_check_for_rst_pf;
46562306a36Sopenharmony_ci	mbx->ops.unlock = igb_release_mbx_lock_pf;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	mbx->stats.msgs_tx = 0;
46862306a36Sopenharmony_ci	mbx->stats.msgs_rx = 0;
46962306a36Sopenharmony_ci	mbx->stats.reqs = 0;
47062306a36Sopenharmony_ci	mbx->stats.acks = 0;
47162306a36Sopenharmony_ci	mbx->stats.rsts = 0;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	return 0;
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
476