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