1 /******************************************************************************
2 SPDX-License-Identifier: BSD-3-Clause
4 Copyright (c) 2001-2017, Intel Corporation
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 3. Neither the name of the Intel Corporation nor the names of its
18 contributors may be used to endorse or promote products derived from
19 this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.
33 ******************************************************************************/
36 #include "ixgbe_type.h"
37 #include "ixgbe_mbx.h"
40 * ixgbe_poll_for_msg - Wait for message notification
41 * @hw: pointer to the HW structure
42 * @mbx_id: id of mailbox to write
44 * returns SUCCESS if it successfully received a message notification
46 static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
48 struct ixgbe_mbx_info *mbx = &hw->mbx;
49 int countdown = mbx->timeout;
51 DEBUGFUNC("ixgbe_poll_for_msg");
53 if (!countdown || !mbx->ops.check_for_msg)
56 while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
60 usec_delay(mbx->usec_delay);
64 ERROR_REPORT2(IXGBE_ERROR_POLLING,
65 "Polling for VF%d mailbox message timedout", mbx_id);
68 return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
72 * ixgbe_poll_for_ack - Wait for message acknowledgement
73 * @hw: pointer to the HW structure
74 * @mbx_id: id of mailbox to write
76 * returns SUCCESS if it successfully received a message acknowledgement
78 static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
80 struct ixgbe_mbx_info *mbx = &hw->mbx;
81 int countdown = mbx->timeout;
83 DEBUGFUNC("ixgbe_poll_for_ack");
85 if (!countdown || !mbx->ops.check_for_ack)
88 while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
92 usec_delay(mbx->usec_delay);
96 ERROR_REPORT2(IXGBE_ERROR_POLLING,
97 "Polling for VF%d mailbox ack timedout", mbx_id);
100 return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
104 * ixgbe_read_posted_mbx - Wait for message notification and receive message
105 * @hw: pointer to the HW structure
106 * @msg: The message buffer
107 * @size: Length of buffer
108 * @mbx_id: id of mailbox to write
110 * returns SUCCESS if it successfully received a message notification and
111 * copied it into the receive buffer.
113 static s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
116 struct ixgbe_mbx_info *mbx = &hw->mbx;
117 s32 ret_val = IXGBE_ERR_MBX;
119 DEBUGFUNC("ixgbe_read_posted_mbx");
124 ret_val = ixgbe_poll_for_msg(hw, mbx_id);
126 /* if ack received read message, otherwise we timed out */
128 ret_val = mbx->ops.read(hw, msg, size, mbx_id);
134 * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
135 * @hw: pointer to the HW structure
136 * @msg: The message buffer
137 * @size: Length of buffer
138 * @mbx_id: id of mailbox to write
140 * returns SUCCESS if it successfully copied message into the buffer and
141 * received an ack to that message within delay * timeout period
143 static s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
146 struct ixgbe_mbx_info *mbx = &hw->mbx;
147 s32 ret_val = IXGBE_ERR_MBX;
149 DEBUGFUNC("ixgbe_write_posted_mbx");
151 /* exit if either we can't write or there isn't a defined timeout */
152 if (!mbx->ops.write || !mbx->timeout)
156 ret_val = mbx->ops.write(hw, msg, size, mbx_id);
158 /* if msg sent wait until we receive an ack */
160 ret_val = ixgbe_poll_for_ack(hw, mbx_id);
166 * ixgbe_init_mbx_ops_generic - Initialize MB function pointers
167 * @hw: pointer to the HW structure
169 * Setups up the mailbox read and write message function pointers
171 void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
173 struct ixgbe_mbx_info *mbx = &hw->mbx;
175 mbx->ops.read_posted = ixgbe_read_posted_mbx;
176 mbx->ops.write_posted = ixgbe_write_posted_mbx;
180 * ixgbe_read_v2p_mailbox - read v2p mailbox
181 * @hw: pointer to the HW structure
183 * This function is used to read the v2p mailbox without losing the read to
186 static u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw)
188 u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
190 v2p_mailbox |= hw->mbx.v2p_mailbox;
191 hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
197 * ixgbe_check_for_bit_vf - Determine if a status bit was set
198 * @hw: pointer to the HW structure
199 * @mask: bitmask for bits to be tested and cleared
201 * This function is used to check for the read to clear bits within
204 static s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask)
206 u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw);
207 s32 ret_val = IXGBE_ERR_MBX;
209 if (v2p_mailbox & mask)
210 ret_val = IXGBE_SUCCESS;
212 hw->mbx.v2p_mailbox &= ~mask;
218 * ixgbe_check_for_msg_vf - checks to see if the PF has sent mail
219 * @hw: pointer to the HW structure
220 * @mbx_id: id of mailbox to check
222 * returns SUCCESS if the PF has set the Status bit or else ERR_MBX
224 static s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id)
226 s32 ret_val = IXGBE_ERR_MBX;
228 UNREFERENCED_1PARAMETER(mbx_id);
229 DEBUGFUNC("ixgbe_check_for_msg_vf");
231 if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) {
232 ret_val = IXGBE_SUCCESS;
233 hw->mbx.stats.reqs++;
240 * ixgbe_check_for_ack_vf - checks to see if the PF has ACK'd
241 * @hw: pointer to the HW structure
242 * @mbx_id: id of mailbox to check
244 * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
246 static s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id)
248 s32 ret_val = IXGBE_ERR_MBX;
250 UNREFERENCED_1PARAMETER(mbx_id);
251 DEBUGFUNC("ixgbe_check_for_ack_vf");
253 if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) {
254 ret_val = IXGBE_SUCCESS;
255 hw->mbx.stats.acks++;
262 * ixgbe_check_for_rst_vf - checks to see if the PF has reset
263 * @hw: pointer to the HW structure
264 * @mbx_id: id of mailbox to check
266 * returns TRUE if the PF has set the reset done bit or else FALSE
268 static s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id)
270 s32 ret_val = IXGBE_ERR_MBX;
272 UNREFERENCED_1PARAMETER(mbx_id);
273 DEBUGFUNC("ixgbe_check_for_rst_vf");
275 if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD |
276 IXGBE_VFMAILBOX_RSTI))) {
277 ret_val = IXGBE_SUCCESS;
278 hw->mbx.stats.rsts++;
285 * ixgbe_obtain_mbx_lock_vf - obtain mailbox lock
286 * @hw: pointer to the HW structure
288 * return SUCCESS if we obtained the mailbox lock
290 static s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
292 s32 ret_val = IXGBE_ERR_MBX;
294 DEBUGFUNC("ixgbe_obtain_mbx_lock_vf");
296 /* Take ownership of the buffer */
297 IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU);
299 /* reserve mailbox for vf use */
300 if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU)
301 ret_val = IXGBE_SUCCESS;
307 * ixgbe_write_mbx_vf - Write a message to the mailbox
308 * @hw: pointer to the HW structure
309 * @msg: The message buffer
310 * @size: Length of buffer
311 * @mbx_id: id of mailbox to write
313 * returns SUCCESS if it successfully copied message into the buffer
315 static s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
321 UNREFERENCED_1PARAMETER(mbx_id);
323 DEBUGFUNC("ixgbe_write_mbx_vf");
325 /* lock the mailbox to prevent pf/vf race condition */
326 ret_val = ixgbe_obtain_mbx_lock_vf(hw);
330 /* flush msg and acks as we are overwriting the message buffer */
331 ixgbe_check_for_msg_vf(hw, 0);
332 ixgbe_check_for_ack_vf(hw, 0);
334 /* copy the caller specified message to the mailbox memory buffer */
335 for (i = 0; i < size; i++)
336 IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]);
339 hw->mbx.stats.msgs_tx++;
341 /* Drop VFU and interrupt the PF to tell it a message has been sent */
342 IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
349 * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
350 * @hw: pointer to the HW structure
351 * @msg: The message buffer
352 * @size: Length of buffer
353 * @mbx_id: id of mailbox to read
355 * returns SUCCESS if it successfully read message from buffer
357 static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
360 s32 ret_val = IXGBE_SUCCESS;
363 DEBUGFUNC("ixgbe_read_mbx_vf");
364 UNREFERENCED_1PARAMETER(mbx_id);
366 /* lock the mailbox to prevent pf/vf race condition */
367 ret_val = ixgbe_obtain_mbx_lock_vf(hw);
371 /* copy the message from the mailbox memory buffer */
372 for (i = 0; i < size; i++)
373 msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i);
375 /* Acknowledge receipt and release mailbox, then we're done */
376 IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
379 hw->mbx.stats.msgs_rx++;
386 * ixgbe_init_mbx_params_vf - set initial values for vf mailbox
387 * @hw: pointer to the HW structure
389 * Initializes the hw->mbx struct to correct values for vf mailbox
391 void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
393 struct ixgbe_mbx_info *mbx = &hw->mbx;
395 /* start mailbox as timed out and let the reset_hw call set the timeout
396 * value to begin communications */
398 mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
400 mbx->size = IXGBE_VFMAILBOX_SIZE;
402 mbx->ops.read = ixgbe_read_mbx_vf;
403 mbx->ops.write = ixgbe_write_mbx_vf;
404 mbx->ops.read_posted = ixgbe_read_posted_mbx;
405 mbx->ops.write_posted = ixgbe_write_posted_mbx;
406 mbx->ops.check_for_msg = ixgbe_check_for_msg_vf;
407 mbx->ops.check_for_ack = ixgbe_check_for_ack_vf;
408 mbx->ops.check_for_rst = ixgbe_check_for_rst_vf;
410 mbx->stats.msgs_tx = 0;
411 mbx->stats.msgs_rx = 0;
417 static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
419 u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
420 s32 ret_val = IXGBE_ERR_MBX;
422 if (mbvficr & mask) {
423 ret_val = IXGBE_SUCCESS;
424 IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
431 * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
432 * @hw: pointer to the HW structure
433 * @vf_number: the VF index
435 * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
437 static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
439 s32 ret_val = IXGBE_ERR_MBX;
440 s32 index = IXGBE_MBVFICR_INDEX(vf_number);
441 u32 vf_bit = vf_number % 16;
443 DEBUGFUNC("ixgbe_check_for_msg_pf");
445 if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
447 ret_val = IXGBE_SUCCESS;
448 hw->mbx.stats.reqs++;
455 * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
456 * @hw: pointer to the HW structure
457 * @vf_number: the VF index
459 * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
461 static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
463 s32 ret_val = IXGBE_ERR_MBX;
464 s32 index = IXGBE_MBVFICR_INDEX(vf_number);
465 u32 vf_bit = vf_number % 16;
467 DEBUGFUNC("ixgbe_check_for_ack_pf");
469 if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
471 ret_val = IXGBE_SUCCESS;
472 hw->mbx.stats.acks++;
479 * ixgbe_check_for_rst_pf - checks to see if the VF has reset
480 * @hw: pointer to the HW structure
481 * @vf_number: the VF index
483 * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
485 static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
487 u32 reg_offset = (vf_number < 32) ? 0 : 1;
488 u32 vf_shift = vf_number % 32;
490 s32 ret_val = IXGBE_ERR_MBX;
492 DEBUGFUNC("ixgbe_check_for_rst_pf");
494 switch (hw->mac.type) {
495 case ixgbe_mac_82599EB:
496 vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
499 case ixgbe_mac_X550EM_x:
500 case ixgbe_mac_X550EM_a:
502 vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
508 if (vflre & (1 << vf_shift)) {
509 ret_val = IXGBE_SUCCESS;
510 IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
511 hw->mbx.stats.rsts++;
518 * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
519 * @hw: pointer to the HW structure
520 * @vf_number: the VF index
522 * return SUCCESS if we obtained the mailbox lock
524 static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
526 s32 ret_val = IXGBE_ERR_MBX;
529 DEBUGFUNC("ixgbe_obtain_mbx_lock_pf");
531 /* Take ownership of the buffer */
532 IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
534 /* reserve mailbox for vf use */
535 p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
536 if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
537 ret_val = IXGBE_SUCCESS;
539 ERROR_REPORT2(IXGBE_ERROR_POLLING,
540 "Failed to obtain mailbox lock for VF%d", vf_number);
547 * ixgbe_write_mbx_pf - Places a message in the mailbox
548 * @hw: pointer to the HW structure
549 * @msg: The message buffer
550 * @size: Length of buffer
551 * @vf_number: the VF index
553 * returns SUCCESS if it successfully copied message into the buffer
555 static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
561 DEBUGFUNC("ixgbe_write_mbx_pf");
563 /* lock the mailbox to prevent pf/vf race condition */
564 ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
568 /* flush msg and acks as we are overwriting the message buffer */
569 ixgbe_check_for_msg_pf(hw, vf_number);
570 ixgbe_check_for_ack_pf(hw, vf_number);
572 /* copy the caller specified message to the mailbox memory buffer */
573 for (i = 0; i < size; i++)
574 IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
576 /* Interrupt VF to tell it a message has been sent and release buffer*/
577 IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
580 hw->mbx.stats.msgs_tx++;
588 * ixgbe_read_mbx_pf - Read a message from the mailbox
589 * @hw: pointer to the HW structure
590 * @msg: The message buffer
591 * @size: Length of buffer
592 * @vf_number: the VF index
594 * This function copies a message from the mailbox buffer to the caller's
595 * memory buffer. The presumption is that the caller knows that there was
596 * a message due to a VF request so no polling for message is needed.
598 static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
604 DEBUGFUNC("ixgbe_read_mbx_pf");
606 /* lock the mailbox to prevent pf/vf race condition */
607 ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
611 /* copy the message to the mailbox memory buffer */
612 for (i = 0; i < size; i++)
613 msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
615 /* Acknowledge the message and release buffer */
616 IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
619 hw->mbx.stats.msgs_rx++;
626 * ixgbe_init_mbx_params_pf - set initial values for pf mailbox
627 * @hw: pointer to the HW structure
629 * Initializes the hw->mbx struct to correct values for pf mailbox
631 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
633 struct ixgbe_mbx_info *mbx = &hw->mbx;
635 if (hw->mac.type != ixgbe_mac_82599EB &&
636 hw->mac.type != ixgbe_mac_X550 &&
637 hw->mac.type != ixgbe_mac_X550EM_x &&
638 hw->mac.type != ixgbe_mac_X550EM_a &&
639 hw->mac.type != ixgbe_mac_X540)
645 mbx->size = IXGBE_VFMAILBOX_SIZE;
647 mbx->ops.read = ixgbe_read_mbx_pf;
648 mbx->ops.write = ixgbe_write_mbx_pf;
649 mbx->ops.read_posted = ixgbe_read_posted_mbx;
650 mbx->ops.write_posted = ixgbe_write_posted_mbx;
651 mbx->ops.check_for_msg = ixgbe_check_for_msg_pf;
652 mbx->ops.check_for_ack = ixgbe_check_for_ack_pf;
653 mbx->ops.check_for_rst = ixgbe_check_for_rst_pf;
655 mbx->stats.msgs_tx = 0;
656 mbx->stats.msgs_rx = 0;