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