1209616Sjfv/******************************************************************************
2209616Sjfv
3294958Smarius  Copyright (c) 2001-2015, Intel Corporation
4209616Sjfv  All rights reserved.
5209616Sjfv
6209616Sjfv  Redistribution and use in source and binary forms, with or without
7209616Sjfv  modification, are permitted provided that the following conditions are met:
8209616Sjfv
9209616Sjfv   1. Redistributions of source code must retain the above copyright notice,
10209616Sjfv      this list of conditions and the following disclaimer.
11209616Sjfv
12209616Sjfv   2. Redistributions in binary form must reproduce the above copyright
13209616Sjfv      notice, this list of conditions and the following disclaimer in the
14209616Sjfv      documentation and/or other materials provided with the distribution.
15209616Sjfv
16209616Sjfv   3. Neither the name of the Intel Corporation nor the names of its
17209616Sjfv      contributors may be used to endorse or promote products derived from
18209616Sjfv      this software without specific prior written permission.
19209616Sjfv
20209616Sjfv  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21209616Sjfv  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22209616Sjfv  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23209616Sjfv  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24209616Sjfv  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25209616Sjfv  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26209616Sjfv  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27209616Sjfv  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28209616Sjfv  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29209616Sjfv  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30209616Sjfv  POSSIBILITY OF SUCH DAMAGE.
31209616Sjfv
32209616Sjfv******************************************************************************/
33209616Sjfv/*$FreeBSD: releng/10.3/sys/dev/e1000/e1000_mbx.c 296055 2016-02-25 19:15:06Z erj $*/
34209616Sjfv
35209616Sjfv#include "e1000_mbx.h"
36209616Sjfv
37209616Sjfv/**
38209616Sjfv *  e1000_null_mbx_check_for_flag - No-op function, return 0
39209616Sjfv *  @hw: pointer to the HW structure
40209616Sjfv **/
41269196Sjfvstatic s32 e1000_null_mbx_check_for_flag(struct e1000_hw E1000_UNUSEDARG *hw,
42269196Sjfv					 u16 E1000_UNUSEDARG mbx_id)
43209616Sjfv{
44209616Sjfv	DEBUGFUNC("e1000_null_mbx_check_flag");
45209616Sjfv
46209616Sjfv	return E1000_SUCCESS;
47209616Sjfv}
48209616Sjfv
49209616Sjfv/**
50209616Sjfv *  e1000_null_mbx_transact - No-op function, return 0
51209616Sjfv *  @hw: pointer to the HW structure
52209616Sjfv **/
53269196Sjfvstatic s32 e1000_null_mbx_transact(struct e1000_hw E1000_UNUSEDARG *hw,
54269196Sjfv				   u32 E1000_UNUSEDARG *msg,
55269196Sjfv				   u16 E1000_UNUSEDARG size,
56269196Sjfv				   u16 E1000_UNUSEDARG mbx_id)
57209616Sjfv{
58209616Sjfv	DEBUGFUNC("e1000_null_mbx_rw_msg");
59209616Sjfv
60209616Sjfv	return E1000_SUCCESS;
61209616Sjfv}
62209616Sjfv
63209616Sjfv/**
64209616Sjfv *  e1000_read_mbx - Reads a message from the mailbox
65209616Sjfv *  @hw: pointer to the HW structure
66209616Sjfv *  @msg: The message buffer
67209616Sjfv *  @size: Length of buffer
68209616Sjfv *  @mbx_id: id of mailbox to read
69209616Sjfv *
70209616Sjfv *  returns SUCCESS if it successfuly read message from buffer
71209616Sjfv **/
72209616Sjfvs32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
73209616Sjfv{
74209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
75209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
76209616Sjfv
77209616Sjfv	DEBUGFUNC("e1000_read_mbx");
78209616Sjfv
79209616Sjfv	/* limit read to size of mailbox */
80209616Sjfv	if (size > mbx->size)
81209616Sjfv		size = mbx->size;
82209616Sjfv
83209616Sjfv	if (mbx->ops.read)
84209616Sjfv		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
85209616Sjfv
86209616Sjfv	return ret_val;
87209616Sjfv}
88209616Sjfv
89209616Sjfv/**
90209616Sjfv *  e1000_write_mbx - Write a message to the mailbox
91209616Sjfv *  @hw: pointer to the HW structure
92209616Sjfv *  @msg: The message buffer
93209616Sjfv *  @size: Length of buffer
94209616Sjfv *  @mbx_id: id of mailbox to write
95209616Sjfv *
96209616Sjfv *  returns SUCCESS if it successfully copied message into the buffer
97209616Sjfv **/
98209616Sjfvs32 e1000_write_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
99209616Sjfv{
100209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
101209616Sjfv	s32 ret_val = E1000_SUCCESS;
102209616Sjfv
103209616Sjfv	DEBUGFUNC("e1000_write_mbx");
104209616Sjfv
105209616Sjfv	if (size > mbx->size)
106209616Sjfv		ret_val = -E1000_ERR_MBX;
107209616Sjfv
108209616Sjfv	else if (mbx->ops.write)
109209616Sjfv		ret_val = mbx->ops.write(hw, msg, size, mbx_id);
110209616Sjfv
111209616Sjfv	return ret_val;
112209616Sjfv}
113209616Sjfv
114209616Sjfv/**
115209616Sjfv *  e1000_check_for_msg - checks to see if someone sent us mail
116209616Sjfv *  @hw: pointer to the HW structure
117209616Sjfv *  @mbx_id: id of mailbox to check
118209616Sjfv *
119209616Sjfv *  returns SUCCESS if the Status bit was found or else ERR_MBX
120209616Sjfv **/
121209616Sjfvs32 e1000_check_for_msg(struct e1000_hw *hw, u16 mbx_id)
122209616Sjfv{
123209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
124209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
125209616Sjfv
126209616Sjfv	DEBUGFUNC("e1000_check_for_msg");
127209616Sjfv
128209616Sjfv	if (mbx->ops.check_for_msg)
129209616Sjfv		ret_val = mbx->ops.check_for_msg(hw, mbx_id);
130209616Sjfv
131209616Sjfv	return ret_val;
132209616Sjfv}
133209616Sjfv
134209616Sjfv/**
135209616Sjfv *  e1000_check_for_ack - checks to see if someone sent us ACK
136209616Sjfv *  @hw: pointer to the HW structure
137209616Sjfv *  @mbx_id: id of mailbox to check
138209616Sjfv *
139209616Sjfv *  returns SUCCESS if the Status bit was found or else ERR_MBX
140209616Sjfv **/
141209616Sjfvs32 e1000_check_for_ack(struct e1000_hw *hw, u16 mbx_id)
142209616Sjfv{
143209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
144209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
145209616Sjfv
146209616Sjfv	DEBUGFUNC("e1000_check_for_ack");
147209616Sjfv
148209616Sjfv	if (mbx->ops.check_for_ack)
149209616Sjfv		ret_val = mbx->ops.check_for_ack(hw, mbx_id);
150209616Sjfv
151209616Sjfv	return ret_val;
152209616Sjfv}
153209616Sjfv
154209616Sjfv/**
155209616Sjfv *  e1000_check_for_rst - checks to see if other side has reset
156209616Sjfv *  @hw: pointer to the HW structure
157209616Sjfv *  @mbx_id: id of mailbox to check
158209616Sjfv *
159209616Sjfv *  returns SUCCESS if the Status bit was found or else ERR_MBX
160209616Sjfv **/
161209616Sjfvs32 e1000_check_for_rst(struct e1000_hw *hw, u16 mbx_id)
162209616Sjfv{
163209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
164209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
165209616Sjfv
166209616Sjfv	DEBUGFUNC("e1000_check_for_rst");
167209616Sjfv
168209616Sjfv	if (mbx->ops.check_for_rst)
169209616Sjfv		ret_val = mbx->ops.check_for_rst(hw, mbx_id);
170209616Sjfv
171209616Sjfv	return ret_val;
172209616Sjfv}
173209616Sjfv
174209616Sjfv/**
175209616Sjfv *  e1000_poll_for_msg - Wait for message notification
176209616Sjfv *  @hw: pointer to the HW structure
177209616Sjfv *  @mbx_id: id of mailbox to write
178209616Sjfv *
179209616Sjfv *  returns SUCCESS if it successfully received a message notification
180209616Sjfv **/
181209616Sjfvstatic s32 e1000_poll_for_msg(struct e1000_hw *hw, u16 mbx_id)
182209616Sjfv{
183209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
184209616Sjfv	int countdown = mbx->timeout;
185209616Sjfv
186209616Sjfv	DEBUGFUNC("e1000_poll_for_msg");
187209616Sjfv
188209616Sjfv	if (!countdown || !mbx->ops.check_for_msg)
189209616Sjfv		goto out;
190209616Sjfv
191209616Sjfv	while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) {
192209616Sjfv		countdown--;
193209616Sjfv		if (!countdown)
194209616Sjfv			break;
195209616Sjfv		usec_delay(mbx->usec_delay);
196209616Sjfv	}
197209616Sjfv
198209616Sjfv	/* if we failed, all future posted messages fail until reset */
199209616Sjfv	if (!countdown)
200209616Sjfv		mbx->timeout = 0;
201209616Sjfvout:
202209616Sjfv	return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
203209616Sjfv}
204209616Sjfv
205209616Sjfv/**
206209616Sjfv *  e1000_poll_for_ack - Wait for message acknowledgement
207209616Sjfv *  @hw: pointer to the HW structure
208209616Sjfv *  @mbx_id: id of mailbox to write
209209616Sjfv *
210209616Sjfv *  returns SUCCESS if it successfully received a message acknowledgement
211209616Sjfv **/
212209616Sjfvstatic s32 e1000_poll_for_ack(struct e1000_hw *hw, u16 mbx_id)
213209616Sjfv{
214209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
215209616Sjfv	int countdown = mbx->timeout;
216209616Sjfv
217209616Sjfv	DEBUGFUNC("e1000_poll_for_ack");
218209616Sjfv
219209616Sjfv	if (!countdown || !mbx->ops.check_for_ack)
220209616Sjfv		goto out;
221209616Sjfv
222209616Sjfv	while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) {
223209616Sjfv		countdown--;
224209616Sjfv		if (!countdown)
225209616Sjfv			break;
226209616Sjfv		usec_delay(mbx->usec_delay);
227209616Sjfv	}
228209616Sjfv
229209616Sjfv	/* if we failed, all future posted messages fail until reset */
230209616Sjfv	if (!countdown)
231209616Sjfv		mbx->timeout = 0;
232209616Sjfvout:
233209616Sjfv	return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
234209616Sjfv}
235209616Sjfv
236209616Sjfv/**
237209616Sjfv *  e1000_read_posted_mbx - Wait for message notification and receive message
238209616Sjfv *  @hw: pointer to the HW structure
239209616Sjfv *  @msg: The message buffer
240209616Sjfv *  @size: Length of buffer
241209616Sjfv *  @mbx_id: id of mailbox to write
242209616Sjfv *
243209616Sjfv *  returns SUCCESS if it successfully received a message notification and
244209616Sjfv *  copied it into the receive buffer.
245209616Sjfv **/
246209616Sjfvs32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
247209616Sjfv{
248209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
249209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
250209616Sjfv
251209616Sjfv	DEBUGFUNC("e1000_read_posted_mbx");
252209616Sjfv
253209616Sjfv	if (!mbx->ops.read)
254209616Sjfv		goto out;
255209616Sjfv
256209616Sjfv	ret_val = e1000_poll_for_msg(hw, mbx_id);
257209616Sjfv
258209616Sjfv	/* if ack received read message, otherwise we timed out */
259209616Sjfv	if (!ret_val)
260209616Sjfv		ret_val = mbx->ops.read(hw, msg, size, mbx_id);
261209616Sjfvout:
262209616Sjfv	return ret_val;
263209616Sjfv}
264209616Sjfv
265209616Sjfv/**
266209616Sjfv *  e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
267209616Sjfv *  @hw: pointer to the HW structure
268209616Sjfv *  @msg: The message buffer
269209616Sjfv *  @size: Length of buffer
270209616Sjfv *  @mbx_id: id of mailbox to write
271209616Sjfv *
272209616Sjfv *  returns SUCCESS if it successfully copied message into the buffer and
273209616Sjfv *  received an ack to that message within delay * timeout period
274209616Sjfv **/
275209616Sjfvs32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id)
276209616Sjfv{
277209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
278209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
279209616Sjfv
280209616Sjfv	DEBUGFUNC("e1000_write_posted_mbx");
281209616Sjfv
282209616Sjfv	/* exit if either we can't write or there isn't a defined timeout */
283209616Sjfv	if (!mbx->ops.write || !mbx->timeout)
284209616Sjfv		goto out;
285209616Sjfv
286209616Sjfv	/* send msg */
287209616Sjfv	ret_val = mbx->ops.write(hw, msg, size, mbx_id);
288209616Sjfv
289209616Sjfv	/* if msg sent wait until we receive an ack */
290209616Sjfv	if (!ret_val)
291209616Sjfv		ret_val = e1000_poll_for_ack(hw, mbx_id);
292209616Sjfvout:
293209616Sjfv	return ret_val;
294209616Sjfv}
295209616Sjfv
296209616Sjfv/**
297209616Sjfv *  e1000_init_mbx_ops_generic - Initialize mbx function pointers
298209616Sjfv *  @hw: pointer to the HW structure
299209616Sjfv *
300209616Sjfv *  Sets the function pointers to no-op functions
301209616Sjfv **/
302209616Sjfvvoid e1000_init_mbx_ops_generic(struct e1000_hw *hw)
303209616Sjfv{
304209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
305209616Sjfv	mbx->ops.init_params = e1000_null_ops_generic;
306209616Sjfv	mbx->ops.read = e1000_null_mbx_transact;
307209616Sjfv	mbx->ops.write = e1000_null_mbx_transact;
308209616Sjfv	mbx->ops.check_for_msg = e1000_null_mbx_check_for_flag;
309209616Sjfv	mbx->ops.check_for_ack = e1000_null_mbx_check_for_flag;
310209616Sjfv	mbx->ops.check_for_rst = e1000_null_mbx_check_for_flag;
311209616Sjfv	mbx->ops.read_posted = e1000_read_posted_mbx;
312209616Sjfv	mbx->ops.write_posted = e1000_write_posted_mbx;
313209616Sjfv}
314209616Sjfv
315209616Sjfv/**
316209616Sjfv *  e1000_read_v2p_mailbox - read v2p mailbox
317209616Sjfv *  @hw: pointer to the HW structure
318209616Sjfv *
319209616Sjfv *  This function is used to read the v2p mailbox without losing the read to
320209616Sjfv *  clear status bits.
321209616Sjfv **/
322209616Sjfvstatic u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
323209616Sjfv{
324209616Sjfv	u32 v2p_mailbox = E1000_READ_REG(hw, E1000_V2PMAILBOX(0));
325209616Sjfv
326209616Sjfv	v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
327209616Sjfv	hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
328209616Sjfv
329209616Sjfv	return v2p_mailbox;
330209616Sjfv}
331209616Sjfv
332209616Sjfv/**
333209616Sjfv *  e1000_check_for_bit_vf - Determine if a status bit was set
334209616Sjfv *  @hw: pointer to the HW structure
335209616Sjfv *  @mask: bitmask for bits to be tested and cleared
336209616Sjfv *
337209616Sjfv *  This function is used to check for the read to clear bits within
338209616Sjfv *  the V2P mailbox.
339209616Sjfv **/
340209616Sjfvstatic s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
341209616Sjfv{
342209616Sjfv	u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
343209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
344209616Sjfv
345209616Sjfv	if (v2p_mailbox & mask)
346209616Sjfv		ret_val = E1000_SUCCESS;
347209616Sjfv
348209616Sjfv	hw->dev_spec.vf.v2p_mailbox &= ~mask;
349209616Sjfv
350209616Sjfv	return ret_val;
351209616Sjfv}
352209616Sjfv
353209616Sjfv/**
354209616Sjfv *  e1000_check_for_msg_vf - checks to see if the PF has sent mail
355209616Sjfv *  @hw: pointer to the HW structure
356209616Sjfv *  @mbx_id: id of mailbox to check
357209616Sjfv *
358209616Sjfv *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
359209616Sjfv **/
360269196Sjfvstatic s32 e1000_check_for_msg_vf(struct e1000_hw *hw,
361269196Sjfv				  u16 E1000_UNUSEDARG mbx_id)
362209616Sjfv{
363209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
364209616Sjfv
365209616Sjfv	DEBUGFUNC("e1000_check_for_msg_vf");
366209616Sjfv
367209616Sjfv	if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
368209616Sjfv		ret_val = E1000_SUCCESS;
369209616Sjfv		hw->mbx.stats.reqs++;
370209616Sjfv	}
371209616Sjfv
372209616Sjfv	return ret_val;
373209616Sjfv}
374209616Sjfv
375209616Sjfv/**
376209616Sjfv *  e1000_check_for_ack_vf - checks to see if the PF has ACK'd
377209616Sjfv *  @hw: pointer to the HW structure
378209616Sjfv *  @mbx_id: id of mailbox to check
379209616Sjfv *
380209616Sjfv *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
381209616Sjfv **/
382269196Sjfvstatic s32 e1000_check_for_ack_vf(struct e1000_hw *hw,
383269196Sjfv				  u16 E1000_UNUSEDARG mbx_id)
384209616Sjfv{
385209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
386209616Sjfv
387209616Sjfv	DEBUGFUNC("e1000_check_for_ack_vf");
388209616Sjfv
389209616Sjfv	if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
390209616Sjfv		ret_val = E1000_SUCCESS;
391209616Sjfv		hw->mbx.stats.acks++;
392209616Sjfv	}
393209616Sjfv
394209616Sjfv	return ret_val;
395209616Sjfv}
396209616Sjfv
397209616Sjfv/**
398209616Sjfv *  e1000_check_for_rst_vf - checks to see if the PF has reset
399209616Sjfv *  @hw: pointer to the HW structure
400209616Sjfv *  @mbx_id: id of mailbox to check
401209616Sjfv *
402209616Sjfv *  returns TRUE if the PF has set the reset done bit or else FALSE
403209616Sjfv **/
404269196Sjfvstatic s32 e1000_check_for_rst_vf(struct e1000_hw *hw,
405269196Sjfv				  u16 E1000_UNUSEDARG mbx_id)
406209616Sjfv{
407209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
408209616Sjfv
409209616Sjfv	DEBUGFUNC("e1000_check_for_rst_vf");
410209616Sjfv
411209616Sjfv	if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
412269196Sjfv					 E1000_V2PMAILBOX_RSTI))) {
413209616Sjfv		ret_val = E1000_SUCCESS;
414209616Sjfv		hw->mbx.stats.rsts++;
415209616Sjfv	}
416209616Sjfv
417209616Sjfv	return ret_val;
418209616Sjfv}
419209616Sjfv
420209616Sjfv/**
421209616Sjfv *  e1000_obtain_mbx_lock_vf - obtain mailbox lock
422209616Sjfv *  @hw: pointer to the HW structure
423209616Sjfv *
424209616Sjfv *  return SUCCESS if we obtained the mailbox lock
425209616Sjfv **/
426209616Sjfvstatic s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
427209616Sjfv{
428209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
429296055Serj	int count = 10;
430209616Sjfv
431209616Sjfv	DEBUGFUNC("e1000_obtain_mbx_lock_vf");
432209616Sjfv
433296055Serj	do {
434296055Serj		/* Take ownership of the buffer */
435296055Serj		E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
436209616Sjfv
437296055Serj		/* reserve mailbox for vf use */
438296055Serj		if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) {
439296055Serj			ret_val = E1000_SUCCESS;
440296055Serj			break;
441296055Serj		}
442296055Serj		usec_delay(1000);
443296055Serj	} while (count-- > 0);
444209616Sjfv
445209616Sjfv	return ret_val;
446209616Sjfv}
447209616Sjfv
448209616Sjfv/**
449209616Sjfv *  e1000_write_mbx_vf - Write a message to the mailbox
450209616Sjfv *  @hw: pointer to the HW structure
451209616Sjfv *  @msg: The message buffer
452209616Sjfv *  @size: Length of buffer
453209616Sjfv *  @mbx_id: id of mailbox to write
454209616Sjfv *
455209616Sjfv *  returns SUCCESS if it successfully copied message into the buffer
456209616Sjfv **/
457209616Sjfvstatic s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
458269196Sjfv			      u16 E1000_UNUSEDARG mbx_id)
459209616Sjfv{
460209616Sjfv	s32 ret_val;
461209616Sjfv	u16 i;
462209616Sjfv
463209616Sjfv
464209616Sjfv	DEBUGFUNC("e1000_write_mbx_vf");
465209616Sjfv
466209616Sjfv	/* lock the mailbox to prevent pf/vf race condition */
467209616Sjfv	ret_val = e1000_obtain_mbx_lock_vf(hw);
468209616Sjfv	if (ret_val)
469209616Sjfv		goto out_no_write;
470209616Sjfv
471209616Sjfv	/* flush msg and acks as we are overwriting the message buffer */
472209616Sjfv	e1000_check_for_msg_vf(hw, 0);
473209616Sjfv	e1000_check_for_ack_vf(hw, 0);
474209616Sjfv
475209616Sjfv	/* copy the caller specified message to the mailbox memory buffer */
476209616Sjfv	for (i = 0; i < size; i++)
477209616Sjfv		E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(0), i, msg[i]);
478209616Sjfv
479209616Sjfv	/* update stats */
480209616Sjfv	hw->mbx.stats.msgs_tx++;
481209616Sjfv
482209616Sjfv	/* Drop VFU and interrupt the PF to tell it a message has been sent */
483209616Sjfv	E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
484209616Sjfv
485209616Sjfvout_no_write:
486209616Sjfv	return ret_val;
487209616Sjfv}
488209616Sjfv
489209616Sjfv/**
490209616Sjfv *  e1000_read_mbx_vf - Reads a message from the inbox intended for vf
491209616Sjfv *  @hw: pointer to the HW structure
492209616Sjfv *  @msg: The message buffer
493209616Sjfv *  @size: Length of buffer
494209616Sjfv *  @mbx_id: id of mailbox to read
495209616Sjfv *
496209616Sjfv *  returns SUCCESS if it successfuly read message from buffer
497209616Sjfv **/
498209616Sjfvstatic s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size,
499269196Sjfv			     u16 E1000_UNUSEDARG mbx_id)
500209616Sjfv{
501209616Sjfv	s32 ret_val = E1000_SUCCESS;
502209616Sjfv	u16 i;
503209616Sjfv
504209616Sjfv	DEBUGFUNC("e1000_read_mbx_vf");
505209616Sjfv
506209616Sjfv	/* lock the mailbox to prevent pf/vf race condition */
507209616Sjfv	ret_val = e1000_obtain_mbx_lock_vf(hw);
508209616Sjfv	if (ret_val)
509209616Sjfv		goto out_no_read;
510209616Sjfv
511209616Sjfv	/* copy the message from the mailbox memory buffer */
512209616Sjfv	for (i = 0; i < size; i++)
513209616Sjfv		msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(0), i);
514209616Sjfv
515209616Sjfv	/* Acknowledge receipt and release mailbox, then we're done */
516209616Sjfv	E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
517209616Sjfv
518209616Sjfv	/* update stats */
519209616Sjfv	hw->mbx.stats.msgs_rx++;
520209616Sjfv
521209616Sjfvout_no_read:
522209616Sjfv	return ret_val;
523209616Sjfv}
524209616Sjfv
525209616Sjfv/**
526209616Sjfv *  e1000_init_mbx_params_vf - set initial values for vf mailbox
527209616Sjfv *  @hw: pointer to the HW structure
528209616Sjfv *
529209616Sjfv *  Initializes the hw->mbx struct to correct values for vf mailbox
530209616Sjfv */
531209616Sjfvs32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
532209616Sjfv{
533209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
534209616Sjfv
535209616Sjfv	/* start mailbox as timed out and let the reset_hw call set the timeout
536209616Sjfv	 * value to begin communications */
537209616Sjfv	mbx->timeout = 0;
538209616Sjfv	mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
539209616Sjfv
540209616Sjfv	mbx->size = E1000_VFMAILBOX_SIZE;
541209616Sjfv
542209616Sjfv	mbx->ops.read = e1000_read_mbx_vf;
543209616Sjfv	mbx->ops.write = e1000_write_mbx_vf;
544209616Sjfv	mbx->ops.read_posted = e1000_read_posted_mbx;
545209616Sjfv	mbx->ops.write_posted = e1000_write_posted_mbx;
546209616Sjfv	mbx->ops.check_for_msg = e1000_check_for_msg_vf;
547209616Sjfv	mbx->ops.check_for_ack = e1000_check_for_ack_vf;
548209616Sjfv	mbx->ops.check_for_rst = e1000_check_for_rst_vf;
549209616Sjfv
550209616Sjfv	mbx->stats.msgs_tx = 0;
551209616Sjfv	mbx->stats.msgs_rx = 0;
552209616Sjfv	mbx->stats.reqs = 0;
553209616Sjfv	mbx->stats.acks = 0;
554209616Sjfv	mbx->stats.rsts = 0;
555209616Sjfv
556209616Sjfv	return E1000_SUCCESS;
557209616Sjfv}
558209616Sjfv
559209616Sjfvstatic s32 e1000_check_for_bit_pf(struct e1000_hw *hw, u32 mask)
560209616Sjfv{
561209616Sjfv	u32 mbvficr = E1000_READ_REG(hw, E1000_MBVFICR);
562209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
563209616Sjfv
564209616Sjfv	if (mbvficr & mask) {
565209616Sjfv		ret_val = E1000_SUCCESS;
566209616Sjfv		E1000_WRITE_REG(hw, E1000_MBVFICR, mask);
567209616Sjfv	}
568209616Sjfv
569209616Sjfv	return ret_val;
570209616Sjfv}
571209616Sjfv
572209616Sjfv/**
573209616Sjfv *  e1000_check_for_msg_pf - checks to see if the VF has sent mail
574209616Sjfv *  @hw: pointer to the HW structure
575209616Sjfv *  @vf_number: the VF index
576209616Sjfv *
577209616Sjfv *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
578209616Sjfv **/
579209616Sjfvstatic s32 e1000_check_for_msg_pf(struct e1000_hw *hw, u16 vf_number)
580209616Sjfv{
581209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
582209616Sjfv
583209616Sjfv	DEBUGFUNC("e1000_check_for_msg_pf");
584209616Sjfv
585209616Sjfv	if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFREQ_VF1 << vf_number)) {
586209616Sjfv		ret_val = E1000_SUCCESS;
587209616Sjfv		hw->mbx.stats.reqs++;
588209616Sjfv	}
589209616Sjfv
590209616Sjfv	return ret_val;
591209616Sjfv}
592209616Sjfv
593209616Sjfv/**
594209616Sjfv *  e1000_check_for_ack_pf - checks to see if the VF has ACKed
595209616Sjfv *  @hw: pointer to the HW structure
596209616Sjfv *  @vf_number: the VF index
597209616Sjfv *
598209616Sjfv *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
599209616Sjfv **/
600209616Sjfvstatic s32 e1000_check_for_ack_pf(struct e1000_hw *hw, u16 vf_number)
601209616Sjfv{
602209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
603209616Sjfv
604209616Sjfv	DEBUGFUNC("e1000_check_for_ack_pf");
605209616Sjfv
606209616Sjfv	if (!e1000_check_for_bit_pf(hw, E1000_MBVFICR_VFACK_VF1 << vf_number)) {
607209616Sjfv		ret_val = E1000_SUCCESS;
608209616Sjfv		hw->mbx.stats.acks++;
609209616Sjfv	}
610209616Sjfv
611209616Sjfv	return ret_val;
612209616Sjfv}
613209616Sjfv
614209616Sjfv/**
615209616Sjfv *  e1000_check_for_rst_pf - checks to see if the VF has reset
616209616Sjfv *  @hw: pointer to the HW structure
617209616Sjfv *  @vf_number: the VF index
618209616Sjfv *
619209616Sjfv *  returns SUCCESS if the VF has set the Status bit or else ERR_MBX
620209616Sjfv **/
621209616Sjfvstatic s32 e1000_check_for_rst_pf(struct e1000_hw *hw, u16 vf_number)
622209616Sjfv{
623209616Sjfv	u32 vflre = E1000_READ_REG(hw, E1000_VFLRE);
624209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
625209616Sjfv
626209616Sjfv	DEBUGFUNC("e1000_check_for_rst_pf");
627209616Sjfv
628209616Sjfv	if (vflre & (1 << vf_number)) {
629209616Sjfv		ret_val = E1000_SUCCESS;
630209616Sjfv		E1000_WRITE_REG(hw, E1000_VFLRE, (1 << vf_number));
631209616Sjfv		hw->mbx.stats.rsts++;
632209616Sjfv	}
633209616Sjfv
634209616Sjfv	return ret_val;
635209616Sjfv}
636209616Sjfv
637209616Sjfv/**
638209616Sjfv *  e1000_obtain_mbx_lock_pf - obtain mailbox lock
639209616Sjfv *  @hw: pointer to the HW structure
640209616Sjfv *  @vf_number: the VF index
641209616Sjfv *
642209616Sjfv *  return SUCCESS if we obtained the mailbox lock
643209616Sjfv **/
644209616Sjfvstatic s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
645209616Sjfv{
646209616Sjfv	s32 ret_val = -E1000_ERR_MBX;
647209616Sjfv	u32 p2v_mailbox;
648296055Serj	int count = 10;
649209616Sjfv
650209616Sjfv	DEBUGFUNC("e1000_obtain_mbx_lock_pf");
651209616Sjfv
652296055Serj	do {
653296055Serj		/* Take ownership of the buffer */
654296055Serj		E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number),
655296055Serj				E1000_P2VMAILBOX_PFU);
656209616Sjfv
657296055Serj		/* reserve mailbox for pf use */
658296055Serj		p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
659296055Serj		if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
660296055Serj			ret_val = E1000_SUCCESS;
661296055Serj			break;
662296055Serj		}
663296055Serj		usec_delay(1000);
664296055Serj	} while (count-- > 0);
665209616Sjfv
666209616Sjfv	return ret_val;
667296055Serj
668209616Sjfv}
669209616Sjfv
670209616Sjfv/**
671209616Sjfv *  e1000_write_mbx_pf - Places a message in the mailbox
672209616Sjfv *  @hw: pointer to the HW structure
673209616Sjfv *  @msg: The message buffer
674209616Sjfv *  @size: Length of buffer
675209616Sjfv *  @vf_number: the VF index
676209616Sjfv *
677209616Sjfv *  returns SUCCESS if it successfully copied message into the buffer
678209616Sjfv **/
679209616Sjfvstatic s32 e1000_write_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
680269196Sjfv			      u16 vf_number)
681209616Sjfv{
682209616Sjfv	s32 ret_val;
683209616Sjfv	u16 i;
684209616Sjfv
685209616Sjfv	DEBUGFUNC("e1000_write_mbx_pf");
686209616Sjfv
687209616Sjfv	/* lock the mailbox to prevent pf/vf race condition */
688209616Sjfv	ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number);
689209616Sjfv	if (ret_val)
690209616Sjfv		goto out_no_write;
691209616Sjfv
692209616Sjfv	/* flush msg and acks as we are overwriting the message buffer */
693209616Sjfv	e1000_check_for_msg_pf(hw, vf_number);
694209616Sjfv	e1000_check_for_ack_pf(hw, vf_number);
695209616Sjfv
696209616Sjfv	/* copy the caller specified message to the mailbox memory buffer */
697209616Sjfv	for (i = 0; i < size; i++)
698209616Sjfv		E1000_WRITE_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i, msg[i]);
699209616Sjfv
700209616Sjfv	/* Interrupt VF to tell it a message has been sent and release buffer*/
701209616Sjfv	E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_STS);
702209616Sjfv
703209616Sjfv	/* update stats */
704209616Sjfv	hw->mbx.stats.msgs_tx++;
705209616Sjfv
706209616Sjfvout_no_write:
707209616Sjfv	return ret_val;
708209616Sjfv
709209616Sjfv}
710209616Sjfv
711209616Sjfv/**
712209616Sjfv *  e1000_read_mbx_pf - Read a message from the mailbox
713209616Sjfv *  @hw: pointer to the HW structure
714209616Sjfv *  @msg: The message buffer
715209616Sjfv *  @size: Length of buffer
716209616Sjfv *  @vf_number: the VF index
717209616Sjfv *
718209616Sjfv *  This function copies a message from the mailbox buffer to the caller's
719209616Sjfv *  memory buffer.  The presumption is that the caller knows that there was
720209616Sjfv *  a message due to a VF request so no polling for message is needed.
721209616Sjfv **/
722209616Sjfvstatic s32 e1000_read_mbx_pf(struct e1000_hw *hw, u32 *msg, u16 size,
723269196Sjfv			     u16 vf_number)
724209616Sjfv{
725209616Sjfv	s32 ret_val;
726209616Sjfv	u16 i;
727209616Sjfv
728209616Sjfv	DEBUGFUNC("e1000_read_mbx_pf");
729209616Sjfv
730209616Sjfv	/* lock the mailbox to prevent pf/vf race condition */
731209616Sjfv	ret_val = e1000_obtain_mbx_lock_pf(hw, vf_number);
732209616Sjfv	if (ret_val)
733209616Sjfv		goto out_no_read;
734209616Sjfv
735209616Sjfv	/* copy the message to the mailbox memory buffer */
736209616Sjfv	for (i = 0; i < size; i++)
737209616Sjfv		msg[i] = E1000_READ_REG_ARRAY(hw, E1000_VMBMEM(vf_number), i);
738209616Sjfv
739209616Sjfv	/* Acknowledge the message and release buffer */
740209616Sjfv	E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_ACK);
741209616Sjfv
742209616Sjfv	/* update stats */
743209616Sjfv	hw->mbx.stats.msgs_rx++;
744209616Sjfv
745209616Sjfvout_no_read:
746209616Sjfv	return ret_val;
747209616Sjfv}
748209616Sjfv
749209616Sjfv/**
750209616Sjfv *  e1000_init_mbx_params_pf - set initial values for pf mailbox
751209616Sjfv *  @hw: pointer to the HW structure
752209616Sjfv *
753209616Sjfv *  Initializes the hw->mbx struct to correct values for pf mailbox
754209616Sjfv */
755209616Sjfvs32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
756209616Sjfv{
757209616Sjfv	struct e1000_mbx_info *mbx = &hw->mbx;
758209616Sjfv
759218530Sjfv	switch (hw->mac.type) {
760218530Sjfv	case e1000_82576:
761218530Sjfv	case e1000_i350:
762269196Sjfv	case e1000_i354:
763209616Sjfv		mbx->timeout = 0;
764209616Sjfv		mbx->usec_delay = 0;
765209616Sjfv
766209616Sjfv		mbx->size = E1000_VFMAILBOX_SIZE;
767209616Sjfv
768209616Sjfv		mbx->ops.read = e1000_read_mbx_pf;
769209616Sjfv		mbx->ops.write = e1000_write_mbx_pf;
770209616Sjfv		mbx->ops.read_posted = e1000_read_posted_mbx;
771209616Sjfv		mbx->ops.write_posted = e1000_write_posted_mbx;
772209616Sjfv		mbx->ops.check_for_msg = e1000_check_for_msg_pf;
773209616Sjfv		mbx->ops.check_for_ack = e1000_check_for_ack_pf;
774209616Sjfv		mbx->ops.check_for_rst = e1000_check_for_rst_pf;
775209616Sjfv
776209616Sjfv		mbx->stats.msgs_tx = 0;
777209616Sjfv		mbx->stats.msgs_rx = 0;
778209616Sjfv		mbx->stats.reqs = 0;
779209616Sjfv		mbx->stats.acks = 0;
780209616Sjfv		mbx->stats.rsts = 0;
781218530Sjfv	default:
782218530Sjfv		return E1000_SUCCESS;
783209616Sjfv	}
784209616Sjfv}
785209616Sjfv
786