1215911Sjfv/****************************************************************************** 2215911Sjfv 3315333Serj Copyright (c) 2001-2017, Intel Corporation 4215911Sjfv All rights reserved. 5315333Serj 6315333Serj Redistribution and use in source and binary forms, with or without 7215911Sjfv modification, are permitted provided that the following conditions are met: 8315333Serj 9315333Serj 1. Redistributions of source code must retain the above copyright notice, 10215911Sjfv this list of conditions and the following disclaimer. 11315333Serj 12315333Serj 2. Redistributions in binary form must reproduce the above copyright 13315333Serj notice, this list of conditions and the following disclaimer in the 14215911Sjfv documentation and/or other materials provided with the distribution. 15315333Serj 16315333Serj 3. Neither the name of the Intel Corporation nor the names of its 17315333Serj contributors may be used to endorse or promote products derived from 18215911Sjfv this software without specific prior written permission. 19315333Serj 20215911Sjfv THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21315333Serj AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22315333Serj IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23315333Serj ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24315333Serj LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25315333Serj CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26315333Serj SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27315333Serj INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28315333Serj CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29215911Sjfv ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30215911Sjfv POSSIBILITY OF SUCH DAMAGE. 31215911Sjfv 32215911Sjfv******************************************************************************/ 33215911Sjfv/*$FreeBSD: stable/10/sys/dev/ixgbe/ixgbe_mbx.c 315333 2017-03-15 21:20:17Z erj $*/ 34215911Sjfv 35215911Sjfv#include "ixgbe_type.h" 36215911Sjfv#include "ixgbe_mbx.h" 37215911Sjfv 38215911Sjfv/** 39215911Sjfv * ixgbe_read_mbx - Reads a message from the mailbox 40215911Sjfv * @hw: pointer to the HW structure 41215911Sjfv * @msg: The message buffer 42215911Sjfv * @size: Length of buffer 43215911Sjfv * @mbx_id: id of mailbox to read 44215911Sjfv * 45215911Sjfv * returns SUCCESS if it successfuly read message from buffer 46215911Sjfv **/ 47215911Sjfvs32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 48215911Sjfv{ 49215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 50215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 51215911Sjfv 52215911Sjfv DEBUGFUNC("ixgbe_read_mbx"); 53215911Sjfv 54215911Sjfv /* limit read to size of mailbox */ 55215911Sjfv if (size > mbx->size) 56215911Sjfv size = mbx->size; 57215911Sjfv 58215911Sjfv if (mbx->ops.read) 59215911Sjfv ret_val = mbx->ops.read(hw, msg, size, mbx_id); 60215911Sjfv 61215911Sjfv return ret_val; 62215911Sjfv} 63215911Sjfv 64215911Sjfv/** 65215911Sjfv * ixgbe_write_mbx - Write a message to the mailbox 66215911Sjfv * @hw: pointer to the HW structure 67215911Sjfv * @msg: The message buffer 68215911Sjfv * @size: Length of buffer 69215911Sjfv * @mbx_id: id of mailbox to write 70215911Sjfv * 71215911Sjfv * returns SUCCESS if it successfully copied message into the buffer 72215911Sjfv **/ 73215911Sjfvs32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 74215911Sjfv{ 75215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 76215911Sjfv s32 ret_val = IXGBE_SUCCESS; 77215911Sjfv 78215911Sjfv DEBUGFUNC("ixgbe_write_mbx"); 79215911Sjfv 80283620Serj if (size > mbx->size) { 81215911Sjfv ret_val = IXGBE_ERR_MBX; 82283620Serj ERROR_REPORT2(IXGBE_ERROR_ARGUMENT, 83283620Serj "Invalid mailbox message size %d", size); 84283620Serj } else if (mbx->ops.write) 85215911Sjfv ret_val = mbx->ops.write(hw, msg, size, mbx_id); 86215911Sjfv 87215911Sjfv return ret_val; 88215911Sjfv} 89215911Sjfv 90215911Sjfv/** 91215911Sjfv * ixgbe_check_for_msg - checks to see if someone sent us mail 92215911Sjfv * @hw: pointer to the HW structure 93215911Sjfv * @mbx_id: id of mailbox to check 94215911Sjfv * 95215911Sjfv * returns SUCCESS if the Status bit was found or else ERR_MBX 96215911Sjfv **/ 97215911Sjfvs32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) 98215911Sjfv{ 99215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 100215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 101215911Sjfv 102215911Sjfv DEBUGFUNC("ixgbe_check_for_msg"); 103215911Sjfv 104215911Sjfv if (mbx->ops.check_for_msg) 105215911Sjfv ret_val = mbx->ops.check_for_msg(hw, mbx_id); 106215911Sjfv 107215911Sjfv return ret_val; 108215911Sjfv} 109215911Sjfv 110215911Sjfv/** 111215911Sjfv * ixgbe_check_for_ack - checks to see if someone sent us ACK 112215911Sjfv * @hw: pointer to the HW structure 113215911Sjfv * @mbx_id: id of mailbox to check 114215911Sjfv * 115215911Sjfv * returns SUCCESS if the Status bit was found or else ERR_MBX 116215911Sjfv **/ 117215911Sjfvs32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) 118215911Sjfv{ 119215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 120215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 121215911Sjfv 122215911Sjfv DEBUGFUNC("ixgbe_check_for_ack"); 123215911Sjfv 124215911Sjfv if (mbx->ops.check_for_ack) 125215911Sjfv ret_val = mbx->ops.check_for_ack(hw, mbx_id); 126215911Sjfv 127215911Sjfv return ret_val; 128215911Sjfv} 129215911Sjfv 130215911Sjfv/** 131215911Sjfv * ixgbe_check_for_rst - checks to see if other side has reset 132215911Sjfv * @hw: pointer to the HW structure 133215911Sjfv * @mbx_id: id of mailbox to check 134215911Sjfv * 135215911Sjfv * returns SUCCESS if the Status bit was found or else ERR_MBX 136215911Sjfv **/ 137215911Sjfvs32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) 138215911Sjfv{ 139215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 140215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 141215911Sjfv 142215911Sjfv DEBUGFUNC("ixgbe_check_for_rst"); 143215911Sjfv 144215911Sjfv if (mbx->ops.check_for_rst) 145215911Sjfv ret_val = mbx->ops.check_for_rst(hw, mbx_id); 146215911Sjfv 147215911Sjfv return ret_val; 148215911Sjfv} 149215911Sjfv 150215911Sjfv/** 151215911Sjfv * ixgbe_poll_for_msg - Wait for message notification 152215911Sjfv * @hw: pointer to the HW structure 153215911Sjfv * @mbx_id: id of mailbox to write 154215911Sjfv * 155215911Sjfv * returns SUCCESS if it successfully received a message notification 156215911Sjfv **/ 157215911Sjfvstatic s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) 158215911Sjfv{ 159215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 160215911Sjfv int countdown = mbx->timeout; 161215911Sjfv 162215911Sjfv DEBUGFUNC("ixgbe_poll_for_msg"); 163215911Sjfv 164215911Sjfv if (!countdown || !mbx->ops.check_for_msg) 165215911Sjfv goto out; 166215911Sjfv 167215911Sjfv while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { 168215911Sjfv countdown--; 169215911Sjfv if (!countdown) 170215911Sjfv break; 171215911Sjfv usec_delay(mbx->usec_delay); 172215911Sjfv } 173215911Sjfv 174283620Serj if (countdown == 0) 175283620Serj ERROR_REPORT2(IXGBE_ERROR_POLLING, 176283620Serj "Polling for VF%d mailbox message timedout", mbx_id); 177283620Serj 178215911Sjfvout: 179215911Sjfv return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; 180215911Sjfv} 181215911Sjfv 182215911Sjfv/** 183215911Sjfv * ixgbe_poll_for_ack - Wait for message acknowledgement 184215911Sjfv * @hw: pointer to the HW structure 185215911Sjfv * @mbx_id: id of mailbox to write 186215911Sjfv * 187215911Sjfv * returns SUCCESS if it successfully received a message acknowledgement 188215911Sjfv **/ 189215911Sjfvstatic s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) 190215911Sjfv{ 191215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 192215911Sjfv int countdown = mbx->timeout; 193215911Sjfv 194215911Sjfv DEBUGFUNC("ixgbe_poll_for_ack"); 195215911Sjfv 196215911Sjfv if (!countdown || !mbx->ops.check_for_ack) 197215911Sjfv goto out; 198215911Sjfv 199215911Sjfv while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { 200215911Sjfv countdown--; 201215911Sjfv if (!countdown) 202215911Sjfv break; 203215911Sjfv usec_delay(mbx->usec_delay); 204215911Sjfv } 205215911Sjfv 206283620Serj if (countdown == 0) 207283620Serj ERROR_REPORT2(IXGBE_ERROR_POLLING, 208283620Serj "Polling for VF%d mailbox ack timedout", mbx_id); 209283620Serj 210215911Sjfvout: 211215911Sjfv return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX; 212215911Sjfv} 213215911Sjfv 214215911Sjfv/** 215215911Sjfv * ixgbe_read_posted_mbx - Wait for message notification and receive message 216215911Sjfv * @hw: pointer to the HW structure 217215911Sjfv * @msg: The message buffer 218215911Sjfv * @size: Length of buffer 219215911Sjfv * @mbx_id: id of mailbox to write 220215911Sjfv * 221215911Sjfv * returns SUCCESS if it successfully received a message notification and 222215911Sjfv * copied it into the receive buffer. 223215911Sjfv **/ 224215911Sjfvs32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 225215911Sjfv{ 226215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 227215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 228215911Sjfv 229215911Sjfv DEBUGFUNC("ixgbe_read_posted_mbx"); 230215911Sjfv 231215911Sjfv if (!mbx->ops.read) 232215911Sjfv goto out; 233215911Sjfv 234215911Sjfv ret_val = ixgbe_poll_for_msg(hw, mbx_id); 235215911Sjfv 236215911Sjfv /* if ack received read message, otherwise we timed out */ 237215911Sjfv if (!ret_val) 238215911Sjfv ret_val = mbx->ops.read(hw, msg, size, mbx_id); 239215911Sjfvout: 240215911Sjfv return ret_val; 241215911Sjfv} 242215911Sjfv 243215911Sjfv/** 244215911Sjfv * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack 245215911Sjfv * @hw: pointer to the HW structure 246215911Sjfv * @msg: The message buffer 247215911Sjfv * @size: Length of buffer 248215911Sjfv * @mbx_id: id of mailbox to write 249215911Sjfv * 250215911Sjfv * returns SUCCESS if it successfully copied message into the buffer and 251215911Sjfv * received an ack to that message within delay * timeout period 252215911Sjfv **/ 253215911Sjfvs32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, 254230775Sjfv u16 mbx_id) 255215911Sjfv{ 256215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 257215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 258215911Sjfv 259215911Sjfv DEBUGFUNC("ixgbe_write_posted_mbx"); 260215911Sjfv 261215911Sjfv /* exit if either we can't write or there isn't a defined timeout */ 262215911Sjfv if (!mbx->ops.write || !mbx->timeout) 263215911Sjfv goto out; 264215911Sjfv 265215911Sjfv /* send msg */ 266215911Sjfv ret_val = mbx->ops.write(hw, msg, size, mbx_id); 267215911Sjfv 268215911Sjfv /* if msg sent wait until we receive an ack */ 269215911Sjfv if (!ret_val) 270215911Sjfv ret_val = ixgbe_poll_for_ack(hw, mbx_id); 271215911Sjfvout: 272215911Sjfv return ret_val; 273215911Sjfv} 274215911Sjfv 275215911Sjfv/** 276215911Sjfv * ixgbe_init_mbx_ops_generic - Initialize MB function pointers 277215911Sjfv * @hw: pointer to the HW structure 278215911Sjfv * 279215911Sjfv * Setups up the mailbox read and write message function pointers 280215911Sjfv **/ 281215911Sjfvvoid ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw) 282215911Sjfv{ 283215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 284215911Sjfv 285215911Sjfv mbx->ops.read_posted = ixgbe_read_posted_mbx; 286215911Sjfv mbx->ops.write_posted = ixgbe_write_posted_mbx; 287215911Sjfv} 288215911Sjfv 289215911Sjfv/** 290215911Sjfv * ixgbe_read_v2p_mailbox - read v2p mailbox 291215911Sjfv * @hw: pointer to the HW structure 292215911Sjfv * 293215911Sjfv * This function is used to read the v2p mailbox without losing the read to 294215911Sjfv * clear status bits. 295215911Sjfv **/ 296215911Sjfvstatic u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw) 297215911Sjfv{ 298215911Sjfv u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); 299215911Sjfv 300215911Sjfv v2p_mailbox |= hw->mbx.v2p_mailbox; 301215911Sjfv hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; 302215911Sjfv 303215911Sjfv return v2p_mailbox; 304215911Sjfv} 305215911Sjfv 306215911Sjfv/** 307215911Sjfv * ixgbe_check_for_bit_vf - Determine if a status bit was set 308215911Sjfv * @hw: pointer to the HW structure 309215911Sjfv * @mask: bitmask for bits to be tested and cleared 310215911Sjfv * 311215911Sjfv * This function is used to check for the read to clear bits within 312215911Sjfv * the V2P mailbox. 313215911Sjfv **/ 314215911Sjfvstatic s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) 315215911Sjfv{ 316215911Sjfv u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw); 317215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 318215911Sjfv 319215911Sjfv if (v2p_mailbox & mask) 320215911Sjfv ret_val = IXGBE_SUCCESS; 321215911Sjfv 322215911Sjfv hw->mbx.v2p_mailbox &= ~mask; 323215911Sjfv 324215911Sjfv return ret_val; 325215911Sjfv} 326215911Sjfv 327215911Sjfv/** 328215911Sjfv * ixgbe_check_for_msg_vf - checks to see if the PF has sent mail 329215911Sjfv * @hw: pointer to the HW structure 330215911Sjfv * @mbx_id: id of mailbox to check 331215911Sjfv * 332215911Sjfv * returns SUCCESS if the PF has set the Status bit or else ERR_MBX 333215911Sjfv **/ 334215911Sjfvstatic s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id) 335215911Sjfv{ 336215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 337215911Sjfv 338230775Sjfv UNREFERENCED_1PARAMETER(mbx_id); 339215911Sjfv DEBUGFUNC("ixgbe_check_for_msg_vf"); 340215911Sjfv 341215911Sjfv if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { 342215911Sjfv ret_val = IXGBE_SUCCESS; 343215911Sjfv hw->mbx.stats.reqs++; 344215911Sjfv } 345215911Sjfv 346215911Sjfv return ret_val; 347215911Sjfv} 348215911Sjfv 349215911Sjfv/** 350215911Sjfv * ixgbe_check_for_ack_vf - checks to see if the PF has ACK'd 351215911Sjfv * @hw: pointer to the HW structure 352215911Sjfv * @mbx_id: id of mailbox to check 353215911Sjfv * 354215911Sjfv * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX 355215911Sjfv **/ 356215911Sjfvstatic s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id) 357215911Sjfv{ 358215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 359215911Sjfv 360230775Sjfv UNREFERENCED_1PARAMETER(mbx_id); 361215911Sjfv DEBUGFUNC("ixgbe_check_for_ack_vf"); 362215911Sjfv 363215911Sjfv if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { 364215911Sjfv ret_val = IXGBE_SUCCESS; 365215911Sjfv hw->mbx.stats.acks++; 366215911Sjfv } 367215911Sjfv 368215911Sjfv return ret_val; 369215911Sjfv} 370215911Sjfv 371215911Sjfv/** 372215911Sjfv * ixgbe_check_for_rst_vf - checks to see if the PF has reset 373215911Sjfv * @hw: pointer to the HW structure 374215911Sjfv * @mbx_id: id of mailbox to check 375215911Sjfv * 376215911Sjfv * returns TRUE if the PF has set the reset done bit or else FALSE 377215911Sjfv **/ 378215911Sjfvstatic s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id) 379215911Sjfv{ 380215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 381215911Sjfv 382230775Sjfv UNREFERENCED_1PARAMETER(mbx_id); 383215911Sjfv DEBUGFUNC("ixgbe_check_for_rst_vf"); 384215911Sjfv 385215911Sjfv if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | 386230775Sjfv IXGBE_VFMAILBOX_RSTI))) { 387215911Sjfv ret_val = IXGBE_SUCCESS; 388215911Sjfv hw->mbx.stats.rsts++; 389215911Sjfv } 390215911Sjfv 391215911Sjfv return ret_val; 392215911Sjfv} 393215911Sjfv 394215911Sjfv/** 395215911Sjfv * ixgbe_obtain_mbx_lock_vf - obtain mailbox lock 396215911Sjfv * @hw: pointer to the HW structure 397215911Sjfv * 398215911Sjfv * return SUCCESS if we obtained the mailbox lock 399215911Sjfv **/ 400215911Sjfvstatic s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw) 401215911Sjfv{ 402215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 403215911Sjfv 404215911Sjfv DEBUGFUNC("ixgbe_obtain_mbx_lock_vf"); 405215911Sjfv 406215911Sjfv /* Take ownership of the buffer */ 407215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); 408215911Sjfv 409215911Sjfv /* reserve mailbox for vf use */ 410215911Sjfv if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) 411215911Sjfv ret_val = IXGBE_SUCCESS; 412215911Sjfv 413215911Sjfv return ret_val; 414215911Sjfv} 415215911Sjfv 416215911Sjfv/** 417215911Sjfv * ixgbe_write_mbx_vf - Write a message to the mailbox 418215911Sjfv * @hw: pointer to the HW structure 419215911Sjfv * @msg: The message buffer 420215911Sjfv * @size: Length of buffer 421215911Sjfv * @mbx_id: id of mailbox to write 422215911Sjfv * 423215911Sjfv * returns SUCCESS if it successfully copied message into the buffer 424215911Sjfv **/ 425215911Sjfvstatic s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, 426230775Sjfv u16 mbx_id) 427215911Sjfv{ 428215911Sjfv s32 ret_val; 429215911Sjfv u16 i; 430215911Sjfv 431230775Sjfv UNREFERENCED_1PARAMETER(mbx_id); 432215911Sjfv 433215911Sjfv DEBUGFUNC("ixgbe_write_mbx_vf"); 434215911Sjfv 435215911Sjfv /* lock the mailbox to prevent pf/vf race condition */ 436215911Sjfv ret_val = ixgbe_obtain_mbx_lock_vf(hw); 437215911Sjfv if (ret_val) 438215911Sjfv goto out_no_write; 439215911Sjfv 440215911Sjfv /* flush msg and acks as we are overwriting the message buffer */ 441215911Sjfv ixgbe_check_for_msg_vf(hw, 0); 442215911Sjfv ixgbe_check_for_ack_vf(hw, 0); 443215911Sjfv 444215911Sjfv /* copy the caller specified message to the mailbox memory buffer */ 445215911Sjfv for (i = 0; i < size; i++) 446215911Sjfv IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); 447215911Sjfv 448215911Sjfv /* update stats */ 449215911Sjfv hw->mbx.stats.msgs_tx++; 450215911Sjfv 451215911Sjfv /* Drop VFU and interrupt the PF to tell it a message has been sent */ 452215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); 453215911Sjfv 454215911Sjfvout_no_write: 455215911Sjfv return ret_val; 456215911Sjfv} 457215911Sjfv 458215911Sjfv/** 459215911Sjfv * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf 460215911Sjfv * @hw: pointer to the HW structure 461215911Sjfv * @msg: The message buffer 462215911Sjfv * @size: Length of buffer 463215911Sjfv * @mbx_id: id of mailbox to read 464215911Sjfv * 465215911Sjfv * returns SUCCESS if it successfuly read message from buffer 466215911Sjfv **/ 467215911Sjfvstatic s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, 468230775Sjfv u16 mbx_id) 469215911Sjfv{ 470215911Sjfv s32 ret_val = IXGBE_SUCCESS; 471215911Sjfv u16 i; 472215911Sjfv 473215911Sjfv DEBUGFUNC("ixgbe_read_mbx_vf"); 474230775Sjfv UNREFERENCED_1PARAMETER(mbx_id); 475215911Sjfv 476215911Sjfv /* lock the mailbox to prevent pf/vf race condition */ 477215911Sjfv ret_val = ixgbe_obtain_mbx_lock_vf(hw); 478215911Sjfv if (ret_val) 479215911Sjfv goto out_no_read; 480215911Sjfv 481215911Sjfv /* copy the message from the mailbox memory buffer */ 482215911Sjfv for (i = 0; i < size; i++) 483215911Sjfv msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); 484215911Sjfv 485215911Sjfv /* Acknowledge receipt and release mailbox, then we're done */ 486215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); 487215911Sjfv 488215911Sjfv /* update stats */ 489215911Sjfv hw->mbx.stats.msgs_rx++; 490215911Sjfv 491215911Sjfvout_no_read: 492215911Sjfv return ret_val; 493215911Sjfv} 494215911Sjfv 495215911Sjfv/** 496215911Sjfv * ixgbe_init_mbx_params_vf - set initial values for vf mailbox 497215911Sjfv * @hw: pointer to the HW structure 498215911Sjfv * 499215911Sjfv * Initializes the hw->mbx struct to correct values for vf mailbox 500215911Sjfv */ 501215911Sjfvvoid ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw) 502215911Sjfv{ 503215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 504215911Sjfv 505215911Sjfv /* start mailbox as timed out and let the reset_hw call set the timeout 506215911Sjfv * value to begin communications */ 507215911Sjfv mbx->timeout = 0; 508215911Sjfv mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY; 509215911Sjfv 510215911Sjfv mbx->size = IXGBE_VFMAILBOX_SIZE; 511215911Sjfv 512215911Sjfv mbx->ops.read = ixgbe_read_mbx_vf; 513215911Sjfv mbx->ops.write = ixgbe_write_mbx_vf; 514215911Sjfv mbx->ops.read_posted = ixgbe_read_posted_mbx; 515215911Sjfv mbx->ops.write_posted = ixgbe_write_posted_mbx; 516215911Sjfv mbx->ops.check_for_msg = ixgbe_check_for_msg_vf; 517215911Sjfv mbx->ops.check_for_ack = ixgbe_check_for_ack_vf; 518215911Sjfv mbx->ops.check_for_rst = ixgbe_check_for_rst_vf; 519215911Sjfv 520215911Sjfv mbx->stats.msgs_tx = 0; 521215911Sjfv mbx->stats.msgs_rx = 0; 522215911Sjfv mbx->stats.reqs = 0; 523215911Sjfv mbx->stats.acks = 0; 524215911Sjfv mbx->stats.rsts = 0; 525215911Sjfv} 526215911Sjfv 527215911Sjfvstatic s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) 528215911Sjfv{ 529215911Sjfv u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); 530215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 531215911Sjfv 532215911Sjfv if (mbvficr & mask) { 533215911Sjfv ret_val = IXGBE_SUCCESS; 534215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); 535215911Sjfv } 536215911Sjfv 537215911Sjfv return ret_val; 538215911Sjfv} 539215911Sjfv 540215911Sjfv/** 541215911Sjfv * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail 542215911Sjfv * @hw: pointer to the HW structure 543215911Sjfv * @vf_number: the VF index 544215911Sjfv * 545215911Sjfv * returns SUCCESS if the VF has set the Status bit or else ERR_MBX 546215911Sjfv **/ 547215911Sjfvstatic s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) 548215911Sjfv{ 549215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 550215911Sjfv s32 index = IXGBE_MBVFICR_INDEX(vf_number); 551215911Sjfv u32 vf_bit = vf_number % 16; 552215911Sjfv 553215911Sjfv DEBUGFUNC("ixgbe_check_for_msg_pf"); 554215911Sjfv 555215911Sjfv if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, 556230775Sjfv index)) { 557215911Sjfv ret_val = IXGBE_SUCCESS; 558215911Sjfv hw->mbx.stats.reqs++; 559215911Sjfv } 560215911Sjfv 561215911Sjfv return ret_val; 562215911Sjfv} 563215911Sjfv 564215911Sjfv/** 565215911Sjfv * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed 566215911Sjfv * @hw: pointer to the HW structure 567215911Sjfv * @vf_number: the VF index 568215911Sjfv * 569215911Sjfv * returns SUCCESS if the VF has set the Status bit or else ERR_MBX 570215911Sjfv **/ 571215911Sjfvstatic s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) 572215911Sjfv{ 573215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 574215911Sjfv s32 index = IXGBE_MBVFICR_INDEX(vf_number); 575215911Sjfv u32 vf_bit = vf_number % 16; 576215911Sjfv 577215911Sjfv DEBUGFUNC("ixgbe_check_for_ack_pf"); 578215911Sjfv 579215911Sjfv if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, 580230775Sjfv index)) { 581215911Sjfv ret_val = IXGBE_SUCCESS; 582215911Sjfv hw->mbx.stats.acks++; 583215911Sjfv } 584215911Sjfv 585215911Sjfv return ret_val; 586215911Sjfv} 587215911Sjfv 588215911Sjfv/** 589215911Sjfv * ixgbe_check_for_rst_pf - checks to see if the VF has reset 590215911Sjfv * @hw: pointer to the HW structure 591215911Sjfv * @vf_number: the VF index 592215911Sjfv * 593215911Sjfv * returns SUCCESS if the VF has set the Status bit or else ERR_MBX 594215911Sjfv **/ 595215911Sjfvstatic s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) 596215911Sjfv{ 597215911Sjfv u32 reg_offset = (vf_number < 32) ? 0 : 1; 598215911Sjfv u32 vf_shift = vf_number % 32; 599215911Sjfv u32 vflre = 0; 600215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 601215911Sjfv 602215911Sjfv DEBUGFUNC("ixgbe_check_for_rst_pf"); 603215911Sjfv 604217593Sjfv switch (hw->mac.type) { 605217593Sjfv case ixgbe_mac_82599EB: 606215911Sjfv vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); 607217593Sjfv break; 608283620Serj case ixgbe_mac_X550: 609283620Serj case ixgbe_mac_X550EM_x: 610315333Serj case ixgbe_mac_X550EM_a: 611230775Sjfv case ixgbe_mac_X540: 612230775Sjfv vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); 613230775Sjfv break; 614217593Sjfv default: 615217593Sjfv break; 616217593Sjfv } 617215911Sjfv 618215911Sjfv if (vflre & (1 << vf_shift)) { 619215911Sjfv ret_val = IXGBE_SUCCESS; 620215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); 621215911Sjfv hw->mbx.stats.rsts++; 622215911Sjfv } 623215911Sjfv 624215911Sjfv return ret_val; 625215911Sjfv} 626215911Sjfv 627215911Sjfv/** 628215911Sjfv * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock 629215911Sjfv * @hw: pointer to the HW structure 630215911Sjfv * @vf_number: the VF index 631215911Sjfv * 632215911Sjfv * return SUCCESS if we obtained the mailbox lock 633215911Sjfv **/ 634215911Sjfvstatic s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) 635215911Sjfv{ 636215911Sjfv s32 ret_val = IXGBE_ERR_MBX; 637215911Sjfv u32 p2v_mailbox; 638215911Sjfv 639215911Sjfv DEBUGFUNC("ixgbe_obtain_mbx_lock_pf"); 640215911Sjfv 641215911Sjfv /* Take ownership of the buffer */ 642215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); 643215911Sjfv 644215911Sjfv /* reserve mailbox for vf use */ 645215911Sjfv p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); 646215911Sjfv if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) 647215911Sjfv ret_val = IXGBE_SUCCESS; 648283620Serj else 649283620Serj ERROR_REPORT2(IXGBE_ERROR_POLLING, 650283620Serj "Failed to obtain mailbox lock for VF%d", vf_number); 651215911Sjfv 652283620Serj 653215911Sjfv return ret_val; 654215911Sjfv} 655215911Sjfv 656215911Sjfv/** 657215911Sjfv * ixgbe_write_mbx_pf - Places a message in the mailbox 658215911Sjfv * @hw: pointer to the HW structure 659215911Sjfv * @msg: The message buffer 660215911Sjfv * @size: Length of buffer 661215911Sjfv * @vf_number: the VF index 662215911Sjfv * 663215911Sjfv * returns SUCCESS if it successfully copied message into the buffer 664215911Sjfv **/ 665215911Sjfvstatic s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, 666230775Sjfv u16 vf_number) 667215911Sjfv{ 668215911Sjfv s32 ret_val; 669215911Sjfv u16 i; 670215911Sjfv 671215911Sjfv DEBUGFUNC("ixgbe_write_mbx_pf"); 672215911Sjfv 673215911Sjfv /* lock the mailbox to prevent pf/vf race condition */ 674215911Sjfv ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); 675215911Sjfv if (ret_val) 676215911Sjfv goto out_no_write; 677215911Sjfv 678215911Sjfv /* flush msg and acks as we are overwriting the message buffer */ 679215911Sjfv ixgbe_check_for_msg_pf(hw, vf_number); 680215911Sjfv ixgbe_check_for_ack_pf(hw, vf_number); 681215911Sjfv 682215911Sjfv /* copy the caller specified message to the mailbox memory buffer */ 683215911Sjfv for (i = 0; i < size; i++) 684215911Sjfv IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); 685215911Sjfv 686215911Sjfv /* Interrupt VF to tell it a message has been sent and release buffer*/ 687215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); 688215911Sjfv 689215911Sjfv /* update stats */ 690215911Sjfv hw->mbx.stats.msgs_tx++; 691215911Sjfv 692215911Sjfvout_no_write: 693215911Sjfv return ret_val; 694215911Sjfv 695215911Sjfv} 696215911Sjfv 697215911Sjfv/** 698215911Sjfv * ixgbe_read_mbx_pf - Read a message from the mailbox 699215911Sjfv * @hw: pointer to the HW structure 700215911Sjfv * @msg: The message buffer 701215911Sjfv * @size: Length of buffer 702215911Sjfv * @vf_number: the VF index 703215911Sjfv * 704215911Sjfv * This function copies a message from the mailbox buffer to the caller's 705215911Sjfv * memory buffer. The presumption is that the caller knows that there was 706215911Sjfv * a message due to a VF request so no polling for message is needed. 707215911Sjfv **/ 708215911Sjfvstatic s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, 709230775Sjfv u16 vf_number) 710215911Sjfv{ 711215911Sjfv s32 ret_val; 712215911Sjfv u16 i; 713215911Sjfv 714215911Sjfv DEBUGFUNC("ixgbe_read_mbx_pf"); 715215911Sjfv 716215911Sjfv /* lock the mailbox to prevent pf/vf race condition */ 717215911Sjfv ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); 718215911Sjfv if (ret_val) 719215911Sjfv goto out_no_read; 720215911Sjfv 721215911Sjfv /* copy the message to the mailbox memory buffer */ 722215911Sjfv for (i = 0; i < size; i++) 723215911Sjfv msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); 724215911Sjfv 725215911Sjfv /* Acknowledge the message and release buffer */ 726215911Sjfv IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); 727215911Sjfv 728215911Sjfv /* update stats */ 729215911Sjfv hw->mbx.stats.msgs_rx++; 730215911Sjfv 731215911Sjfvout_no_read: 732215911Sjfv return ret_val; 733215911Sjfv} 734215911Sjfv 735215911Sjfv/** 736215911Sjfv * ixgbe_init_mbx_params_pf - set initial values for pf mailbox 737215911Sjfv * @hw: pointer to the HW structure 738215911Sjfv * 739215911Sjfv * Initializes the hw->mbx struct to correct values for pf mailbox 740215911Sjfv */ 741215911Sjfvvoid ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) 742215911Sjfv{ 743215911Sjfv struct ixgbe_mbx_info *mbx = &hw->mbx; 744215911Sjfv 745230775Sjfv if (hw->mac.type != ixgbe_mac_82599EB && 746283620Serj hw->mac.type != ixgbe_mac_X550 && 747283620Serj hw->mac.type != ixgbe_mac_X550EM_x && 748315333Serj hw->mac.type != ixgbe_mac_X550EM_a && 749230775Sjfv hw->mac.type != ixgbe_mac_X540) 750215911Sjfv return; 751215911Sjfv 752215911Sjfv mbx->timeout = 0; 753215911Sjfv mbx->usec_delay = 0; 754215911Sjfv 755215911Sjfv mbx->size = IXGBE_VFMAILBOX_SIZE; 756215911Sjfv 757215911Sjfv mbx->ops.read = ixgbe_read_mbx_pf; 758215911Sjfv mbx->ops.write = ixgbe_write_mbx_pf; 759215911Sjfv mbx->ops.read_posted = ixgbe_read_posted_mbx; 760215911Sjfv mbx->ops.write_posted = ixgbe_write_posted_mbx; 761215911Sjfv mbx->ops.check_for_msg = ixgbe_check_for_msg_pf; 762215911Sjfv mbx->ops.check_for_ack = ixgbe_check_for_ack_pf; 763215911Sjfv mbx->ops.check_for_rst = ixgbe_check_for_rst_pf; 764215911Sjfv 765215911Sjfv mbx->stats.msgs_tx = 0; 766215911Sjfv mbx->stats.msgs_rx = 0; 767215911Sjfv mbx->stats.reqs = 0; 768215911Sjfv mbx->stats.acks = 0; 769215911Sjfv mbx->stats.rsts = 0; 770215911Sjfv} 771