1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2013 - 2019 Intel Corporation. */
4 #include "fm10k_common.h"
7 * fm10k_fifo_init - Initialize a message FIFO
8 * @fifo: pointer to FIFO
9 * @buffer: pointer to memory to be used to store FIFO
10 * @size: maximum message size to store in FIFO, must be 2^n - 1
12 static void fm10k_fifo_init(struct fm10k_mbx_fifo
*fifo
, u32
*buffer
, u16 size
)
14 fifo
->buffer
= buffer
;
21 * fm10k_fifo_used - Retrieve used space in FIFO
22 * @fifo: pointer to FIFO
24 * This function returns the number of DWORDs used in the FIFO
26 static u16
fm10k_fifo_used(struct fm10k_mbx_fifo
*fifo
)
28 return fifo
->tail
- fifo
->head
;
32 * fm10k_fifo_unused - Retrieve unused space in FIFO
33 * @fifo: pointer to FIFO
35 * This function returns the number of unused DWORDs in the FIFO
37 static u16
fm10k_fifo_unused(struct fm10k_mbx_fifo
*fifo
)
39 return fifo
->size
+ fifo
->head
- fifo
->tail
;
43 * fm10k_fifo_empty - Test to verify if FIFO is empty
44 * @fifo: pointer to FIFO
46 * This function returns true if the FIFO is empty, else false
48 static bool fm10k_fifo_empty(struct fm10k_mbx_fifo
*fifo
)
50 return fifo
->head
== fifo
->tail
;
54 * fm10k_fifo_head_offset - returns indices of head with given offset
55 * @fifo: pointer to FIFO
56 * @offset: offset to add to head
58 * This function returns the indices into the FIFO based on head + offset
60 static u16
fm10k_fifo_head_offset(struct fm10k_mbx_fifo
*fifo
, u16 offset
)
62 return (fifo
->head
+ offset
) & (fifo
->size
- 1);
66 * fm10k_fifo_tail_offset - returns indices of tail with given offset
67 * @fifo: pointer to FIFO
68 * @offset: offset to add to tail
70 * This function returns the indices into the FIFO based on tail + offset
72 static u16
fm10k_fifo_tail_offset(struct fm10k_mbx_fifo
*fifo
, u16 offset
)
74 return (fifo
->tail
+ offset
) & (fifo
->size
- 1);
78 * fm10k_fifo_head_len - Retrieve length of first message in FIFO
79 * @fifo: pointer to FIFO
81 * This function returns the size of the first message in the FIFO
83 static u16
fm10k_fifo_head_len(struct fm10k_mbx_fifo
*fifo
)
85 u32
*head
= fifo
->buffer
+ fm10k_fifo_head_offset(fifo
, 0);
87 /* verify there is at least 1 DWORD in the fifo so *head is valid */
88 if (fm10k_fifo_empty(fifo
))
91 /* retieve the message length */
92 return FM10K_TLV_DWORD_LEN(*head
);
96 * fm10k_fifo_head_drop - Drop the first message in FIFO
97 * @fifo: pointer to FIFO
99 * This function returns the size of the message dropped from the FIFO
101 static u16
fm10k_fifo_head_drop(struct fm10k_mbx_fifo
*fifo
)
103 u16 len
= fm10k_fifo_head_len(fifo
);
105 /* update head so it is at the start of next frame */
112 * fm10k_fifo_drop_all - Drop all messages in FIFO
113 * @fifo: pointer to FIFO
115 * This function resets the head pointer to drop all messages in the FIFO and
116 * ensure the FIFO is empty.
118 static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo
*fifo
)
120 fifo
->head
= fifo
->tail
;
124 * fm10k_mbx_index_len - Convert a head/tail index into a length value
125 * @mbx: pointer to mailbox
129 * This function takes the head and tail index and determines the length
130 * of the data indicated by this pair.
132 static u16
fm10k_mbx_index_len(struct fm10k_mbx_info
*mbx
, u16 head
, u16 tail
)
134 u16 len
= tail
- head
;
136 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
140 return len
& ((mbx
->mbmem_len
<< 1) - 1);
144 * fm10k_mbx_tail_add - Determine new tail value with added offset
145 * @mbx: pointer to mailbox
146 * @offset: length to add to tail offset
148 * This function takes the local tail index and recomputes it for
149 * a given length added as an offset.
151 static u16
fm10k_mbx_tail_add(struct fm10k_mbx_info
*mbx
, u16 offset
)
153 u16 tail
= (mbx
->tail
+ offset
+ 1) & ((mbx
->mbmem_len
<< 1) - 1);
155 /* add/sub 1 because we cannot have offset 0 or all 1s */
156 return (tail
> mbx
->tail
) ? --tail
: ++tail
;
160 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
161 * @mbx: pointer to mailbox
162 * @offset: length to add to tail offset
164 * This function takes the local tail index and recomputes it for
165 * a given length added as an offset.
167 static u16
fm10k_mbx_tail_sub(struct fm10k_mbx_info
*mbx
, u16 offset
)
169 u16 tail
= (mbx
->tail
- offset
- 1) & ((mbx
->mbmem_len
<< 1) - 1);
171 /* sub/add 1 because we cannot have offset 0 or all 1s */
172 return (tail
< mbx
->tail
) ? ++tail
: --tail
;
176 * fm10k_mbx_head_add - Determine new head value with added offset
177 * @mbx: pointer to mailbox
178 * @offset: length to add to head offset
180 * This function takes the local head index and recomputes it for
181 * a given length added as an offset.
183 static u16
fm10k_mbx_head_add(struct fm10k_mbx_info
*mbx
, u16 offset
)
185 u16 head
= (mbx
->head
+ offset
+ 1) & ((mbx
->mbmem_len
<< 1) - 1);
187 /* add/sub 1 because we cannot have offset 0 or all 1s */
188 return (head
> mbx
->head
) ? --head
: ++head
;
192 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
193 * @mbx: pointer to mailbox
194 * @offset: length to add to head offset
196 * This function takes the local head index and recomputes it for
197 * a given length added as an offset.
199 static u16
fm10k_mbx_head_sub(struct fm10k_mbx_info
*mbx
, u16 offset
)
201 u16 head
= (mbx
->head
- offset
- 1) & ((mbx
->mbmem_len
<< 1) - 1);
203 /* sub/add 1 because we cannot have offset 0 or all 1s */
204 return (head
< mbx
->head
) ? ++head
: --head
;
208 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
209 * @mbx: pointer to mailbox
211 * This function will return the length of the message currently being
212 * pushed onto the tail of the Rx queue.
214 static u16
fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info
*mbx
)
216 u32
*tail
= mbx
->rx
.buffer
+ fm10k_fifo_tail_offset(&mbx
->rx
, 0);
218 /* pushed tail is only valid if pushed is set */
222 return FM10K_TLV_DWORD_LEN(*tail
);
226 * fm10k_fifo_write_copy - pulls data off of msg and places it in FIFO
227 * @fifo: pointer to FIFO
228 * @msg: message array to populate
229 * @tail_offset: additional offset to add to tail pointer
230 * @len: length of FIFO to copy into message header
232 * This function will take a message and copy it into a section of the
233 * FIFO. In order to get something into a location other than just
234 * the tail you can use tail_offset to adjust the pointer.
236 static void fm10k_fifo_write_copy(struct fm10k_mbx_fifo
*fifo
,
237 const u32
*msg
, u16 tail_offset
, u16 len
)
239 u16 end
= fm10k_fifo_tail_offset(fifo
, tail_offset
);
240 u32
*tail
= fifo
->buffer
+ end
;
242 /* track when we should cross the end of the FIFO */
243 end
= fifo
->size
- end
;
245 /* copy end of message before start of message */
247 memcpy(fifo
->buffer
, msg
+ end
, (len
- end
) << 2);
251 /* Copy remaining message into Tx FIFO */
252 memcpy(tail
, msg
, end
<< 2);
256 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
257 * @fifo: pointer to FIFO
258 * @msg: message array to read
260 * This function enqueues a message up to the size specified by the length
261 * contained in the first DWORD of the message and will place at the tail
262 * of the FIFO. It will return 0 on success, or a negative value on error.
264 static s32
fm10k_fifo_enqueue(struct fm10k_mbx_fifo
*fifo
, const u32
*msg
)
266 u16 len
= FM10K_TLV_DWORD_LEN(*msg
);
268 /* verify parameters */
269 if (len
> fifo
->size
)
270 return FM10K_MBX_ERR_SIZE
;
272 /* verify there is room for the message */
273 if (len
> fm10k_fifo_unused(fifo
))
274 return FM10K_MBX_ERR_NO_SPACE
;
276 /* Copy message into FIFO */
277 fm10k_fifo_write_copy(fifo
, msg
, 0, len
);
279 /* memory barrier to guarantee FIFO is written before tail update */
282 /* Update Tx FIFO tail */
289 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
290 * @mbx: pointer to mailbox
291 * @len: length of data pushed onto buffer
293 * This function analyzes the frame and will return a non-zero value when
294 * the start of a message larger than the mailbox is detected.
296 static u16
fm10k_mbx_validate_msg_size(struct fm10k_mbx_info
*mbx
, u16 len
)
298 struct fm10k_mbx_fifo
*fifo
= &mbx
->rx
;
299 u16 total_len
= 0, msg_len
;
301 /* length should include previous amounts pushed */
304 /* offset in message is based off of current message size */
308 msg
= fifo
->buffer
+ fm10k_fifo_tail_offset(fifo
, total_len
);
309 msg_len
= FM10K_TLV_DWORD_LEN(*msg
);
310 total_len
+= msg_len
;
311 } while (total_len
< len
);
313 /* message extends out of pushed section, but fits in FIFO */
314 if ((len
< total_len
) && (msg_len
<= mbx
->max_size
))
317 /* return length of invalid section */
318 return (len
< total_len
) ? len
: (len
- total_len
);
322 * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
323 * @hw: pointer to hardware structure
324 * @mbx: pointer to mailbox
326 * This function will take a section of the Tx FIFO and copy it into the
327 * mailbox memory. The offset in mbmem is based on the lower bits of the
328 * tail and len determines the length to copy.
330 static void fm10k_mbx_write_copy(struct fm10k_hw
*hw
,
331 struct fm10k_mbx_info
*mbx
)
333 struct fm10k_mbx_fifo
*fifo
= &mbx
->tx
;
334 u32 mbmem
= mbx
->mbmem_reg
;
335 u32
*head
= fifo
->buffer
;
336 u16 end
, len
, tail
, mask
;
341 /* determine data length and mbmem tail index */
342 mask
= mbx
->mbmem_len
- 1;
344 tail
= fm10k_mbx_tail_sub(mbx
, len
);
348 /* determine offset in the ring */
349 end
= fm10k_fifo_head_offset(fifo
, mbx
->pulled
);
352 /* memory barrier to guarantee data is ready to be read */
355 /* Copy message from Tx FIFO */
356 for (end
= fifo
->size
- end
; len
; head
= fifo
->buffer
) {
358 /* adjust tail to match offset for FIFO */
363 mbx
->tx_mbmem_pulled
++;
365 /* write message to hardware FIFO */
366 fm10k_write_reg(hw
, mbmem
+ tail
++, *(head
++));
367 } while (--len
&& --end
);
372 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
373 * @hw: pointer to hardware structure
374 * @mbx: pointer to mailbox
375 * @head: acknowledgement number last received
377 * This function will push the tail index forward based on the remote
378 * head index. It will then pull up to mbmem_len DWORDs off of the
379 * head of the FIFO and will place it in the MBMEM registers
380 * associated with the mailbox.
382 static void fm10k_mbx_pull_head(struct fm10k_hw
*hw
,
383 struct fm10k_mbx_info
*mbx
, u16 head
)
385 u16 mbmem_len
, len
, ack
= fm10k_mbx_index_len(mbx
, head
, mbx
->tail
);
386 struct fm10k_mbx_fifo
*fifo
= &mbx
->tx
;
388 /* update number of bytes pulled and update bytes in transit */
389 mbx
->pulled
+= mbx
->tail_len
- ack
;
391 /* determine length of data to pull, reserve space for mbmem header */
392 mbmem_len
= mbx
->mbmem_len
- 1;
393 len
= fm10k_fifo_used(fifo
) - mbx
->pulled
;
397 /* update tail and record number of bytes in transit */
398 mbx
->tail
= fm10k_mbx_tail_add(mbx
, len
- ack
);
401 /* drop pulled messages from the FIFO */
402 for (len
= fm10k_fifo_head_len(fifo
);
403 len
&& (mbx
->pulled
>= len
);
404 len
= fm10k_fifo_head_len(fifo
)) {
405 mbx
->pulled
-= fm10k_fifo_head_drop(fifo
);
407 mbx
->tx_dwords
+= len
;
410 /* Copy message out from the Tx FIFO */
411 fm10k_mbx_write_copy(hw
, mbx
);
415 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
416 * @hw: pointer to hardware structure
417 * @mbx: pointer to mailbox
419 * This function will take a section of the mailbox memory and copy it
420 * into the Rx FIFO. The offset is based on the lower bits of the
421 * head and len determines the length to copy.
423 static void fm10k_mbx_read_copy(struct fm10k_hw
*hw
,
424 struct fm10k_mbx_info
*mbx
)
426 struct fm10k_mbx_fifo
*fifo
= &mbx
->rx
;
427 u32 mbmem
= mbx
->mbmem_reg
^ mbx
->mbmem_len
;
428 u32
*tail
= fifo
->buffer
;
431 /* determine data length and mbmem head index */
433 head
= fm10k_mbx_head_sub(mbx
, len
);
434 if (head
>= mbx
->mbmem_len
)
437 /* determine offset in the ring */
438 end
= fm10k_fifo_tail_offset(fifo
, mbx
->pushed
);
441 /* Copy message into Rx FIFO */
442 for (end
= fifo
->size
- end
; len
; tail
= fifo
->buffer
) {
444 /* adjust head to match offset for FIFO */
445 head
&= mbx
->mbmem_len
- 1;
449 mbx
->rx_mbmem_pushed
++;
451 /* read message from hardware FIFO */
452 *(tail
++) = fm10k_read_reg(hw
, mbmem
+ head
++);
453 } while (--len
&& --end
);
456 /* memory barrier to guarantee FIFO is written before tail update */
461 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
462 * @hw: pointer to hardware structure
463 * @mbx: pointer to mailbox
464 * @tail: tail index of message
466 * This function will first validate the tail index and size for the
467 * incoming message. It then updates the acknowledgment number and
468 * copies the data into the FIFO. It will return the number of messages
469 * dequeued on success and a negative value on error.
471 static s32
fm10k_mbx_push_tail(struct fm10k_hw
*hw
,
472 struct fm10k_mbx_info
*mbx
,
475 struct fm10k_mbx_fifo
*fifo
= &mbx
->rx
;
476 u16 len
, seq
= fm10k_mbx_index_len(mbx
, mbx
->head
, tail
);
478 /* determine length of data to push */
479 len
= fm10k_fifo_unused(fifo
) - mbx
->pushed
;
483 /* update head and record bytes received */
484 mbx
->head
= fm10k_mbx_head_add(mbx
, len
);
487 /* nothing to do if there is no data */
491 /* Copy msg into Rx FIFO */
492 fm10k_mbx_read_copy(hw
, mbx
);
494 /* determine if there are any invalid lengths in message */
495 if (fm10k_mbx_validate_msg_size(mbx
, len
))
496 return FM10K_MBX_ERR_SIZE
;
501 /* flush any completed messages */
502 for (len
= fm10k_mbx_pushed_tail_len(mbx
);
503 len
&& (mbx
->pushed
>= len
);
504 len
= fm10k_mbx_pushed_tail_len(mbx
)) {
508 mbx
->rx_dwords
+= len
;
514 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
515 static const u16 fm10k_crc_16b_table
[256] = {
516 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
517 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
518 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
519 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
520 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
521 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
522 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
523 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
524 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
525 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
526 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
527 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
528 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
529 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
530 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
531 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
532 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
533 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
534 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
535 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
536 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
537 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
538 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
539 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
540 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
541 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
542 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
543 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
544 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
545 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
546 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
547 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
550 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
551 * @data: pointer to data to process
552 * @seed: seed value for CRC
553 * @len: length measured in 16 bits words
555 * This function will generate a CRC based on the polynomial 0xAC9A and
556 * whatever value is stored in the seed variable. Note that this
557 * value inverts the local seed and the result in order to capture all
558 * leading and trailing zeros.
560 static u16
fm10k_crc_16b(const u32
*data
, u16 seed
, u16 len
)
566 result
= (result
>> 8) ^ fm10k_crc_16b_table
[result
& 0xFF];
567 result
= (result
>> 8) ^ fm10k_crc_16b_table
[result
& 0xFF];
572 result
= (result
>> 8) ^ fm10k_crc_16b_table
[result
& 0xFF];
573 result
= (result
>> 8) ^ fm10k_crc_16b_table
[result
& 0xFF];
580 * fm10k_fifo_crc - generate a CRC based off of FIFO data
581 * @fifo: pointer to FIFO
582 * @offset: offset point for start of FIFO
583 * @len: number of DWORDS words to process
584 * @seed: seed value for CRC
586 * This function generates a CRC for some region of the FIFO
588 static u16
fm10k_fifo_crc(struct fm10k_mbx_fifo
*fifo
, u16 offset
,
591 u32
*data
= fifo
->buffer
+ offset
;
593 /* track when we should cross the end of the FIFO */
594 offset
= fifo
->size
- offset
;
596 /* if we are in 2 blocks process the end of the FIFO first */
598 seed
= fm10k_crc_16b(data
, seed
, offset
* 2);
603 /* process any remaining bits */
604 return fm10k_crc_16b(data
, seed
, len
* 2);
608 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
609 * @mbx: pointer to mailbox
610 * @head: head index provided by remote mailbox
612 * This function will generate the CRC for all data from the end of the
613 * last head update to the current one. It uses the result of the
614 * previous CRC as the seed for this update. The result is stored in
617 static void fm10k_mbx_update_local_crc(struct fm10k_mbx_info
*mbx
, u16 head
)
619 u16 len
= mbx
->tail_len
- fm10k_mbx_index_len(mbx
, head
, mbx
->tail
);
621 /* determine the offset for the start of the region to be pulled */
622 head
= fm10k_fifo_head_offset(&mbx
->tx
, mbx
->pulled
);
624 /* update local CRC to include all of the pulled data */
625 mbx
->local
= fm10k_fifo_crc(&mbx
->tx
, head
, len
, mbx
->local
);
629 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
630 * @mbx: pointer to mailbox
632 * This function will take all data that has been provided from the remote
633 * end and generate a CRC for it. This is stored in mbx->remote. The
634 * CRC for the header is then computed and if the result is non-zero this
635 * is an error and we signal an error dropping all data and resetting the
638 static s32
fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info
*mbx
)
640 struct fm10k_mbx_fifo
*fifo
= &mbx
->rx
;
641 u16 len
= mbx
->head_len
;
642 u16 offset
= fm10k_fifo_tail_offset(fifo
, mbx
->pushed
) - len
;
645 /* update the remote CRC if new data has been received */
647 mbx
->remote
= fm10k_fifo_crc(fifo
, offset
, len
, mbx
->remote
);
649 /* process the full header as we have to validate the CRC */
650 crc
= fm10k_crc_16b(&mbx
->mbx_hdr
, mbx
->remote
, 1);
652 /* notify other end if we have a problem */
653 return crc
? FM10K_MBX_ERR_CRC
: 0;
657 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
658 * @mbx: pointer to mailbox
660 * This function returns true if there is a message in the Rx FIFO to dequeue.
662 static bool fm10k_mbx_rx_ready(struct fm10k_mbx_info
*mbx
)
664 u16 msg_size
= fm10k_fifo_head_len(&mbx
->rx
);
666 return msg_size
&& (fm10k_fifo_used(&mbx
->rx
) >= msg_size
);
670 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
671 * @mbx: pointer to mailbox
672 * @len: verify free space is >= this value
674 * This function returns true if the mailbox is in a state ready to transmit.
676 static bool fm10k_mbx_tx_ready(struct fm10k_mbx_info
*mbx
, u16 len
)
678 u16 fifo_unused
= fm10k_fifo_unused(&mbx
->tx
);
680 return (mbx
->state
== FM10K_STATE_OPEN
) && (fifo_unused
>= len
);
684 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
685 * @mbx: pointer to mailbox
687 * This function returns true if the Tx FIFO is empty.
689 static bool fm10k_mbx_tx_complete(struct fm10k_mbx_info
*mbx
)
691 return fm10k_fifo_empty(&mbx
->tx
);
695 * fm10k_mbx_dequeue_rx - Dequeues the message from the head in the Rx FIFO
696 * @hw: pointer to hardware structure
697 * @mbx: pointer to mailbox
699 * This function dequeues messages and hands them off to the TLV parser.
700 * It will return the number of messages processed when called.
702 static u16
fm10k_mbx_dequeue_rx(struct fm10k_hw
*hw
,
703 struct fm10k_mbx_info
*mbx
)
705 struct fm10k_mbx_fifo
*fifo
= &mbx
->rx
;
709 /* parse Rx messages out of the Rx FIFO to empty it */
710 for (cnt
= 0; !fm10k_fifo_empty(fifo
); cnt
++) {
711 err
= fm10k_tlv_msg_parse(hw
, fifo
->buffer
+ fifo
->head
,
716 fm10k_fifo_head_drop(fifo
);
719 /* shift remaining bytes back to start of FIFO */
720 memmove(fifo
->buffer
, fifo
->buffer
+ fifo
->tail
, mbx
->pushed
<< 2);
722 /* shift head and tail based on the memory we moved */
723 fifo
->tail
-= fifo
->head
;
730 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
731 * @hw: pointer to hardware structure
732 * @mbx: pointer to mailbox
733 * @msg: message array to read
735 * This function enqueues a message up to the size specified by the length
736 * contained in the first DWORD of the message and will place at the tail
737 * of the FIFO. It will return 0 on success, or a negative value on error.
739 static s32
fm10k_mbx_enqueue_tx(struct fm10k_hw
*hw
,
740 struct fm10k_mbx_info
*mbx
, const u32
*msg
)
742 u32 countdown
= mbx
->timeout
;
745 switch (mbx
->state
) {
746 case FM10K_STATE_CLOSED
:
747 case FM10K_STATE_DISCONNECT
:
748 return FM10K_MBX_ERR_NO_MBX
;
753 /* enqueue the message on the Tx FIFO */
754 err
= fm10k_fifo_enqueue(&mbx
->tx
, msg
);
756 /* if it failed give the FIFO a chance to drain */
757 while (err
&& countdown
) {
760 mbx
->ops
.process(hw
, mbx
);
761 err
= fm10k_fifo_enqueue(&mbx
->tx
, msg
);
764 /* if we failed treat the error */
770 /* begin processing message, ignore errors as this is just meant
771 * to start the mailbox flow so we are not concerned if there
772 * is a bad error, or the mailbox is already busy with a request
775 mbx
->ops
.process(hw
, mbx
);
781 * fm10k_mbx_read - Copies the mbmem to local message buffer
782 * @hw: pointer to hardware structure
783 * @mbx: pointer to mailbox
785 * This function copies the message from the mbmem to the message array
787 static s32
fm10k_mbx_read(struct fm10k_hw
*hw
, struct fm10k_mbx_info
*mbx
)
789 /* only allow one reader in here at a time */
791 return FM10K_MBX_ERR_BUSY
;
793 /* read to capture initial interrupt bits */
794 if (fm10k_read_reg(hw
, mbx
->mbx_reg
) & FM10K_MBX_REQ_INTERRUPT
)
795 mbx
->mbx_lock
= FM10K_MBX_ACK
;
797 /* write back interrupt bits to clear */
798 fm10k_write_reg(hw
, mbx
->mbx_reg
,
799 FM10K_MBX_REQ_INTERRUPT
| FM10K_MBX_ACK_INTERRUPT
);
801 /* read remote header */
802 mbx
->mbx_hdr
= fm10k_read_reg(hw
, mbx
->mbmem_reg
^ mbx
->mbmem_len
);
808 * fm10k_mbx_write - Copies the local message buffer to mbmem
809 * @hw: pointer to hardware structure
810 * @mbx: pointer to mailbox
812 * This function copies the message from the message array to mbmem
814 static void fm10k_mbx_write(struct fm10k_hw
*hw
, struct fm10k_mbx_info
*mbx
)
816 u32 mbmem
= mbx
->mbmem_reg
;
818 /* write new msg header to notify recipient of change */
819 fm10k_write_reg(hw
, mbmem
, mbx
->mbx_hdr
);
821 /* write mailbox to send interrupt */
823 fm10k_write_reg(hw
, mbx
->mbx_reg
, mbx
->mbx_lock
);
825 /* we no longer are using the header so free it */
831 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
832 * @mbx: pointer to mailbox
834 * This function returns a connection mailbox header
836 static void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info
*mbx
)
838 mbx
->mbx_lock
|= FM10K_MBX_REQ
;
840 mbx
->mbx_hdr
= FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT
, TYPE
) |
841 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, HEAD
) |
842 FM10K_MSG_HDR_FIELD_SET(mbx
->rx
.size
- 1, CONNECT_SIZE
);
846 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
847 * @mbx: pointer to mailbox
849 * This function returns a data mailbox header
851 static void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info
*mbx
)
853 u32 hdr
= FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA
, TYPE
) |
854 FM10K_MSG_HDR_FIELD_SET(mbx
->tail
, TAIL
) |
855 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, HEAD
);
856 struct fm10k_mbx_fifo
*fifo
= &mbx
->tx
;
860 mbx
->mbx_lock
|= FM10K_MBX_REQ
;
862 /* generate CRC for data in flight and header */
863 crc
= fm10k_fifo_crc(fifo
, fm10k_fifo_head_offset(fifo
, mbx
->pulled
),
864 mbx
->tail_len
, mbx
->local
);
865 crc
= fm10k_crc_16b(&hdr
, crc
, 1);
867 /* load header to memory to be written */
868 mbx
->mbx_hdr
= hdr
| FM10K_MSG_HDR_FIELD_SET(crc
, CRC
);
872 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
873 * @mbx: pointer to mailbox
875 * This function returns a disconnect mailbox header
877 static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info
*mbx
)
879 u32 hdr
= FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT
, TYPE
) |
880 FM10K_MSG_HDR_FIELD_SET(mbx
->tail
, TAIL
) |
881 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, HEAD
);
882 u16 crc
= fm10k_crc_16b(&hdr
, mbx
->local
, 1);
884 mbx
->mbx_lock
|= FM10K_MBX_ACK
;
886 /* load header to memory to be written */
887 mbx
->mbx_hdr
= hdr
| FM10K_MSG_HDR_FIELD_SET(crc
, CRC
);
891 * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mbox hdr
892 * @mbx: pointer to mailbox
894 * This function creates a fake disconnect header for loading into remote
895 * mailbox header. The primary purpose is to prevent errors on immediate
896 * start up after mbx->connect.
898 static void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info
*mbx
)
900 u32 hdr
= FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT
, TYPE
) |
901 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, TAIL
) |
902 FM10K_MSG_HDR_FIELD_SET(mbx
->tail
, HEAD
);
903 u16 crc
= fm10k_crc_16b(&hdr
, mbx
->local
, 1);
905 mbx
->mbx_lock
|= FM10K_MBX_ACK
;
907 /* load header to memory to be written */
908 mbx
->mbx_hdr
= hdr
| FM10K_MSG_HDR_FIELD_SET(crc
, CRC
);
912 * fm10k_mbx_create_error_msg - Generate an error message
913 * @mbx: pointer to mailbox
914 * @err: local error encountered
916 * This function will interpret the error provided by err, and based on
917 * that it may shift the message by 1 DWORD and then place an error header
918 * at the start of the message.
920 static void fm10k_mbx_create_error_msg(struct fm10k_mbx_info
*mbx
, s32 err
)
922 /* only generate an error message for these types */
924 case FM10K_MBX_ERR_TAIL
:
925 case FM10K_MBX_ERR_HEAD
:
926 case FM10K_MBX_ERR_TYPE
:
927 case FM10K_MBX_ERR_SIZE
:
928 case FM10K_MBX_ERR_RSVD0
:
929 case FM10K_MBX_ERR_CRC
:
935 mbx
->mbx_lock
|= FM10K_MBX_REQ
;
937 mbx
->mbx_hdr
= FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR
, TYPE
) |
938 FM10K_MSG_HDR_FIELD_SET(err
, ERR_NO
) |
939 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, HEAD
);
943 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
944 * @mbx: pointer to mailbox
946 * This function will parse up the fields in the mailbox header and return
947 * an error if the header contains any of a number of invalid configurations
948 * including unrecognized type, invalid route, or a malformed message.
950 static s32
fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info
*mbx
)
952 u16 type
, rsvd0
, head
, tail
, size
;
953 const u32
*hdr
= &mbx
->mbx_hdr
;
955 type
= FM10K_MSG_HDR_FIELD_GET(*hdr
, TYPE
);
956 rsvd0
= FM10K_MSG_HDR_FIELD_GET(*hdr
, RSVD0
);
957 tail
= FM10K_MSG_HDR_FIELD_GET(*hdr
, TAIL
);
958 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, HEAD
);
959 size
= FM10K_MSG_HDR_FIELD_GET(*hdr
, CONNECT_SIZE
);
962 return FM10K_MBX_ERR_RSVD0
;
965 case FM10K_MSG_DISCONNECT
:
966 /* validate that all data has been received */
967 if (tail
!= mbx
->head
)
968 return FM10K_MBX_ERR_TAIL
;
972 /* validate that head is moving correctly */
973 if (!head
|| (head
== FM10K_MSG_HDR_MASK(HEAD
)))
974 return FM10K_MBX_ERR_HEAD
;
975 if (fm10k_mbx_index_len(mbx
, head
, mbx
->tail
) > mbx
->tail_len
)
976 return FM10K_MBX_ERR_HEAD
;
978 /* validate that tail is moving correctly */
979 if (!tail
|| (tail
== FM10K_MSG_HDR_MASK(TAIL
)))
980 return FM10K_MBX_ERR_TAIL
;
981 if (fm10k_mbx_index_len(mbx
, mbx
->head
, tail
) < mbx
->mbmem_len
)
984 return FM10K_MBX_ERR_TAIL
;
985 case FM10K_MSG_CONNECT
:
986 /* validate size is in range and is power of 2 mask */
987 if ((size
< FM10K_VFMBX_MSG_MTU
) || (size
& (size
+ 1)))
988 return FM10K_MBX_ERR_SIZE
;
991 case FM10K_MSG_ERROR
:
992 if (!head
|| (head
== FM10K_MSG_HDR_MASK(HEAD
)))
993 return FM10K_MBX_ERR_HEAD
;
994 /* neither create nor error include a tail offset */
996 return FM10K_MBX_ERR_TAIL
;
1000 return FM10K_MBX_ERR_TYPE
;
1007 * fm10k_mbx_create_reply - Generate reply based on state and remote head
1008 * @hw: pointer to hardware structure
1009 * @mbx: pointer to mailbox
1010 * @head: acknowledgement number
1012 * This function will generate an outgoing message based on the current
1013 * mailbox state and the remote FIFO head. It will return the length
1014 * of the outgoing message excluding header on success, and a negative value
1017 static s32
fm10k_mbx_create_reply(struct fm10k_hw
*hw
,
1018 struct fm10k_mbx_info
*mbx
, u16 head
)
1020 switch (mbx
->state
) {
1021 case FM10K_STATE_OPEN
:
1022 case FM10K_STATE_DISCONNECT
:
1023 /* update our checksum for the outgoing data */
1024 fm10k_mbx_update_local_crc(mbx
, head
);
1026 /* as long as other end recognizes us keep sending data */
1027 fm10k_mbx_pull_head(hw
, mbx
, head
);
1029 /* generate new header based on data */
1030 if (mbx
->tail_len
|| (mbx
->state
== FM10K_STATE_OPEN
))
1031 fm10k_mbx_create_data_hdr(mbx
);
1033 fm10k_mbx_create_disconnect_hdr(mbx
);
1035 case FM10K_STATE_CONNECT
:
1036 /* send disconnect even if we aren't connected */
1037 fm10k_mbx_create_connect_hdr(mbx
);
1039 case FM10K_STATE_CLOSED
:
1040 /* generate new header based on data */
1041 fm10k_mbx_create_disconnect_hdr(mbx
);
1051 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1052 * @mbx: pointer to mailbox
1054 * This function will reset all internal pointers so any work in progress
1055 * is dropped. This call should occur every time we transition from the
1056 * open state to the connect state.
1058 static void fm10k_mbx_reset_work(struct fm10k_mbx_info
*mbx
)
1062 /* reset our outgoing max size back to Rx limits */
1063 mbx
->max_size
= mbx
->rx
.size
- 1;
1065 /* update mbx->pulled to account for tail_len and ack */
1066 head
= FM10K_MSG_HDR_FIELD_GET(mbx
->mbx_hdr
, HEAD
);
1067 ack
= fm10k_mbx_index_len(mbx
, head
, mbx
->tail
);
1068 mbx
->pulled
+= mbx
->tail_len
- ack
;
1070 /* now drop any messages which have started or finished transmitting */
1071 while (fm10k_fifo_head_len(&mbx
->tx
) && mbx
->pulled
) {
1072 len
= fm10k_fifo_head_drop(&mbx
->tx
);
1074 if (mbx
->pulled
>= len
)
1080 /* just do a quick resysnc to start of message */
1090 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1091 * @mbx: pointer to mailbox
1092 * @size: new value for max_size
1094 * This function updates the max_size value and drops any outgoing messages
1095 * at the head of the Tx FIFO if they are larger than max_size. It does not
1096 * drop all messages, as this is too difficult to parse and remove them from
1097 * the FIFO. Instead, rely on the checking to ensure that messages larger
1098 * than max_size aren't pushed into the memory buffer.
1100 static void fm10k_mbx_update_max_size(struct fm10k_mbx_info
*mbx
, u16 size
)
1104 mbx
->max_size
= size
;
1106 /* flush any oversized messages from the queue */
1107 for (len
= fm10k_fifo_head_len(&mbx
->tx
);
1109 len
= fm10k_fifo_head_len(&mbx
->tx
)) {
1110 fm10k_fifo_head_drop(&mbx
->tx
);
1116 * fm10k_mbx_connect_reset - Reset following request for reset
1117 * @mbx: pointer to mailbox
1119 * This function resets the mailbox to either a disconnected state
1120 * or a connect state depending on the current mailbox state
1122 static void fm10k_mbx_connect_reset(struct fm10k_mbx_info
*mbx
)
1124 /* just do a quick resysnc to start of frame */
1125 fm10k_mbx_reset_work(mbx
);
1127 /* reset CRC seeds */
1128 mbx
->local
= FM10K_MBX_CRC_SEED
;
1129 mbx
->remote
= FM10K_MBX_CRC_SEED
;
1131 /* we cannot exit connect until the size is good */
1132 if (mbx
->state
== FM10K_STATE_OPEN
)
1133 mbx
->state
= FM10K_STATE_CONNECT
;
1135 mbx
->state
= FM10K_STATE_CLOSED
;
1139 * fm10k_mbx_process_connect - Process connect header
1140 * @hw: pointer to hardware structure
1141 * @mbx: pointer to mailbox
1143 * This function will read an incoming connect header and reply with the
1144 * appropriate message. It will return a value indicating the number of
1145 * data DWORDs on success, or will return a negative value on failure.
1147 static s32
fm10k_mbx_process_connect(struct fm10k_hw
*hw
,
1148 struct fm10k_mbx_info
*mbx
)
1150 const enum fm10k_mbx_state state
= mbx
->state
;
1151 const u32
*hdr
= &mbx
->mbx_hdr
;
1154 /* we will need to pull all of the fields for verification */
1155 size
= FM10K_MSG_HDR_FIELD_GET(*hdr
, CONNECT_SIZE
);
1156 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, HEAD
);
1159 case FM10K_STATE_DISCONNECT
:
1160 case FM10K_STATE_OPEN
:
1161 /* reset any in-progress work */
1162 fm10k_mbx_connect_reset(mbx
);
1164 case FM10K_STATE_CONNECT
:
1165 /* we cannot exit connect until the size is good */
1166 if (size
> mbx
->rx
.size
) {
1167 mbx
->max_size
= mbx
->rx
.size
- 1;
1169 /* record the remote system requesting connection */
1170 mbx
->state
= FM10K_STATE_OPEN
;
1172 fm10k_mbx_update_max_size(mbx
, size
);
1179 /* align our tail index to remote head index */
1182 return fm10k_mbx_create_reply(hw
, mbx
, head
);
1186 * fm10k_mbx_process_data - Process data header
1187 * @hw: pointer to hardware structure
1188 * @mbx: pointer to mailbox
1190 * This function will read an incoming data header and reply with the
1191 * appropriate message. It will return a value indicating the number of
1192 * data DWORDs on success, or will return a negative value on failure.
1194 static s32
fm10k_mbx_process_data(struct fm10k_hw
*hw
,
1195 struct fm10k_mbx_info
*mbx
)
1197 const u32
*hdr
= &mbx
->mbx_hdr
;
1201 /* we will need to pull all of the fields for verification */
1202 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, HEAD
);
1203 tail
= FM10K_MSG_HDR_FIELD_GET(*hdr
, TAIL
);
1205 /* if we are in connect just update our data and go */
1206 if (mbx
->state
== FM10K_STATE_CONNECT
) {
1208 mbx
->state
= FM10K_STATE_OPEN
;
1211 /* abort on message size errors */
1212 err
= fm10k_mbx_push_tail(hw
, mbx
, tail
);
1216 /* verify the checksum on the incoming data */
1217 err
= fm10k_mbx_verify_remote_crc(mbx
);
1221 /* process messages if we have received any */
1222 fm10k_mbx_dequeue_rx(hw
, mbx
);
1224 return fm10k_mbx_create_reply(hw
, mbx
, head
);
1228 * fm10k_mbx_process_disconnect - Process disconnect header
1229 * @hw: pointer to hardware structure
1230 * @mbx: pointer to mailbox
1232 * This function will read an incoming disconnect header and reply with the
1233 * appropriate message. It will return a value indicating the number of
1234 * data DWORDs on success, or will return a negative value on failure.
1236 static s32
fm10k_mbx_process_disconnect(struct fm10k_hw
*hw
,
1237 struct fm10k_mbx_info
*mbx
)
1239 const enum fm10k_mbx_state state
= mbx
->state
;
1240 const u32
*hdr
= &mbx
->mbx_hdr
;
1244 /* we will need to pull the header field for verification */
1245 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, HEAD
);
1247 /* We should not be receiving disconnect if Rx is incomplete */
1249 return FM10K_MBX_ERR_TAIL
;
1251 /* we have already verified mbx->head == tail so we know this is 0 */
1254 /* verify the checksum on the incoming header is correct */
1255 err
= fm10k_mbx_verify_remote_crc(mbx
);
1260 case FM10K_STATE_DISCONNECT
:
1261 case FM10K_STATE_OPEN
:
1262 /* state doesn't change if we still have work to do */
1263 if (!fm10k_mbx_tx_complete(mbx
))
1266 /* verify the head indicates we completed all transmits */
1267 if (head
!= mbx
->tail
)
1268 return FM10K_MBX_ERR_HEAD
;
1270 /* reset any in-progress work */
1271 fm10k_mbx_connect_reset(mbx
);
1277 return fm10k_mbx_create_reply(hw
, mbx
, head
);
1281 * fm10k_mbx_process_error - Process error header
1282 * @hw: pointer to hardware structure
1283 * @mbx: pointer to mailbox
1285 * This function will read an incoming error header and reply with the
1286 * appropriate message. It will return a value indicating the number of
1287 * data DWORDs on success, or will return a negative value on failure.
1289 static s32
fm10k_mbx_process_error(struct fm10k_hw
*hw
,
1290 struct fm10k_mbx_info
*mbx
)
1292 const u32
*hdr
= &mbx
->mbx_hdr
;
1295 /* we will need to pull all of the fields for verification */
1296 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, HEAD
);
1298 switch (mbx
->state
) {
1299 case FM10K_STATE_OPEN
:
1300 case FM10K_STATE_DISCONNECT
:
1301 /* flush any uncompleted work */
1302 fm10k_mbx_reset_work(mbx
);
1304 /* reset CRC seeds */
1305 mbx
->local
= FM10K_MBX_CRC_SEED
;
1306 mbx
->remote
= FM10K_MBX_CRC_SEED
;
1308 /* reset tail index and size to prepare for reconnect */
1311 /* if open then reset max_size and go back to connect */
1312 if (mbx
->state
== FM10K_STATE_OPEN
) {
1313 mbx
->state
= FM10K_STATE_CONNECT
;
1317 /* send a connect message to get data flowing again */
1318 fm10k_mbx_create_connect_hdr(mbx
);
1324 return fm10k_mbx_create_reply(hw
, mbx
, mbx
->tail
);
1328 * fm10k_mbx_process - Process mailbox interrupt
1329 * @hw: pointer to hardware structure
1330 * @mbx: pointer to mailbox
1332 * This function will process incoming mailbox events and generate mailbox
1333 * replies. It will return a value indicating the number of DWORDs
1334 * transmitted excluding header on success or a negative value on error.
1336 static s32
fm10k_mbx_process(struct fm10k_hw
*hw
,
1337 struct fm10k_mbx_info
*mbx
)
1341 /* we do not read mailbox if closed */
1342 if (mbx
->state
== FM10K_STATE_CLOSED
)
1345 /* copy data from mailbox */
1346 err
= fm10k_mbx_read(hw
, mbx
);
1350 /* validate type, source, and destination */
1351 err
= fm10k_mbx_validate_msg_hdr(mbx
);
1355 switch (FM10K_MSG_HDR_FIELD_GET(mbx
->mbx_hdr
, TYPE
)) {
1356 case FM10K_MSG_CONNECT
:
1357 err
= fm10k_mbx_process_connect(hw
, mbx
);
1359 case FM10K_MSG_DATA
:
1360 err
= fm10k_mbx_process_data(hw
, mbx
);
1362 case FM10K_MSG_DISCONNECT
:
1363 err
= fm10k_mbx_process_disconnect(hw
, mbx
);
1365 case FM10K_MSG_ERROR
:
1366 err
= fm10k_mbx_process_error(hw
, mbx
);
1369 err
= FM10K_MBX_ERR_TYPE
;
1374 /* notify partner of errors on our end */
1376 fm10k_mbx_create_error_msg(mbx
, err
);
1378 /* copy data from mailbox */
1379 fm10k_mbx_write(hw
, mbx
);
1385 * fm10k_mbx_disconnect - Shutdown mailbox connection
1386 * @hw: pointer to hardware structure
1387 * @mbx: pointer to mailbox
1389 * This function will shut down the mailbox. It places the mailbox first
1390 * in the disconnect state, it then allows up to a predefined timeout for
1391 * the mailbox to transition to close on its own. If this does not occur
1392 * then the mailbox will be forced into the closed state.
1394 * Any mailbox transactions not completed before calling this function
1395 * are not guaranteed to complete and may be dropped.
1397 static void fm10k_mbx_disconnect(struct fm10k_hw
*hw
,
1398 struct fm10k_mbx_info
*mbx
)
1400 int timeout
= mbx
->timeout
? FM10K_MBX_DISCONNECT_TIMEOUT
: 0;
1402 /* Place mbx in ready to disconnect state */
1403 mbx
->state
= FM10K_STATE_DISCONNECT
;
1405 /* trigger interrupt to start shutdown process */
1406 fm10k_write_reg(hw
, mbx
->mbx_reg
, FM10K_MBX_REQ
|
1407 FM10K_MBX_INTERRUPT_DISABLE
);
1409 udelay(FM10K_MBX_POLL_DELAY
);
1410 mbx
->ops
.process(hw
, mbx
);
1411 timeout
-= FM10K_MBX_POLL_DELAY
;
1412 } while ((timeout
> 0) && (mbx
->state
!= FM10K_STATE_CLOSED
));
1414 /* in case we didn't close, just force the mailbox into shutdown and
1415 * drop all left over messages in the FIFO.
1417 fm10k_mbx_connect_reset(mbx
);
1418 fm10k_fifo_drop_all(&mbx
->tx
);
1420 fm10k_write_reg(hw
, mbx
->mbmem_reg
, 0);
1424 * fm10k_mbx_connect - Start mailbox connection
1425 * @hw: pointer to hardware structure
1426 * @mbx: pointer to mailbox
1428 * This function will initiate a mailbox connection. It will populate the
1429 * mailbox with a broadcast connect message and then initialize the lock.
1430 * This is safe since the connect message is a single DWORD so the mailbox
1431 * transaction is guaranteed to be atomic.
1433 * This function will return an error if the mailbox has not been initiated
1434 * or is currently in use.
1436 static s32
fm10k_mbx_connect(struct fm10k_hw
*hw
, struct fm10k_mbx_info
*mbx
)
1438 /* we cannot connect an uninitialized mailbox */
1439 if (!mbx
->rx
.buffer
)
1440 return FM10K_MBX_ERR_NO_SPACE
;
1442 /* we cannot connect an already connected mailbox */
1443 if (mbx
->state
!= FM10K_STATE_CLOSED
)
1444 return FM10K_MBX_ERR_BUSY
;
1446 /* mailbox timeout can now become active */
1447 mbx
->timeout
= FM10K_MBX_INIT_TIMEOUT
;
1449 /* Place mbx in ready to connect state */
1450 mbx
->state
= FM10K_STATE_CONNECT
;
1452 fm10k_mbx_reset_work(mbx
);
1454 /* initialize header of remote mailbox */
1455 fm10k_mbx_create_fake_disconnect_hdr(mbx
);
1456 fm10k_write_reg(hw
, mbx
->mbmem_reg
^ mbx
->mbmem_len
, mbx
->mbx_hdr
);
1458 /* enable interrupt and notify other party of new message */
1459 mbx
->mbx_lock
= FM10K_MBX_REQ_INTERRUPT
| FM10K_MBX_ACK_INTERRUPT
|
1460 FM10K_MBX_INTERRUPT_ENABLE
;
1462 /* generate and load connect header into mailbox */
1463 fm10k_mbx_create_connect_hdr(mbx
);
1464 fm10k_mbx_write(hw
, mbx
);
1470 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1471 * @msg_data: handlers for mailbox events
1473 * This function validates the layout of the message parsing data. This
1474 * should be mostly static, but it is important to catch any errors that
1475 * are made when constructing the parsers.
1477 static s32
fm10k_mbx_validate_handlers(const struct fm10k_msg_data
*msg_data
)
1479 const struct fm10k_tlv_attr
*attr
;
1482 /* Allow NULL mailboxes that transmit but don't receive */
1486 while (msg_data
->id
!= FM10K_TLV_ERROR
) {
1487 /* all messages should have a function handler */
1488 if (!msg_data
->func
)
1489 return FM10K_ERR_PARAM
;
1491 /* parser is optional */
1492 attr
= msg_data
->attr
;
1494 while (attr
->id
!= FM10K_TLV_ERROR
) {
1497 /* ID should always be increasing */
1499 return FM10K_ERR_PARAM
;
1500 /* ID should fit in results array */
1501 if (id
>= FM10K_TLV_RESULTS_MAX
)
1502 return FM10K_ERR_PARAM
;
1505 /* verify terminator is in the list */
1506 if (attr
->id
!= FM10K_TLV_ERROR
)
1507 return FM10K_ERR_PARAM
;
1512 /* ID should always be increasing */
1513 if (id
>= msg_data
->id
)
1514 return FM10K_ERR_PARAM
;
1517 /* verify terminator is in the list */
1518 if ((msg_data
->id
!= FM10K_TLV_ERROR
) || !msg_data
->func
)
1519 return FM10K_ERR_PARAM
;
1525 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1526 * @mbx: pointer to mailbox
1527 * @msg_data: handlers for mailbox events
1529 * This function associates a set of message handling ops with a mailbox.
1531 static s32
fm10k_mbx_register_handlers(struct fm10k_mbx_info
*mbx
,
1532 const struct fm10k_msg_data
*msg_data
)
1534 /* validate layout of handlers before assigning them */
1535 if (fm10k_mbx_validate_handlers(msg_data
))
1536 return FM10K_ERR_PARAM
;
1538 /* initialize the message handlers */
1539 mbx
->msg_data
= msg_data
;
1545 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1546 * @hw: pointer to hardware structure
1547 * @mbx: pointer to mailbox
1548 * @msg_data: handlers for mailbox events
1549 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1551 * This function initializes the mailbox for use. It will split the
1552 * buffer provided and use that to populate both the Tx and Rx FIFO by
1553 * evenly splitting it. In order to allow for easy masking of head/tail
1554 * the value reported in size must be a power of 2 and is reported in
1555 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1558 s32
fm10k_pfvf_mbx_init(struct fm10k_hw
*hw
, struct fm10k_mbx_info
*mbx
,
1559 const struct fm10k_msg_data
*msg_data
, u8 id
)
1561 /* initialize registers */
1562 switch (hw
->mac
.type
) {
1564 mbx
->mbx_reg
= FM10K_VFMBX
;
1565 mbx
->mbmem_reg
= FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR
);
1568 /* there are only 64 VF <-> PF mailboxes */
1570 mbx
->mbx_reg
= FM10K_MBX(id
);
1571 mbx
->mbmem_reg
= FM10K_MBMEM_VF(id
, 0);
1576 return FM10K_MBX_ERR_NO_MBX
;
1579 /* start out in closed state */
1580 mbx
->state
= FM10K_STATE_CLOSED
;
1582 /* validate layout of handlers before assigning them */
1583 if (fm10k_mbx_validate_handlers(msg_data
))
1584 return FM10K_ERR_PARAM
;
1586 /* initialize the message handlers */
1587 mbx
->msg_data
= msg_data
;
1589 /* start mailbox as timed out and let the reset_hw call
1590 * set the timeout value to begin communications
1593 mbx
->udelay
= FM10K_MBX_INIT_DELAY
;
1595 /* initialize tail and head */
1599 /* initialize CRC seeds */
1600 mbx
->local
= FM10K_MBX_CRC_SEED
;
1601 mbx
->remote
= FM10K_MBX_CRC_SEED
;
1603 /* Split buffer for use by Tx/Rx FIFOs */
1604 mbx
->max_size
= FM10K_MBX_MSG_MAX_SIZE
;
1605 mbx
->mbmem_len
= FM10K_VFMBMEM_VF_XOR
;
1607 /* initialize the FIFOs, sizes are in 4 byte increments */
1608 fm10k_fifo_init(&mbx
->tx
, mbx
->buffer
, FM10K_MBX_TX_BUFFER_SIZE
);
1609 fm10k_fifo_init(&mbx
->rx
, &mbx
->buffer
[FM10K_MBX_TX_BUFFER_SIZE
],
1610 FM10K_MBX_RX_BUFFER_SIZE
);
1612 /* initialize function pointers */
1613 mbx
->ops
.connect
= fm10k_mbx_connect
;
1614 mbx
->ops
.disconnect
= fm10k_mbx_disconnect
;
1615 mbx
->ops
.rx_ready
= fm10k_mbx_rx_ready
;
1616 mbx
->ops
.tx_ready
= fm10k_mbx_tx_ready
;
1617 mbx
->ops
.tx_complete
= fm10k_mbx_tx_complete
;
1618 mbx
->ops
.enqueue_tx
= fm10k_mbx_enqueue_tx
;
1619 mbx
->ops
.process
= fm10k_mbx_process
;
1620 mbx
->ops
.register_handlers
= fm10k_mbx_register_handlers
;
1626 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1627 * @mbx: pointer to mailbox
1629 * This function returns a data mailbox header
1631 static void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info
*mbx
)
1634 mbx
->mbx_lock
|= FM10K_MBX_REQ
;
1636 mbx
->mbx_hdr
= FM10K_MSG_HDR_FIELD_SET(mbx
->tail
, SM_TAIL
) |
1637 FM10K_MSG_HDR_FIELD_SET(mbx
->remote
, SM_VER
) |
1638 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, SM_HEAD
);
1642 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1643 * @mbx: pointer to mailbox
1644 * @err: error flags to report if any
1646 * This function returns a connection mailbox header
1648 static void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info
*mbx
, u8 err
)
1651 mbx
->mbx_lock
|= FM10K_MBX_REQ
;
1653 mbx
->mbx_hdr
= FM10K_MSG_HDR_FIELD_SET(mbx
->tail
, SM_TAIL
) |
1654 FM10K_MSG_HDR_FIELD_SET(mbx
->remote
, SM_VER
) |
1655 FM10K_MSG_HDR_FIELD_SET(mbx
->head
, SM_HEAD
) |
1656 FM10K_MSG_HDR_FIELD_SET(err
, SM_ERR
);
1660 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1661 * @mbx: pointer to mailbox
1663 * This function resets the mailbox to a just connected state
1665 static void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info
*mbx
)
1667 /* flush any uncompleted work */
1668 fm10k_mbx_reset_work(mbx
);
1670 /* set local version to max and remote version to 0 */
1671 mbx
->local
= FM10K_SM_MBX_VERSION
;
1674 /* initialize tail and head */
1678 /* reset state back to connect */
1679 mbx
->state
= FM10K_STATE_CONNECT
;
1683 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1684 * @hw: pointer to hardware structure
1685 * @mbx: pointer to mailbox
1687 * This function will initiate a mailbox connection with the switch
1688 * manager. To do this it will first disconnect the mailbox, and then
1689 * reconnect it in order to complete a reset of the mailbox.
1691 * This function will return an error if the mailbox has not been initiated
1692 * or is currently in use.
1694 static s32
fm10k_sm_mbx_connect(struct fm10k_hw
*hw
, struct fm10k_mbx_info
*mbx
)
1696 /* we cannot connect an uninitialized mailbox */
1697 if (!mbx
->rx
.buffer
)
1698 return FM10K_MBX_ERR_NO_SPACE
;
1700 /* we cannot connect an already connected mailbox */
1701 if (mbx
->state
!= FM10K_STATE_CLOSED
)
1702 return FM10K_MBX_ERR_BUSY
;
1704 /* mailbox timeout can now become active */
1705 mbx
->timeout
= FM10K_MBX_INIT_TIMEOUT
;
1707 /* Place mbx in ready to connect state */
1708 mbx
->state
= FM10K_STATE_CONNECT
;
1709 mbx
->max_size
= FM10K_MBX_MSG_MAX_SIZE
;
1711 /* reset interface back to connect */
1712 fm10k_sm_mbx_connect_reset(mbx
);
1714 /* enable interrupt and notify other party of new message */
1715 mbx
->mbx_lock
= FM10K_MBX_REQ_INTERRUPT
| FM10K_MBX_ACK_INTERRUPT
|
1716 FM10K_MBX_INTERRUPT_ENABLE
;
1718 /* generate and load connect header into mailbox */
1719 fm10k_sm_mbx_create_connect_hdr(mbx
, 0);
1720 fm10k_mbx_write(hw
, mbx
);
1726 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1727 * @hw: pointer to hardware structure
1728 * @mbx: pointer to mailbox
1730 * This function will shut down the mailbox. It places the mailbox first
1731 * in the disconnect state, it then allows up to a predefined timeout for
1732 * the mailbox to transition to close on its own. If this does not occur
1733 * then the mailbox will be forced into the closed state.
1735 * Any mailbox transactions not completed before calling this function
1736 * are not guaranteed to complete and may be dropped.
1738 static void fm10k_sm_mbx_disconnect(struct fm10k_hw
*hw
,
1739 struct fm10k_mbx_info
*mbx
)
1741 int timeout
= mbx
->timeout
? FM10K_MBX_DISCONNECT_TIMEOUT
: 0;
1743 /* Place mbx in ready to disconnect state */
1744 mbx
->state
= FM10K_STATE_DISCONNECT
;
1746 /* trigger interrupt to start shutdown process */
1747 fm10k_write_reg(hw
, mbx
->mbx_reg
, FM10K_MBX_REQ
|
1748 FM10K_MBX_INTERRUPT_DISABLE
);
1750 udelay(FM10K_MBX_POLL_DELAY
);
1751 mbx
->ops
.process(hw
, mbx
);
1752 timeout
-= FM10K_MBX_POLL_DELAY
;
1753 } while ((timeout
> 0) && (mbx
->state
!= FM10K_STATE_CLOSED
));
1755 /* in case we didn't close just force the mailbox into shutdown */
1756 mbx
->state
= FM10K_STATE_CLOSED
;
1758 fm10k_mbx_reset_work(mbx
);
1759 fm10k_fifo_drop_all(&mbx
->tx
);
1761 fm10k_write_reg(hw
, mbx
->mbmem_reg
, 0);
1765 * fm10k_sm_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1766 * @mbx: pointer to mailbox
1768 * This function will parse up the fields in the mailbox header and return
1769 * an error if the header contains any of a number of invalid configurations
1770 * including unrecognized offsets or version numbers.
1772 static s32
fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info
*mbx
)
1774 const u32
*hdr
= &mbx
->mbx_hdr
;
1775 u16 tail
, head
, ver
;
1777 tail
= FM10K_MSG_HDR_FIELD_GET(*hdr
, SM_TAIL
);
1778 ver
= FM10K_MSG_HDR_FIELD_GET(*hdr
, SM_VER
);
1779 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, SM_HEAD
);
1784 case FM10K_SM_MBX_VERSION
:
1785 if (!head
|| head
> FM10K_SM_MBX_FIFO_LEN
)
1786 return FM10K_MBX_ERR_HEAD
;
1787 if (!tail
|| tail
> FM10K_SM_MBX_FIFO_LEN
)
1788 return FM10K_MBX_ERR_TAIL
;
1789 if (mbx
->tail
< head
)
1790 head
+= mbx
->mbmem_len
- 1;
1791 if (tail
< mbx
->head
)
1792 tail
+= mbx
->mbmem_len
- 1;
1793 if (fm10k_mbx_index_len(mbx
, head
, mbx
->tail
) > mbx
->tail_len
)
1794 return FM10K_MBX_ERR_HEAD
;
1795 if (fm10k_mbx_index_len(mbx
, mbx
->head
, tail
) < mbx
->mbmem_len
)
1797 return FM10K_MBX_ERR_TAIL
;
1799 return FM10K_MBX_ERR_SRC
;
1806 * fm10k_sm_mbx_process_error - Process header with error flag set
1807 * @mbx: pointer to mailbox
1809 * This function is meant to respond to a request where the error flag
1810 * is set. As a result we will terminate a connection if one is present
1811 * and fall back into the reset state with a connection header of version
1814 static void fm10k_sm_mbx_process_error(struct fm10k_mbx_info
*mbx
)
1816 const enum fm10k_mbx_state state
= mbx
->state
;
1819 case FM10K_STATE_DISCONNECT
:
1820 /* if there is an error just disconnect */
1823 case FM10K_STATE_OPEN
:
1824 /* flush any uncompleted work */
1825 fm10k_sm_mbx_connect_reset(mbx
);
1827 case FM10K_STATE_CONNECT
:
1828 /* try connecting at lower version */
1830 while (mbx
->local
> 1)
1839 fm10k_sm_mbx_create_connect_hdr(mbx
, 0);
1843 * fm10k_sm_mbx_create_error_msg - Process an error in FIFO header
1844 * @mbx: pointer to mailbox
1845 * @err: local error encountered
1847 * This function will interpret the error provided by err, and based on
1848 * that it may set the error bit in the local message header
1850 static void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info
*mbx
, s32 err
)
1852 /* only generate an error message for these types */
1854 case FM10K_MBX_ERR_TAIL
:
1855 case FM10K_MBX_ERR_HEAD
:
1856 case FM10K_MBX_ERR_SRC
:
1857 case FM10K_MBX_ERR_SIZE
:
1858 case FM10K_MBX_ERR_RSVD0
:
1864 /* process it as though we received an error, and send error reply */
1865 fm10k_sm_mbx_process_error(mbx
);
1866 fm10k_sm_mbx_create_connect_hdr(mbx
, 1);
1870 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1871 * @hw: pointer to hardware structure
1872 * @mbx: pointer to mailbox
1873 * @tail: tail index of message
1875 * This function will dequeue one message from the Rx switch manager mailbox
1876 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1878 static s32
fm10k_sm_mbx_receive(struct fm10k_hw
*hw
,
1879 struct fm10k_mbx_info
*mbx
,
1882 /* reduce length by 1 to convert to a mask */
1883 u16 mbmem_len
= mbx
->mbmem_len
- 1;
1886 /* push tail in front of head */
1887 if (tail
< mbx
->head
)
1890 /* copy data to the Rx FIFO */
1891 err
= fm10k_mbx_push_tail(hw
, mbx
, tail
);
1895 /* process messages if we have received any */
1896 fm10k_mbx_dequeue_rx(hw
, mbx
);
1898 /* guarantee head aligns with the end of the last message */
1899 mbx
->head
= fm10k_mbx_head_sub(mbx
, mbx
->pushed
);
1902 /* clear any extra bits left over since index adds 1 extra bit */
1903 if (mbx
->head
> mbmem_len
)
1904 mbx
->head
-= mbmem_len
;
1910 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1911 * @hw: pointer to hardware structure
1912 * @mbx: pointer to mailbox
1913 * @head: head index of message
1915 * This function will dequeue one message from the Tx mailbox FIFO and place
1916 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1918 static void fm10k_sm_mbx_transmit(struct fm10k_hw
*hw
,
1919 struct fm10k_mbx_info
*mbx
, u16 head
)
1921 struct fm10k_mbx_fifo
*fifo
= &mbx
->tx
;
1922 /* reduce length by 1 to convert to a mask */
1923 u16 mbmem_len
= mbx
->mbmem_len
- 1;
1924 u16 tail_len
, len
= 0;
1926 /* push head behind tail */
1927 if (mbx
->tail
< head
)
1930 fm10k_mbx_pull_head(hw
, mbx
, head
);
1932 /* determine msg aligned offset for end of buffer */
1936 msg
= fifo
->buffer
+ fm10k_fifo_head_offset(fifo
, len
);
1938 len
+= FM10K_TLV_DWORD_LEN(*msg
);
1939 } while ((len
<= mbx
->tail_len
) && (len
< mbmem_len
));
1941 /* guarantee we stop on a message boundary */
1942 if (mbx
->tail_len
> tail_len
) {
1943 mbx
->tail
= fm10k_mbx_tail_sub(mbx
, mbx
->tail_len
- tail_len
);
1944 mbx
->tail_len
= tail_len
;
1947 /* clear any extra bits left over since index adds 1 extra bit */
1948 if (mbx
->tail
> mbmem_len
)
1949 mbx
->tail
-= mbmem_len
;
1953 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1954 * @hw: pointer to hardware structure
1955 * @mbx: pointer to mailbox
1956 * @head: acknowledgement number
1958 * This function will generate an outgoing message based on the current
1959 * mailbox state and the remote FIFO head. It will return the length
1960 * of the outgoing message excluding header on success, and a negative value
1963 static void fm10k_sm_mbx_create_reply(struct fm10k_hw
*hw
,
1964 struct fm10k_mbx_info
*mbx
, u16 head
)
1966 switch (mbx
->state
) {
1967 case FM10K_STATE_OPEN
:
1968 case FM10K_STATE_DISCONNECT
:
1969 /* flush out Tx data */
1970 fm10k_sm_mbx_transmit(hw
, mbx
, head
);
1972 /* generate new header based on data */
1973 if (mbx
->tail_len
|| (mbx
->state
== FM10K_STATE_OPEN
)) {
1974 fm10k_sm_mbx_create_data_hdr(mbx
);
1977 fm10k_sm_mbx_create_connect_hdr(mbx
, 0);
1980 case FM10K_STATE_CONNECT
:
1981 case FM10K_STATE_CLOSED
:
1982 fm10k_sm_mbx_create_connect_hdr(mbx
, 0);
1990 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
1991 * @hw: pointer to hardware structure
1992 * @mbx: pointer to mailbox
1994 * This function is meant to respond to a request where the version data
1995 * is set to 0. As such we will either terminate the connection or go
1996 * into the connect state in order to re-establish the connection. This
1997 * function can also be used to respond to an error as the connection
1998 * resetting would also be a means of dealing with errors.
2000 static s32
fm10k_sm_mbx_process_reset(struct fm10k_hw
*hw
,
2001 struct fm10k_mbx_info
*mbx
)
2004 const enum fm10k_mbx_state state
= mbx
->state
;
2007 case FM10K_STATE_DISCONNECT
:
2008 /* drop remote connections and disconnect */
2009 mbx
->state
= FM10K_STATE_CLOSED
;
2013 case FM10K_STATE_OPEN
:
2014 /* flush any incomplete work */
2015 fm10k_sm_mbx_connect_reset(mbx
);
2016 err
= FM10K_ERR_RESET_REQUESTED
;
2018 case FM10K_STATE_CONNECT
:
2019 /* Update remote value to match local value */
2020 mbx
->remote
= mbx
->local
;
2026 fm10k_sm_mbx_create_reply(hw
, mbx
, mbx
->tail
);
2032 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2033 * @hw: pointer to hardware structure
2034 * @mbx: pointer to mailbox
2036 * This function is meant to process messages received when the remote
2037 * mailbox is active.
2039 static s32
fm10k_sm_mbx_process_version_1(struct fm10k_hw
*hw
,
2040 struct fm10k_mbx_info
*mbx
)
2042 const u32
*hdr
= &mbx
->mbx_hdr
;
2046 /* pull all fields needed for verification */
2047 tail
= FM10K_MSG_HDR_FIELD_GET(*hdr
, SM_TAIL
);
2048 head
= FM10K_MSG_HDR_FIELD_GET(*hdr
, SM_HEAD
);
2050 /* if we are in connect and wanting version 1 then start up and go */
2051 if (mbx
->state
== FM10K_STATE_CONNECT
) {
2054 if (mbx
->remote
!= 1)
2055 return FM10K_MBX_ERR_SRC
;
2057 mbx
->state
= FM10K_STATE_OPEN
;
2061 /* abort on message size errors */
2062 len
= fm10k_sm_mbx_receive(hw
, mbx
, tail
);
2066 /* continue until we have flushed the Rx FIFO */
2070 fm10k_sm_mbx_create_reply(hw
, mbx
, head
);
2076 * fm10k_sm_mbx_process - Process switch manager mailbox interrupt
2077 * @hw: pointer to hardware structure
2078 * @mbx: pointer to mailbox
2080 * This function will process incoming mailbox events and generate mailbox
2081 * replies. It will return a value indicating the number of DWORDs
2082 * transmitted excluding header on success or a negative value on error.
2084 static s32
fm10k_sm_mbx_process(struct fm10k_hw
*hw
,
2085 struct fm10k_mbx_info
*mbx
)
2089 /* we do not read mailbox if closed */
2090 if (mbx
->state
== FM10K_STATE_CLOSED
)
2093 /* retrieve data from switch manager */
2094 err
= fm10k_mbx_read(hw
, mbx
);
2098 err
= fm10k_sm_mbx_validate_fifo_hdr(mbx
);
2102 if (FM10K_MSG_HDR_FIELD_GET(mbx
->mbx_hdr
, SM_ERR
)) {
2103 fm10k_sm_mbx_process_error(mbx
);
2107 switch (FM10K_MSG_HDR_FIELD_GET(mbx
->mbx_hdr
, SM_VER
)) {
2109 err
= fm10k_sm_mbx_process_reset(hw
, mbx
);
2111 case FM10K_SM_MBX_VERSION
:
2112 err
= fm10k_sm_mbx_process_version_1(hw
, mbx
);
2118 fm10k_sm_mbx_create_error_msg(mbx
, err
);
2120 /* report data to switch manager */
2121 fm10k_mbx_write(hw
, mbx
);
2127 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2128 * @hw: pointer to hardware structure
2129 * @mbx: pointer to mailbox
2130 * @msg_data: handlers for mailbox events
2132 * This function initializes the PF/SM mailbox for use. It will split the
2133 * buffer provided and use that to populate both the Tx and Rx FIFO by
2134 * evenly splitting it. In order to allow for easy masking of head/tail
2135 * the value reported in size must be a power of 2 and is reported in
2136 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
2139 s32
fm10k_sm_mbx_init(struct fm10k_hw __always_unused
*hw
,
2140 struct fm10k_mbx_info
*mbx
,
2141 const struct fm10k_msg_data
*msg_data
)
2143 mbx
->mbx_reg
= FM10K_GMBX
;
2144 mbx
->mbmem_reg
= FM10K_MBMEM_PF(0);
2146 /* start out in closed state */
2147 mbx
->state
= FM10K_STATE_CLOSED
;
2149 /* validate layout of handlers before assigning them */
2150 if (fm10k_mbx_validate_handlers(msg_data
))
2151 return FM10K_ERR_PARAM
;
2153 /* initialize the message handlers */
2154 mbx
->msg_data
= msg_data
;
2156 /* start mailbox as timed out and let the reset_hw call
2157 * set the timeout value to begin communications
2160 mbx
->udelay
= FM10K_MBX_INIT_DELAY
;
2162 /* Split buffer for use by Tx/Rx FIFOs */
2163 mbx
->max_size
= FM10K_MBX_MSG_MAX_SIZE
;
2164 mbx
->mbmem_len
= FM10K_MBMEM_PF_XOR
;
2166 /* initialize the FIFOs, sizes are in 4 byte increments */
2167 fm10k_fifo_init(&mbx
->tx
, mbx
->buffer
, FM10K_MBX_TX_BUFFER_SIZE
);
2168 fm10k_fifo_init(&mbx
->rx
, &mbx
->buffer
[FM10K_MBX_TX_BUFFER_SIZE
],
2169 FM10K_MBX_RX_BUFFER_SIZE
);
2171 /* initialize function pointers */
2172 mbx
->ops
.connect
= fm10k_sm_mbx_connect
;
2173 mbx
->ops
.disconnect
= fm10k_sm_mbx_disconnect
;
2174 mbx
->ops
.rx_ready
= fm10k_mbx_rx_ready
;
2175 mbx
->ops
.tx_ready
= fm10k_mbx_tx_ready
;
2176 mbx
->ops
.tx_complete
= fm10k_mbx_tx_complete
;
2177 mbx
->ops
.enqueue_tx
= fm10k_mbx_enqueue_tx
;
2178 mbx
->ops
.process
= fm10k_sm_mbx_process
;
2179 mbx
->ops
.register_handlers
= fm10k_mbx_register_handlers
;