1ae06c70bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0 2*51dce24bSJeff Kirsher /* Copyright(c) 2009 - 2018 Intel Corporation. */ 3dee1ad47SJeff Kirsher 4dee1ad47SJeff Kirsher #include "mbx.h" 5dee1ad47SJeff Kirsher 6dee1ad47SJeff Kirsher /** 7dee1ad47SJeff Kirsher * e1000_poll_for_msg - Wait for message notification 8dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 9dee1ad47SJeff Kirsher * 10dee1ad47SJeff Kirsher * returns SUCCESS if it successfully received a message notification 11dee1ad47SJeff Kirsher **/ 12dee1ad47SJeff Kirsher static s32 e1000_poll_for_msg(struct e1000_hw *hw) 13dee1ad47SJeff Kirsher { 14dee1ad47SJeff Kirsher struct e1000_mbx_info *mbx = &hw->mbx; 15dee1ad47SJeff Kirsher int countdown = mbx->timeout; 16dee1ad47SJeff Kirsher 17dee1ad47SJeff Kirsher if (!mbx->ops.check_for_msg) 18dee1ad47SJeff Kirsher goto out; 19dee1ad47SJeff Kirsher 20dee1ad47SJeff Kirsher while (countdown && mbx->ops.check_for_msg(hw)) { 21dee1ad47SJeff Kirsher countdown--; 22dee1ad47SJeff Kirsher udelay(mbx->usec_delay); 23dee1ad47SJeff Kirsher } 24dee1ad47SJeff Kirsher 25dee1ad47SJeff Kirsher /* if we failed, all future posted messages fail until reset */ 26dee1ad47SJeff Kirsher if (!countdown) 27dee1ad47SJeff Kirsher mbx->timeout = 0; 28dee1ad47SJeff Kirsher out: 29dee1ad47SJeff Kirsher return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; 30dee1ad47SJeff Kirsher } 31dee1ad47SJeff Kirsher 32dee1ad47SJeff Kirsher /** 330340501bSJeff Kirsher * e1000_poll_for_ack - Wait for message acknowledgment 34dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 35dee1ad47SJeff Kirsher * 360340501bSJeff Kirsher * returns SUCCESS if it successfully received a message acknowledgment 37dee1ad47SJeff Kirsher **/ 38dee1ad47SJeff Kirsher static s32 e1000_poll_for_ack(struct e1000_hw *hw) 39dee1ad47SJeff Kirsher { 40dee1ad47SJeff Kirsher struct e1000_mbx_info *mbx = &hw->mbx; 41dee1ad47SJeff Kirsher int countdown = mbx->timeout; 42dee1ad47SJeff Kirsher 43dee1ad47SJeff Kirsher if (!mbx->ops.check_for_ack) 44dee1ad47SJeff Kirsher goto out; 45dee1ad47SJeff Kirsher 46dee1ad47SJeff Kirsher while (countdown && mbx->ops.check_for_ack(hw)) { 47dee1ad47SJeff Kirsher countdown--; 48dee1ad47SJeff Kirsher udelay(mbx->usec_delay); 49dee1ad47SJeff Kirsher } 50dee1ad47SJeff Kirsher 51dee1ad47SJeff Kirsher /* if we failed, all future posted messages fail until reset */ 52dee1ad47SJeff Kirsher if (!countdown) 53dee1ad47SJeff Kirsher mbx->timeout = 0; 54dee1ad47SJeff Kirsher out: 55dee1ad47SJeff Kirsher return countdown ? E1000_SUCCESS : -E1000_ERR_MBX; 56dee1ad47SJeff Kirsher } 57dee1ad47SJeff Kirsher 58dee1ad47SJeff Kirsher /** 59dee1ad47SJeff Kirsher * e1000_read_posted_mbx - Wait for message notification and receive message 60dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 61dee1ad47SJeff Kirsher * @msg: The message buffer 62dee1ad47SJeff Kirsher * @size: Length of buffer 63dee1ad47SJeff Kirsher * 64dee1ad47SJeff Kirsher * returns SUCCESS if it successfully received a message notification and 65dee1ad47SJeff Kirsher * copied it into the receive buffer. 66dee1ad47SJeff Kirsher **/ 67dee1ad47SJeff Kirsher static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size) 68dee1ad47SJeff Kirsher { 69dee1ad47SJeff Kirsher struct e1000_mbx_info *mbx = &hw->mbx; 70dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 71dee1ad47SJeff Kirsher 72dee1ad47SJeff Kirsher if (!mbx->ops.read) 73dee1ad47SJeff Kirsher goto out; 74dee1ad47SJeff Kirsher 75dee1ad47SJeff Kirsher ret_val = e1000_poll_for_msg(hw); 76dee1ad47SJeff Kirsher 77dee1ad47SJeff Kirsher /* if ack received read message, otherwise we timed out */ 78dee1ad47SJeff Kirsher if (!ret_val) 79dee1ad47SJeff Kirsher ret_val = mbx->ops.read(hw, msg, size); 80dee1ad47SJeff Kirsher out: 81dee1ad47SJeff Kirsher return ret_val; 82dee1ad47SJeff Kirsher } 83dee1ad47SJeff Kirsher 84dee1ad47SJeff Kirsher /** 85dee1ad47SJeff Kirsher * e1000_write_posted_mbx - Write a message to the mailbox, wait for ack 86dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 87dee1ad47SJeff Kirsher * @msg: The message buffer 88dee1ad47SJeff Kirsher * @size: Length of buffer 89dee1ad47SJeff Kirsher * 90dee1ad47SJeff Kirsher * returns SUCCESS if it successfully copied message into the buffer and 91dee1ad47SJeff Kirsher * received an ack to that message within delay * timeout period 92dee1ad47SJeff Kirsher **/ 93dee1ad47SJeff Kirsher static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size) 94dee1ad47SJeff Kirsher { 95dee1ad47SJeff Kirsher struct e1000_mbx_info *mbx = &hw->mbx; 96dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 97dee1ad47SJeff Kirsher 98dee1ad47SJeff Kirsher /* exit if we either can't write or there isn't a defined timeout */ 99dee1ad47SJeff Kirsher if (!mbx->ops.write || !mbx->timeout) 100dee1ad47SJeff Kirsher goto out; 101dee1ad47SJeff Kirsher 102dee1ad47SJeff Kirsher /* send msg*/ 103dee1ad47SJeff Kirsher ret_val = mbx->ops.write(hw, msg, size); 104dee1ad47SJeff Kirsher 105dee1ad47SJeff Kirsher /* if msg sent wait until we receive an ack */ 106dee1ad47SJeff Kirsher if (!ret_val) 107dee1ad47SJeff Kirsher ret_val = e1000_poll_for_ack(hw); 108dee1ad47SJeff Kirsher out: 109dee1ad47SJeff Kirsher return ret_val; 110dee1ad47SJeff Kirsher } 111dee1ad47SJeff Kirsher 112dee1ad47SJeff Kirsher /** 113dee1ad47SJeff Kirsher * e1000_read_v2p_mailbox - read v2p mailbox 114dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 115dee1ad47SJeff Kirsher * 116dee1ad47SJeff Kirsher * This function is used to read the v2p mailbox without losing the read to 117dee1ad47SJeff Kirsher * clear status bits. 118dee1ad47SJeff Kirsher **/ 119dee1ad47SJeff Kirsher static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw) 120dee1ad47SJeff Kirsher { 121dee1ad47SJeff Kirsher u32 v2p_mailbox = er32(V2PMAILBOX(0)); 122dee1ad47SJeff Kirsher 123dee1ad47SJeff Kirsher v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox; 124dee1ad47SJeff Kirsher hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS; 125dee1ad47SJeff Kirsher 126dee1ad47SJeff Kirsher return v2p_mailbox; 127dee1ad47SJeff Kirsher } 128dee1ad47SJeff Kirsher 129dee1ad47SJeff Kirsher /** 130dee1ad47SJeff Kirsher * e1000_check_for_bit_vf - Determine if a status bit was set 131dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 132dee1ad47SJeff Kirsher * @mask: bitmask for bits to be tested and cleared 133dee1ad47SJeff Kirsher * 134dee1ad47SJeff Kirsher * This function is used to check for the read to clear bits within 135dee1ad47SJeff Kirsher * the V2P mailbox. 136dee1ad47SJeff Kirsher **/ 137dee1ad47SJeff Kirsher static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask) 138dee1ad47SJeff Kirsher { 139dee1ad47SJeff Kirsher u32 v2p_mailbox = e1000_read_v2p_mailbox(hw); 140dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 141dee1ad47SJeff Kirsher 142dee1ad47SJeff Kirsher if (v2p_mailbox & mask) 143dee1ad47SJeff Kirsher ret_val = E1000_SUCCESS; 144dee1ad47SJeff Kirsher 145dee1ad47SJeff Kirsher hw->dev_spec.vf.v2p_mailbox &= ~mask; 146dee1ad47SJeff Kirsher 147dee1ad47SJeff Kirsher return ret_val; 148dee1ad47SJeff Kirsher } 149dee1ad47SJeff Kirsher 150dee1ad47SJeff Kirsher /** 151dee1ad47SJeff Kirsher * e1000_check_for_msg_vf - checks to see if the PF has sent mail 152dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 153dee1ad47SJeff Kirsher * 154dee1ad47SJeff Kirsher * returns SUCCESS if the PF has set the Status bit or else ERR_MBX 155dee1ad47SJeff Kirsher **/ 156dee1ad47SJeff Kirsher static s32 e1000_check_for_msg_vf(struct e1000_hw *hw) 157dee1ad47SJeff Kirsher { 158dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 159dee1ad47SJeff Kirsher 160dee1ad47SJeff Kirsher if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) { 161dee1ad47SJeff Kirsher ret_val = E1000_SUCCESS; 162dee1ad47SJeff Kirsher hw->mbx.stats.reqs++; 163dee1ad47SJeff Kirsher } 164dee1ad47SJeff Kirsher 165dee1ad47SJeff Kirsher return ret_val; 166dee1ad47SJeff Kirsher } 167dee1ad47SJeff Kirsher 168dee1ad47SJeff Kirsher /** 169dee1ad47SJeff Kirsher * e1000_check_for_ack_vf - checks to see if the PF has ACK'd 170dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 171dee1ad47SJeff Kirsher * 172dee1ad47SJeff Kirsher * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX 173dee1ad47SJeff Kirsher **/ 174dee1ad47SJeff Kirsher static s32 e1000_check_for_ack_vf(struct e1000_hw *hw) 175dee1ad47SJeff Kirsher { 176dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 177dee1ad47SJeff Kirsher 178dee1ad47SJeff Kirsher if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) { 179dee1ad47SJeff Kirsher ret_val = E1000_SUCCESS; 180dee1ad47SJeff Kirsher hw->mbx.stats.acks++; 181dee1ad47SJeff Kirsher } 182dee1ad47SJeff Kirsher 183dee1ad47SJeff Kirsher return ret_val; 184dee1ad47SJeff Kirsher } 185dee1ad47SJeff Kirsher 186dee1ad47SJeff Kirsher /** 187dee1ad47SJeff Kirsher * e1000_check_for_rst_vf - checks to see if the PF has reset 188dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 189dee1ad47SJeff Kirsher * 190dee1ad47SJeff Kirsher * returns true if the PF has set the reset done bit or else false 191dee1ad47SJeff Kirsher **/ 192dee1ad47SJeff Kirsher static s32 e1000_check_for_rst_vf(struct e1000_hw *hw) 193dee1ad47SJeff Kirsher { 194dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 195dee1ad47SJeff Kirsher 196dee1ad47SJeff Kirsher if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD | 197dee1ad47SJeff Kirsher E1000_V2PMAILBOX_RSTI))) { 198dee1ad47SJeff Kirsher ret_val = E1000_SUCCESS; 199dee1ad47SJeff Kirsher hw->mbx.stats.rsts++; 200dee1ad47SJeff Kirsher } 201dee1ad47SJeff Kirsher 202dee1ad47SJeff Kirsher return ret_val; 203dee1ad47SJeff Kirsher } 204dee1ad47SJeff Kirsher 205dee1ad47SJeff Kirsher /** 206dee1ad47SJeff Kirsher * e1000_obtain_mbx_lock_vf - obtain mailbox lock 207dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 208dee1ad47SJeff Kirsher * 209dee1ad47SJeff Kirsher * return SUCCESS if we obtained the mailbox lock 210dee1ad47SJeff Kirsher **/ 211dee1ad47SJeff Kirsher static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw) 212dee1ad47SJeff Kirsher { 213dee1ad47SJeff Kirsher s32 ret_val = -E1000_ERR_MBX; 2149ce0e8d7SMitch Williams int count = 10; 215dee1ad47SJeff Kirsher 2169ce0e8d7SMitch Williams do { 217dee1ad47SJeff Kirsher /* Take ownership of the buffer */ 218dee1ad47SJeff Kirsher ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU); 219dee1ad47SJeff Kirsher 2200340501bSJeff Kirsher /* reserve mailbox for VF use */ 2219ce0e8d7SMitch Williams if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) { 2229ce0e8d7SMitch Williams ret_val = 0; 2239ce0e8d7SMitch Williams break; 2249ce0e8d7SMitch Williams } 2259ce0e8d7SMitch Williams udelay(1000); 2269ce0e8d7SMitch Williams } while (count-- > 0); 227dee1ad47SJeff Kirsher 228dee1ad47SJeff Kirsher return ret_val; 229dee1ad47SJeff Kirsher } 230dee1ad47SJeff Kirsher 231dee1ad47SJeff Kirsher /** 232dee1ad47SJeff Kirsher * e1000_write_mbx_vf - Write a message to the mailbox 233dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 234dee1ad47SJeff Kirsher * @msg: The message buffer 235dee1ad47SJeff Kirsher * @size: Length of buffer 236dee1ad47SJeff Kirsher * 237dee1ad47SJeff Kirsher * returns SUCCESS if it successfully copied message into the buffer 238dee1ad47SJeff Kirsher **/ 239dee1ad47SJeff Kirsher static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size) 240dee1ad47SJeff Kirsher { 241dee1ad47SJeff Kirsher s32 err; 242dee1ad47SJeff Kirsher u16 i; 243dee1ad47SJeff Kirsher 24432652c2aSGreg Edwards WARN_ON_ONCE(!spin_is_locked(&hw->mbx_lock)); 24532652c2aSGreg Edwards 246dee1ad47SJeff Kirsher /* lock the mailbox to prevent pf/vf race condition */ 247dee1ad47SJeff Kirsher err = e1000_obtain_mbx_lock_vf(hw); 248dee1ad47SJeff Kirsher if (err) 249dee1ad47SJeff Kirsher goto out_no_write; 250dee1ad47SJeff Kirsher 251dee1ad47SJeff Kirsher /* flush any ack or msg as we are going to overwrite mailbox */ 252dee1ad47SJeff Kirsher e1000_check_for_ack_vf(hw); 253dee1ad47SJeff Kirsher e1000_check_for_msg_vf(hw); 254dee1ad47SJeff Kirsher 255dee1ad47SJeff Kirsher /* copy the caller specified message to the mailbox memory buffer */ 256dee1ad47SJeff Kirsher for (i = 0; i < size; i++) 257dee1ad47SJeff Kirsher array_ew32(VMBMEM(0), i, msg[i]); 258dee1ad47SJeff Kirsher 259dee1ad47SJeff Kirsher /* update stats */ 260dee1ad47SJeff Kirsher hw->mbx.stats.msgs_tx++; 261dee1ad47SJeff Kirsher 262dee1ad47SJeff Kirsher /* Drop VFU and interrupt the PF to tell it a message has been sent */ 263dee1ad47SJeff Kirsher ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ); 264dee1ad47SJeff Kirsher 265dee1ad47SJeff Kirsher out_no_write: 266dee1ad47SJeff Kirsher return err; 267dee1ad47SJeff Kirsher } 268dee1ad47SJeff Kirsher 269dee1ad47SJeff Kirsher /** 2700340501bSJeff Kirsher * e1000_read_mbx_vf - Reads a message from the inbox intended for VF 271dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 272dee1ad47SJeff Kirsher * @msg: The message buffer 273dee1ad47SJeff Kirsher * @size: Length of buffer 274dee1ad47SJeff Kirsher * 2758a9ea323SLinus Torvalds * returns SUCCESS if it successfully read message from buffer 276dee1ad47SJeff Kirsher **/ 277dee1ad47SJeff Kirsher static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size) 278dee1ad47SJeff Kirsher { 279dee1ad47SJeff Kirsher s32 err; 280dee1ad47SJeff Kirsher u16 i; 281dee1ad47SJeff Kirsher 28232652c2aSGreg Edwards WARN_ON_ONCE(!spin_is_locked(&hw->mbx_lock)); 28332652c2aSGreg Edwards 284dee1ad47SJeff Kirsher /* lock the mailbox to prevent pf/vf race condition */ 285dee1ad47SJeff Kirsher err = e1000_obtain_mbx_lock_vf(hw); 286dee1ad47SJeff Kirsher if (err) 287dee1ad47SJeff Kirsher goto out_no_read; 288dee1ad47SJeff Kirsher 289dee1ad47SJeff Kirsher /* copy the message from the mailbox memory buffer */ 290dee1ad47SJeff Kirsher for (i = 0; i < size; i++) 291dee1ad47SJeff Kirsher msg[i] = array_er32(VMBMEM(0), i); 292dee1ad47SJeff Kirsher 293dee1ad47SJeff Kirsher /* Acknowledge receipt and release mailbox, then we're done */ 294dee1ad47SJeff Kirsher ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK); 295dee1ad47SJeff Kirsher 296dee1ad47SJeff Kirsher /* update stats */ 297dee1ad47SJeff Kirsher hw->mbx.stats.msgs_rx++; 298dee1ad47SJeff Kirsher 299dee1ad47SJeff Kirsher out_no_read: 300dee1ad47SJeff Kirsher return err; 301dee1ad47SJeff Kirsher } 302dee1ad47SJeff Kirsher 303dee1ad47SJeff Kirsher /** 3040340501bSJeff Kirsher * e1000_init_mbx_params_vf - set initial values for VF mailbox 305dee1ad47SJeff Kirsher * @hw: pointer to the HW structure 306dee1ad47SJeff Kirsher * 3070340501bSJeff Kirsher * Initializes the hw->mbx struct to correct values for VF mailbox 308dee1ad47SJeff Kirsher */ 309dee1ad47SJeff Kirsher s32 e1000_init_mbx_params_vf(struct e1000_hw *hw) 310dee1ad47SJeff Kirsher { 311dee1ad47SJeff Kirsher struct e1000_mbx_info *mbx = &hw->mbx; 312dee1ad47SJeff Kirsher 313dee1ad47SJeff Kirsher /* start mailbox as timed out and let the reset_hw call set the timeout 3140340501bSJeff Kirsher * value to being communications 3150340501bSJeff Kirsher */ 316dee1ad47SJeff Kirsher mbx->timeout = 0; 317dee1ad47SJeff Kirsher mbx->usec_delay = E1000_VF_MBX_INIT_DELAY; 318dee1ad47SJeff Kirsher 319dee1ad47SJeff Kirsher mbx->size = E1000_VFMAILBOX_SIZE; 320dee1ad47SJeff Kirsher 321dee1ad47SJeff Kirsher mbx->ops.read = e1000_read_mbx_vf; 322dee1ad47SJeff Kirsher mbx->ops.write = e1000_write_mbx_vf; 323dee1ad47SJeff Kirsher mbx->ops.read_posted = e1000_read_posted_mbx; 324dee1ad47SJeff Kirsher mbx->ops.write_posted = e1000_write_posted_mbx; 325dee1ad47SJeff Kirsher mbx->ops.check_for_msg = e1000_check_for_msg_vf; 326dee1ad47SJeff Kirsher mbx->ops.check_for_ack = e1000_check_for_ack_vf; 327dee1ad47SJeff Kirsher mbx->ops.check_for_rst = e1000_check_for_rst_vf; 328dee1ad47SJeff Kirsher 329dee1ad47SJeff Kirsher mbx->stats.msgs_tx = 0; 330dee1ad47SJeff Kirsher mbx->stats.msgs_rx = 0; 331dee1ad47SJeff Kirsher mbx->stats.reqs = 0; 332dee1ad47SJeff Kirsher mbx->stats.acks = 0; 333dee1ad47SJeff Kirsher mbx->stats.rsts = 0; 334dee1ad47SJeff Kirsher 335dee1ad47SJeff Kirsher return E1000_SUCCESS; 336dee1ad47SJeff Kirsher } 337