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