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