18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2007 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "e1000_mbx.h" 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/** 78c2ecf20Sopenharmony_ci * igb_read_mbx - Reads a message from the mailbox 88c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 98c2ecf20Sopenharmony_ci * @msg: The message buffer 108c2ecf20Sopenharmony_ci * @size: Length of buffer 118c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to read 128c2ecf20Sopenharmony_ci * @unlock: skip locking or not 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * returns SUCCESS if it successfully read message from buffer 158c2ecf20Sopenharmony_ci **/ 168c2ecf20Sopenharmony_cis32 igb_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id, 178c2ecf20Sopenharmony_ci bool unlock) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 208c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_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.read) 278c2ecf20Sopenharmony_ci ret_val = mbx->ops.read(hw, msg, size, mbx_id, unlock); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci return ret_val; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/** 338c2ecf20Sopenharmony_ci * igb_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 igb_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 448c2ecf20Sopenharmony_ci s32 ret_val = 0; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (size > mbx->size) 478c2ecf20Sopenharmony_ci ret_val = -E1000_ERR_MBX; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci else if (mbx->ops.write) 508c2ecf20Sopenharmony_ci ret_val = mbx->ops.write(hw, msg, size, mbx_id); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return ret_val; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/** 568c2ecf20Sopenharmony_ci * igb_check_for_msg - checks to see if someone sent us mail 578c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 588c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to check 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * returns SUCCESS if the Status bit was found or else ERR_MBX 618c2ecf20Sopenharmony_ci **/ 628c2ecf20Sopenharmony_cis32 igb_check_for_msg(struct e1000_hw *hw, u16 mbx_id) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 658c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci if (mbx->ops.check_for_msg) 688c2ecf20Sopenharmony_ci ret_val = mbx->ops.check_for_msg(hw, mbx_id); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return ret_val; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/** 748c2ecf20Sopenharmony_ci * igb_check_for_ack - checks to see if someone sent us ACK 758c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 768c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to check 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * returns SUCCESS if the Status bit was found or else ERR_MBX 798c2ecf20Sopenharmony_ci **/ 808c2ecf20Sopenharmony_cis32 igb_check_for_ack(struct e1000_hw *hw, u16 mbx_id) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 838c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (mbx->ops.check_for_ack) 868c2ecf20Sopenharmony_ci ret_val = mbx->ops.check_for_ack(hw, mbx_id); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return ret_val; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/** 928c2ecf20Sopenharmony_ci * igb_check_for_rst - checks to see if other side has reset 938c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 948c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to check 958c2ecf20Sopenharmony_ci * 968c2ecf20Sopenharmony_ci * returns SUCCESS if the Status bit was found or else ERR_MBX 978c2ecf20Sopenharmony_ci **/ 988c2ecf20Sopenharmony_cis32 igb_check_for_rst(struct e1000_hw *hw, u16 mbx_id) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 1018c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (mbx->ops.check_for_rst) 1048c2ecf20Sopenharmony_ci ret_val = mbx->ops.check_for_rst(hw, mbx_id); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return ret_val; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/** 1108c2ecf20Sopenharmony_ci * igb_unlock_mbx - unlock the mailbox 1118c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 1128c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to check 1138c2ecf20Sopenharmony_ci * 1148c2ecf20Sopenharmony_ci * returns SUCCESS if the mailbox was unlocked or else ERR_MBX 1158c2ecf20Sopenharmony_ci **/ 1168c2ecf20Sopenharmony_cis32 igb_unlock_mbx(struct e1000_hw *hw, u16 mbx_id) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 1198c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (mbx->ops.unlock) 1228c2ecf20Sopenharmony_ci ret_val = mbx->ops.unlock(hw, mbx_id); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return ret_val; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/** 1288c2ecf20Sopenharmony_ci * igb_poll_for_msg - Wait for message notification 1298c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 1308c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to write 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * returns SUCCESS if it successfully received a message notification 1338c2ecf20Sopenharmony_ci **/ 1348c2ecf20Sopenharmony_cistatic s32 igb_poll_for_msg(struct e1000_hw *hw, u16 mbx_id) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 1378c2ecf20Sopenharmony_ci int countdown = mbx->timeout; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (!countdown || !mbx->ops.check_for_msg) 1408c2ecf20Sopenharmony_ci goto out; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { 1438c2ecf20Sopenharmony_ci countdown--; 1448c2ecf20Sopenharmony_ci if (!countdown) 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci udelay(mbx->usec_delay); 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* if we failed, all future posted messages fail until reset */ 1508c2ecf20Sopenharmony_ci if (!countdown) 1518c2ecf20Sopenharmony_ci mbx->timeout = 0; 1528c2ecf20Sopenharmony_ciout: 1538c2ecf20Sopenharmony_ci return countdown ? 0 : -E1000_ERR_MBX; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci/** 1578c2ecf20Sopenharmony_ci * igb_poll_for_ack - Wait for message acknowledgement 1588c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 1598c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to write 1608c2ecf20Sopenharmony_ci * 1618c2ecf20Sopenharmony_ci * returns SUCCESS if it successfully received a message acknowledgement 1628c2ecf20Sopenharmony_ci **/ 1638c2ecf20Sopenharmony_cistatic s32 igb_poll_for_ack(struct e1000_hw *hw, u16 mbx_id) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 1668c2ecf20Sopenharmony_ci int countdown = mbx->timeout; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (!countdown || !mbx->ops.check_for_ack) 1698c2ecf20Sopenharmony_ci goto out; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { 1728c2ecf20Sopenharmony_ci countdown--; 1738c2ecf20Sopenharmony_ci if (!countdown) 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci udelay(mbx->usec_delay); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* if we failed, all future posted messages fail until reset */ 1798c2ecf20Sopenharmony_ci if (!countdown) 1808c2ecf20Sopenharmony_ci mbx->timeout = 0; 1818c2ecf20Sopenharmony_ciout: 1828c2ecf20Sopenharmony_ci return countdown ? 0 : -E1000_ERR_MBX; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci/** 1868c2ecf20Sopenharmony_ci * igb_read_posted_mbx - Wait for message notification and receive message 1878c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 1888c2ecf20Sopenharmony_ci * @msg: The message buffer 1898c2ecf20Sopenharmony_ci * @size: Length of buffer 1908c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to write 1918c2ecf20Sopenharmony_ci * 1928c2ecf20Sopenharmony_ci * returns SUCCESS if it successfully received a message notification and 1938c2ecf20Sopenharmony_ci * copied it into the receive buffer. 1948c2ecf20Sopenharmony_ci **/ 1958c2ecf20Sopenharmony_cistatic s32 igb_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, 1968c2ecf20Sopenharmony_ci u16 mbx_id) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 1998c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci if (!mbx->ops.read) 2028c2ecf20Sopenharmony_ci goto out; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci ret_val = igb_poll_for_msg(hw, mbx_id); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (!ret_val) 2078c2ecf20Sopenharmony_ci ret_val = mbx->ops.read(hw, msg, size, mbx_id, true); 2088c2ecf20Sopenharmony_ciout: 2098c2ecf20Sopenharmony_ci return ret_val; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/** 2138c2ecf20Sopenharmony_ci * igb_write_posted_mbx - Write a message to the mailbox, wait for ack 2148c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2158c2ecf20Sopenharmony_ci * @msg: The message buffer 2168c2ecf20Sopenharmony_ci * @size: Length of buffer 2178c2ecf20Sopenharmony_ci * @mbx_id: id of mailbox to write 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * returns SUCCESS if it successfully copied message into the buffer and 2208c2ecf20Sopenharmony_ci * received an ack to that message within delay * timeout period 2218c2ecf20Sopenharmony_ci **/ 2228c2ecf20Sopenharmony_cistatic s32 igb_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, 2238c2ecf20Sopenharmony_ci u16 mbx_id) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 2268c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* exit if either we can't write or there isn't a defined timeout */ 2298c2ecf20Sopenharmony_ci if (!mbx->ops.write || !mbx->timeout) 2308c2ecf20Sopenharmony_ci goto out; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* send msg */ 2338c2ecf20Sopenharmony_ci ret_val = mbx->ops.write(hw, msg, size, mbx_id); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* if msg sent wait until we receive an ack */ 2368c2ecf20Sopenharmony_ci if (!ret_val) 2378c2ecf20Sopenharmony_ci ret_val = igb_poll_for_ack(hw, mbx_id); 2388c2ecf20Sopenharmony_ciout: 2398c2ecf20Sopenharmony_ci return ret_val; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic s32 igb_check_for_bit_pf(struct e1000_hw *hw, u32 mask) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci u32 mbvficr = rd32(E1000_MBVFICR); 2458c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (mbvficr & mask) { 2488c2ecf20Sopenharmony_ci ret_val = 0; 2498c2ecf20Sopenharmony_ci wr32(E1000_MBVFICR, mask); 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci return ret_val; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci/** 2568c2ecf20Sopenharmony_ci * igb_check_for_msg_pf - checks to see if the VF has sent mail 2578c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2588c2ecf20Sopenharmony_ci * @vf_number: the VF index 2598c2ecf20Sopenharmony_ci * 2608c2ecf20Sopenharmony_ci * returns SUCCESS if the VF has set the Status bit or else ERR_MBX 2618c2ecf20Sopenharmony_ci **/ 2628c2ecf20Sopenharmony_cistatic s32 igb_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) { 2678c2ecf20Sopenharmony_ci ret_val = 0; 2688c2ecf20Sopenharmony_ci hw->mbx.stats.reqs++; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return ret_val; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci/** 2758c2ecf20Sopenharmony_ci * igb_check_for_ack_pf - checks to see if the VF has ACKed 2768c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2778c2ecf20Sopenharmony_ci * @vf_number: the VF index 2788c2ecf20Sopenharmony_ci * 2798c2ecf20Sopenharmony_ci * returns SUCCESS if the VF has set the Status bit or else ERR_MBX 2808c2ecf20Sopenharmony_ci **/ 2818c2ecf20Sopenharmony_cistatic s32 igb_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (!igb_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) { 2868c2ecf20Sopenharmony_ci ret_val = 0; 2878c2ecf20Sopenharmony_ci hw->mbx.stats.acks++; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return ret_val; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/** 2948c2ecf20Sopenharmony_ci * igb_check_for_rst_pf - checks to see if the VF has reset 2958c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2968c2ecf20Sopenharmony_ci * @vf_number: the VF index 2978c2ecf20Sopenharmony_ci * 2988c2ecf20Sopenharmony_ci * returns SUCCESS if the VF has set the Status bit or else ERR_MBX 2998c2ecf20Sopenharmony_ci **/ 3008c2ecf20Sopenharmony_cistatic s32 igb_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci u32 vflre = rd32(E1000_VFLRE); 3038c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (vflre & BIT(vf_number)) { 3068c2ecf20Sopenharmony_ci ret_val = 0; 3078c2ecf20Sopenharmony_ci wr32(E1000_VFLRE, BIT(vf_number)); 3088c2ecf20Sopenharmony_ci hw->mbx.stats.rsts++; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return ret_val; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/** 3158c2ecf20Sopenharmony_ci * igb_obtain_mbx_lock_pf - obtain mailbox lock 3168c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 3178c2ecf20Sopenharmony_ci * @vf_number: the VF index 3188c2ecf20Sopenharmony_ci * 3198c2ecf20Sopenharmony_ci * return SUCCESS if we obtained the mailbox lock 3208c2ecf20Sopenharmony_ci **/ 3218c2ecf20Sopenharmony_cistatic s32 igb_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci s32 ret_val = -E1000_ERR_MBX; 3248c2ecf20Sopenharmony_ci u32 p2v_mailbox; 3258c2ecf20Sopenharmony_ci int count = 10; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci do { 3288c2ecf20Sopenharmony_ci /* Take ownership of the buffer */ 3298c2ecf20Sopenharmony_ci wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* reserve mailbox for vf use */ 3328c2ecf20Sopenharmony_ci p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); 3338c2ecf20Sopenharmony_ci if (p2v_mailbox & E1000_P2VMAILBOX_PFU) { 3348c2ecf20Sopenharmony_ci ret_val = 0; 3358c2ecf20Sopenharmony_ci break; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci udelay(1000); 3388c2ecf20Sopenharmony_ci } while (count-- > 0); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci return ret_val; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/** 3448c2ecf20Sopenharmony_ci * igb_release_mbx_lock_pf - release mailbox lock 3458c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 3468c2ecf20Sopenharmony_ci * @vf_number: the VF index 3478c2ecf20Sopenharmony_ci * 3488c2ecf20Sopenharmony_ci * return SUCCESS if we released the mailbox lock 3498c2ecf20Sopenharmony_ci **/ 3508c2ecf20Sopenharmony_cistatic s32 igb_release_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci u32 p2v_mailbox; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* drop PF lock of mailbox, if set */ 3558c2ecf20Sopenharmony_ci p2v_mailbox = rd32(E1000_P2VMAILBOX(vf_number)); 3568c2ecf20Sopenharmony_ci if (p2v_mailbox & E1000_P2VMAILBOX_PFU) 3578c2ecf20Sopenharmony_ci wr32(E1000_P2VMAILBOX(vf_number), 3588c2ecf20Sopenharmony_ci p2v_mailbox & ~E1000_P2VMAILBOX_PFU); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci return 0; 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci/** 3648c2ecf20Sopenharmony_ci * igb_write_mbx_pf - Places a message in the mailbox 3658c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 3668c2ecf20Sopenharmony_ci * @msg: The message buffer 3678c2ecf20Sopenharmony_ci * @size: Length of buffer 3688c2ecf20Sopenharmony_ci * @vf_number: the VF index 3698c2ecf20Sopenharmony_ci * 3708c2ecf20Sopenharmony_ci * returns SUCCESS if it successfully copied message into the buffer 3718c2ecf20Sopenharmony_ci **/ 3728c2ecf20Sopenharmony_cistatic s32 igb_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, 3738c2ecf20Sopenharmony_ci u16 vf_number) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci s32 ret_val; 3768c2ecf20Sopenharmony_ci u16 i; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* lock the mailbox to prevent pf/vf race condition */ 3798c2ecf20Sopenharmony_ci ret_val = igb_obtain_mbx_lock_pf(hw, vf_number); 3808c2ecf20Sopenharmony_ci if (ret_val) 3818c2ecf20Sopenharmony_ci goto out_no_write; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* flush msg and acks as we are overwriting the message buffer */ 3848c2ecf20Sopenharmony_ci igb_check_for_msg_pf(hw, vf_number); 3858c2ecf20Sopenharmony_ci igb_check_for_ack_pf(hw, vf_number); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* copy the caller specified message to the mailbox memory buffer */ 3888c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) 3898c2ecf20Sopenharmony_ci array_wr32(E1000_VMBMEM(vf_number), i, msg[i]); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* Interrupt VF to tell it a message has been sent and release buffer*/ 3928c2ecf20Sopenharmony_ci wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* update stats */ 3958c2ecf20Sopenharmony_ci hw->mbx.stats.msgs_tx++; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ciout_no_write: 3988c2ecf20Sopenharmony_ci return ret_val; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci/** 4038c2ecf20Sopenharmony_ci * igb_read_mbx_pf - Read a message from the mailbox 4048c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 4058c2ecf20Sopenharmony_ci * @msg: The message buffer 4068c2ecf20Sopenharmony_ci * @size: Length of buffer 4078c2ecf20Sopenharmony_ci * @vf_number: the VF index 4088c2ecf20Sopenharmony_ci * @unlock: unlock the mailbox when done? 4098c2ecf20Sopenharmony_ci * 4108c2ecf20Sopenharmony_ci * This function copies a message from the mailbox buffer to the caller's 4118c2ecf20Sopenharmony_ci * memory buffer. The presumption is that the caller knows that there was 4128c2ecf20Sopenharmony_ci * a message due to a VF request so no polling for message is needed. 4138c2ecf20Sopenharmony_ci **/ 4148c2ecf20Sopenharmony_cistatic s32 igb_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size, 4158c2ecf20Sopenharmony_ci u16 vf_number, bool unlock) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci s32 ret_val; 4188c2ecf20Sopenharmony_ci u16 i; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* lock the mailbox to prevent pf/vf race condition */ 4218c2ecf20Sopenharmony_ci ret_val = igb_obtain_mbx_lock_pf(hw, vf_number); 4228c2ecf20Sopenharmony_ci if (ret_val) 4238c2ecf20Sopenharmony_ci goto out_no_read; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* copy the message to the mailbox memory buffer */ 4268c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) 4278c2ecf20Sopenharmony_ci msg[i] = array_rd32(E1000_VMBMEM(vf_number), i); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci /* Acknowledge the message and release mailbox lock (or not) */ 4308c2ecf20Sopenharmony_ci if (unlock) 4318c2ecf20Sopenharmony_ci wr32(E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK); 4328c2ecf20Sopenharmony_ci else 4338c2ecf20Sopenharmony_ci wr32(E1000_P2VMAILBOX(vf_number), 4348c2ecf20Sopenharmony_ci E1000_P2VMAILBOX_ACK | E1000_P2VMAILBOX_PFU); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci /* update stats */ 4378c2ecf20Sopenharmony_ci hw->mbx.stats.msgs_rx++; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ciout_no_read: 4408c2ecf20Sopenharmony_ci return ret_val; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci/** 4448c2ecf20Sopenharmony_ci * e1000_init_mbx_params_pf - set initial values for pf mailbox 4458c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * Initializes the hw->mbx struct to correct values for pf mailbox 4488c2ecf20Sopenharmony_ci */ 4498c2ecf20Sopenharmony_cis32 igb_init_mbx_params_pf(struct e1000_hw *hw) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci struct e1000_mbx_info *mbx = &hw->mbx; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci mbx->timeout = 0; 4548c2ecf20Sopenharmony_ci mbx->usec_delay = 0; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci mbx->size = E1000_VFMAILBOX_SIZE; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci mbx->ops.read = igb_read_mbx_pf; 4598c2ecf20Sopenharmony_ci mbx->ops.write = igb_write_mbx_pf; 4608c2ecf20Sopenharmony_ci mbx->ops.read_posted = igb_read_posted_mbx; 4618c2ecf20Sopenharmony_ci mbx->ops.write_posted = igb_write_posted_mbx; 4628c2ecf20Sopenharmony_ci mbx->ops.check_for_msg = igb_check_for_msg_pf; 4638c2ecf20Sopenharmony_ci mbx->ops.check_for_ack = igb_check_for_ack_pf; 4648c2ecf20Sopenharmony_ci mbx->ops.check_for_rst = igb_check_for_rst_pf; 4658c2ecf20Sopenharmony_ci mbx->ops.unlock = igb_release_mbx_lock_pf; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci mbx->stats.msgs_tx = 0; 4688c2ecf20Sopenharmony_ci mbx->stats.msgs_rx = 0; 4698c2ecf20Sopenharmony_ci mbx->stats.reqs = 0; 4708c2ecf20Sopenharmony_ci mbx->stats.acks = 0; 4718c2ecf20Sopenharmony_ci mbx->stats.rsts = 0; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci return 0; 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 476