160229dcfSJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause 260229dcfSJiawen Wu * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 360229dcfSJiawen Wu * Copyright(c) 2010-2017 Intel Corporation 460229dcfSJiawen Wu */ 560229dcfSJiawen Wu 660229dcfSJiawen Wu #include "ngbe_type.h" 760229dcfSJiawen Wu 860229dcfSJiawen Wu #include "ngbe_mbx.h" 960229dcfSJiawen Wu 1060229dcfSJiawen Wu /** 11e2a289a7SJiawen Wu * ngbe_read_mbx - Reads a message from the mailbox 12e2a289a7SJiawen Wu * @hw: pointer to the HW structure 13e2a289a7SJiawen Wu * @msg: The message buffer 14e2a289a7SJiawen Wu * @size: Length of buffer 15e2a289a7SJiawen Wu * @mbx_id: id of mailbox to read 16e2a289a7SJiawen Wu * 17e2a289a7SJiawen Wu * returns 0 if it successfully read message from buffer 18e2a289a7SJiawen Wu **/ 19e2a289a7SJiawen Wu s32 ngbe_read_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 20e2a289a7SJiawen Wu { 21e2a289a7SJiawen Wu struct ngbe_mbx_info *mbx = &hw->mbx; 22e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 23e2a289a7SJiawen Wu 24e2a289a7SJiawen Wu /* limit read to size of mailbox */ 25e2a289a7SJiawen Wu if (size > mbx->size) 26e2a289a7SJiawen Wu size = mbx->size; 27e2a289a7SJiawen Wu 28e2a289a7SJiawen Wu if (mbx->read) 29e2a289a7SJiawen Wu ret_val = mbx->read(hw, msg, size, mbx_id); 30e2a289a7SJiawen Wu 31e2a289a7SJiawen Wu return ret_val; 32e2a289a7SJiawen Wu } 33e2a289a7SJiawen Wu 34e2a289a7SJiawen Wu /** 35e2a289a7SJiawen Wu * ngbe_write_mbx - Write a message to the mailbox 36e2a289a7SJiawen Wu * @hw: pointer to the HW structure 37e2a289a7SJiawen Wu * @msg: The message buffer 38e2a289a7SJiawen Wu * @size: Length of buffer 39e2a289a7SJiawen Wu * @mbx_id: id of mailbox to write 40e2a289a7SJiawen Wu * 41e2a289a7SJiawen Wu * returns 0 if it successfully copied message into the buffer 42e2a289a7SJiawen Wu **/ 43e2a289a7SJiawen Wu s32 ngbe_write_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 44e2a289a7SJiawen Wu { 45e2a289a7SJiawen Wu struct ngbe_mbx_info *mbx = &hw->mbx; 46e2a289a7SJiawen Wu s32 ret_val = 0; 47e2a289a7SJiawen Wu 48e2a289a7SJiawen Wu if (size > mbx->size) { 49e2a289a7SJiawen Wu ret_val = NGBE_ERR_MBX; 50e2a289a7SJiawen Wu DEBUGOUT("Invalid mailbox message size %d", size); 51e2a289a7SJiawen Wu } else if (mbx->write) { 52e2a289a7SJiawen Wu ret_val = mbx->write(hw, msg, size, mbx_id); 53e2a289a7SJiawen Wu } 54e2a289a7SJiawen Wu 55e2a289a7SJiawen Wu return ret_val; 56e2a289a7SJiawen Wu } 57e2a289a7SJiawen Wu 58e2a289a7SJiawen Wu /** 59e2a289a7SJiawen Wu * ngbe_check_for_msg - checks to see if someone sent us mail 60e2a289a7SJiawen Wu * @hw: pointer to the HW structure 61e2a289a7SJiawen Wu * @mbx_id: id of mailbox to check 62e2a289a7SJiawen Wu * 63e2a289a7SJiawen Wu * returns 0 if the Status bit was found or else ERR_MBX 64e2a289a7SJiawen Wu **/ 65e2a289a7SJiawen Wu s32 ngbe_check_for_msg(struct ngbe_hw *hw, u16 mbx_id) 66e2a289a7SJiawen Wu { 67e2a289a7SJiawen Wu struct ngbe_mbx_info *mbx = &hw->mbx; 68e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 69e2a289a7SJiawen Wu 70e2a289a7SJiawen Wu if (mbx->check_for_msg) 71e2a289a7SJiawen Wu ret_val = mbx->check_for_msg(hw, mbx_id); 72e2a289a7SJiawen Wu 73e2a289a7SJiawen Wu return ret_val; 74e2a289a7SJiawen Wu } 75e2a289a7SJiawen Wu 76e2a289a7SJiawen Wu /** 77e2a289a7SJiawen Wu * ngbe_check_for_ack - checks to see if someone sent us ACK 78e2a289a7SJiawen Wu * @hw: pointer to the HW structure 79e2a289a7SJiawen Wu * @mbx_id: id of mailbox to check 80e2a289a7SJiawen Wu * 81e2a289a7SJiawen Wu * returns 0 if the Status bit was found or else ERR_MBX 82e2a289a7SJiawen Wu **/ 83e2a289a7SJiawen Wu s32 ngbe_check_for_ack(struct ngbe_hw *hw, u16 mbx_id) 84e2a289a7SJiawen Wu { 85e2a289a7SJiawen Wu struct ngbe_mbx_info *mbx = &hw->mbx; 86e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 87e2a289a7SJiawen Wu 88e2a289a7SJiawen Wu if (mbx->check_for_ack) 89e2a289a7SJiawen Wu ret_val = mbx->check_for_ack(hw, mbx_id); 90e2a289a7SJiawen Wu 91e2a289a7SJiawen Wu return ret_val; 92e2a289a7SJiawen Wu } 93e2a289a7SJiawen Wu 94e2a289a7SJiawen Wu /** 95e2a289a7SJiawen Wu * ngbe_check_for_rst - checks to see if other side has reset 96e2a289a7SJiawen Wu * @hw: pointer to the HW structure 97e2a289a7SJiawen Wu * @mbx_id: id of mailbox to check 98e2a289a7SJiawen Wu * 99e2a289a7SJiawen Wu * returns 0 if the Status bit was found or else ERR_MBX 100e2a289a7SJiawen Wu **/ 101e2a289a7SJiawen Wu s32 ngbe_check_for_rst(struct ngbe_hw *hw, u16 mbx_id) 102e2a289a7SJiawen Wu { 103e2a289a7SJiawen Wu struct ngbe_mbx_info *mbx = &hw->mbx; 104e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 105e2a289a7SJiawen Wu 106e2a289a7SJiawen Wu if (mbx->check_for_rst) 107e2a289a7SJiawen Wu ret_val = mbx->check_for_rst(hw, mbx_id); 108e2a289a7SJiawen Wu 109e2a289a7SJiawen Wu return ret_val; 110e2a289a7SJiawen Wu } 111e2a289a7SJiawen Wu 112*ace44974SZaiyu Wang /** 113*ace44974SZaiyu Wang * ngbe_poll_for_msg - Wait for message notification 114*ace44974SZaiyu Wang * @hw: pointer to the HW structure 115*ace44974SZaiyu Wang * @mbx_id: id of mailbox to write 116*ace44974SZaiyu Wang * 117*ace44974SZaiyu Wang * returns SUCCESS if it successfully received a message notification 118*ace44974SZaiyu Wang **/ 119*ace44974SZaiyu Wang STATIC s32 ngbe_poll_for_msg(struct ngbe_hw *hw, u16 mbx_id) 120*ace44974SZaiyu Wang { 121*ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 122*ace44974SZaiyu Wang int countdown = mbx->timeout; 123*ace44974SZaiyu Wang 124*ace44974SZaiyu Wang if (!countdown || !mbx->check_for_msg) 125*ace44974SZaiyu Wang goto out; 126*ace44974SZaiyu Wang 127*ace44974SZaiyu Wang while (countdown && mbx->check_for_msg(hw, mbx_id)) { 128*ace44974SZaiyu Wang countdown--; 129*ace44974SZaiyu Wang if (!countdown) 130*ace44974SZaiyu Wang break; 131*ace44974SZaiyu Wang usec_delay(mbx->usec_delay); 132*ace44974SZaiyu Wang } 133*ace44974SZaiyu Wang 134*ace44974SZaiyu Wang if (countdown == 0) 135*ace44974SZaiyu Wang DEBUGOUT("Polling for VF%d mailbox message timedout", mbx_id); 136*ace44974SZaiyu Wang 137*ace44974SZaiyu Wang out: 138*ace44974SZaiyu Wang return countdown ? 0 : NGBE_ERR_MBX; 139*ace44974SZaiyu Wang } 140*ace44974SZaiyu Wang 141*ace44974SZaiyu Wang /** 142*ace44974SZaiyu Wang * ngbe_poll_for_ack - Wait for message acknowledgment 143*ace44974SZaiyu Wang * @hw: pointer to the HW structure 144*ace44974SZaiyu Wang * @mbx_id: id of mailbox to write 145*ace44974SZaiyu Wang * 146*ace44974SZaiyu Wang * returns SUCCESS if it successfully received a message acknowledgment 147*ace44974SZaiyu Wang **/ 148*ace44974SZaiyu Wang STATIC s32 ngbe_poll_for_ack(struct ngbe_hw *hw, u16 mbx_id) 149*ace44974SZaiyu Wang { 150*ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 151*ace44974SZaiyu Wang int countdown = mbx->timeout; 152*ace44974SZaiyu Wang 153*ace44974SZaiyu Wang if (!countdown || !mbx->check_for_ack) 154*ace44974SZaiyu Wang goto out; 155*ace44974SZaiyu Wang 156*ace44974SZaiyu Wang while (countdown && mbx->check_for_ack(hw, mbx_id)) { 157*ace44974SZaiyu Wang countdown--; 158*ace44974SZaiyu Wang if (!countdown) 159*ace44974SZaiyu Wang break; 160*ace44974SZaiyu Wang usec_delay(mbx->usec_delay); 161*ace44974SZaiyu Wang } 162*ace44974SZaiyu Wang 163*ace44974SZaiyu Wang if (countdown == 0) 164*ace44974SZaiyu Wang DEBUGOUT("Polling for VF%d mailbox ack timedout", mbx_id); 165*ace44974SZaiyu Wang 166*ace44974SZaiyu Wang out: 167*ace44974SZaiyu Wang return countdown ? 0 : NGBE_ERR_MBX; 168*ace44974SZaiyu Wang } 169*ace44974SZaiyu Wang 170*ace44974SZaiyu Wang /** 171*ace44974SZaiyu Wang * ngbe_read_posted_mbx - Wait for message notification and receive message 172*ace44974SZaiyu Wang * @hw: pointer to the HW structure 173*ace44974SZaiyu Wang * @msg: The message buffer 174*ace44974SZaiyu Wang * @size: Length of buffer 175*ace44974SZaiyu Wang * @mbx_id: id of mailbox to write 176*ace44974SZaiyu Wang * 177*ace44974SZaiyu Wang * returns SUCCESS if it successfully received a message notification and 178*ace44974SZaiyu Wang * copied it into the receive buffer. 179*ace44974SZaiyu Wang **/ 180*ace44974SZaiyu Wang s32 ngbe_read_posted_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) 181*ace44974SZaiyu Wang { 182*ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 183*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 184*ace44974SZaiyu Wang 185*ace44974SZaiyu Wang if (!mbx->read) 186*ace44974SZaiyu Wang goto out; 187*ace44974SZaiyu Wang 188*ace44974SZaiyu Wang ret_val = ngbe_poll_for_msg(hw, mbx_id); 189*ace44974SZaiyu Wang 190*ace44974SZaiyu Wang /* if ack received read message, otherwise we timed out */ 191*ace44974SZaiyu Wang if (!ret_val) 192*ace44974SZaiyu Wang ret_val = mbx->read(hw, msg, size, mbx_id); 193*ace44974SZaiyu Wang out: 194*ace44974SZaiyu Wang return ret_val; 195*ace44974SZaiyu Wang } 196*ace44974SZaiyu Wang 197*ace44974SZaiyu Wang /** 198*ace44974SZaiyu Wang * ngbe_write_posted_mbx - Write a message to the mailbox, wait for ack 199*ace44974SZaiyu Wang * @hw: pointer to the HW structure 200*ace44974SZaiyu Wang * @msg: The message buffer 201*ace44974SZaiyu Wang * @size: Length of buffer 202*ace44974SZaiyu Wang * @mbx_id: id of mailbox to write 203*ace44974SZaiyu Wang * 204*ace44974SZaiyu Wang * returns SUCCESS if it successfully copied message into the buffer and 205*ace44974SZaiyu Wang * received an ack to that message within delay * timeout period 206*ace44974SZaiyu Wang **/ 207*ace44974SZaiyu Wang s32 ngbe_write_posted_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, 208*ace44974SZaiyu Wang u16 mbx_id) 209*ace44974SZaiyu Wang { 210*ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 211*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 212*ace44974SZaiyu Wang 213*ace44974SZaiyu Wang /* exit if either we can't write or there isn't a defined timeout */ 214*ace44974SZaiyu Wang if (!mbx->write || !mbx->timeout) 215*ace44974SZaiyu Wang goto out; 216*ace44974SZaiyu Wang 217*ace44974SZaiyu Wang /* send msg */ 218*ace44974SZaiyu Wang ret_val = mbx->write(hw, msg, size, mbx_id); 219*ace44974SZaiyu Wang 220*ace44974SZaiyu Wang /* if msg sent wait until we receive an ack */ 221*ace44974SZaiyu Wang if (!ret_val) 222*ace44974SZaiyu Wang ret_val = ngbe_poll_for_ack(hw, mbx_id); 223*ace44974SZaiyu Wang out: 224*ace44974SZaiyu Wang return ret_val; 225*ace44974SZaiyu Wang } 226*ace44974SZaiyu Wang 227*ace44974SZaiyu Wang /** 228*ace44974SZaiyu Wang * ngbe_read_v2p_mailbox - read v2p mailbox 229*ace44974SZaiyu Wang * @hw: pointer to the HW structure 230*ace44974SZaiyu Wang * 231*ace44974SZaiyu Wang * This function is used to read the v2p mailbox without losing the read to 232*ace44974SZaiyu Wang * clear status bits. 233*ace44974SZaiyu Wang **/ 234*ace44974SZaiyu Wang STATIC u32 ngbe_read_v2p_mailbox(struct ngbe_hw *hw) 235*ace44974SZaiyu Wang { 236*ace44974SZaiyu Wang u32 v2p_mailbox = rd32(hw, NGBE_VFMBCTL); 237*ace44974SZaiyu Wang 238*ace44974SZaiyu Wang v2p_mailbox |= hw->mbx.v2p_mailbox; 239*ace44974SZaiyu Wang hw->mbx.v2p_mailbox |= v2p_mailbox & NGBE_VFMBCTL_R2C_BITS; 240*ace44974SZaiyu Wang 241*ace44974SZaiyu Wang return v2p_mailbox; 242*ace44974SZaiyu Wang } 243*ace44974SZaiyu Wang 244*ace44974SZaiyu Wang /** 245*ace44974SZaiyu Wang * ngbe_check_for_bit_vf - Determine if a status bit was set 246*ace44974SZaiyu Wang * @hw: pointer to the HW structure 247*ace44974SZaiyu Wang * @mask: bitmask for bits to be tested and cleared 248*ace44974SZaiyu Wang * 249*ace44974SZaiyu Wang * This function is used to check for the read to clear bits within 250*ace44974SZaiyu Wang * the V2P mailbox. 251*ace44974SZaiyu Wang **/ 252*ace44974SZaiyu Wang STATIC s32 ngbe_check_for_bit_vf(struct ngbe_hw *hw, u32 mask) 253*ace44974SZaiyu Wang { 254*ace44974SZaiyu Wang u32 v2p_mailbox = ngbe_read_v2p_mailbox(hw); 255*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 256*ace44974SZaiyu Wang 257*ace44974SZaiyu Wang if (v2p_mailbox & mask) 258*ace44974SZaiyu Wang ret_val = 0; 259*ace44974SZaiyu Wang 260*ace44974SZaiyu Wang hw->mbx.v2p_mailbox &= ~mask; 261*ace44974SZaiyu Wang 262*ace44974SZaiyu Wang return ret_val; 263*ace44974SZaiyu Wang } 264*ace44974SZaiyu Wang 265*ace44974SZaiyu Wang /** 266*ace44974SZaiyu Wang * ngbe_check_for_msg_vf - checks to see if the PF has sent mail 267*ace44974SZaiyu Wang * @hw: pointer to the HW structure 268*ace44974SZaiyu Wang * @mbx_id: id of mailbox to check 269*ace44974SZaiyu Wang * 270*ace44974SZaiyu Wang * returns SUCCESS if the PF has set the Status bit or else ERR_MBX 271*ace44974SZaiyu Wang **/ 272*ace44974SZaiyu Wang s32 ngbe_check_for_msg_vf(struct ngbe_hw *hw, u16 mbx_id) 273*ace44974SZaiyu Wang { 274*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 275*ace44974SZaiyu Wang 276*ace44974SZaiyu Wang UNREFERENCED_PARAMETER(mbx_id); 277*ace44974SZaiyu Wang 278*ace44974SZaiyu Wang if (!ngbe_check_for_bit_vf(hw, NGBE_VFMBCTL_PFSTS)) { 279*ace44974SZaiyu Wang ret_val = 0; 280*ace44974SZaiyu Wang hw->mbx.stats.reqs++; 281*ace44974SZaiyu Wang } 282*ace44974SZaiyu Wang 283*ace44974SZaiyu Wang return ret_val; 284*ace44974SZaiyu Wang } 285*ace44974SZaiyu Wang 286*ace44974SZaiyu Wang /** 287*ace44974SZaiyu Wang * ngbe_check_for_ack_vf - checks to see if the PF has ACK'd 288*ace44974SZaiyu Wang * @hw: pointer to the HW structure 289*ace44974SZaiyu Wang * @mbx_id: id of mailbox to check 290*ace44974SZaiyu Wang * 291*ace44974SZaiyu Wang * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX 292*ace44974SZaiyu Wang **/ 293*ace44974SZaiyu Wang s32 ngbe_check_for_ack_vf(struct ngbe_hw *hw, u16 mbx_id) 294*ace44974SZaiyu Wang { 295*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 296*ace44974SZaiyu Wang 297*ace44974SZaiyu Wang UNREFERENCED_PARAMETER(mbx_id); 298*ace44974SZaiyu Wang 299*ace44974SZaiyu Wang if (!ngbe_check_for_bit_vf(hw, NGBE_VFMBCTL_PFACK)) { 300*ace44974SZaiyu Wang ret_val = 0; 301*ace44974SZaiyu Wang hw->mbx.stats.acks++; 302*ace44974SZaiyu Wang } 303*ace44974SZaiyu Wang 304*ace44974SZaiyu Wang return ret_val; 305*ace44974SZaiyu Wang } 306*ace44974SZaiyu Wang 307*ace44974SZaiyu Wang /** 308*ace44974SZaiyu Wang * ngbe_check_for_rst_vf - checks to see if the PF has reset 309*ace44974SZaiyu Wang * @hw: pointer to the HW structure 310*ace44974SZaiyu Wang * @mbx_id: id of mailbox to check 311*ace44974SZaiyu Wang * 312*ace44974SZaiyu Wang * returns true if the PF has set the reset done bit or else false 313*ace44974SZaiyu Wang **/ 314*ace44974SZaiyu Wang s32 ngbe_check_for_rst_vf(struct ngbe_hw *hw, u16 mbx_id) 315*ace44974SZaiyu Wang { 316*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 317*ace44974SZaiyu Wang 318*ace44974SZaiyu Wang UNREFERENCED_PARAMETER(mbx_id); 319*ace44974SZaiyu Wang 320*ace44974SZaiyu Wang if (!ngbe_check_for_bit_vf(hw, (NGBE_VFMBCTL_RSTD | 321*ace44974SZaiyu Wang NGBE_VFMBCTL_RSTI))) { 322*ace44974SZaiyu Wang ret_val = 0; 323*ace44974SZaiyu Wang hw->mbx.stats.rsts++; 324*ace44974SZaiyu Wang } 325*ace44974SZaiyu Wang 326*ace44974SZaiyu Wang return ret_val; 327*ace44974SZaiyu Wang } 328*ace44974SZaiyu Wang 329*ace44974SZaiyu Wang /** 330*ace44974SZaiyu Wang * ngbe_obtain_mbx_lock_vf - obtain mailbox lock 331*ace44974SZaiyu Wang * @hw: pointer to the HW structure 332*ace44974SZaiyu Wang * 333*ace44974SZaiyu Wang * return SUCCESS if we obtained the mailbox lock 334*ace44974SZaiyu Wang **/ 335*ace44974SZaiyu Wang STATIC s32 ngbe_obtain_mbx_lock_vf(struct ngbe_hw *hw) 336*ace44974SZaiyu Wang { 337*ace44974SZaiyu Wang s32 ret_val = NGBE_ERR_MBX; 338*ace44974SZaiyu Wang 339*ace44974SZaiyu Wang /* Take ownership of the buffer */ 340*ace44974SZaiyu Wang wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_VFU); 341*ace44974SZaiyu Wang 342*ace44974SZaiyu Wang /* reserve mailbox for vf use */ 343*ace44974SZaiyu Wang if (ngbe_read_v2p_mailbox(hw) & NGBE_VFMBCTL_VFU) 344*ace44974SZaiyu Wang ret_val = 0; 345*ace44974SZaiyu Wang 346*ace44974SZaiyu Wang return ret_val; 347*ace44974SZaiyu Wang } 348*ace44974SZaiyu Wang 349*ace44974SZaiyu Wang /** 350*ace44974SZaiyu Wang * ngbe_write_mbx_vf - Write a message to the mailbox 351*ace44974SZaiyu Wang * @hw: pointer to the HW structure 352*ace44974SZaiyu Wang * @msg: The message buffer 353*ace44974SZaiyu Wang * @size: Length of buffer 354*ace44974SZaiyu Wang * @mbx_id: id of mailbox to write 355*ace44974SZaiyu Wang * 356*ace44974SZaiyu Wang * returns SUCCESS if it successfully copied message into the buffer 357*ace44974SZaiyu Wang **/ 358*ace44974SZaiyu Wang s32 ngbe_write_mbx_vf(struct ngbe_hw *hw, u32 *msg, u16 size, 359*ace44974SZaiyu Wang u16 mbx_id) 360*ace44974SZaiyu Wang { 361*ace44974SZaiyu Wang s32 ret_val; 362*ace44974SZaiyu Wang u16 i; 363*ace44974SZaiyu Wang 364*ace44974SZaiyu Wang UNREFERENCED_PARAMETER(mbx_id); 365*ace44974SZaiyu Wang 366*ace44974SZaiyu Wang /* lock the mailbox to prevent pf/vf race condition */ 367*ace44974SZaiyu Wang ret_val = ngbe_obtain_mbx_lock_vf(hw); 368*ace44974SZaiyu Wang if (ret_val) 369*ace44974SZaiyu Wang goto out_no_write; 370*ace44974SZaiyu Wang 371*ace44974SZaiyu Wang /* flush msg and acks as we are overwriting the message buffer */ 372*ace44974SZaiyu Wang ngbe_check_for_msg_vf(hw, 0); 373*ace44974SZaiyu Wang ngbe_check_for_ack_vf(hw, 0); 374*ace44974SZaiyu Wang 375*ace44974SZaiyu Wang /* copy the caller specified message to the mailbox memory buffer */ 376*ace44974SZaiyu Wang for (i = 0; i < size; i++) 377*ace44974SZaiyu Wang wr32a(hw, NGBE_VFMBX, i, msg[i]); 378*ace44974SZaiyu Wang 379*ace44974SZaiyu Wang /* update stats */ 380*ace44974SZaiyu Wang hw->mbx.stats.msgs_tx++; 381*ace44974SZaiyu Wang 382*ace44974SZaiyu Wang /* Drop VFU and interrupt the PF to tell it a message has been sent */ 383*ace44974SZaiyu Wang wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_REQ); 384*ace44974SZaiyu Wang 385*ace44974SZaiyu Wang out_no_write: 386*ace44974SZaiyu Wang return ret_val; 387*ace44974SZaiyu Wang } 388*ace44974SZaiyu Wang 389*ace44974SZaiyu Wang /** 390*ace44974SZaiyu Wang * ngbe_read_mbx_vf - Reads a message from the inbox intended for vf 391*ace44974SZaiyu Wang * @hw: pointer to the HW structure 392*ace44974SZaiyu Wang * @msg: The message buffer 393*ace44974SZaiyu Wang * @size: Length of buffer 394*ace44974SZaiyu Wang * @mbx_id: id of mailbox to read 395*ace44974SZaiyu Wang * 396*ace44974SZaiyu Wang * returns SUCCESS if it successfully read message from buffer 397*ace44974SZaiyu Wang **/ 398*ace44974SZaiyu Wang s32 ngbe_read_mbx_vf(struct ngbe_hw *hw, u32 *msg, u16 size, 399*ace44974SZaiyu Wang u16 mbx_id) 400*ace44974SZaiyu Wang { 401*ace44974SZaiyu Wang s32 ret_val = 0; 402*ace44974SZaiyu Wang u16 i; 403*ace44974SZaiyu Wang 404*ace44974SZaiyu Wang UNREFERENCED_PARAMETER(mbx_id); 405*ace44974SZaiyu Wang 406*ace44974SZaiyu Wang /* lock the mailbox to prevent pf/vf race condition */ 407*ace44974SZaiyu Wang ret_val = ngbe_obtain_mbx_lock_vf(hw); 408*ace44974SZaiyu Wang if (ret_val) 409*ace44974SZaiyu Wang goto out_no_read; 410*ace44974SZaiyu Wang 411*ace44974SZaiyu Wang /* copy the message from the mailbox memory buffer */ 412*ace44974SZaiyu Wang for (i = 0; i < size; i++) 413*ace44974SZaiyu Wang msg[i] = rd32a(hw, NGBE_VFMBX, i); 414*ace44974SZaiyu Wang 415*ace44974SZaiyu Wang /* Acknowledge receipt and release mailbox, then we're done */ 416*ace44974SZaiyu Wang wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_ACK); 417*ace44974SZaiyu Wang 418*ace44974SZaiyu Wang /* update stats */ 419*ace44974SZaiyu Wang hw->mbx.stats.msgs_rx++; 420*ace44974SZaiyu Wang 421*ace44974SZaiyu Wang out_no_read: 422*ace44974SZaiyu Wang return ret_val; 423*ace44974SZaiyu Wang } 424*ace44974SZaiyu Wang 425*ace44974SZaiyu Wang /** 426*ace44974SZaiyu Wang * ngbe_init_mbx_params_vf - set initial values for vf mailbox 427*ace44974SZaiyu Wang * @hw: pointer to the HW structure 428*ace44974SZaiyu Wang * 429*ace44974SZaiyu Wang * Initializes the hw->mbx struct to correct values for vf mailbox 430*ace44974SZaiyu Wang */ 431*ace44974SZaiyu Wang void ngbe_init_mbx_params_vf(struct ngbe_hw *hw) 432*ace44974SZaiyu Wang { 433*ace44974SZaiyu Wang struct ngbe_mbx_info *mbx = &hw->mbx; 434*ace44974SZaiyu Wang 435*ace44974SZaiyu Wang /* start mailbox as timed out and let the reset_hw call set the timeout 436*ace44974SZaiyu Wang * value to begin communications 437*ace44974SZaiyu Wang */ 438*ace44974SZaiyu Wang mbx->timeout = 0; 439*ace44974SZaiyu Wang mbx->usec_delay = NGBE_VF_MBX_INIT_DELAY; 440*ace44974SZaiyu Wang 441*ace44974SZaiyu Wang mbx->size = NGBE_P2VMBX_SIZE; 442*ace44974SZaiyu Wang 443*ace44974SZaiyu Wang mbx->stats.msgs_tx = 0; 444*ace44974SZaiyu Wang mbx->stats.msgs_rx = 0; 445*ace44974SZaiyu Wang mbx->stats.reqs = 0; 446*ace44974SZaiyu Wang mbx->stats.acks = 0; 447*ace44974SZaiyu Wang mbx->stats.rsts = 0; 448*ace44974SZaiyu Wang } 449*ace44974SZaiyu Wang 450e2a289a7SJiawen Wu STATIC s32 ngbe_check_for_bit_pf(struct ngbe_hw *hw, u32 mask) 451e2a289a7SJiawen Wu { 452e2a289a7SJiawen Wu u32 mbvficr = rd32(hw, NGBE_MBVFICR); 453e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 454e2a289a7SJiawen Wu 455e2a289a7SJiawen Wu if (mbvficr & mask) { 456e2a289a7SJiawen Wu ret_val = 0; 457e2a289a7SJiawen Wu wr32(hw, NGBE_MBVFICR, mask); 458e2a289a7SJiawen Wu } 459e2a289a7SJiawen Wu 460e2a289a7SJiawen Wu return ret_val; 461e2a289a7SJiawen Wu } 462e2a289a7SJiawen Wu 463e2a289a7SJiawen Wu /** 464e2a289a7SJiawen Wu * ngbe_check_for_msg_pf - checks to see if the VF has sent mail 465e2a289a7SJiawen Wu * @hw: pointer to the HW structure 466e2a289a7SJiawen Wu * @vf_number: the VF index 467e2a289a7SJiawen Wu * 468e2a289a7SJiawen Wu * returns 0 if the VF has set the Status bit or else ERR_MBX 469e2a289a7SJiawen Wu **/ 470e2a289a7SJiawen Wu s32 ngbe_check_for_msg_pf(struct ngbe_hw *hw, u16 vf_number) 471e2a289a7SJiawen Wu { 472e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 473e2a289a7SJiawen Wu u32 vf_bit = vf_number; 474e2a289a7SJiawen Wu 475e2a289a7SJiawen Wu if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFREQ_VF1 << vf_bit)) { 476e2a289a7SJiawen Wu ret_val = 0; 477e2a289a7SJiawen Wu hw->mbx.stats.reqs++; 478e2a289a7SJiawen Wu } 479e2a289a7SJiawen Wu 480e2a289a7SJiawen Wu return ret_val; 481e2a289a7SJiawen Wu } 482e2a289a7SJiawen Wu 483e2a289a7SJiawen Wu /** 484e2a289a7SJiawen Wu * ngbe_check_for_ack_pf - checks to see if the VF has ACKed 485e2a289a7SJiawen Wu * @hw: pointer to the HW structure 486e2a289a7SJiawen Wu * @vf_number: the VF index 487e2a289a7SJiawen Wu * 488e2a289a7SJiawen Wu * returns 0 if the VF has set the Status bit or else ERR_MBX 489e2a289a7SJiawen Wu **/ 490e2a289a7SJiawen Wu s32 ngbe_check_for_ack_pf(struct ngbe_hw *hw, u16 vf_number) 491e2a289a7SJiawen Wu { 492e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 493e2a289a7SJiawen Wu u32 vf_bit = vf_number; 494e2a289a7SJiawen Wu 495e2a289a7SJiawen Wu if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFACK_VF1 << vf_bit)) { 496e2a289a7SJiawen Wu ret_val = 0; 497e2a289a7SJiawen Wu hw->mbx.stats.acks++; 498e2a289a7SJiawen Wu } 499e2a289a7SJiawen Wu 500e2a289a7SJiawen Wu return ret_val; 501e2a289a7SJiawen Wu } 502e2a289a7SJiawen Wu 503e2a289a7SJiawen Wu /** 504e2a289a7SJiawen Wu * ngbe_check_for_rst_pf - checks to see if the VF has reset 505e2a289a7SJiawen Wu * @hw: pointer to the HW structure 506e2a289a7SJiawen Wu * @vf_number: the VF index 507e2a289a7SJiawen Wu * 508e2a289a7SJiawen Wu * returns 0 if the VF has set the Status bit or else ERR_MBX 509e2a289a7SJiawen Wu **/ 510e2a289a7SJiawen Wu s32 ngbe_check_for_rst_pf(struct ngbe_hw *hw, u16 vf_number) 511e2a289a7SJiawen Wu { 512e2a289a7SJiawen Wu u32 vflre = 0; 513e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 514e2a289a7SJiawen Wu 515e2a289a7SJiawen Wu vflre = rd32(hw, NGBE_FLRVFE); 516e2a289a7SJiawen Wu if (vflre & (1 << vf_number)) { 517e2a289a7SJiawen Wu ret_val = 0; 518e2a289a7SJiawen Wu wr32(hw, NGBE_FLRVFEC, (1 << vf_number)); 519e2a289a7SJiawen Wu hw->mbx.stats.rsts++; 520e2a289a7SJiawen Wu } 521e2a289a7SJiawen Wu 522e2a289a7SJiawen Wu return ret_val; 523e2a289a7SJiawen Wu } 524e2a289a7SJiawen Wu 525e2a289a7SJiawen Wu /** 526e2a289a7SJiawen Wu * ngbe_obtain_mbx_lock_pf - obtain mailbox lock 527e2a289a7SJiawen Wu * @hw: pointer to the HW structure 528e2a289a7SJiawen Wu * @vf_number: the VF index 529e2a289a7SJiawen Wu * 530e2a289a7SJiawen Wu * return 0 if we obtained the mailbox lock 531e2a289a7SJiawen Wu **/ 532e2a289a7SJiawen Wu STATIC s32 ngbe_obtain_mbx_lock_pf(struct ngbe_hw *hw, u16 vf_number) 533e2a289a7SJiawen Wu { 534e2a289a7SJiawen Wu s32 ret_val = NGBE_ERR_MBX; 535e2a289a7SJiawen Wu u32 p2v_mailbox; 536e2a289a7SJiawen Wu 537e2a289a7SJiawen Wu /* Take ownership of the buffer */ 538e2a289a7SJiawen Wu wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_PFU); 539e2a289a7SJiawen Wu 540e2a289a7SJiawen Wu /* reserve mailbox for vf use */ 541e2a289a7SJiawen Wu p2v_mailbox = rd32(hw, NGBE_MBCTL(vf_number)); 542e2a289a7SJiawen Wu if (p2v_mailbox & NGBE_MBCTL_PFU) 543e2a289a7SJiawen Wu ret_val = 0; 544e2a289a7SJiawen Wu else 545e2a289a7SJiawen Wu DEBUGOUT("Failed to obtain mailbox lock for VF%d", vf_number); 546e2a289a7SJiawen Wu 547e2a289a7SJiawen Wu 548e2a289a7SJiawen Wu return ret_val; 549e2a289a7SJiawen Wu } 550e2a289a7SJiawen Wu 551e2a289a7SJiawen Wu /** 552e2a289a7SJiawen Wu * ngbe_write_mbx_pf - Places a message in the mailbox 553e2a289a7SJiawen Wu * @hw: pointer to the HW structure 554e2a289a7SJiawen Wu * @msg: The message buffer 555e2a289a7SJiawen Wu * @size: Length of buffer 556e2a289a7SJiawen Wu * @vf_number: the VF index 557e2a289a7SJiawen Wu * 558e2a289a7SJiawen Wu * returns 0 if it successfully copied message into the buffer 559e2a289a7SJiawen Wu **/ 560e2a289a7SJiawen Wu s32 ngbe_write_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number) 561e2a289a7SJiawen Wu { 562e2a289a7SJiawen Wu s32 ret_val; 563e2a289a7SJiawen Wu u16 i; 564e2a289a7SJiawen Wu 565e2a289a7SJiawen Wu /* lock the mailbox to prevent pf/vf race condition */ 566e2a289a7SJiawen Wu ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number); 567e2a289a7SJiawen Wu if (ret_val) 568e2a289a7SJiawen Wu goto out_no_write; 569e2a289a7SJiawen Wu 570e2a289a7SJiawen Wu /* flush msg and acks as we are overwriting the message buffer */ 571e2a289a7SJiawen Wu ngbe_check_for_msg_pf(hw, vf_number); 572e2a289a7SJiawen Wu ngbe_check_for_ack_pf(hw, vf_number); 573e2a289a7SJiawen Wu 574e2a289a7SJiawen Wu /* copy the caller specified message to the mailbox memory buffer */ 575e2a289a7SJiawen Wu for (i = 0; i < size; i++) 576e2a289a7SJiawen Wu wr32a(hw, NGBE_MBMEM(vf_number), i, msg[i]); 577e2a289a7SJiawen Wu 578e2a289a7SJiawen Wu /* Interrupt VF to tell it a message has been sent and release buffer*/ 579e2a289a7SJiawen Wu wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_STS); 580e2a289a7SJiawen Wu 581e2a289a7SJiawen Wu /* update stats */ 582e2a289a7SJiawen Wu hw->mbx.stats.msgs_tx++; 583e2a289a7SJiawen Wu 584e2a289a7SJiawen Wu out_no_write: 585e2a289a7SJiawen Wu return ret_val; 586e2a289a7SJiawen Wu } 587e2a289a7SJiawen Wu 588e2a289a7SJiawen Wu /** 589e2a289a7SJiawen Wu * ngbe_read_mbx_pf - Read a message from the mailbox 590e2a289a7SJiawen Wu * @hw: pointer to the HW structure 591e2a289a7SJiawen Wu * @msg: The message buffer 592e2a289a7SJiawen Wu * @size: Length of buffer 593e2a289a7SJiawen Wu * @vf_number: the VF index 594e2a289a7SJiawen Wu * 595e2a289a7SJiawen Wu * This function copies a message from the mailbox buffer to the caller's 596e2a289a7SJiawen Wu * memory buffer. The presumption is that the caller knows that there was 597e2a289a7SJiawen Wu * a message due to a VF request so no polling for message is needed. 598e2a289a7SJiawen Wu **/ 599e2a289a7SJiawen Wu s32 ngbe_read_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number) 600e2a289a7SJiawen Wu { 601e2a289a7SJiawen Wu s32 ret_val; 602e2a289a7SJiawen Wu u16 i; 603e2a289a7SJiawen Wu 604e2a289a7SJiawen Wu /* lock the mailbox to prevent pf/vf race condition */ 605e2a289a7SJiawen Wu ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number); 606e2a289a7SJiawen Wu if (ret_val) 607e2a289a7SJiawen Wu goto out_no_read; 608e2a289a7SJiawen Wu 609e2a289a7SJiawen Wu /* copy the message to the mailbox memory buffer */ 610e2a289a7SJiawen Wu for (i = 0; i < size; i++) 611e2a289a7SJiawen Wu msg[i] = rd32a(hw, NGBE_MBMEM(vf_number), i); 612e2a289a7SJiawen Wu 613e2a289a7SJiawen Wu /* Acknowledge the message and release buffer */ 614e2a289a7SJiawen Wu wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_ACK); 615e2a289a7SJiawen Wu 616e2a289a7SJiawen Wu /* update stats */ 617e2a289a7SJiawen Wu hw->mbx.stats.msgs_rx++; 618e2a289a7SJiawen Wu 619e2a289a7SJiawen Wu out_no_read: 620e2a289a7SJiawen Wu return ret_val; 621e2a289a7SJiawen Wu } 622e2a289a7SJiawen Wu 623e2a289a7SJiawen Wu /** 62460229dcfSJiawen Wu * ngbe_init_mbx_params_pf - set initial values for pf mailbox 62560229dcfSJiawen Wu * @hw: pointer to the HW structure 62660229dcfSJiawen Wu * 62760229dcfSJiawen Wu * Initializes the hw->mbx struct to correct values for pf mailbox 62860229dcfSJiawen Wu */ 62960229dcfSJiawen Wu void ngbe_init_mbx_params_pf(struct ngbe_hw *hw) 63060229dcfSJiawen Wu { 63160229dcfSJiawen Wu struct ngbe_mbx_info *mbx = &hw->mbx; 63260229dcfSJiawen Wu 63360229dcfSJiawen Wu mbx->timeout = 0; 63460229dcfSJiawen Wu mbx->usec_delay = 0; 63560229dcfSJiawen Wu 63660229dcfSJiawen Wu mbx->size = NGBE_P2VMBX_SIZE; 63760229dcfSJiawen Wu 63860229dcfSJiawen Wu mbx->stats.msgs_tx = 0; 63960229dcfSJiawen Wu mbx->stats.msgs_rx = 0; 64060229dcfSJiawen Wu mbx->stats.reqs = 0; 64160229dcfSJiawen Wu mbx->stats.acks = 0; 64260229dcfSJiawen Wu mbx->stats.rsts = 0; 64360229dcfSJiawen Wu } 644