162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "mbx.h" 562306a36Sopenharmony_ci#include "ixgbevf.h" 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/** 862306a36Sopenharmony_ci * ixgbevf_poll_for_msg - Wait for message notification 962306a36Sopenharmony_ci * @hw: pointer to the HW structure 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * returns 0 if it successfully received a message notification 1262306a36Sopenharmony_ci **/ 1362306a36Sopenharmony_cistatic s32 ixgbevf_poll_for_msg(struct ixgbe_hw *hw) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct ixgbe_mbx_info *mbx = &hw->mbx; 1662306a36Sopenharmony_ci int countdown = mbx->timeout; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci if (!countdown || !mbx->ops.check_for_msg) 1962306a36Sopenharmony_ci return IXGBE_ERR_CONFIG; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci while (countdown && mbx->ops.check_for_msg(hw)) { 2262306a36Sopenharmony_ci countdown--; 2362306a36Sopenharmony_ci udelay(mbx->udelay); 2462306a36Sopenharmony_ci } 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci return countdown ? 0 : IXGBE_ERR_TIMEOUT; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/** 3062306a36Sopenharmony_ci * ixgbevf_poll_for_ack - Wait for message acknowledgment 3162306a36Sopenharmony_ci * @hw: pointer to the HW structure 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * returns 0 if it successfully received a message acknowledgment 3462306a36Sopenharmony_ci **/ 3562306a36Sopenharmony_cistatic s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct ixgbe_mbx_info *mbx = &hw->mbx; 3862306a36Sopenharmony_ci int countdown = mbx->timeout; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (!countdown || !mbx->ops.check_for_ack) 4162306a36Sopenharmony_ci return IXGBE_ERR_CONFIG; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci while (countdown && mbx->ops.check_for_ack(hw)) { 4462306a36Sopenharmony_ci countdown--; 4562306a36Sopenharmony_ci udelay(mbx->udelay); 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci return countdown ? 0 : IXGBE_ERR_TIMEOUT; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/** 5262306a36Sopenharmony_ci * ixgbevf_read_mailbox_vf - read VF's mailbox register 5362306a36Sopenharmony_ci * @hw: pointer to the HW structure 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * This function is used to read the mailbox register dedicated for VF without 5662306a36Sopenharmony_ci * losing the read to clear status bits. 5762306a36Sopenharmony_ci **/ 5862306a36Sopenharmony_cistatic u32 ixgbevf_read_mailbox_vf(struct ixgbe_hw *hw) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci u32 vf_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci vf_mailbox |= hw->mbx.vf_mailbox; 6362306a36Sopenharmony_ci hw->mbx.vf_mailbox |= vf_mailbox & IXGBE_VFMAILBOX_R2C_BITS; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return vf_mailbox; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/** 6962306a36Sopenharmony_ci * ixgbevf_clear_msg_vf - clear PF status bit 7062306a36Sopenharmony_ci * @hw: pointer to the HW structure 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * This function is used to clear PFSTS bit in the VFMAILBOX register 7362306a36Sopenharmony_ci **/ 7462306a36Sopenharmony_cistatic void ixgbevf_clear_msg_vf(struct ixgbe_hw *hw) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci u32 vf_mailbox = ixgbevf_read_mailbox_vf(hw); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (vf_mailbox & IXGBE_VFMAILBOX_PFSTS) { 7962306a36Sopenharmony_ci hw->mbx.stats.reqs++; 8062306a36Sopenharmony_ci hw->mbx.vf_mailbox &= ~IXGBE_VFMAILBOX_PFSTS; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/** 8562306a36Sopenharmony_ci * ixgbevf_clear_ack_vf - clear PF ACK bit 8662306a36Sopenharmony_ci * @hw: pointer to the HW structure 8762306a36Sopenharmony_ci * 8862306a36Sopenharmony_ci * This function is used to clear PFACK bit in the VFMAILBOX register 8962306a36Sopenharmony_ci **/ 9062306a36Sopenharmony_cistatic void ixgbevf_clear_ack_vf(struct ixgbe_hw *hw) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci u32 vf_mailbox = ixgbevf_read_mailbox_vf(hw); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (vf_mailbox & IXGBE_VFMAILBOX_PFACK) { 9562306a36Sopenharmony_ci hw->mbx.stats.acks++; 9662306a36Sopenharmony_ci hw->mbx.vf_mailbox &= ~IXGBE_VFMAILBOX_PFACK; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/** 10162306a36Sopenharmony_ci * ixgbevf_clear_rst_vf - clear PF reset bit 10262306a36Sopenharmony_ci * @hw: pointer to the HW structure 10362306a36Sopenharmony_ci * 10462306a36Sopenharmony_ci * This function is used to clear reset indication and reset done bit in 10562306a36Sopenharmony_ci * VFMAILBOX register after reset the shared resources and the reset sequence. 10662306a36Sopenharmony_ci **/ 10762306a36Sopenharmony_cistatic void ixgbevf_clear_rst_vf(struct ixgbe_hw *hw) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci u32 vf_mailbox = ixgbevf_read_mailbox_vf(hw); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (vf_mailbox & (IXGBE_VFMAILBOX_RSTI | IXGBE_VFMAILBOX_RSTD)) { 11262306a36Sopenharmony_ci hw->mbx.stats.rsts++; 11362306a36Sopenharmony_ci hw->mbx.vf_mailbox &= ~(IXGBE_VFMAILBOX_RSTI | 11462306a36Sopenharmony_ci IXGBE_VFMAILBOX_RSTD); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/** 11962306a36Sopenharmony_ci * ixgbevf_check_for_bit_vf - Determine if a status bit was set 12062306a36Sopenharmony_ci * @hw: pointer to the HW structure 12162306a36Sopenharmony_ci * @mask: bitmask for bits to be tested and cleared 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * This function is used to check for the read to clear bits within 12462306a36Sopenharmony_ci * the V2P mailbox. 12562306a36Sopenharmony_ci **/ 12662306a36Sopenharmony_cistatic s32 ixgbevf_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci u32 vf_mailbox = ixgbevf_read_mailbox_vf(hw); 12962306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_MBX; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (vf_mailbox & mask) 13262306a36Sopenharmony_ci ret_val = 0; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return ret_val; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/** 13862306a36Sopenharmony_ci * ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail 13962306a36Sopenharmony_ci * @hw: pointer to the HW structure 14062306a36Sopenharmony_ci * 14162306a36Sopenharmony_ci * returns 0 if the PF has set the Status bit or else ERR_MBX 14262306a36Sopenharmony_ci **/ 14362306a36Sopenharmony_cistatic s32 ixgbevf_check_for_msg_vf(struct ixgbe_hw *hw) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_MBX; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { 14862306a36Sopenharmony_ci ret_val = 0; 14962306a36Sopenharmony_ci hw->mbx.stats.reqs++; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return ret_val; 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/** 15662306a36Sopenharmony_ci * ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd 15762306a36Sopenharmony_ci * @hw: pointer to the HW structure 15862306a36Sopenharmony_ci * 15962306a36Sopenharmony_ci * returns 0 if the PF has set the ACK bit or else ERR_MBX 16062306a36Sopenharmony_ci **/ 16162306a36Sopenharmony_cistatic s32 ixgbevf_check_for_ack_vf(struct ixgbe_hw *hw) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_MBX; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { 16662306a36Sopenharmony_ci ret_val = 0; 16762306a36Sopenharmony_ci ixgbevf_clear_ack_vf(hw); 16862306a36Sopenharmony_ci hw->mbx.stats.acks++; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return ret_val; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/** 17562306a36Sopenharmony_ci * ixgbevf_check_for_rst_vf - checks to see if the PF has reset 17662306a36Sopenharmony_ci * @hw: pointer to the HW structure 17762306a36Sopenharmony_ci * 17862306a36Sopenharmony_ci * returns true if the PF has set the reset done bit or else false 17962306a36Sopenharmony_ci **/ 18062306a36Sopenharmony_cistatic s32 ixgbevf_check_for_rst_vf(struct ixgbe_hw *hw) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_MBX; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (!ixgbevf_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | 18562306a36Sopenharmony_ci IXGBE_VFMAILBOX_RSTI))) { 18662306a36Sopenharmony_ci ret_val = 0; 18762306a36Sopenharmony_ci ixgbevf_clear_rst_vf(hw); 18862306a36Sopenharmony_ci hw->mbx.stats.rsts++; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return ret_val; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/** 19562306a36Sopenharmony_ci * ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock 19662306a36Sopenharmony_ci * @hw: pointer to the HW structure 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * return 0 if we obtained the mailbox lock 19962306a36Sopenharmony_ci **/ 20062306a36Sopenharmony_cistatic s32 ixgbevf_obtain_mbx_lock_vf(struct ixgbe_hw *hw) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci struct ixgbe_mbx_info *mbx = &hw->mbx; 20362306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_CONFIG; 20462306a36Sopenharmony_ci int countdown = mbx->timeout; 20562306a36Sopenharmony_ci u32 vf_mailbox; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (!mbx->timeout) 20862306a36Sopenharmony_ci return ret_val; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci while (countdown--) { 21162306a36Sopenharmony_ci /* Reserve mailbox for VF use */ 21262306a36Sopenharmony_ci vf_mailbox = ixgbevf_read_mailbox_vf(hw); 21362306a36Sopenharmony_ci vf_mailbox |= IXGBE_VFMAILBOX_VFU; 21462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* Verify that VF is the owner of the lock */ 21762306a36Sopenharmony_ci if (ixgbevf_read_mailbox_vf(hw) & IXGBE_VFMAILBOX_VFU) { 21862306a36Sopenharmony_ci ret_val = 0; 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* Wait a bit before trying again */ 22362306a36Sopenharmony_ci udelay(mbx->udelay); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (ret_val) 22762306a36Sopenharmony_ci ret_val = IXGBE_ERR_TIMEOUT; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci return ret_val; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci/** 23362306a36Sopenharmony_ci * ixgbevf_release_mbx_lock_vf - release mailbox lock 23462306a36Sopenharmony_ci * @hw: pointer to the HW structure 23562306a36Sopenharmony_ci **/ 23662306a36Sopenharmony_cistatic void ixgbevf_release_mbx_lock_vf(struct ixgbe_hw *hw) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci u32 vf_mailbox; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* Return ownership of the buffer */ 24162306a36Sopenharmony_ci vf_mailbox = ixgbevf_read_mailbox_vf(hw); 24262306a36Sopenharmony_ci vf_mailbox &= ~IXGBE_VFMAILBOX_VFU; 24362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/** 24762306a36Sopenharmony_ci * ixgbevf_release_mbx_lock_vf_legacy - release mailbox lock 24862306a36Sopenharmony_ci * @hw: pointer to the HW structure 24962306a36Sopenharmony_ci **/ 25062306a36Sopenharmony_cistatic void ixgbevf_release_mbx_lock_vf_legacy(struct ixgbe_hw *__always_unused hw) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci/** 25562306a36Sopenharmony_ci * ixgbevf_write_mbx_vf - Write a message to the mailbox 25662306a36Sopenharmony_ci * @hw: pointer to the HW structure 25762306a36Sopenharmony_ci * @msg: The message buffer 25862306a36Sopenharmony_ci * @size: Length of buffer 25962306a36Sopenharmony_ci * 26062306a36Sopenharmony_ci * returns 0 if it successfully copied message into the buffer 26162306a36Sopenharmony_ci **/ 26262306a36Sopenharmony_cistatic s32 ixgbevf_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci u32 vf_mailbox; 26562306a36Sopenharmony_ci s32 ret_val; 26662306a36Sopenharmony_ci u16 i; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* lock the mailbox to prevent PF/VF race condition */ 26962306a36Sopenharmony_ci ret_val = ixgbevf_obtain_mbx_lock_vf(hw); 27062306a36Sopenharmony_ci if (ret_val) 27162306a36Sopenharmony_ci goto out_no_write; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* flush msg and acks as we are overwriting the message buffer */ 27462306a36Sopenharmony_ci ixgbevf_clear_msg_vf(hw); 27562306a36Sopenharmony_ci ixgbevf_clear_ack_vf(hw); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* copy the caller specified message to the mailbox memory buffer */ 27862306a36Sopenharmony_ci for (i = 0; i < size; i++) 27962306a36Sopenharmony_ci IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* update stats */ 28262306a36Sopenharmony_ci hw->mbx.stats.msgs_tx++; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* interrupt the PF to tell it a message has been sent */ 28562306a36Sopenharmony_ci vf_mailbox = ixgbevf_read_mailbox_vf(hw); 28662306a36Sopenharmony_ci vf_mailbox |= IXGBE_VFMAILBOX_REQ; 28762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* if msg sent wait until we receive an ack */ 29062306a36Sopenharmony_ci ret_val = ixgbevf_poll_for_ack(hw); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciout_no_write: 29362306a36Sopenharmony_ci hw->mbx.ops.release(hw); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci return ret_val; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci/** 29962306a36Sopenharmony_ci * ixgbevf_write_mbx_vf_legacy - Write a message to the mailbox 30062306a36Sopenharmony_ci * @hw: pointer to the HW structure 30162306a36Sopenharmony_ci * @msg: The message buffer 30262306a36Sopenharmony_ci * @size: Length of buffer 30362306a36Sopenharmony_ci * 30462306a36Sopenharmony_ci * returns 0 if it successfully copied message into the buffer 30562306a36Sopenharmony_ci **/ 30662306a36Sopenharmony_cistatic s32 ixgbevf_write_mbx_vf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci s32 ret_val; 30962306a36Sopenharmony_ci u16 i; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* lock the mailbox to prevent PF/VF race condition */ 31262306a36Sopenharmony_ci ret_val = ixgbevf_obtain_mbx_lock_vf(hw); 31362306a36Sopenharmony_ci if (ret_val) 31462306a36Sopenharmony_ci goto out_no_write; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* flush msg and acks as we are overwriting the message buffer */ 31762306a36Sopenharmony_ci ixgbevf_check_for_msg_vf(hw); 31862306a36Sopenharmony_ci ixgbevf_clear_msg_vf(hw); 31962306a36Sopenharmony_ci ixgbevf_check_for_ack_vf(hw); 32062306a36Sopenharmony_ci ixgbevf_clear_ack_vf(hw); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci /* copy the caller specified message to the mailbox memory buffer */ 32362306a36Sopenharmony_ci for (i = 0; i < size; i++) 32462306a36Sopenharmony_ci IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* update stats */ 32762306a36Sopenharmony_ci hw->mbx.stats.msgs_tx++; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* Drop VFU and interrupt the PF to tell it a message has been sent */ 33062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ciout_no_write: 33362306a36Sopenharmony_ci return ret_val; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/** 33762306a36Sopenharmony_ci * ixgbevf_read_mbx_vf - Reads a message from the inbox intended for VF 33862306a36Sopenharmony_ci * @hw: pointer to the HW structure 33962306a36Sopenharmony_ci * @msg: The message buffer 34062306a36Sopenharmony_ci * @size: Length of buffer 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci * returns 0 if it successfully read message from buffer 34362306a36Sopenharmony_ci **/ 34462306a36Sopenharmony_cistatic s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci u32 vf_mailbox; 34762306a36Sopenharmony_ci s32 ret_val; 34862306a36Sopenharmony_ci u16 i; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* check if there is a message from PF */ 35162306a36Sopenharmony_ci ret_val = ixgbevf_check_for_msg_vf(hw); 35262306a36Sopenharmony_ci if (ret_val) 35362306a36Sopenharmony_ci return ret_val; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci ixgbevf_clear_msg_vf(hw); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* copy the message from the mailbox memory buffer */ 35862306a36Sopenharmony_ci for (i = 0; i < size; i++) 35962306a36Sopenharmony_ci msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Acknowledge receipt */ 36262306a36Sopenharmony_ci vf_mailbox = ixgbevf_read_mailbox_vf(hw); 36362306a36Sopenharmony_ci vf_mailbox |= IXGBE_VFMAILBOX_ACK; 36462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, vf_mailbox); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* update stats */ 36762306a36Sopenharmony_ci hw->mbx.stats.msgs_rx++; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return ret_val; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci/** 37362306a36Sopenharmony_ci * ixgbevf_read_mbx_vf_legacy - Reads a message from the inbox intended for VF 37462306a36Sopenharmony_ci * @hw: pointer to the HW structure 37562306a36Sopenharmony_ci * @msg: The message buffer 37662306a36Sopenharmony_ci * @size: Length of buffer 37762306a36Sopenharmony_ci * 37862306a36Sopenharmony_ci * returns 0 if it successfully read message from buffer 37962306a36Sopenharmony_ci **/ 38062306a36Sopenharmony_cistatic s32 ixgbevf_read_mbx_vf_legacy(struct ixgbe_hw *hw, u32 *msg, u16 size) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci s32 ret_val = 0; 38362306a36Sopenharmony_ci u16 i; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* lock the mailbox to prevent PF/VF race condition */ 38662306a36Sopenharmony_ci ret_val = ixgbevf_obtain_mbx_lock_vf(hw); 38762306a36Sopenharmony_ci if (ret_val) 38862306a36Sopenharmony_ci goto out_no_read; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* copy the message from the mailbox memory buffer */ 39162306a36Sopenharmony_ci for (i = 0; i < size; i++) 39262306a36Sopenharmony_ci msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* Acknowledge receipt and release mailbox, then we're done */ 39562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci /* update stats */ 39862306a36Sopenharmony_ci hw->mbx.stats.msgs_rx++; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ciout_no_read: 40162306a36Sopenharmony_ci return ret_val; 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci/** 40562306a36Sopenharmony_ci * ixgbevf_init_mbx_params_vf - set initial values for VF mailbox 40662306a36Sopenharmony_ci * @hw: pointer to the HW structure 40762306a36Sopenharmony_ci * 40862306a36Sopenharmony_ci * Initializes the hw->mbx struct to correct values for VF mailbox 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_cistatic s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci struct ixgbe_mbx_info *mbx = &hw->mbx; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci /* start mailbox as timed out and let the reset_hw call set the timeout 41562306a36Sopenharmony_ci * value to begin communications 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_ci mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; 41862306a36Sopenharmony_ci mbx->udelay = IXGBE_VF_MBX_INIT_DELAY; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci mbx->size = IXGBE_VFMAILBOX_SIZE; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci mbx->stats.msgs_tx = 0; 42362306a36Sopenharmony_ci mbx->stats.msgs_rx = 0; 42462306a36Sopenharmony_ci mbx->stats.reqs = 0; 42562306a36Sopenharmony_ci mbx->stats.acks = 0; 42662306a36Sopenharmony_ci mbx->stats.rsts = 0; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci return 0; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci/** 43262306a36Sopenharmony_ci * ixgbevf_poll_mbx - Wait for message and read it from the mailbox 43362306a36Sopenharmony_ci * @hw: pointer to the HW structure 43462306a36Sopenharmony_ci * @msg: The message buffer 43562306a36Sopenharmony_ci * @size: Length of buffer 43662306a36Sopenharmony_ci * 43762306a36Sopenharmony_ci * returns 0 if it successfully read message from buffer 43862306a36Sopenharmony_ci **/ 43962306a36Sopenharmony_cis32 ixgbevf_poll_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci struct ixgbe_mbx_info *mbx = &hw->mbx; 44262306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_CONFIG; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (!mbx->ops.read || !mbx->ops.check_for_msg || !mbx->timeout) 44562306a36Sopenharmony_ci return ret_val; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* limit read to size of mailbox */ 44862306a36Sopenharmony_ci if (size > mbx->size) 44962306a36Sopenharmony_ci size = mbx->size; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci ret_val = ixgbevf_poll_for_msg(hw); 45262306a36Sopenharmony_ci /* if ack received read message, otherwise we timed out */ 45362306a36Sopenharmony_ci if (!ret_val) 45462306a36Sopenharmony_ci ret_val = mbx->ops.read(hw, msg, size); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci return ret_val; 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci/** 46062306a36Sopenharmony_ci * ixgbevf_write_mbx - Write a message to the mailbox and wait for ACK 46162306a36Sopenharmony_ci * @hw: pointer to the HW structure 46262306a36Sopenharmony_ci * @msg: The message buffer 46362306a36Sopenharmony_ci * @size: Length of buffer 46462306a36Sopenharmony_ci * 46562306a36Sopenharmony_ci * returns 0 if it successfully copied message into the buffer and 46662306a36Sopenharmony_ci * received an ACK to that message within specified period 46762306a36Sopenharmony_ci **/ 46862306a36Sopenharmony_cis32 ixgbevf_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci struct ixgbe_mbx_info *mbx = &hw->mbx; 47162306a36Sopenharmony_ci s32 ret_val = IXGBE_ERR_CONFIG; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /** 47462306a36Sopenharmony_ci * exit if either we can't write, release 47562306a36Sopenharmony_ci * or there is no timeout defined 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_ci if (!mbx->ops.write || !mbx->ops.check_for_ack || !mbx->ops.release || 47862306a36Sopenharmony_ci !mbx->timeout) 47962306a36Sopenharmony_ci return ret_val; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (size > mbx->size) 48262306a36Sopenharmony_ci ret_val = IXGBE_ERR_PARAM; 48362306a36Sopenharmony_ci else 48462306a36Sopenharmony_ci ret_val = mbx->ops.write(hw, msg, size); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci return ret_val; 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ciconst struct ixgbe_mbx_operations ixgbevf_mbx_ops = { 49062306a36Sopenharmony_ci .init_params = ixgbevf_init_mbx_params_vf, 49162306a36Sopenharmony_ci .release = ixgbevf_release_mbx_lock_vf, 49262306a36Sopenharmony_ci .read = ixgbevf_read_mbx_vf, 49362306a36Sopenharmony_ci .write = ixgbevf_write_mbx_vf, 49462306a36Sopenharmony_ci .check_for_msg = ixgbevf_check_for_msg_vf, 49562306a36Sopenharmony_ci .check_for_ack = ixgbevf_check_for_ack_vf, 49662306a36Sopenharmony_ci .check_for_rst = ixgbevf_check_for_rst_vf, 49762306a36Sopenharmony_ci}; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ciconst struct ixgbe_mbx_operations ixgbevf_mbx_ops_legacy = { 50062306a36Sopenharmony_ci .init_params = ixgbevf_init_mbx_params_vf, 50162306a36Sopenharmony_ci .release = ixgbevf_release_mbx_lock_vf_legacy, 50262306a36Sopenharmony_ci .read = ixgbevf_read_mbx_vf_legacy, 50362306a36Sopenharmony_ci .write = ixgbevf_write_mbx_vf_legacy, 50462306a36Sopenharmony_ci .check_for_msg = ixgbevf_check_for_msg_vf, 50562306a36Sopenharmony_ci .check_for_ack = ixgbevf_check_for_ack_vf, 50662306a36Sopenharmony_ci .check_for_rst = ixgbevf_check_for_rst_vf, 50762306a36Sopenharmony_ci}; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci/* Mailbox operations when running on Hyper-V. 51062306a36Sopenharmony_ci * On Hyper-V, PF/VF communication is not through the 51162306a36Sopenharmony_ci * hardware mailbox; this communication is through 51262306a36Sopenharmony_ci * a software mediated path. 51362306a36Sopenharmony_ci * Most mail box operations are noop while running on 51462306a36Sopenharmony_ci * Hyper-V. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ciconst struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops = { 51762306a36Sopenharmony_ci .init_params = ixgbevf_init_mbx_params_vf, 51862306a36Sopenharmony_ci .check_for_rst = ixgbevf_check_for_rst_vf, 51962306a36Sopenharmony_ci}; 520