xref: /dpdk/drivers/net/ngbe/base/ngbe_mbx.c (revision f8dbaebbf1c9efcbb2e2354b341ed62175466a57)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5 
6 #include "ngbe_type.h"
7 
8 #include "ngbe_mbx.h"
9 
10 /**
11  *  ngbe_read_mbx - Reads a message from the mailbox
12  *  @hw: pointer to the HW structure
13  *  @msg: The message buffer
14  *  @size: Length of buffer
15  *  @mbx_id: id of mailbox to read
16  *
17  *  returns 0 if it successfully read message from buffer
18  **/
19 s32 ngbe_read_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
20 {
21 	struct ngbe_mbx_info *mbx = &hw->mbx;
22 	s32 ret_val = NGBE_ERR_MBX;
23 
24 	DEBUGFUNC("ngbe_read_mbx");
25 
26 	/* limit read to size of mailbox */
27 	if (size > mbx->size)
28 		size = mbx->size;
29 
30 	if (mbx->read)
31 		ret_val = mbx->read(hw, msg, size, mbx_id);
32 
33 	return ret_val;
34 }
35 
36 /**
37  *  ngbe_write_mbx - Write a message to the mailbox
38  *  @hw: pointer to the HW structure
39  *  @msg: The message buffer
40  *  @size: Length of buffer
41  *  @mbx_id: id of mailbox to write
42  *
43  *  returns 0 if it successfully copied message into the buffer
44  **/
45 s32 ngbe_write_mbx(struct ngbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
46 {
47 	struct ngbe_mbx_info *mbx = &hw->mbx;
48 	s32 ret_val = 0;
49 
50 	DEBUGFUNC("ngbe_write_mbx");
51 
52 	if (size > mbx->size) {
53 		ret_val = NGBE_ERR_MBX;
54 		DEBUGOUT("Invalid mailbox message size %d", size);
55 	} else if (mbx->write) {
56 		ret_val = mbx->write(hw, msg, size, mbx_id);
57 	}
58 
59 	return ret_val;
60 }
61 
62 /**
63  *  ngbe_check_for_msg - checks to see if someone sent us mail
64  *  @hw: pointer to the HW structure
65  *  @mbx_id: id of mailbox to check
66  *
67  *  returns 0 if the Status bit was found or else ERR_MBX
68  **/
69 s32 ngbe_check_for_msg(struct ngbe_hw *hw, u16 mbx_id)
70 {
71 	struct ngbe_mbx_info *mbx = &hw->mbx;
72 	s32 ret_val = NGBE_ERR_MBX;
73 
74 	DEBUGFUNC("ngbe_check_for_msg");
75 
76 	if (mbx->check_for_msg)
77 		ret_val = mbx->check_for_msg(hw, mbx_id);
78 
79 	return ret_val;
80 }
81 
82 /**
83  *  ngbe_check_for_ack - checks to see if someone sent us ACK
84  *  @hw: pointer to the HW structure
85  *  @mbx_id: id of mailbox to check
86  *
87  *  returns 0 if the Status bit was found or else ERR_MBX
88  **/
89 s32 ngbe_check_for_ack(struct ngbe_hw *hw, u16 mbx_id)
90 {
91 	struct ngbe_mbx_info *mbx = &hw->mbx;
92 	s32 ret_val = NGBE_ERR_MBX;
93 
94 	DEBUGFUNC("ngbe_check_for_ack");
95 
96 	if (mbx->check_for_ack)
97 		ret_val = mbx->check_for_ack(hw, mbx_id);
98 
99 	return ret_val;
100 }
101 
102 /**
103  *  ngbe_check_for_rst - checks to see if other side has reset
104  *  @hw: pointer to the HW structure
105  *  @mbx_id: id of mailbox to check
106  *
107  *  returns 0 if the Status bit was found or else ERR_MBX
108  **/
109 s32 ngbe_check_for_rst(struct ngbe_hw *hw, u16 mbx_id)
110 {
111 	struct ngbe_mbx_info *mbx = &hw->mbx;
112 	s32 ret_val = NGBE_ERR_MBX;
113 
114 	DEBUGFUNC("ngbe_check_for_rst");
115 
116 	if (mbx->check_for_rst)
117 		ret_val = mbx->check_for_rst(hw, mbx_id);
118 
119 	return ret_val;
120 }
121 
122 STATIC s32 ngbe_check_for_bit_pf(struct ngbe_hw *hw, u32 mask)
123 {
124 	u32 mbvficr = rd32(hw, NGBE_MBVFICR);
125 	s32 ret_val = NGBE_ERR_MBX;
126 
127 	if (mbvficr & mask) {
128 		ret_val = 0;
129 		wr32(hw, NGBE_MBVFICR, mask);
130 	}
131 
132 	return ret_val;
133 }
134 
135 /**
136  *  ngbe_check_for_msg_pf - checks to see if the VF has sent mail
137  *  @hw: pointer to the HW structure
138  *  @vf_number: the VF index
139  *
140  *  returns 0 if the VF has set the Status bit or else ERR_MBX
141  **/
142 s32 ngbe_check_for_msg_pf(struct ngbe_hw *hw, u16 vf_number)
143 {
144 	s32 ret_val = NGBE_ERR_MBX;
145 	u32 vf_bit = vf_number;
146 
147 	DEBUGFUNC("ngbe_check_for_msg_pf");
148 
149 	if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFREQ_VF1 << vf_bit)) {
150 		ret_val = 0;
151 		hw->mbx.stats.reqs++;
152 	}
153 
154 	return ret_val;
155 }
156 
157 /**
158  *  ngbe_check_for_ack_pf - checks to see if the VF has ACKed
159  *  @hw: pointer to the HW structure
160  *  @vf_number: the VF index
161  *
162  *  returns 0 if the VF has set the Status bit or else ERR_MBX
163  **/
164 s32 ngbe_check_for_ack_pf(struct ngbe_hw *hw, u16 vf_number)
165 {
166 	s32 ret_val = NGBE_ERR_MBX;
167 	u32 vf_bit = vf_number;
168 
169 	DEBUGFUNC("ngbe_check_for_ack_pf");
170 
171 	if (!ngbe_check_for_bit_pf(hw, NGBE_MBVFICR_VFACK_VF1 << vf_bit)) {
172 		ret_val = 0;
173 		hw->mbx.stats.acks++;
174 	}
175 
176 	return ret_val;
177 }
178 
179 /**
180  *  ngbe_check_for_rst_pf - checks to see if the VF has reset
181  *  @hw: pointer to the HW structure
182  *  @vf_number: the VF index
183  *
184  *  returns 0 if the VF has set the Status bit or else ERR_MBX
185  **/
186 s32 ngbe_check_for_rst_pf(struct ngbe_hw *hw, u16 vf_number)
187 {
188 	u32 vflre = 0;
189 	s32 ret_val = NGBE_ERR_MBX;
190 
191 	DEBUGFUNC("ngbe_check_for_rst_pf");
192 
193 	vflre = rd32(hw, NGBE_FLRVFE);
194 	if (vflre & (1 << vf_number)) {
195 		ret_val = 0;
196 		wr32(hw, NGBE_FLRVFEC, (1 << vf_number));
197 		hw->mbx.stats.rsts++;
198 	}
199 
200 	return ret_val;
201 }
202 
203 /**
204  *  ngbe_obtain_mbx_lock_pf - obtain mailbox lock
205  *  @hw: pointer to the HW structure
206  *  @vf_number: the VF index
207  *
208  *  return 0 if we obtained the mailbox lock
209  **/
210 STATIC s32 ngbe_obtain_mbx_lock_pf(struct ngbe_hw *hw, u16 vf_number)
211 {
212 	s32 ret_val = NGBE_ERR_MBX;
213 	u32 p2v_mailbox;
214 
215 	DEBUGFUNC("ngbe_obtain_mbx_lock_pf");
216 
217 	/* Take ownership of the buffer */
218 	wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_PFU);
219 
220 	/* reserve mailbox for vf use */
221 	p2v_mailbox = rd32(hw, NGBE_MBCTL(vf_number));
222 	if (p2v_mailbox & NGBE_MBCTL_PFU)
223 		ret_val = 0;
224 	else
225 		DEBUGOUT("Failed to obtain mailbox lock for VF%d", vf_number);
226 
227 
228 	return ret_val;
229 }
230 
231 /**
232  *  ngbe_write_mbx_pf - Places a message in the mailbox
233  *  @hw: pointer to the HW structure
234  *  @msg: The message buffer
235  *  @size: Length of buffer
236  *  @vf_number: the VF index
237  *
238  *  returns 0 if it successfully copied message into the buffer
239  **/
240 s32 ngbe_write_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number)
241 {
242 	s32 ret_val;
243 	u16 i;
244 
245 	DEBUGFUNC("ngbe_write_mbx_pf");
246 
247 	/* lock the mailbox to prevent pf/vf race condition */
248 	ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number);
249 	if (ret_val)
250 		goto out_no_write;
251 
252 	/* flush msg and acks as we are overwriting the message buffer */
253 	ngbe_check_for_msg_pf(hw, vf_number);
254 	ngbe_check_for_ack_pf(hw, vf_number);
255 
256 	/* copy the caller specified message to the mailbox memory buffer */
257 	for (i = 0; i < size; i++)
258 		wr32a(hw, NGBE_MBMEM(vf_number), i, msg[i]);
259 
260 	/* Interrupt VF to tell it a message has been sent and release buffer*/
261 	wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_STS);
262 
263 	/* update stats */
264 	hw->mbx.stats.msgs_tx++;
265 
266 out_no_write:
267 	return ret_val;
268 }
269 
270 /**
271  *  ngbe_read_mbx_pf - Read a message from the mailbox
272  *  @hw: pointer to the HW structure
273  *  @msg: The message buffer
274  *  @size: Length of buffer
275  *  @vf_number: the VF index
276  *
277  *  This function copies a message from the mailbox buffer to the caller's
278  *  memory buffer.  The presumption is that the caller knows that there was
279  *  a message due to a VF request so no polling for message is needed.
280  **/
281 s32 ngbe_read_mbx_pf(struct ngbe_hw *hw, u32 *msg, u16 size, u16 vf_number)
282 {
283 	s32 ret_val;
284 	u16 i;
285 
286 	DEBUGFUNC("ngbe_read_mbx_pf");
287 
288 	/* lock the mailbox to prevent pf/vf race condition */
289 	ret_val = ngbe_obtain_mbx_lock_pf(hw, vf_number);
290 	if (ret_val)
291 		goto out_no_read;
292 
293 	/* copy the message to the mailbox memory buffer */
294 	for (i = 0; i < size; i++)
295 		msg[i] = rd32a(hw, NGBE_MBMEM(vf_number), i);
296 
297 	/* Acknowledge the message and release buffer */
298 	wr32(hw, NGBE_MBCTL(vf_number), NGBE_MBCTL_ACK);
299 
300 	/* update stats */
301 	hw->mbx.stats.msgs_rx++;
302 
303 out_no_read:
304 	return ret_val;
305 }
306 
307 /**
308  *  ngbe_init_mbx_params_pf - set initial values for pf mailbox
309  *  @hw: pointer to the HW structure
310  *
311  *  Initializes the hw->mbx struct to correct values for pf mailbox
312  */
313 void ngbe_init_mbx_params_pf(struct ngbe_hw *hw)
314 {
315 	struct ngbe_mbx_info *mbx = &hw->mbx;
316 
317 	mbx->timeout = 0;
318 	mbx->usec_delay = 0;
319 
320 	mbx->size = NGBE_P2VMBX_SIZE;
321 
322 	mbx->stats.msgs_tx = 0;
323 	mbx->stats.msgs_rx = 0;
324 	mbx->stats.reqs = 0;
325 	mbx->stats.acks = 0;
326 	mbx->stats.rsts = 0;
327 }
328