xref: /freebsd/sys/dev/ixgbe/ixgbe_mbx.c (revision a8089ea5aee578e08acab2438e82fc9a9ae50ed8)
1 /******************************************************************************
2   SPDX-License-Identifier: BSD-3-Clause
3 
4   Copyright (c) 2001-2020, Intel Corporation
5   All rights reserved.
6 
7   Redistribution and use in source and binary forms, with or without
8   modification, are permitted provided that the following conditions are met:
9 
10    1. Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12 
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.
16 
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.
20 
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.
32 
33 ******************************************************************************/
34 
35 #include "ixgbe_type.h"
36 #include "ixgbe_mbx.h"
37 
38 /**
39  * ixgbe_read_mbx - Reads a message from the mailbox
40  * @hw: pointer to the HW structure
41  * @msg: The message buffer
42  * @size: Length of buffer
43  * @mbx_id: id of mailbox to read
44  *
45  * returns SUCCESS if it successfully read message from buffer
46  **/
47 s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
48 {
49 	struct ixgbe_mbx_info *mbx = &hw->mbx;
50 	s32 ret_val = IXGBE_ERR_MBX;
51 
52 	DEBUGFUNC("ixgbe_read_mbx");
53 
54 	/* limit read to size of mailbox */
55 	if (size > mbx->size)
56 		size = mbx->size;
57 
58 	if (mbx->ops.read)
59 		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
60 
61 	return ret_val;
62 }
63 
64 /**
65  * ixgbe_write_mbx - Write a message to the mailbox
66  * @hw: pointer to the HW structure
67  * @msg: The message buffer
68  * @size: Length of buffer
69  * @mbx_id: id of mailbox to write
70  *
71  * returns SUCCESS if it successfully copied message into the buffer
72  **/
73 s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
74 {
75 	struct ixgbe_mbx_info *mbx = &hw->mbx;
76 	s32 ret_val = IXGBE_SUCCESS;
77 
78 	DEBUGFUNC("ixgbe_write_mbx");
79 
80 	if (size > mbx->size) {
81 		ret_val = IXGBE_ERR_MBX;
82 		ERROR_REPORT2(IXGBE_ERROR_ARGUMENT,
83 			     "Invalid mailbox message size %d", size);
84 	} else if (mbx->ops.write)
85 		ret_val = mbx->ops.write(hw, msg, size, mbx_id);
86 
87 	return ret_val;
88 }
89 
90 /**
91  * ixgbe_check_for_msg - checks to see if someone sent us mail
92  * @hw: pointer to the HW structure
93  * @mbx_id: id of mailbox to check
94  *
95  * returns SUCCESS if the Status bit was found or else ERR_MBX
96  **/
97 s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
98 {
99 	struct ixgbe_mbx_info *mbx = &hw->mbx;
100 	s32 ret_val = IXGBE_ERR_MBX;
101 
102 	DEBUGFUNC("ixgbe_check_for_msg");
103 
104 	if (mbx->ops.check_for_msg)
105 		ret_val = mbx->ops.check_for_msg(hw, mbx_id);
106 
107 	return ret_val;
108 }
109 
110 /**
111  * ixgbe_check_for_ack - checks to see if someone sent us ACK
112  * @hw: pointer to the HW structure
113  * @mbx_id: id of mailbox to check
114  *
115  * returns SUCCESS if the Status bit was found or else ERR_MBX
116  **/
117 s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
118 {
119 	struct ixgbe_mbx_info *mbx = &hw->mbx;
120 	s32 ret_val = IXGBE_ERR_MBX;
121 
122 	DEBUGFUNC("ixgbe_check_for_ack");
123 
124 	if (mbx->ops.check_for_ack)
125 		ret_val = mbx->ops.check_for_ack(hw, mbx_id);
126 
127 	return ret_val;
128 }
129 
130 /**
131  * ixgbe_check_for_rst - checks to see if other side has reset
132  * @hw: pointer to the HW structure
133  * @mbx_id: id of mailbox to check
134  *
135  * returns SUCCESS if the Status bit was found or else ERR_MBX
136  **/
137 s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id)
138 {
139 	struct ixgbe_mbx_info *mbx = &hw->mbx;
140 	s32 ret_val = IXGBE_ERR_MBX;
141 
142 	DEBUGFUNC("ixgbe_check_for_rst");
143 
144 	if (mbx->ops.check_for_rst)
145 		ret_val = mbx->ops.check_for_rst(hw, mbx_id);
146 
147 	return ret_val;
148 }
149 
150 /**
151  * ixgbe_poll_for_msg - Wait for message notification
152  * @hw: pointer to the HW structure
153  * @mbx_id: id of mailbox to write
154  *
155  * returns SUCCESS if it successfully received a message notification
156  **/
157 static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
158 {
159 	struct ixgbe_mbx_info *mbx = &hw->mbx;
160 	int countdown = mbx->timeout;
161 
162 	DEBUGFUNC("ixgbe_poll_for_msg");
163 
164 	if (!countdown || !mbx->ops.check_for_msg)
165 		goto out;
166 
167 	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
168 		countdown--;
169 		if (!countdown)
170 			break;
171 		usec_delay(mbx->usec_delay);
172 	}
173 
174 	if (countdown == 0)
175 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
176 			   "Polling for VF%d mailbox message timedout", mbx_id);
177 
178 out:
179 	return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
180 }
181 
182 /**
183  * ixgbe_poll_for_ack - Wait for message acknowledgment
184  * @hw: pointer to the HW structure
185  * @mbx_id: id of mailbox to write
186  *
187  * returns SUCCESS if it successfully received a message acknowledgment
188  **/
189 static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
190 {
191 	struct ixgbe_mbx_info *mbx = &hw->mbx;
192 	int countdown = mbx->timeout;
193 
194 	DEBUGFUNC("ixgbe_poll_for_ack");
195 
196 	if (!countdown || !mbx->ops.check_for_ack)
197 		goto out;
198 
199 	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
200 		countdown--;
201 		if (!countdown)
202 			break;
203 		usec_delay(mbx->usec_delay);
204 	}
205 
206 	if (countdown == 0)
207 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
208 			     "Polling for VF%d mailbox ack timedout", mbx_id);
209 
210 out:
211 	return countdown ? IXGBE_SUCCESS : IXGBE_ERR_MBX;
212 }
213 
214 /**
215  * ixgbe_read_posted_mbx - Wait for message notification and receive message
216  * @hw: pointer to the HW structure
217  * @msg: The message buffer
218  * @size: Length of buffer
219  * @mbx_id: id of mailbox to write
220  *
221  * returns SUCCESS if it successfully received a message notification and
222  * copied it into the receive buffer.
223  **/
224 s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
225 				 u16 mbx_id)
226 {
227 	struct ixgbe_mbx_info *mbx = &hw->mbx;
228 	s32 ret_val = IXGBE_ERR_MBX;
229 
230 	DEBUGFUNC("ixgbe_read_posted_mbx");
231 
232 	if (!mbx->ops.read)
233 		goto out;
234 
235 	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
236 
237 	/* if ack received read message, otherwise we timed out */
238 	if (!ret_val)
239 		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
240 out:
241 	return ret_val;
242 }
243 
244 /**
245  * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
246  * @hw: pointer to the HW structure
247  * @msg: The message buffer
248  * @size: Length of buffer
249  * @mbx_id: id of mailbox to write
250  *
251  * returns SUCCESS if it successfully copied message into the buffer and
252  * received an ack to that message within delay * timeout period
253  **/
254 s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size,
255 				  u16 mbx_id)
256 {
257 	struct ixgbe_mbx_info *mbx = &hw->mbx;
258 	s32 ret_val = IXGBE_ERR_MBX;
259 
260 	DEBUGFUNC("ixgbe_write_posted_mbx");
261 
262 	/* exit if either we can't write or there isn't a defined timeout */
263 	if (!mbx->ops.write || !mbx->timeout)
264 		goto out;
265 
266 	/* send msg */
267 	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
268 
269 	/* if msg sent wait until we receive an ack */
270 	if (!ret_val)
271 		ret_val = ixgbe_poll_for_ack(hw, mbx_id);
272 out:
273 	return ret_val;
274 }
275 
276 /**
277  * ixgbe_init_mbx_ops_generic - Initialize MB function pointers
278  * @hw: pointer to the HW structure
279  *
280  * Setups up the mailbox read and write message function pointers
281  **/
282 void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw)
283 {
284 	struct ixgbe_mbx_info *mbx = &hw->mbx;
285 
286 	mbx->ops.read_posted = ixgbe_read_posted_mbx;
287 	mbx->ops.write_posted = ixgbe_write_posted_mbx;
288 }
289 
290 /**
291  * ixgbe_read_v2p_mailbox - read v2p mailbox
292  * @hw: pointer to the HW structure
293  *
294  * This function is used to read the v2p mailbox without losing the read to
295  * clear status bits.
296  **/
297 static u32 ixgbe_read_v2p_mailbox(struct ixgbe_hw *hw)
298 {
299 	u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX);
300 
301 	v2p_mailbox |= hw->mbx.v2p_mailbox;
302 	hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS;
303 
304 	return v2p_mailbox;
305 }
306 
307 /**
308  * ixgbe_check_for_bit_vf - Determine if a status bit was set
309  * @hw: pointer to the HW structure
310  * @mask: bitmask for bits to be tested and cleared
311  *
312  * This function is used to check for the read to clear bits within
313  * the V2P mailbox.
314  **/
315 static s32 ixgbe_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask)
316 {
317 	u32 v2p_mailbox = ixgbe_read_v2p_mailbox(hw);
318 	s32 ret_val = IXGBE_ERR_MBX;
319 
320 	if (v2p_mailbox & mask)
321 		ret_val = IXGBE_SUCCESS;
322 
323 	hw->mbx.v2p_mailbox &= ~mask;
324 
325 	return ret_val;
326 }
327 
328 /**
329  * ixgbe_check_for_msg_vf - checks to see if the PF has sent mail
330  * @hw: pointer to the HW structure
331  * @mbx_id: id of mailbox to check
332  *
333  * returns SUCCESS if the PF has set the Status bit or else ERR_MBX
334  **/
335 static s32 ixgbe_check_for_msg_vf(struct ixgbe_hw *hw, u16 mbx_id)
336 {
337 	s32 ret_val = IXGBE_ERR_MBX;
338 
339 	UNREFERENCED_1PARAMETER(mbx_id);
340 	DEBUGFUNC("ixgbe_check_for_msg_vf");
341 
342 	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) {
343 		ret_val = IXGBE_SUCCESS;
344 		hw->mbx.stats.reqs++;
345 	}
346 
347 	return ret_val;
348 }
349 
350 /**
351  * ixgbe_check_for_ack_vf - checks to see if the PF has ACK'd
352  * @hw: pointer to the HW structure
353  * @mbx_id: id of mailbox to check
354  *
355  * returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
356  **/
357 static s32 ixgbe_check_for_ack_vf(struct ixgbe_hw *hw, u16 mbx_id)
358 {
359 	s32 ret_val = IXGBE_ERR_MBX;
360 
361 	UNREFERENCED_1PARAMETER(mbx_id);
362 	DEBUGFUNC("ixgbe_check_for_ack_vf");
363 
364 	if (!ixgbe_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) {
365 		ret_val = IXGBE_SUCCESS;
366 		hw->mbx.stats.acks++;
367 	}
368 
369 	return ret_val;
370 }
371 
372 /**
373  * ixgbe_check_for_rst_vf - checks to see if the PF has reset
374  * @hw: pointer to the HW structure
375  * @mbx_id: id of mailbox to check
376  *
377  * returns true if the PF has set the reset done bit or else false
378  **/
379 static s32 ixgbe_check_for_rst_vf(struct ixgbe_hw *hw, u16 mbx_id)
380 {
381 	s32 ret_val = IXGBE_ERR_MBX;
382 
383 	UNREFERENCED_1PARAMETER(mbx_id);
384 	DEBUGFUNC("ixgbe_check_for_rst_vf");
385 
386 	if (!ixgbe_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD |
387 	    IXGBE_VFMAILBOX_RSTI))) {
388 		ret_val = IXGBE_SUCCESS;
389 		hw->mbx.stats.rsts++;
390 	}
391 
392 	return ret_val;
393 }
394 
395 /**
396  * ixgbe_obtain_mbx_lock_vf - obtain mailbox lock
397  * @hw: pointer to the HW structure
398  *
399  * return SUCCESS if we obtained the mailbox lock
400  **/
401 static s32 ixgbe_obtain_mbx_lock_vf(struct ixgbe_hw *hw)
402 {
403 	s32 ret_val = IXGBE_ERR_MBX;
404 
405 	DEBUGFUNC("ixgbe_obtain_mbx_lock_vf");
406 
407 	/* Take ownership of the buffer */
408 	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU);
409 
410 	/* reserve mailbox for vf use */
411 	if (ixgbe_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU)
412 		ret_val = IXGBE_SUCCESS;
413 
414 	return ret_val;
415 }
416 
417 /**
418  * ixgbe_write_mbx_vf - Write a message to the mailbox
419  * @hw: pointer to the HW structure
420  * @msg: The message buffer
421  * @size: Length of buffer
422  * @mbx_id: id of mailbox to write
423  *
424  * returns SUCCESS if it successfully copied message into the buffer
425  **/
426 static s32 ixgbe_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
427 			      u16 mbx_id)
428 {
429 	s32 ret_val;
430 	u16 i;
431 
432 	UNREFERENCED_1PARAMETER(mbx_id);
433 
434 	DEBUGFUNC("ixgbe_write_mbx_vf");
435 
436 	/* lock the mailbox to prevent pf/vf race condition */
437 	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
438 	if (ret_val)
439 		goto out_no_write;
440 
441 	/* flush msg and acks as we are overwriting the message buffer */
442 	ixgbe_check_for_msg_vf(hw, 0);
443 	ixgbe_check_for_ack_vf(hw, 0);
444 
445 	/* copy the caller specified message to the mailbox memory buffer */
446 	for (i = 0; i < size; i++)
447 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]);
448 
449 	/* update stats */
450 	hw->mbx.stats.msgs_tx++;
451 
452 	/* Drop VFU and interrupt the PF to tell it a message has been sent */
453 	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ);
454 
455 out_no_write:
456 	return ret_val;
457 }
458 
459 /**
460  * ixgbe_read_mbx_vf - Reads a message from the inbox intended for vf
461  * @hw: pointer to the HW structure
462  * @msg: The message buffer
463  * @size: Length of buffer
464  * @mbx_id: id of mailbox to read
465  *
466  * returns SUCCESS if it successfully read message from buffer
467  **/
468 static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size,
469 			     u16 mbx_id)
470 {
471 	s32 ret_val = IXGBE_SUCCESS;
472 	u16 i;
473 
474 	DEBUGFUNC("ixgbe_read_mbx_vf");
475 	UNREFERENCED_1PARAMETER(mbx_id);
476 
477 	/* lock the mailbox to prevent pf/vf race condition */
478 	ret_val = ixgbe_obtain_mbx_lock_vf(hw);
479 	if (ret_val)
480 		goto out_no_read;
481 
482 	/* copy the message from the mailbox memory buffer */
483 	for (i = 0; i < size; i++)
484 		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i);
485 
486 	/* Acknowledge receipt and release mailbox, then we're done */
487 	IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK);
488 
489 	/* update stats */
490 	hw->mbx.stats.msgs_rx++;
491 
492 out_no_read:
493 	return ret_val;
494 }
495 
496 /**
497  * ixgbe_init_mbx_params_vf - set initial values for vf mailbox
498  * @hw: pointer to the HW structure
499  *
500  * Initializes the hw->mbx struct to correct values for vf mailbox
501  */
502 void ixgbe_init_mbx_params_vf(struct ixgbe_hw *hw)
503 {
504 	struct ixgbe_mbx_info *mbx = &hw->mbx;
505 
506 	/* start mailbox as timed out and let the reset_hw call set the timeout
507 	 * value to begin communications */
508 	mbx->timeout = 0;
509 	mbx->usec_delay = IXGBE_VF_MBX_INIT_DELAY;
510 
511 	mbx->size = IXGBE_VFMAILBOX_SIZE;
512 
513 	mbx->ops.read = ixgbe_read_mbx_vf;
514 	mbx->ops.write = ixgbe_write_mbx_vf;
515 	mbx->ops.read_posted = ixgbe_read_posted_mbx;
516 	mbx->ops.write_posted = ixgbe_write_posted_mbx;
517 	mbx->ops.check_for_msg = ixgbe_check_for_msg_vf;
518 	mbx->ops.check_for_ack = ixgbe_check_for_ack_vf;
519 	mbx->ops.check_for_rst = ixgbe_check_for_rst_vf;
520 
521 	mbx->stats.msgs_tx = 0;
522 	mbx->stats.msgs_rx = 0;
523 	mbx->stats.reqs = 0;
524 	mbx->stats.acks = 0;
525 	mbx->stats.rsts = 0;
526 }
527 
528 static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index)
529 {
530 	u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index));
531 	s32 ret_val = IXGBE_ERR_MBX;
532 
533 	if (mbvficr & mask) {
534 		ret_val = IXGBE_SUCCESS;
535 		IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask);
536 	}
537 
538 	return ret_val;
539 }
540 
541 /**
542  * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail
543  * @hw: pointer to the HW structure
544  * @vf_number: the VF index
545  *
546  * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
547  **/
548 static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number)
549 {
550 	s32 ret_val = IXGBE_ERR_MBX;
551 	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
552 	u32 vf_bit = vf_number % 16;
553 
554 	DEBUGFUNC("ixgbe_check_for_msg_pf");
555 
556 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit,
557 				    index)) {
558 		ret_val = IXGBE_SUCCESS;
559 		hw->mbx.stats.reqs++;
560 	}
561 
562 	return ret_val;
563 }
564 
565 /**
566  * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed
567  * @hw: pointer to the HW structure
568  * @vf_number: the VF index
569  *
570  * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
571  **/
572 static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number)
573 {
574 	s32 ret_val = IXGBE_ERR_MBX;
575 	s32 index = IXGBE_MBVFICR_INDEX(vf_number);
576 	u32 vf_bit = vf_number % 16;
577 
578 	DEBUGFUNC("ixgbe_check_for_ack_pf");
579 
580 	if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit,
581 				    index)) {
582 		ret_val = IXGBE_SUCCESS;
583 		hw->mbx.stats.acks++;
584 	}
585 
586 	return ret_val;
587 }
588 
589 /**
590  * ixgbe_check_for_rst_pf - checks to see if the VF has reset
591  * @hw: pointer to the HW structure
592  * @vf_number: the VF index
593  *
594  * returns SUCCESS if the VF has set the Status bit or else ERR_MBX
595  **/
596 static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
597 {
598 	u32 reg_offset = (vf_number < 32) ? 0 : 1;
599 	u32 vf_shift = vf_number % 32;
600 	u32 vflre = 0;
601 	s32 ret_val = IXGBE_ERR_MBX;
602 
603 	DEBUGFUNC("ixgbe_check_for_rst_pf");
604 
605 	switch (hw->mac.type) {
606 	case ixgbe_mac_82599EB:
607 		vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
608 		break;
609 	case ixgbe_mac_X550:
610 	case ixgbe_mac_X550EM_x:
611 	case ixgbe_mac_X550EM_a:
612 	case ixgbe_mac_X540:
613 		vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
614 		break;
615 	default:
616 		break;
617 	}
618 
619 	if (vflre & (1 << vf_shift)) {
620 		ret_val = IXGBE_SUCCESS;
621 		IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift));
622 		hw->mbx.stats.rsts++;
623 	}
624 
625 	return ret_val;
626 }
627 
628 /**
629  * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock
630  * @hw: pointer to the HW structure
631  * @vf_number: the VF index
632  *
633  * return SUCCESS if we obtained the mailbox lock
634  **/
635 static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number)
636 {
637 	s32 ret_val = IXGBE_ERR_MBX;
638 	u32 p2v_mailbox;
639 
640 	DEBUGFUNC("ixgbe_obtain_mbx_lock_pf");
641 
642 	/* Take ownership of the buffer */
643 	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU);
644 
645 	/* reserve mailbox for vf use */
646 	p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number));
647 	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
648 		ret_val = IXGBE_SUCCESS;
649 	else
650 		ERROR_REPORT2(IXGBE_ERROR_POLLING,
651 			   "Failed to obtain mailbox lock for VF%d", vf_number);
652 
653 
654 	return ret_val;
655 }
656 
657 /**
658  * ixgbe_write_mbx_pf - Places a message in the mailbox
659  * @hw: pointer to the HW structure
660  * @msg: The message buffer
661  * @size: Length of buffer
662  * @vf_number: the VF index
663  *
664  * returns SUCCESS if it successfully copied message into the buffer
665  **/
666 static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
667 			      u16 vf_number)
668 {
669 	s32 ret_val;
670 	u16 i;
671 
672 	DEBUGFUNC("ixgbe_write_mbx_pf");
673 
674 	/* lock the mailbox to prevent pf/vf race condition */
675 	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
676 	if (ret_val)
677 		goto out_no_write;
678 
679 	/* flush msg and acks as we are overwriting the message buffer */
680 	ixgbe_check_for_msg_pf(hw, vf_number);
681 	ixgbe_check_for_ack_pf(hw, vf_number);
682 
683 	/* copy the caller specified message to the mailbox memory buffer */
684 	for (i = 0; i < size; i++)
685 		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]);
686 
687 	/* Interrupt VF to tell it a message has been sent and release buffer*/
688 	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS);
689 
690 	/* update stats */
691 	hw->mbx.stats.msgs_tx++;
692 
693 out_no_write:
694 	return ret_val;
695 
696 }
697 
698 /**
699  * ixgbe_read_mbx_pf - Read a message from the mailbox
700  * @hw: pointer to the HW structure
701  * @msg: The message buffer
702  * @size: Length of buffer
703  * @vf_number: the VF index
704  *
705  * This function copies a message from the mailbox buffer to the caller's
706  * memory buffer.  The presumption is that the caller knows that there was
707  * a message due to a VF request so no polling for message is needed.
708  **/
709 static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size,
710 			     u16 vf_number)
711 {
712 	s32 ret_val;
713 	u16 i;
714 
715 	DEBUGFUNC("ixgbe_read_mbx_pf");
716 
717 	/* lock the mailbox to prevent pf/vf race condition */
718 	ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number);
719 	if (ret_val)
720 		goto out_no_read;
721 
722 	/* copy the message to the mailbox memory buffer */
723 	for (i = 0; i < size; i++)
724 		msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i);
725 
726 	/* Acknowledge the message and release buffer */
727 	IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK);
728 
729 	/* update stats */
730 	hw->mbx.stats.msgs_rx++;
731 
732 out_no_read:
733 	return ret_val;
734 }
735 
736 /**
737  * ixgbe_init_mbx_params_pf - set initial values for pf mailbox
738  * @hw: pointer to the HW structure
739  *
740  * Initializes the hw->mbx struct to correct values for pf mailbox
741  */
742 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
743 {
744 	struct ixgbe_mbx_info *mbx = &hw->mbx;
745 
746 	if (hw->mac.type != ixgbe_mac_82599EB &&
747 	    hw->mac.type != ixgbe_mac_X550 &&
748 	    hw->mac.type != ixgbe_mac_X550EM_x &&
749 	    hw->mac.type != ixgbe_mac_X550EM_a &&
750 	    hw->mac.type != ixgbe_mac_X540)
751 		return;
752 
753 	mbx->timeout = 0;
754 	mbx->usec_delay = 0;
755 
756 	mbx->size = IXGBE_VFMAILBOX_SIZE;
757 
758 	mbx->ops.read = ixgbe_read_mbx_pf;
759 	mbx->ops.write = ixgbe_write_mbx_pf;
760 	mbx->ops.read_posted = ixgbe_read_posted_mbx;
761 	mbx->ops.write_posted = ixgbe_write_posted_mbx;
762 	mbx->ops.check_for_msg = ixgbe_check_for_msg_pf;
763 	mbx->ops.check_for_ack = ixgbe_check_for_ack_pf;
764 	mbx->ops.check_for_rst = ixgbe_check_for_rst_pf;
765 
766 	mbx->stats.msgs_tx = 0;
767 	mbx->stats.msgs_rx = 0;
768 	mbx->stats.reqs = 0;
769 	mbx->stats.acks = 0;
770 	mbx->stats.rsts = 0;
771 }
772