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