xref: /dpdk/drivers/net/ngbe/base/ngbe_mbx.c (revision ace44974a1b767dee3417a5b737d962127c4a289)
160229dcfSJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause
260229dcfSJiawen Wu  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
360229dcfSJiawen Wu  * Copyright(c) 2010-2017 Intel Corporation
460229dcfSJiawen Wu  */
560229dcfSJiawen Wu 
660229dcfSJiawen Wu #include "ngbe_type.h"
760229dcfSJiawen Wu 
860229dcfSJiawen Wu #include "ngbe_mbx.h"
960229dcfSJiawen Wu 
1060229dcfSJiawen Wu /**
11e2a289a7SJiawen Wu  *  ngbe_read_mbx - Reads a message from the mailbox
12e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
13e2a289a7SJiawen Wu  *  @msg: The message buffer
14e2a289a7SJiawen Wu  *  @size: Length of buffer
15e2a289a7SJiawen Wu  *  @mbx_id: id of mailbox to read
16e2a289a7SJiawen Wu  *
17e2a289a7SJiawen Wu  *  returns 0 if it successfully read message from buffer
18e2a289a7SJiawen Wu  **/
19e2a289a7SJiawen Wu s32 ngbe_read_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
20e2a289a7SJiawen Wu {
21e2a289a7SJiawen Wu 	struct ngbe_mbx_info *mbx = &hw->mbx;
22e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
23e2a289a7SJiawen Wu 
24e2a289a7SJiawen Wu 	/* limit read to size of mailbox */
25e2a289a7SJiawen Wu 	if (size > mbx->size)
26e2a289a7SJiawen Wu 		size = mbx->size;
27e2a289a7SJiawen Wu 
28e2a289a7SJiawen Wu 	if (mbx->read)
29e2a289a7SJiawen Wu 		ret_val = mbx->read(hw, msg, size, mbx_id);
30e2a289a7SJiawen Wu 
31e2a289a7SJiawen Wu 	return ret_val;
32e2a289a7SJiawen Wu }
33e2a289a7SJiawen Wu 
34e2a289a7SJiawen Wu /**
35e2a289a7SJiawen Wu  *  ngbe_write_mbx - Write a message to the mailbox
36e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
37e2a289a7SJiawen Wu  *  @msg: The message buffer
38e2a289a7SJiawen Wu  *  @size: Length of buffer
39e2a289a7SJiawen Wu  *  @mbx_id: id of mailbox to write
40e2a289a7SJiawen Wu  *
41e2a289a7SJiawen Wu  *  returns 0 if it successfully copied message into the buffer
42e2a289a7SJiawen Wu  **/
43e2a289a7SJiawen Wu s32 ngbe_write_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
44e2a289a7SJiawen Wu {
45e2a289a7SJiawen Wu 	struct ngbe_mbx_info *mbx = &hw->mbx;
46e2a289a7SJiawen Wu 	s32 ret_val = 0;
47e2a289a7SJiawen Wu 
48e2a289a7SJiawen Wu 	if (size > mbx->size) {
49e2a289a7SJiawen Wu 		ret_val = NGBE_ERR_MBX;
50e2a289a7SJiawen Wu 		DEBUGOUT("Invalid mailbox message size %d", size);
51e2a289a7SJiawen Wu 	} else if (mbx->write) {
52e2a289a7SJiawen Wu 		ret_val = mbx->write(hw, msg, size, mbx_id);
53e2a289a7SJiawen Wu 	}
54e2a289a7SJiawen Wu 
55e2a289a7SJiawen Wu 	return ret_val;
56e2a289a7SJiawen Wu }
57e2a289a7SJiawen Wu 
58e2a289a7SJiawen Wu /**
59e2a289a7SJiawen Wu  *  ngbe_check_for_msg - checks to see if someone sent us mail
60e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
61e2a289a7SJiawen Wu  *  @mbx_id: id of mailbox to check
62e2a289a7SJiawen Wu  *
63e2a289a7SJiawen Wu  *  returns 0 if the Status bit was found or else ERR_MBX
64e2a289a7SJiawen Wu  **/
65e2a289a7SJiawen Wu s32 ngbe_check_for_msg(struct ngbe_hw *hw, u16 mbx_id)
66e2a289a7SJiawen Wu {
67e2a289a7SJiawen Wu 	struct ngbe_mbx_info *mbx = &hw->mbx;
68e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
69e2a289a7SJiawen Wu 
70e2a289a7SJiawen Wu 	if (mbx->check_for_msg)
71e2a289a7SJiawen Wu 		ret_val = mbx->check_for_msg(hw, mbx_id);
72e2a289a7SJiawen Wu 
73e2a289a7SJiawen Wu 	return ret_val;
74e2a289a7SJiawen Wu }
75e2a289a7SJiawen Wu 
76e2a289a7SJiawen Wu /**
77e2a289a7SJiawen Wu  *  ngbe_check_for_ack - checks to see if someone sent us ACK
78e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
79e2a289a7SJiawen Wu  *  @mbx_id: id of mailbox to check
80e2a289a7SJiawen Wu  *
81e2a289a7SJiawen Wu  *  returns 0 if the Status bit was found or else ERR_MBX
82e2a289a7SJiawen Wu  **/
83e2a289a7SJiawen Wu s32 ngbe_check_for_ack(struct ngbe_hw *hw, u16 mbx_id)
84e2a289a7SJiawen Wu {
85e2a289a7SJiawen Wu 	struct ngbe_mbx_info *mbx = &hw->mbx;
86e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
87e2a289a7SJiawen Wu 
88e2a289a7SJiawen Wu 	if (mbx->check_for_ack)
89e2a289a7SJiawen Wu 		ret_val = mbx->check_for_ack(hw, mbx_id);
90e2a289a7SJiawen Wu 
91e2a289a7SJiawen Wu 	return ret_val;
92e2a289a7SJiawen Wu }
93e2a289a7SJiawen Wu 
94e2a289a7SJiawen Wu /**
95e2a289a7SJiawen Wu  *  ngbe_check_for_rst - checks to see if other side has reset
96e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
97e2a289a7SJiawen Wu  *  @mbx_id: id of mailbox to check
98e2a289a7SJiawen Wu  *
99e2a289a7SJiawen Wu  *  returns 0 if the Status bit was found or else ERR_MBX
100e2a289a7SJiawen Wu  **/
101e2a289a7SJiawen Wu s32 ngbe_check_for_rst(struct ngbe_hw *hw, u16 mbx_id)
102e2a289a7SJiawen Wu {
103e2a289a7SJiawen Wu 	struct ngbe_mbx_info *mbx = &hw->mbx;
104e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
105e2a289a7SJiawen Wu 
106e2a289a7SJiawen Wu 	if (mbx->check_for_rst)
107e2a289a7SJiawen Wu 		ret_val = mbx->check_for_rst(hw, mbx_id);
108e2a289a7SJiawen Wu 
109e2a289a7SJiawen Wu 	return ret_val;
110e2a289a7SJiawen Wu }
111e2a289a7SJiawen Wu 
112*ace44974SZaiyu Wang /**
113*ace44974SZaiyu Wang  *  ngbe_poll_for_msg - Wait for message notification
114*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
115*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to write
116*ace44974SZaiyu Wang  *
117*ace44974SZaiyu Wang  *  returns SUCCESS if it successfully received a message notification
118*ace44974SZaiyu Wang  **/
119*ace44974SZaiyu Wang STATIC s32 ngbe_poll_for_msg(struct ngbe_hw *hw, u16 mbx_id)
120*ace44974SZaiyu Wang {
121*ace44974SZaiyu Wang 	struct ngbe_mbx_info *mbx = &hw->mbx;
122*ace44974SZaiyu Wang 	int countdown = mbx->timeout;
123*ace44974SZaiyu Wang 
124*ace44974SZaiyu Wang 	if (!countdown || !mbx->check_for_msg)
125*ace44974SZaiyu Wang 		goto out;
126*ace44974SZaiyu Wang 
127*ace44974SZaiyu Wang 	while (countdown && mbx->check_for_msg(hw, mbx_id)) {
128*ace44974SZaiyu Wang 		countdown--;
129*ace44974SZaiyu Wang 		if (!countdown)
130*ace44974SZaiyu Wang 			break;
131*ace44974SZaiyu Wang 		usec_delay(mbx->usec_delay);
132*ace44974SZaiyu Wang 	}
133*ace44974SZaiyu Wang 
134*ace44974SZaiyu Wang 	if (countdown == 0)
135*ace44974SZaiyu Wang 		DEBUGOUT("Polling for VF%d mailbox message timedout", mbx_id);
136*ace44974SZaiyu Wang 
137*ace44974SZaiyu Wang out:
138*ace44974SZaiyu Wang 	return countdown ? 0 : NGBE_ERR_MBX;
139*ace44974SZaiyu Wang }
140*ace44974SZaiyu Wang 
141*ace44974SZaiyu Wang /**
142*ace44974SZaiyu Wang  *  ngbe_poll_for_ack - Wait for message acknowledgment
143*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
144*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to write
145*ace44974SZaiyu Wang  *
146*ace44974SZaiyu Wang  *  returns SUCCESS if it successfully received a message acknowledgment
147*ace44974SZaiyu Wang  **/
148*ace44974SZaiyu Wang STATIC s32 ngbe_poll_for_ack(struct ngbe_hw *hw, u16 mbx_id)
149*ace44974SZaiyu Wang {
150*ace44974SZaiyu Wang 	struct ngbe_mbx_info *mbx = &hw->mbx;
151*ace44974SZaiyu Wang 	int countdown = mbx->timeout;
152*ace44974SZaiyu Wang 
153*ace44974SZaiyu Wang 	if (!countdown || !mbx->check_for_ack)
154*ace44974SZaiyu Wang 		goto out;
155*ace44974SZaiyu Wang 
156*ace44974SZaiyu Wang 	while (countdown && mbx->check_for_ack(hw, mbx_id)) {
157*ace44974SZaiyu Wang 		countdown--;
158*ace44974SZaiyu Wang 		if (!countdown)
159*ace44974SZaiyu Wang 			break;
160*ace44974SZaiyu Wang 		usec_delay(mbx->usec_delay);
161*ace44974SZaiyu Wang 	}
162*ace44974SZaiyu Wang 
163*ace44974SZaiyu Wang 	if (countdown == 0)
164*ace44974SZaiyu Wang 		DEBUGOUT("Polling for VF%d mailbox ack timedout", mbx_id);
165*ace44974SZaiyu Wang 
166*ace44974SZaiyu Wang out:
167*ace44974SZaiyu Wang 	return countdown ? 0 : NGBE_ERR_MBX;
168*ace44974SZaiyu Wang }
169*ace44974SZaiyu Wang 
170*ace44974SZaiyu Wang /**
171*ace44974SZaiyu Wang  *  ngbe_read_posted_mbx - Wait for message notification and receive message
172*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
173*ace44974SZaiyu Wang  *  @msg: The message buffer
174*ace44974SZaiyu Wang  *  @size: Length of buffer
175*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to write
176*ace44974SZaiyu Wang  *
177*ace44974SZaiyu Wang  *  returns SUCCESS if it successfully received a message notification and
178*ace44974SZaiyu Wang  *  copied it into the receive buffer.
179*ace44974SZaiyu Wang  **/
180*ace44974SZaiyu Wang s32 ngbe_read_posted_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
181*ace44974SZaiyu Wang {
182*ace44974SZaiyu Wang 	struct ngbe_mbx_info *mbx = &hw->mbx;
183*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
184*ace44974SZaiyu Wang 
185*ace44974SZaiyu Wang 	if (!mbx->read)
186*ace44974SZaiyu Wang 		goto out;
187*ace44974SZaiyu Wang 
188*ace44974SZaiyu Wang 	ret_val = ngbe_poll_for_msg(hw, mbx_id);
189*ace44974SZaiyu Wang 
190*ace44974SZaiyu Wang 	/* if ack received read message, otherwise we timed out */
191*ace44974SZaiyu Wang 	if (!ret_val)
192*ace44974SZaiyu Wang 		ret_val = mbx->read(hw, msg, size, mbx_id);
193*ace44974SZaiyu Wang out:
194*ace44974SZaiyu Wang 	return ret_val;
195*ace44974SZaiyu Wang }
196*ace44974SZaiyu Wang 
197*ace44974SZaiyu Wang /**
198*ace44974SZaiyu Wang  *  ngbe_write_posted_mbx - Write a message to the mailbox, wait for ack
199*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
200*ace44974SZaiyu Wang  *  @msg: The message buffer
201*ace44974SZaiyu Wang  *  @size: Length of buffer
202*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to write
203*ace44974SZaiyu Wang  *
204*ace44974SZaiyu Wang  *  returns SUCCESS if it successfully copied message into the buffer and
205*ace44974SZaiyu Wang  *  received an ack to that message within delay * timeout period
206*ace44974SZaiyu Wang  **/
207*ace44974SZaiyu Wang s32 ngbe_write_posted_mbx(struct ngbe_hw *hw, u32 *msg, u16 size,
208*ace44974SZaiyu Wang 			   u16 mbx_id)
209*ace44974SZaiyu Wang {
210*ace44974SZaiyu Wang 	struct ngbe_mbx_info *mbx = &hw->mbx;
211*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
212*ace44974SZaiyu Wang 
213*ace44974SZaiyu Wang 	/* exit if either we can't write or there isn't a defined timeout */
214*ace44974SZaiyu Wang 	if (!mbx->write || !mbx->timeout)
215*ace44974SZaiyu Wang 		goto out;
216*ace44974SZaiyu Wang 
217*ace44974SZaiyu Wang 	/* send msg */
218*ace44974SZaiyu Wang 	ret_val = mbx->write(hw, msg, size, mbx_id);
219*ace44974SZaiyu Wang 
220*ace44974SZaiyu Wang 	/* if msg sent wait until we receive an ack */
221*ace44974SZaiyu Wang 	if (!ret_val)
222*ace44974SZaiyu Wang 		ret_val = ngbe_poll_for_ack(hw, mbx_id);
223*ace44974SZaiyu Wang out:
224*ace44974SZaiyu Wang 	return ret_val;
225*ace44974SZaiyu Wang }
226*ace44974SZaiyu Wang 
227*ace44974SZaiyu Wang /**
228*ace44974SZaiyu Wang  *  ngbe_read_v2p_mailbox - read v2p mailbox
229*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
230*ace44974SZaiyu Wang  *
231*ace44974SZaiyu Wang  *  This function is used to read the v2p mailbox without losing the read to
232*ace44974SZaiyu Wang  *  clear status bits.
233*ace44974SZaiyu Wang  **/
234*ace44974SZaiyu Wang STATIC u32 ngbe_read_v2p_mailbox(struct ngbe_hw *hw)
235*ace44974SZaiyu Wang {
236*ace44974SZaiyu Wang 	u32 v2p_mailbox = rd32(hw, NGBE_VFMBCTL);
237*ace44974SZaiyu Wang 
238*ace44974SZaiyu Wang 	v2p_mailbox |= hw->mbx.v2p_mailbox;
239*ace44974SZaiyu Wang 	hw->mbx.v2p_mailbox |= v2p_mailbox & NGBE_VFMBCTL_R2C_BITS;
240*ace44974SZaiyu Wang 
241*ace44974SZaiyu Wang 	return v2p_mailbox;
242*ace44974SZaiyu Wang }
243*ace44974SZaiyu Wang 
244*ace44974SZaiyu Wang /**
245*ace44974SZaiyu Wang  *  ngbe_check_for_bit_vf - Determine if a status bit was set
246*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
247*ace44974SZaiyu Wang  *  @mask: bitmask for bits to be tested and cleared
248*ace44974SZaiyu Wang  *
249*ace44974SZaiyu Wang  *  This function is used to check for the read to clear bits within
250*ace44974SZaiyu Wang  *  the V2P mailbox.
251*ace44974SZaiyu Wang  **/
252*ace44974SZaiyu Wang STATIC s32 ngbe_check_for_bit_vf(struct ngbe_hw *hw, u32 mask)
253*ace44974SZaiyu Wang {
254*ace44974SZaiyu Wang 	u32 v2p_mailbox = ngbe_read_v2p_mailbox(hw);
255*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
256*ace44974SZaiyu Wang 
257*ace44974SZaiyu Wang 	if (v2p_mailbox & mask)
258*ace44974SZaiyu Wang 		ret_val = 0;
259*ace44974SZaiyu Wang 
260*ace44974SZaiyu Wang 	hw->mbx.v2p_mailbox &= ~mask;
261*ace44974SZaiyu Wang 
262*ace44974SZaiyu Wang 	return ret_val;
263*ace44974SZaiyu Wang }
264*ace44974SZaiyu Wang 
265*ace44974SZaiyu Wang /**
266*ace44974SZaiyu Wang  *  ngbe_check_for_msg_vf - checks to see if the PF has sent mail
267*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
268*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to check
269*ace44974SZaiyu Wang  *
270*ace44974SZaiyu Wang  *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
271*ace44974SZaiyu Wang  **/
272*ace44974SZaiyu Wang s32 ngbe_check_for_msg_vf(struct ngbe_hw *hw, u16 mbx_id)
273*ace44974SZaiyu Wang {
274*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
275*ace44974SZaiyu Wang 
276*ace44974SZaiyu Wang 	UNREFERENCED_PARAMETER(mbx_id);
277*ace44974SZaiyu Wang 
278*ace44974SZaiyu Wang 	if (!ngbe_check_for_bit_vf(hw, NGBE_VFMBCTL_PFSTS)) {
279*ace44974SZaiyu Wang 		ret_val = 0;
280*ace44974SZaiyu Wang 		hw->mbx.stats.reqs++;
281*ace44974SZaiyu Wang 	}
282*ace44974SZaiyu Wang 
283*ace44974SZaiyu Wang 	return ret_val;
284*ace44974SZaiyu Wang }
285*ace44974SZaiyu Wang 
286*ace44974SZaiyu Wang /**
287*ace44974SZaiyu Wang  *  ngbe_check_for_ack_vf - checks to see if the PF has ACK'd
288*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
289*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to check
290*ace44974SZaiyu Wang  *
291*ace44974SZaiyu Wang  *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
292*ace44974SZaiyu Wang  **/
293*ace44974SZaiyu Wang s32 ngbe_check_for_ack_vf(struct ngbe_hw *hw, u16 mbx_id)
294*ace44974SZaiyu Wang {
295*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
296*ace44974SZaiyu Wang 
297*ace44974SZaiyu Wang 	UNREFERENCED_PARAMETER(mbx_id);
298*ace44974SZaiyu Wang 
299*ace44974SZaiyu Wang 	if (!ngbe_check_for_bit_vf(hw, NGBE_VFMBCTL_PFACK)) {
300*ace44974SZaiyu Wang 		ret_val = 0;
301*ace44974SZaiyu Wang 		hw->mbx.stats.acks++;
302*ace44974SZaiyu Wang 	}
303*ace44974SZaiyu Wang 
304*ace44974SZaiyu Wang 	return ret_val;
305*ace44974SZaiyu Wang }
306*ace44974SZaiyu Wang 
307*ace44974SZaiyu Wang /**
308*ace44974SZaiyu Wang  *  ngbe_check_for_rst_vf - checks to see if the PF has reset
309*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
310*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to check
311*ace44974SZaiyu Wang  *
312*ace44974SZaiyu Wang  *  returns true if the PF has set the reset done bit or else false
313*ace44974SZaiyu Wang  **/
314*ace44974SZaiyu Wang s32 ngbe_check_for_rst_vf(struct ngbe_hw *hw, u16 mbx_id)
315*ace44974SZaiyu Wang {
316*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
317*ace44974SZaiyu Wang 
318*ace44974SZaiyu Wang 	UNREFERENCED_PARAMETER(mbx_id);
319*ace44974SZaiyu Wang 
320*ace44974SZaiyu Wang 	if (!ngbe_check_for_bit_vf(hw, (NGBE_VFMBCTL_RSTD |
321*ace44974SZaiyu Wang 	    NGBE_VFMBCTL_RSTI))) {
322*ace44974SZaiyu Wang 		ret_val = 0;
323*ace44974SZaiyu Wang 		hw->mbx.stats.rsts++;
324*ace44974SZaiyu Wang 	}
325*ace44974SZaiyu Wang 
326*ace44974SZaiyu Wang 	return ret_val;
327*ace44974SZaiyu Wang }
328*ace44974SZaiyu Wang 
329*ace44974SZaiyu Wang /**
330*ace44974SZaiyu Wang  *  ngbe_obtain_mbx_lock_vf - obtain mailbox lock
331*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
332*ace44974SZaiyu Wang  *
333*ace44974SZaiyu Wang  *  return SUCCESS if we obtained the mailbox lock
334*ace44974SZaiyu Wang  **/
335*ace44974SZaiyu Wang STATIC s32 ngbe_obtain_mbx_lock_vf(struct ngbe_hw *hw)
336*ace44974SZaiyu Wang {
337*ace44974SZaiyu Wang 	s32 ret_val = NGBE_ERR_MBX;
338*ace44974SZaiyu Wang 
339*ace44974SZaiyu Wang 	/* Take ownership of the buffer */
340*ace44974SZaiyu Wang 	wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_VFU);
341*ace44974SZaiyu Wang 
342*ace44974SZaiyu Wang 	/* reserve mailbox for vf use */
343*ace44974SZaiyu Wang 	if (ngbe_read_v2p_mailbox(hw) & NGBE_VFMBCTL_VFU)
344*ace44974SZaiyu Wang 		ret_val = 0;
345*ace44974SZaiyu Wang 
346*ace44974SZaiyu Wang 	return ret_val;
347*ace44974SZaiyu Wang }
348*ace44974SZaiyu Wang 
349*ace44974SZaiyu Wang /**
350*ace44974SZaiyu Wang  *  ngbe_write_mbx_vf - Write a message to the mailbox
351*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
352*ace44974SZaiyu Wang  *  @msg: The message buffer
353*ace44974SZaiyu Wang  *  @size: Length of buffer
354*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to write
355*ace44974SZaiyu Wang  *
356*ace44974SZaiyu Wang  *  returns SUCCESS if it successfully copied message into the buffer
357*ace44974SZaiyu Wang  **/
358*ace44974SZaiyu Wang s32 ngbe_write_mbx_vf(struct ngbe_hw *hw, u32 *msg, u16 size,
359*ace44974SZaiyu Wang 			      u16 mbx_id)
360*ace44974SZaiyu Wang {
361*ace44974SZaiyu Wang 	s32 ret_val;
362*ace44974SZaiyu Wang 	u16 i;
363*ace44974SZaiyu Wang 
364*ace44974SZaiyu Wang 	UNREFERENCED_PARAMETER(mbx_id);
365*ace44974SZaiyu Wang 
366*ace44974SZaiyu Wang 	/* lock the mailbox to prevent pf/vf race condition */
367*ace44974SZaiyu Wang 	ret_val = ngbe_obtain_mbx_lock_vf(hw);
368*ace44974SZaiyu Wang 	if (ret_val)
369*ace44974SZaiyu Wang 		goto out_no_write;
370*ace44974SZaiyu Wang 
371*ace44974SZaiyu Wang 	/* flush msg and acks as we are overwriting the message buffer */
372*ace44974SZaiyu Wang 	ngbe_check_for_msg_vf(hw, 0);
373*ace44974SZaiyu Wang 	ngbe_check_for_ack_vf(hw, 0);
374*ace44974SZaiyu Wang 
375*ace44974SZaiyu Wang 	/* copy the caller specified message to the mailbox memory buffer */
376*ace44974SZaiyu Wang 	for (i = 0; i < size; i++)
377*ace44974SZaiyu Wang 		wr32a(hw, NGBE_VFMBX, i, msg[i]);
378*ace44974SZaiyu Wang 
379*ace44974SZaiyu Wang 	/* update stats */
380*ace44974SZaiyu Wang 	hw->mbx.stats.msgs_tx++;
381*ace44974SZaiyu Wang 
382*ace44974SZaiyu Wang 	/* Drop VFU and interrupt the PF to tell it a message has been sent */
383*ace44974SZaiyu Wang 	wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_REQ);
384*ace44974SZaiyu Wang 
385*ace44974SZaiyu Wang out_no_write:
386*ace44974SZaiyu Wang 	return ret_val;
387*ace44974SZaiyu Wang }
388*ace44974SZaiyu Wang 
389*ace44974SZaiyu Wang /**
390*ace44974SZaiyu Wang  *  ngbe_read_mbx_vf - Reads a message from the inbox intended for vf
391*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
392*ace44974SZaiyu Wang  *  @msg: The message buffer
393*ace44974SZaiyu Wang  *  @size: Length of buffer
394*ace44974SZaiyu Wang  *  @mbx_id: id of mailbox to read
395*ace44974SZaiyu Wang  *
396*ace44974SZaiyu Wang  *  returns SUCCESS if it successfully read message from buffer
397*ace44974SZaiyu Wang  **/
398*ace44974SZaiyu Wang s32 ngbe_read_mbx_vf(struct ngbe_hw *hw, u32 *msg, u16 size,
399*ace44974SZaiyu Wang 			     u16 mbx_id)
400*ace44974SZaiyu Wang {
401*ace44974SZaiyu Wang 	s32 ret_val = 0;
402*ace44974SZaiyu Wang 	u16 i;
403*ace44974SZaiyu Wang 
404*ace44974SZaiyu Wang 	UNREFERENCED_PARAMETER(mbx_id);
405*ace44974SZaiyu Wang 
406*ace44974SZaiyu Wang 	/* lock the mailbox to prevent pf/vf race condition */
407*ace44974SZaiyu Wang 	ret_val = ngbe_obtain_mbx_lock_vf(hw);
408*ace44974SZaiyu Wang 	if (ret_val)
409*ace44974SZaiyu Wang 		goto out_no_read;
410*ace44974SZaiyu Wang 
411*ace44974SZaiyu Wang 	/* copy the message from the mailbox memory buffer */
412*ace44974SZaiyu Wang 	for (i = 0; i < size; i++)
413*ace44974SZaiyu Wang 		msg[i] = rd32a(hw, NGBE_VFMBX, i);
414*ace44974SZaiyu Wang 
415*ace44974SZaiyu Wang 	/* Acknowledge receipt and release mailbox, then we're done */
416*ace44974SZaiyu Wang 	wr32(hw, NGBE_VFMBCTL, NGBE_VFMBCTL_ACK);
417*ace44974SZaiyu Wang 
418*ace44974SZaiyu Wang 	/* update stats */
419*ace44974SZaiyu Wang 	hw->mbx.stats.msgs_rx++;
420*ace44974SZaiyu Wang 
421*ace44974SZaiyu Wang out_no_read:
422*ace44974SZaiyu Wang 	return ret_val;
423*ace44974SZaiyu Wang }
424*ace44974SZaiyu Wang 
425*ace44974SZaiyu Wang /**
426*ace44974SZaiyu Wang  *  ngbe_init_mbx_params_vf - set initial values for vf mailbox
427*ace44974SZaiyu Wang  *  @hw: pointer to the HW structure
428*ace44974SZaiyu Wang  *
429*ace44974SZaiyu Wang  *  Initializes the hw->mbx struct to correct values for vf mailbox
430*ace44974SZaiyu Wang  */
431*ace44974SZaiyu Wang void ngbe_init_mbx_params_vf(struct ngbe_hw *hw)
432*ace44974SZaiyu Wang {
433*ace44974SZaiyu Wang 	struct ngbe_mbx_info *mbx = &hw->mbx;
434*ace44974SZaiyu Wang 
435*ace44974SZaiyu Wang 	/* start mailbox as timed out and let the reset_hw call set the timeout
436*ace44974SZaiyu Wang 	 * value to begin communications
437*ace44974SZaiyu Wang 	 */
438*ace44974SZaiyu Wang 	mbx->timeout = 0;
439*ace44974SZaiyu Wang 	mbx->usec_delay = NGBE_VF_MBX_INIT_DELAY;
440*ace44974SZaiyu Wang 
441*ace44974SZaiyu Wang 	mbx->size = NGBE_P2VMBX_SIZE;
442*ace44974SZaiyu Wang 
443*ace44974SZaiyu Wang 	mbx->stats.msgs_tx = 0;
444*ace44974SZaiyu Wang 	mbx->stats.msgs_rx = 0;
445*ace44974SZaiyu Wang 	mbx->stats.reqs = 0;
446*ace44974SZaiyu Wang 	mbx->stats.acks = 0;
447*ace44974SZaiyu Wang 	mbx->stats.rsts = 0;
448*ace44974SZaiyu Wang }
449*ace44974SZaiyu Wang 
450e2a289a7SJiawen Wu STATIC s32 ngbe_check_for_bit_pf(struct ngbe_hw *hw, u32 mask)
451e2a289a7SJiawen Wu {
452e2a289a7SJiawen Wu 	u32 mbvficr = rd32(hw, NGBE_MBVFICR);
453e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
454e2a289a7SJiawen Wu 
455e2a289a7SJiawen Wu 	if (mbvficr & mask) {
456e2a289a7SJiawen Wu 		ret_val = 0;
457e2a289a7SJiawen Wu 		wr32(hw, NGBE_MBVFICR, mask);
458e2a289a7SJiawen Wu 	}
459e2a289a7SJiawen Wu 
460e2a289a7SJiawen Wu 	return ret_val;
461e2a289a7SJiawen Wu }
462e2a289a7SJiawen Wu 
463e2a289a7SJiawen Wu /**
464e2a289a7SJiawen Wu  *  ngbe_check_for_msg_pf - checks to see if the VF has sent mail
465e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
466e2a289a7SJiawen Wu  *  @vf_number: the VF index
467e2a289a7SJiawen Wu  *
468e2a289a7SJiawen Wu  *  returns 0 if the VF has set the Status bit or else ERR_MBX
469e2a289a7SJiawen Wu  **/
470e2a289a7SJiawen Wu s32 ngbe_check_for_msg_pf(struct ngbe_hw *hw, u16 vf_number)
471e2a289a7SJiawen Wu {
472e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
473e2a289a7SJiawen Wu 	u32 vf_bit = vf_number;
474e2a289a7SJiawen Wu 
475e2a289a7SJiawen Wu 	if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFREQ_VF1 << vf_bit)) {
476e2a289a7SJiawen Wu 		ret_val = 0;
477e2a289a7SJiawen Wu 		hw->mbx.stats.reqs++;
478e2a289a7SJiawen Wu 	}
479e2a289a7SJiawen Wu 
480e2a289a7SJiawen Wu 	return ret_val;
481e2a289a7SJiawen Wu }
482e2a289a7SJiawen Wu 
483e2a289a7SJiawen Wu /**
484e2a289a7SJiawen Wu  *  ngbe_check_for_ack_pf - checks to see if the VF has ACKed
485e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
486e2a289a7SJiawen Wu  *  @vf_number: the VF index
487e2a289a7SJiawen Wu  *
488e2a289a7SJiawen Wu  *  returns 0 if the VF has set the Status bit or else ERR_MBX
489e2a289a7SJiawen Wu  **/
490e2a289a7SJiawen Wu s32 ngbe_check_for_ack_pf(struct ngbe_hw *hw, u16 vf_number)
491e2a289a7SJiawen Wu {
492e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
493e2a289a7SJiawen Wu 	u32 vf_bit = vf_number;
494e2a289a7SJiawen Wu 
495e2a289a7SJiawen Wu 	if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFACK_VF1 << vf_bit)) {
496e2a289a7SJiawen Wu 		ret_val = 0;
497e2a289a7SJiawen Wu 		hw->mbx.stats.acks++;
498e2a289a7SJiawen Wu 	}
499e2a289a7SJiawen Wu 
500e2a289a7SJiawen Wu 	return ret_val;
501e2a289a7SJiawen Wu }
502e2a289a7SJiawen Wu 
503e2a289a7SJiawen Wu /**
504e2a289a7SJiawen Wu  *  ngbe_check_for_rst_pf - checks to see if the VF has reset
505e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
506e2a289a7SJiawen Wu  *  @vf_number: the VF index
507e2a289a7SJiawen Wu  *
508e2a289a7SJiawen Wu  *  returns 0 if the VF has set the Status bit or else ERR_MBX
509e2a289a7SJiawen Wu  **/
510e2a289a7SJiawen Wu s32 ngbe_check_for_rst_pf(struct ngbe_hw *hw, u16 vf_number)
511e2a289a7SJiawen Wu {
512e2a289a7SJiawen Wu 	u32 vflre = 0;
513e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
514e2a289a7SJiawen Wu 
515e2a289a7SJiawen Wu 	vflre = rd32(hw, NGBE_FLRVFE);
516e2a289a7SJiawen Wu 	if (vflre & (1 << vf_number)) {
517e2a289a7SJiawen Wu 		ret_val = 0;
518e2a289a7SJiawen Wu 		wr32(hw, NGBE_FLRVFEC, (1 << vf_number));
519e2a289a7SJiawen Wu 		hw->mbx.stats.rsts++;
520e2a289a7SJiawen Wu 	}
521e2a289a7SJiawen Wu 
522e2a289a7SJiawen Wu 	return ret_val;
523e2a289a7SJiawen Wu }
524e2a289a7SJiawen Wu 
525e2a289a7SJiawen Wu /**
526e2a289a7SJiawen Wu  *  ngbe_obtain_mbx_lock_pf - obtain mailbox lock
527e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
528e2a289a7SJiawen Wu  *  @vf_number: the VF index
529e2a289a7SJiawen Wu  *
530e2a289a7SJiawen Wu  *  return 0 if we obtained the mailbox lock
531e2a289a7SJiawen Wu  **/
532e2a289a7SJiawen Wu STATIC s32 ngbe_obtain_mbx_lock_pf(struct ngbe_hw *hw, u16 vf_number)
533e2a289a7SJiawen Wu {
534e2a289a7SJiawen Wu 	s32 ret_val = NGBE_ERR_MBX;
535e2a289a7SJiawen Wu 	u32 p2v_mailbox;
536e2a289a7SJiawen Wu 
537e2a289a7SJiawen Wu 	/* Take ownership of the buffer */
538e2a289a7SJiawen Wu 	wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_PFU);
539e2a289a7SJiawen Wu 
540e2a289a7SJiawen Wu 	/* reserve mailbox for vf use */
541e2a289a7SJiawen Wu 	p2v_mailbox = rd32(hw, NGBE_MBCTL(vf_number));
542e2a289a7SJiawen Wu 	if (p2v_mailbox & NGBE_MBCTL_PFU)
543e2a289a7SJiawen Wu 		ret_val = 0;
544e2a289a7SJiawen Wu 	else
545e2a289a7SJiawen Wu 		DEBUGOUT("Failed to obtain mailbox lock for VF%d", vf_number);
546e2a289a7SJiawen Wu 
547e2a289a7SJiawen Wu 
548e2a289a7SJiawen Wu 	return ret_val;
549e2a289a7SJiawen Wu }
550e2a289a7SJiawen Wu 
551e2a289a7SJiawen Wu /**
552e2a289a7SJiawen Wu  *  ngbe_write_mbx_pf - Places a message in the mailbox
553e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
554e2a289a7SJiawen Wu  *  @msg: The message buffer
555e2a289a7SJiawen Wu  *  @size: Length of buffer
556e2a289a7SJiawen Wu  *  @vf_number: the VF index
557e2a289a7SJiawen Wu  *
558e2a289a7SJiawen Wu  *  returns 0 if it successfully copied message into the buffer
559e2a289a7SJiawen Wu  **/
560e2a289a7SJiawen Wu s32 ngbe_write_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number)
561e2a289a7SJiawen Wu {
562e2a289a7SJiawen Wu 	s32 ret_val;
563e2a289a7SJiawen Wu 	u16 i;
564e2a289a7SJiawen Wu 
565e2a289a7SJiawen Wu 	/* lock the mailbox to prevent pf/vf race condition */
566e2a289a7SJiawen Wu 	ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number);
567e2a289a7SJiawen Wu 	if (ret_val)
568e2a289a7SJiawen Wu 		goto out_no_write;
569e2a289a7SJiawen Wu 
570e2a289a7SJiawen Wu 	/* flush msg and acks as we are overwriting the message buffer */
571e2a289a7SJiawen Wu 	ngbe_check_for_msg_pf(hw, vf_number);
572e2a289a7SJiawen Wu 	ngbe_check_for_ack_pf(hw, vf_number);
573e2a289a7SJiawen Wu 
574e2a289a7SJiawen Wu 	/* copy the caller specified message to the mailbox memory buffer */
575e2a289a7SJiawen Wu 	for (i = 0; i < size; i++)
576e2a289a7SJiawen Wu 		wr32a(hw, NGBE_MBMEM(vf_number), i, msg[i]);
577e2a289a7SJiawen Wu 
578e2a289a7SJiawen Wu 	/* Interrupt VF to tell it a message has been sent and release buffer*/
579e2a289a7SJiawen Wu 	wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_STS);
580e2a289a7SJiawen Wu 
581e2a289a7SJiawen Wu 	/* update stats */
582e2a289a7SJiawen Wu 	hw->mbx.stats.msgs_tx++;
583e2a289a7SJiawen Wu 
584e2a289a7SJiawen Wu out_no_write:
585e2a289a7SJiawen Wu 	return ret_val;
586e2a289a7SJiawen Wu }
587e2a289a7SJiawen Wu 
588e2a289a7SJiawen Wu /**
589e2a289a7SJiawen Wu  *  ngbe_read_mbx_pf - Read a message from the mailbox
590e2a289a7SJiawen Wu  *  @hw: pointer to the HW structure
591e2a289a7SJiawen Wu  *  @msg: The message buffer
592e2a289a7SJiawen Wu  *  @size: Length of buffer
593e2a289a7SJiawen Wu  *  @vf_number: the VF index
594e2a289a7SJiawen Wu  *
595e2a289a7SJiawen Wu  *  This function copies a message from the mailbox buffer to the caller's
596e2a289a7SJiawen Wu  *  memory buffer.  The presumption is that the caller knows that there was
597e2a289a7SJiawen Wu  *  a message due to a VF request so no polling for message is needed.
598e2a289a7SJiawen Wu  **/
599e2a289a7SJiawen Wu s32 ngbe_read_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number)
600e2a289a7SJiawen Wu {
601e2a289a7SJiawen Wu 	s32 ret_val;
602e2a289a7SJiawen Wu 	u16 i;
603e2a289a7SJiawen Wu 
604e2a289a7SJiawen Wu 	/* lock the mailbox to prevent pf/vf race condition */
605e2a289a7SJiawen Wu 	ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number);
606e2a289a7SJiawen Wu 	if (ret_val)
607e2a289a7SJiawen Wu 		goto out_no_read;
608e2a289a7SJiawen Wu 
609e2a289a7SJiawen Wu 	/* copy the message to the mailbox memory buffer */
610e2a289a7SJiawen Wu 	for (i = 0; i < size; i++)
611e2a289a7SJiawen Wu 		msg[i] = rd32a(hw, NGBE_MBMEM(vf_number), i);
612e2a289a7SJiawen Wu 
613e2a289a7SJiawen Wu 	/* Acknowledge the message and release buffer */
614e2a289a7SJiawen Wu 	wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_ACK);
615e2a289a7SJiawen Wu 
616e2a289a7SJiawen Wu 	/* update stats */
617e2a289a7SJiawen Wu 	hw->mbx.stats.msgs_rx++;
618e2a289a7SJiawen Wu 
619e2a289a7SJiawen Wu out_no_read:
620e2a289a7SJiawen Wu 	return ret_val;
621e2a289a7SJiawen Wu }
622e2a289a7SJiawen Wu 
623e2a289a7SJiawen Wu /**
62460229dcfSJiawen Wu  *  ngbe_init_mbx_params_pf - set initial values for pf mailbox
62560229dcfSJiawen Wu  *  @hw: pointer to the HW structure
62660229dcfSJiawen Wu  *
62760229dcfSJiawen Wu  *  Initializes the hw->mbx struct to correct values for pf mailbox
62860229dcfSJiawen Wu  */
62960229dcfSJiawen Wu void ngbe_init_mbx_params_pf(struct ngbe_hw *hw)
63060229dcfSJiawen Wu {
63160229dcfSJiawen Wu 	struct ngbe_mbx_info *mbx = &hw->mbx;
63260229dcfSJiawen Wu 
63360229dcfSJiawen Wu 	mbx->timeout = 0;
63460229dcfSJiawen Wu 	mbx->usec_delay = 0;
63560229dcfSJiawen Wu 
63660229dcfSJiawen Wu 	mbx->size = NGBE_P2VMBX_SIZE;
63760229dcfSJiawen Wu 
63860229dcfSJiawen Wu 	mbx->stats.msgs_tx = 0;
63960229dcfSJiawen Wu 	mbx->stats.msgs_rx = 0;
64060229dcfSJiawen Wu 	mbx->stats.reqs = 0;
64160229dcfSJiawen Wu 	mbx->stats.acks = 0;
64260229dcfSJiawen Wu 	mbx->stats.rsts = 0;
64360229dcfSJiawen Wu }
644