18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/pci.h>
58c2ecf20Sopenharmony_ci#include <linux/delay.h>
68c2ecf20Sopenharmony_ci#include "ixgbe.h"
78c2ecf20Sopenharmony_ci#include "ixgbe_mbx.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci/**
108c2ecf20Sopenharmony_ci *  ixgbe_read_mbx - Reads a message from the mailbox
118c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
128c2ecf20Sopenharmony_ci *  @msg: The message buffer
138c2ecf20Sopenharmony_ci *  @size: Length of buffer
148c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to read
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully read message from buffer
178c2ecf20Sopenharmony_ci **/
188c2ecf20Sopenharmony_cis32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	/* limit read to size of mailbox */
238c2ecf20Sopenharmony_ci	if (size > mbx->size)
248c2ecf20Sopenharmony_ci		size = mbx->size;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	if (!mbx->ops)
278c2ecf20Sopenharmony_ci		return -EIO;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	return mbx->ops->read(hw, msg, size, mbx_id);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/**
338c2ecf20Sopenharmony_ci *  ixgbe_write_mbx - Write a message to the mailbox
348c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
358c2ecf20Sopenharmony_ci *  @msg: The message buffer
368c2ecf20Sopenharmony_ci *  @size: Length of buffer
378c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to write
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer
408c2ecf20Sopenharmony_ci **/
418c2ecf20Sopenharmony_cis32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	if (size > mbx->size)
468c2ecf20Sopenharmony_ci		return -EINVAL;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (!mbx->ops)
498c2ecf20Sopenharmony_ci		return -EIO;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	return mbx->ops->write(hw, msg, size, mbx_id);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/**
558c2ecf20Sopenharmony_ci *  ixgbe_check_for_msg - checks to see if someone sent us mail
568c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
578c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to check
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
608c2ecf20Sopenharmony_ci **/
618c2ecf20Sopenharmony_cis32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	if (!mbx->ops)
668c2ecf20Sopenharmony_ci		return -EIO;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	return mbx->ops->check_for_msg(hw, mbx_id);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci/**
728c2ecf20Sopenharmony_ci *  ixgbe_check_for_ack - checks to see if someone sent us ACK
738c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
748c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to check
758c2ecf20Sopenharmony_ci *
768c2ecf20Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
778c2ecf20Sopenharmony_ci **/
788c2ecf20Sopenharmony_cis32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	if (!mbx->ops)
838c2ecf20Sopenharmony_ci		return -EIO;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	return mbx->ops->check_for_ack(hw, mbx_id);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/**
898c2ecf20Sopenharmony_ci *  ixgbe_check_for_rst - checks to see if other side has reset
908c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
918c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to check
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci *  returns SUCCESS if the Status bit was found or else ERR_MBX
948c2ecf20Sopenharmony_ci **/
958c2ecf20Sopenharmony_cis32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	if (!mbx->ops)
1008c2ecf20Sopenharmony_ci		return -EIO;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	return mbx->ops->check_for_rst(hw, mbx_id);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/**
1068c2ecf20Sopenharmony_ci *  ixgbe_poll_for_msg - Wait for message notification
1078c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
1088c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to write
1098c2ecf20Sopenharmony_ci *
1108c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully received a message notification
1118c2ecf20Sopenharmony_ci **/
1128c2ecf20Sopenharmony_cistatic s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
1158c2ecf20Sopenharmony_ci	int countdown = mbx->timeout;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	if (!countdown || !mbx->ops)
1188c2ecf20Sopenharmony_ci		return -EIO;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	while (mbx->ops->check_for_msg(hw, mbx_id)) {
1218c2ecf20Sopenharmony_ci		countdown--;
1228c2ecf20Sopenharmony_ci		if (!countdown)
1238c2ecf20Sopenharmony_ci			return -EIO;
1248c2ecf20Sopenharmony_ci		udelay(mbx->usec_delay);
1258c2ecf20Sopenharmony_ci	}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	return 0;
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci/**
1318c2ecf20Sopenharmony_ci *  ixgbe_poll_for_ack - Wait for message acknowledgement
1328c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
1338c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to write
1348c2ecf20Sopenharmony_ci *
1358c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully received a message acknowledgement
1368c2ecf20Sopenharmony_ci **/
1378c2ecf20Sopenharmony_cistatic s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
1408c2ecf20Sopenharmony_ci	int countdown = mbx->timeout;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	if (!countdown || !mbx->ops)
1438c2ecf20Sopenharmony_ci		return -EIO;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	while (mbx->ops->check_for_ack(hw, mbx_id)) {
1468c2ecf20Sopenharmony_ci		countdown--;
1478c2ecf20Sopenharmony_ci		if (!countdown)
1488c2ecf20Sopenharmony_ci			return -EIO;
1498c2ecf20Sopenharmony_ci		udelay(mbx->usec_delay);
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return 0;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/**
1568c2ecf20Sopenharmony_ci *  ixgbe_read_posted_mbx - Wait for message notification and receive message
1578c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
1588c2ecf20Sopenharmony_ci *  @msg: The message buffer
1598c2ecf20Sopenharmony_ci *  @size: Length of buffer
1608c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to write
1618c2ecf20Sopenharmony_ci *
1628c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully received a message notification and
1638c2ecf20Sopenharmony_ci *  copied it into the receive buffer.
1648c2ecf20Sopenharmony_ci **/
1658c2ecf20Sopenharmony_cistatic s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
1668c2ecf20Sopenharmony_ci				 u16 mbx_id)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
1698c2ecf20Sopenharmony_ci	s32 ret_val;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (!mbx->ops)
1728c2ecf20Sopenharmony_ci		return -EIO;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
1758c2ecf20Sopenharmony_ci	if (ret_val)
1768c2ecf20Sopenharmony_ci		return ret_val;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	/* if ack received read message */
1798c2ecf20Sopenharmony_ci	return mbx->ops->read(hw, msg, size, mbx_id);
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/**
1838c2ecf20Sopenharmony_ci *  ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
1848c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
1858c2ecf20Sopenharmony_ci *  @msg: The message buffer
1868c2ecf20Sopenharmony_ci *  @size: Length of buffer
1878c2ecf20Sopenharmony_ci *  @mbx_id: id of mailbox to write
1888c2ecf20Sopenharmony_ci *
1898c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer and
1908c2ecf20Sopenharmony_ci *  received an ack to that message within delay * timeout period
1918c2ecf20Sopenharmony_ci **/
1928c2ecf20Sopenharmony_cistatic s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
1938c2ecf20Sopenharmony_ci			   u16 mbx_id)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
1968c2ecf20Sopenharmony_ci	s32 ret_val;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	/* exit if either we can't write or there isn't a defined timeout */
1998c2ecf20Sopenharmony_ci	if (!mbx->ops || !mbx->timeout)
2008c2ecf20Sopenharmony_ci		return -EIO;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	/* send msg */
2038c2ecf20Sopenharmony_ci	ret_val = mbx->ops->write(hw, msg, size, mbx_id);
2048c2ecf20Sopenharmony_ci	if (ret_val)
2058c2ecf20Sopenharmony_ci		return ret_val;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* if msg sent wait until we receive an ack */
2088c2ecf20Sopenharmony_ci	return ixgbe_poll_for_ack(hw, mbx_id);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (mbvficr & mask) {
2168c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
2178c2ecf20Sopenharmony_ci		return 0;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	return -EIO;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci/**
2248c2ecf20Sopenharmony_ci *  ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
2258c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
2268c2ecf20Sopenharmony_ci *  @vf_number: the VF index
2278c2ecf20Sopenharmony_ci *
2288c2ecf20Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
2298c2ecf20Sopenharmony_ci **/
2308c2ecf20Sopenharmony_cistatic s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
2338c2ecf20Sopenharmony_ci	u32 vf_bit = vf_number % 16;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
2368c2ecf20Sopenharmony_ci				    index)) {
2378c2ecf20Sopenharmony_ci		hw->mbx.stats.reqs++;
2388c2ecf20Sopenharmony_ci		return 0;
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	return -EIO;
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci/**
2458c2ecf20Sopenharmony_ci *  ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
2468c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
2478c2ecf20Sopenharmony_ci *  @vf_number: the VF index
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
2508c2ecf20Sopenharmony_ci **/
2518c2ecf20Sopenharmony_cistatic s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
2548c2ecf20Sopenharmony_ci	u32 vf_bit = vf_number % 16;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
2578c2ecf20Sopenharmony_ci				    index)) {
2588c2ecf20Sopenharmony_ci		hw->mbx.stats.acks++;
2598c2ecf20Sopenharmony_ci		return 0;
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	return -EIO;
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci/**
2668c2ecf20Sopenharmony_ci *  ixgbe_check_for_rst_pf - checks to see if the VF has reset
2678c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
2688c2ecf20Sopenharmony_ci *  @vf_number: the VF index
2698c2ecf20Sopenharmony_ci *
2708c2ecf20Sopenharmony_ci *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
2718c2ecf20Sopenharmony_ci **/
2728c2ecf20Sopenharmony_cistatic s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
2738c2ecf20Sopenharmony_ci{
2748c2ecf20Sopenharmony_ci	u32 reg_offset = (vf_number < 32) ? 0 : 1;
2758c2ecf20Sopenharmony_ci	u32 vf_shift = vf_number % 32;
2768c2ecf20Sopenharmony_ci	u32 vflre = 0;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	switch (hw->mac.type) {
2798c2ecf20Sopenharmony_ci	case ixgbe_mac_82599EB:
2808c2ecf20Sopenharmony_ci		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
2818c2ecf20Sopenharmony_ci		break;
2828c2ecf20Sopenharmony_ci	case ixgbe_mac_X540:
2838c2ecf20Sopenharmony_ci	case ixgbe_mac_X550:
2848c2ecf20Sopenharmony_ci	case ixgbe_mac_X550EM_x:
2858c2ecf20Sopenharmony_ci	case ixgbe_mac_x550em_a:
2868c2ecf20Sopenharmony_ci		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
2878c2ecf20Sopenharmony_ci		break;
2888c2ecf20Sopenharmony_ci	default:
2898c2ecf20Sopenharmony_ci		break;
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (vflre & BIT(vf_shift)) {
2938c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), BIT(vf_shift));
2948c2ecf20Sopenharmony_ci		hw->mbx.stats.rsts++;
2958c2ecf20Sopenharmony_ci		return 0;
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	return -EIO;
2998c2ecf20Sopenharmony_ci}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci/**
3028c2ecf20Sopenharmony_ci *  ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
3038c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
3048c2ecf20Sopenharmony_ci *  @vf_number: the VF index
3058c2ecf20Sopenharmony_ci *
3068c2ecf20Sopenharmony_ci *  return SUCCESS if we obtained the mailbox lock
3078c2ecf20Sopenharmony_ci **/
3088c2ecf20Sopenharmony_cistatic s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
3098c2ecf20Sopenharmony_ci{
3108c2ecf20Sopenharmony_ci	u32 p2v_mailbox;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	/* Take ownership of the buffer */
3138c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	/* reserve mailbox for vf use */
3168c2ecf20Sopenharmony_ci	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
3178c2ecf20Sopenharmony_ci	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
3188c2ecf20Sopenharmony_ci		return 0;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	return -EIO;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci/**
3248c2ecf20Sopenharmony_ci *  ixgbe_write_mbx_pf - Places a message in the mailbox
3258c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
3268c2ecf20Sopenharmony_ci *  @msg: The message buffer
3278c2ecf20Sopenharmony_ci *  @size: Length of buffer
3288c2ecf20Sopenharmony_ci *  @vf_number: the VF index
3298c2ecf20Sopenharmony_ci *
3308c2ecf20Sopenharmony_ci *  returns SUCCESS if it successfully copied message into the buffer
3318c2ecf20Sopenharmony_ci **/
3328c2ecf20Sopenharmony_cistatic s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
3338c2ecf20Sopenharmony_ci			      u16 vf_number)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	s32 ret_val;
3368c2ecf20Sopenharmony_ci	u16 i;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	/* lock the mailbox to prevent pf/vf race condition */
3398c2ecf20Sopenharmony_ci	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
3408c2ecf20Sopenharmony_ci	if (ret_val)
3418c2ecf20Sopenharmony_ci		return ret_val;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	/* flush msg and acks as we are overwriting the message buffer */
3448c2ecf20Sopenharmony_ci	ixgbe_check_for_msg_pf(hw, vf_number);
3458c2ecf20Sopenharmony_ci	ixgbe_check_for_ack_pf(hw, vf_number);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	/* copy the caller specified message to the mailbox memory buffer */
3488c2ecf20Sopenharmony_ci	for (i = 0; i < size; i++)
3498c2ecf20Sopenharmony_ci		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/* Interrupt VF to tell it a message has been sent and release buffer*/
3528c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	/* update stats */
3558c2ecf20Sopenharmony_ci	hw->mbx.stats.msgs_tx++;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return 0;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci/**
3618c2ecf20Sopenharmony_ci *  ixgbe_read_mbx_pf - Read a message from the mailbox
3628c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
3638c2ecf20Sopenharmony_ci *  @msg: The message buffer
3648c2ecf20Sopenharmony_ci *  @size: Length of buffer
3658c2ecf20Sopenharmony_ci *  @vf_number: the VF index
3668c2ecf20Sopenharmony_ci *
3678c2ecf20Sopenharmony_ci *  This function copies a message from the mailbox buffer to the caller's
3688c2ecf20Sopenharmony_ci *  memory buffer.  The presumption is that the caller knows that there was
3698c2ecf20Sopenharmony_ci *  a message due to a VF request so no polling for message is needed.
3708c2ecf20Sopenharmony_ci **/
3718c2ecf20Sopenharmony_cistatic s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
3728c2ecf20Sopenharmony_ci			     u16 vf_number)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	s32 ret_val;
3758c2ecf20Sopenharmony_ci	u16 i;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	/* lock the mailbox to prevent pf/vf race condition */
3788c2ecf20Sopenharmony_ci	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
3798c2ecf20Sopenharmony_ci	if (ret_val)
3808c2ecf20Sopenharmony_ci		return ret_val;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	/* copy the message to the mailbox memory buffer */
3838c2ecf20Sopenharmony_ci	for (i = 0; i < size; i++)
3848c2ecf20Sopenharmony_ci		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	/* Acknowledge the message and release buffer */
3878c2ecf20Sopenharmony_ci	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	/* update stats */
3908c2ecf20Sopenharmony_ci	hw->mbx.stats.msgs_rx++;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	return 0;
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV
3968c2ecf20Sopenharmony_ci/**
3978c2ecf20Sopenharmony_ci *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
3988c2ecf20Sopenharmony_ci *  @hw: pointer to the HW structure
3998c2ecf20Sopenharmony_ci *
4008c2ecf20Sopenharmony_ci *  Initializes the hw->mbx struct to correct values for pf mailbox
4018c2ecf20Sopenharmony_ci */
4028c2ecf20Sopenharmony_civoid ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	struct ixgbe_mbx_info *mbx = &hw->mbx;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	if (hw->mac.type != ixgbe_mac_82599EB &&
4078c2ecf20Sopenharmony_ci	    hw->mac.type != ixgbe_mac_X550 &&
4088c2ecf20Sopenharmony_ci	    hw->mac.type != ixgbe_mac_X550EM_x &&
4098c2ecf20Sopenharmony_ci	    hw->mac.type != ixgbe_mac_x550em_a &&
4108c2ecf20Sopenharmony_ci	    hw->mac.type != ixgbe_mac_X540)
4118c2ecf20Sopenharmony_ci		return;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	mbx->timeout = 0;
4148c2ecf20Sopenharmony_ci	mbx->usec_delay = 0;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	mbx->stats.msgs_tx = 0;
4178c2ecf20Sopenharmony_ci	mbx->stats.msgs_rx = 0;
4188c2ecf20Sopenharmony_ci	mbx->stats.reqs = 0;
4198c2ecf20Sopenharmony_ci	mbx->stats.acks = 0;
4208c2ecf20Sopenharmony_ci	mbx->stats.rsts = 0;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	mbx->size = IXGBE_VFMAILBOX_SIZE;
4238c2ecf20Sopenharmony_ci}
4248c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI_IOV */
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ciconst struct ixgbe_mbx_operations mbx_ops_generic = {
4278c2ecf20Sopenharmony_ci	.read                   = ixgbe_read_mbx_pf,
4288c2ecf20Sopenharmony_ci	.write                  = ixgbe_write_mbx_pf,
4298c2ecf20Sopenharmony_ci	.read_posted            = ixgbe_read_posted_mbx,
4308c2ecf20Sopenharmony_ci	.write_posted           = ixgbe_write_posted_mbx,
4318c2ecf20Sopenharmony_ci	.check_for_msg          = ixgbe_check_for_msg_pf,
4328c2ecf20Sopenharmony_ci	.check_for_ack          = ixgbe_check_for_ack_pf,
4338c2ecf20Sopenharmony_ci	.check_for_rst          = ixgbe_check_for_rst_pf,
4348c2ecf20Sopenharmony_ci};
4358c2ecf20Sopenharmony_ci
436