1 /*******************************************************************************
3 Copyright (c) 2013 - 2015, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
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.
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.
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.
32 ***************************************************************************/
34 #include "fm10k_common.h"
37 * fm10k_fifo_init - Initialize a message FIFO
38 * @fifo: pointer to FIFO
39 * @buffer: pointer to memory to be used to store FIFO
40 * @size: maximum message size to store in FIFO, must be 2^n - 1
42 STATIC void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
44 fifo->buffer = buffer;
51 * fm10k_fifo_used - Retrieve used space in FIFO
52 * @fifo: pointer to FIFO
54 * This function returns the number of DWORDs used in the FIFO
56 STATIC u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
58 return fifo->tail - fifo->head;
62 * fm10k_fifo_unused - Retrieve unused space in FIFO
63 * @fifo: pointer to FIFO
65 * This function returns the number of unused DWORDs in the FIFO
67 STATIC u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
69 return fifo->size + fifo->head - fifo->tail;
73 * fm10k_fifo_empty - Test to verify if FIFO is empty
74 * @fifo: pointer to FIFO
76 * This function returns true if the FIFO is empty, else false
78 STATIC bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
80 return fifo->head == fifo->tail;
84 * fm10k_fifo_head_offset - returns indices of head with given offset
85 * @fifo: pointer to FIFO
86 * @offset: offset to add to head
88 * This function returns the indices into the FIFO based on head + offset
90 STATIC u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
92 return (fifo->head + offset) & (fifo->size - 1);
96 * fm10k_fifo_tail_offset - returns indices of tail with given offset
97 * @fifo: pointer to FIFO
98 * @offset: offset to add to tail
100 * This function returns the indices into the FIFO based on tail + offset
102 STATIC u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
104 return (fifo->tail + offset) & (fifo->size - 1);
108 * fm10k_fifo_head_len - Retrieve length of first message in FIFO
109 * @fifo: pointer to FIFO
111 * This function returns the size of the first message in the FIFO
113 STATIC u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
115 u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
117 /* verify there is at least 1 DWORD in the fifo so *head is valid */
118 if (fm10k_fifo_empty(fifo))
121 /* retieve the message length */
122 return FM10K_TLV_DWORD_LEN(*head);
126 * fm10k_fifo_head_drop - Drop the first message in FIFO
127 * @fifo: pointer to FIFO
129 * This function returns the size of the message dropped from the FIFO
131 STATIC u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
133 u16 len = fm10k_fifo_head_len(fifo);
135 /* update head so it is at the start of next frame */
142 * fm10k_fifo_drop_all - Drop all messages in FIFO
143 * @fifo: pointer to FIFO
145 * This function resets the head pointer to drop all messages in the FIFO and
146 * ensure the FIFO is empty.
148 STATIC void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
150 fifo->head = fifo->tail;
154 * fm10k_mbx_index_len - Convert a head/tail index into a length value
155 * @mbx: pointer to mailbox
159 * This function takes the head and tail index and determines the length
160 * of the data indicated by this pair.
162 STATIC u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
164 u16 len = tail - head;
166 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
170 return len & ((mbx->mbmem_len << 1) - 1);
174 * fm10k_mbx_tail_add - Determine new tail value with added offset
175 * @mbx: pointer to mailbox
176 * @offset: length to add to tail offset
178 * This function takes the local tail index and recomputes it for
179 * a given length added as an offset.
181 STATIC u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
183 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
185 /* add/sub 1 because we cannot have offset 0 or all 1s */
186 return (tail > mbx->tail) ? --tail : ++tail;
190 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
191 * @mbx: pointer to mailbox
192 * @offset: length to add to tail offset
194 * This function takes the local tail index and recomputes it for
195 * a given length added as an offset.
197 STATIC u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
199 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
201 /* sub/add 1 because we cannot have offset 0 or all 1s */
202 return (tail < mbx->tail) ? ++tail : --tail;
206 * fm10k_mbx_head_add - Determine new head value with added offset
207 * @mbx: pointer to mailbox
208 * @offset: length to add to head offset
210 * This function takes the local head index and recomputes it for
211 * a given length added as an offset.
213 STATIC u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
215 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
217 /* add/sub 1 because we cannot have offset 0 or all 1s */
218 return (head > mbx->head) ? --head : ++head;
222 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
223 * @mbx: pointer to mailbox
224 * @offset: length to add to head offset
226 * This function takes the local head index and recomputes it for
227 * a given length added as an offset.
229 STATIC u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
231 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
233 /* sub/add 1 because we cannot have offset 0 or all 1s */
234 return (head < mbx->head) ? ++head : --head;
238 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
239 * @mbx: pointer to mailbox
241 * This function will return the length of the message currently being
242 * pushed onto the tail of the Rx queue.
244 STATIC u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
246 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
248 /* pushed tail is only valid if pushed is set */
252 return FM10K_TLV_DWORD_LEN(*tail);
256 * fm10k_fifo_write_copy - pulls data off of msg and places it in FIFO
257 * @fifo: pointer to FIFO
258 * @msg: message array to populate
259 * @tail_offset: additional offset to add to tail pointer
260 * @len: length of FIFO to copy into message header
262 * This function will take a message and copy it into a section of the
263 * FIFO. In order to get something into a location other than just
264 * the tail you can use tail_offset to adjust the pointer.
266 STATIC void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
267 const u32 *msg, u16 tail_offset, u16 len)
269 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
270 u32 *tail = fifo->buffer + end;
272 /* track when we should cross the end of the FIFO */
273 end = fifo->size - end;
275 /* copy end of message before start of message */
277 memcpy(fifo->buffer, msg + end, (len - end) << 2);
281 /* Copy remaining message into Tx FIFO */
282 memcpy(tail, msg, end << 2);
286 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
287 * @fifo: pointer to FIFO
288 * @msg: message array to read
290 * This function enqueues a message up to the size specified by the length
291 * contained in the first DWORD of the message and will place at the tail
292 * of the FIFO. It will return 0 on success, or a negative value on error.
294 STATIC s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
296 u16 len = FM10K_TLV_DWORD_LEN(*msg);
298 DEBUGFUNC("fm10k_fifo_enqueue");
300 /* verify parameters */
301 if (len > fifo->size)
302 return FM10K_MBX_ERR_SIZE;
304 /* verify there is room for the message */
305 if (len > fm10k_fifo_unused(fifo))
306 return FM10K_MBX_ERR_NO_SPACE;
308 /* Copy message into FIFO */
309 fm10k_fifo_write_copy(fifo, msg, 0, len);
311 /* memory barrier to guarantee FIFO is written before tail update */
314 /* Update Tx FIFO tail */
317 return FM10K_SUCCESS;
321 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
322 * @mbx: pointer to mailbox
323 * @len: length of data pushed onto buffer
325 * This function analyzes the frame and will return a non-zero value when
326 * the start of a message larger than the mailbox is detected.
328 STATIC u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
330 struct fm10k_mbx_fifo *fifo = &mbx->rx;
331 u16 total_len = 0, msg_len;
334 DEBUGFUNC("fm10k_mbx_validate_msg_size");
336 /* length should include previous amounts pushed */
339 /* offset in message is based off of current message size */
341 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
342 msg_len = FM10K_TLV_DWORD_LEN(*msg);
343 total_len += msg_len;
344 } while (total_len < len);
346 /* message extends out of pushed section, but fits in FIFO */
347 if ((len < total_len) && (msg_len <= mbx->max_size))
350 /* return length of invalid section */
351 return (len < total_len) ? len : (len - total_len);
355 * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
356 * @hw: pointer to hardware structure
357 * @mbx: pointer to mailbox
359 * This function will take a section of the Tx FIFO and copy it into the
360 * mailbox memory. The offset in mbmem is based on the lower bits of the
361 * tail and len determines the length to copy.
363 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
364 struct fm10k_mbx_info *mbx)
366 struct fm10k_mbx_fifo *fifo = &mbx->tx;
367 u32 mbmem = mbx->mbmem_reg;
368 u32 *head = fifo->buffer;
369 u16 end, len, tail, mask;
371 DEBUGFUNC("fm10k_mbx_write_copy");
376 /* determine data length and mbmem tail index */
377 mask = mbx->mbmem_len - 1;
379 tail = fm10k_mbx_tail_sub(mbx, len);
383 /* determine offset in the ring */
384 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
387 /* memory barrier to guarantee data is ready to be read */
390 /* Copy message from Tx FIFO */
391 for (end = fifo->size - end; len; head = fifo->buffer) {
393 /* adjust tail to match offset for FIFO */
398 mbx->tx_mbmem_pulled++;
400 /* write message to hardware FIFO */
401 FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
402 } while (--len && --end);
407 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
408 * @hw: pointer to hardware structure
409 * @mbx: pointer to mailbox
410 * @head: acknowledgement number last received
412 * This function will push the tail index forward based on the remote
413 * head index. It will then pull up to mbmem_len DWORDs off of the
414 * head of the FIFO and will place it in the MBMEM registers
415 * associated with the mailbox.
417 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
418 struct fm10k_mbx_info *mbx, u16 head)
420 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
421 struct fm10k_mbx_fifo *fifo = &mbx->tx;
423 /* update number of bytes pulled and update bytes in transit */
424 mbx->pulled += mbx->tail_len - ack;
426 /* determine length of data to pull, reserve space for mbmem header */
427 mbmem_len = mbx->mbmem_len - 1;
428 len = fm10k_fifo_used(fifo) - mbx->pulled;
432 /* update tail and record number of bytes in transit */
433 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
436 /* drop pulled messages from the FIFO */
437 for (len = fm10k_fifo_head_len(fifo);
438 len && (mbx->pulled >= len);
439 len = fm10k_fifo_head_len(fifo)) {
440 mbx->pulled -= fm10k_fifo_head_drop(fifo);
442 mbx->tx_dwords += len;
445 /* Copy message out from the Tx FIFO */
446 fm10k_mbx_write_copy(hw, mbx);
450 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
451 * @hw: pointer to hardware structure
452 * @mbx: pointer to mailbox
454 * This function will take a section of the mailbox memory and copy it
455 * into the Rx FIFO. The offset is based on the lower bits of the
456 * head and len determines the length to copy.
458 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
459 struct fm10k_mbx_info *mbx)
461 struct fm10k_mbx_fifo *fifo = &mbx->rx;
462 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
463 u32 *tail = fifo->buffer;
466 DEBUGFUNC("fm10k_mbx_read_copy");
468 /* determine data length and mbmem head index */
470 head = fm10k_mbx_head_sub(mbx, len);
471 if (head >= mbx->mbmem_len)
474 /* determine offset in the ring */
475 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
478 /* Copy message into Rx FIFO */
479 for (end = fifo->size - end; len; tail = fifo->buffer) {
481 /* adjust head to match offset for FIFO */
482 head &= mbx->mbmem_len - 1;
486 mbx->rx_mbmem_pushed++;
488 /* read message from hardware FIFO */
489 *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
490 } while (--len && --end);
493 /* memory barrier to guarantee FIFO is written before tail update */
498 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
499 * @hw: pointer to hardware structure
500 * @mbx: pointer to mailbox
501 * @tail: tail index of message
503 * This function will first validate the tail index and size for the
504 * incoming message. It then updates the acknowledgment number and
505 * copies the data into the FIFO. It will return the number of messages
506 * dequeued on success and a negative value on error.
508 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
509 struct fm10k_mbx_info *mbx,
512 struct fm10k_mbx_fifo *fifo = &mbx->rx;
513 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
515 DEBUGFUNC("fm10k_mbx_push_tail");
517 /* determine length of data to push */
518 len = fm10k_fifo_unused(fifo) - mbx->pushed;
522 /* update head and record bytes received */
523 mbx->head = fm10k_mbx_head_add(mbx, len);
526 /* nothing to do if there is no data */
528 return FM10K_SUCCESS;
530 /* Copy msg into Rx FIFO */
531 fm10k_mbx_read_copy(hw, mbx);
533 /* determine if there are any invalid lengths in message */
534 if (fm10k_mbx_validate_msg_size(mbx, len))
535 return FM10K_MBX_ERR_SIZE;
540 /* flush any completed messages */
541 for (len = fm10k_mbx_pushed_tail_len(mbx);
542 len && (mbx->pushed >= len);
543 len = fm10k_mbx_pushed_tail_len(mbx)) {
547 mbx->rx_dwords += len;
550 return FM10K_SUCCESS;
553 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
554 static const u16 fm10k_crc_16b_table[256] = {
555 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
556 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
557 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
558 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
559 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
560 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
561 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
562 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
563 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
564 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
565 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
566 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
567 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
568 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
569 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
570 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
571 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
572 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
573 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
574 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
575 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
576 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
577 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
578 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
579 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
580 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
581 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
582 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
583 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
584 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
585 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
586 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
589 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
590 * @data: pointer to data to process
591 * @seed: seed value for CRC
592 * @len: length measured in 16 bits words
594 * This function will generate a CRC based on the polynomial 0xAC9A and
595 * whatever value is stored in the seed variable. Note that this
596 * value inverts the local seed and the result in order to capture all
597 * leading and trailing zeros.
599 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
605 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
606 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
611 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
612 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
619 * fm10k_fifo_crc - generate a CRC based off of FIFO data
620 * @fifo: pointer to FIFO
621 * @offset: offset point for start of FIFO
622 * @len: number of DWORDS words to process
623 * @seed: seed value for CRC
625 * This function generates a CRC for some region of the FIFO
627 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
630 u32 *data = fifo->buffer + offset;
632 /* track when we should cross the end of the FIFO */
633 offset = fifo->size - offset;
635 /* if we are in 2 blocks process the end of the FIFO first */
637 seed = fm10k_crc_16b(data, seed, offset * 2);
642 /* process any remaining bits */
643 return fm10k_crc_16b(data, seed, len * 2);
647 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
648 * @mbx: pointer to mailbox
649 * @head: head index provided by remote mailbox
651 * This function will generate the CRC for all data from the end of the
652 * last head update to the current one. It uses the result of the
653 * previous CRC as the seed for this update. The result is stored in
656 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
658 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
660 /* determine the offset for the start of the region to be pulled */
661 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
663 /* update local CRC to include all of the pulled data */
664 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
668 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
669 * @mbx: pointer to mailbox
671 * This function will take all data that has been provided from the remote
672 * end and generate a CRC for it. This is stored in mbx->remote. The
673 * CRC for the header is then computed and if the result is non-zero this
674 * is an error and we signal an error dropping all data and resetting the
677 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
679 struct fm10k_mbx_fifo *fifo = &mbx->rx;
680 u16 len = mbx->head_len;
681 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
684 /* update the remote CRC if new data has been received */
686 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
688 /* process the full header as we have to validate the CRC */
689 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
691 /* notify other end if we have a problem */
692 return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
696 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
697 * @mbx: pointer to mailbox
699 * This function returns true if there is a message in the Rx FIFO to dequeue.
701 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
703 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
705 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
709 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
710 * @mbx: pointer to mailbox
711 * @len: verify free space is >= this value
713 * This function returns true if the mailbox is in a state ready to transmit.
715 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
717 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
719 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
723 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
724 * @mbx: pointer to mailbox
726 * This function returns true if the Tx FIFO is empty.
728 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
730 return fm10k_fifo_empty(&mbx->tx);
734 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
735 * @hw: pointer to hardware structure
736 * @mbx: pointer to mailbox
738 * This function dequeues messages and hands them off to the TLV parser.
739 * It will return the number of messages processed when called.
741 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
742 struct fm10k_mbx_info *mbx)
744 struct fm10k_mbx_fifo *fifo = &mbx->rx;
748 /* parse Rx messages out of the Rx FIFO to empty it */
749 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
750 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
755 fm10k_fifo_head_drop(fifo);
758 /* shift remaining bytes back to start of FIFO */
759 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
761 /* shift head and tail based on the memory we moved */
762 fifo->tail -= fifo->head;
769 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
770 * @hw: pointer to hardware structure
771 * @mbx: pointer to mailbox
772 * @msg: message array to read
774 * This function enqueues a message up to the size specified by the length
775 * contained in the first DWORD of the message and will place at the tail
776 * of the FIFO. It will return 0 on success, or a negative value on error.
778 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
779 struct fm10k_mbx_info *mbx, const u32 *msg)
781 u32 countdown = mbx->timeout;
784 switch (mbx->state) {
785 case FM10K_STATE_CLOSED:
786 case FM10K_STATE_DISCONNECT:
787 return FM10K_MBX_ERR_NO_MBX;
792 /* enqueue the message on the Tx FIFO */
793 err = fm10k_fifo_enqueue(&mbx->tx, msg);
795 /* if it failed give the FIFO a chance to drain */
796 while (err && countdown) {
798 usec_delay(mbx->usec_delay);
799 mbx->ops.process(hw, mbx);
800 err = fm10k_fifo_enqueue(&mbx->tx, msg);
803 /* if we failed treat the error */
809 /* begin processing message, ignore errors as this is just meant
810 * to start the mailbox flow so we are not concerned if there
811 * is a bad error, or the mailbox is already busy with a request
814 mbx->ops.process(hw, mbx);
816 return FM10K_SUCCESS;
820 * fm10k_mbx_read - Copies the mbmem to local message buffer
821 * @hw: pointer to hardware structure
822 * @mbx: pointer to mailbox
824 * This function copies the message from the mbmem to the message array
826 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
828 DEBUGFUNC("fm10k_mbx_read");
830 /* only allow one reader in here at a time */
832 return FM10K_MBX_ERR_BUSY;
834 /* read to capture initial interrupt bits */
835 if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
836 mbx->mbx_lock = FM10K_MBX_ACK;
838 /* write back interrupt bits to clear */
839 FM10K_WRITE_MBX(hw, mbx->mbx_reg,
840 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
842 /* read remote header */
843 mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
845 return FM10K_SUCCESS;
849 * fm10k_mbx_write - Copies the local message buffer to mbmem
850 * @hw: pointer to hardware structure
851 * @mbx: pointer to mailbox
853 * This function copies the message from the message array to mbmem
855 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
857 u32 mbmem = mbx->mbmem_reg;
859 DEBUGFUNC("fm10k_mbx_write");
861 /* write new msg header to notify recipient of change */
862 FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
864 /* write mailbox to send interrupt */
866 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
868 /* we no longer are using the header so free it */
874 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
875 * @mbx: pointer to mailbox
877 * This function returns a connection mailbox header
879 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
881 mbx->mbx_lock |= FM10K_MBX_REQ;
883 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
884 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
885 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
889 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
890 * @mbx: pointer to mailbox
892 * This function returns a data mailbox header
894 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
896 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
897 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
898 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
899 struct fm10k_mbx_fifo *fifo = &mbx->tx;
903 mbx->mbx_lock |= FM10K_MBX_REQ;
905 /* generate CRC for data in flight and header */
906 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
907 mbx->tail_len, mbx->local);
908 crc = fm10k_crc_16b(&hdr, crc, 1);
910 /* load header to memory to be written */
911 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
915 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
916 * @mbx: pointer to mailbox
918 * This function returns a disconnect mailbox header
920 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
922 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
923 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
924 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
925 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
927 mbx->mbx_lock |= FM10K_MBX_ACK;
929 /* load header to memory to be written */
930 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
934 * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mbox hdr
935 * @mbx: pointer to mailbox
937 * This function creates a fake disconnect header for loading into remote
938 * mailbox header. The primary purpose is to prevent errors on immediate
939 * start up after mbx->connect.
941 STATIC void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
943 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
944 FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
945 FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
946 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
948 mbx->mbx_lock |= FM10K_MBX_ACK;
950 /* load header to memory to be written */
951 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
955 * fm10k_mbx_create_error_msg - Generate an error message
956 * @mbx: pointer to mailbox
957 * @err: local error encountered
959 * This function will interpret the error provided by err, and based on
960 * that it may shift the message by 1 DWORD and then place an error header
961 * at the start of the message.
963 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
965 /* only generate an error message for these types */
967 case FM10K_MBX_ERR_TAIL:
968 case FM10K_MBX_ERR_HEAD:
969 case FM10K_MBX_ERR_TYPE:
970 case FM10K_MBX_ERR_SIZE:
971 case FM10K_MBX_ERR_RSVD0:
972 case FM10K_MBX_ERR_CRC:
978 mbx->mbx_lock |= FM10K_MBX_REQ;
980 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
981 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
982 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
986 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
987 * @mbx: pointer to mailbox
989 * This function will parse up the fields in the mailbox header and return
990 * an error if the header contains any of a number of invalid configurations
991 * including unrecognized type, invalid route, or a malformed message.
993 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
995 u16 type, rsvd0, head, tail, size;
996 const u32 *hdr = &mbx->mbx_hdr;
998 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1000 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
1001 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
1002 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1003 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1004 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1007 return FM10K_MBX_ERR_RSVD0;
1010 case FM10K_MSG_DISCONNECT:
1011 /* validate that all data has been received */
1012 if (tail != mbx->head)
1013 return FM10K_MBX_ERR_TAIL;
1016 case FM10K_MSG_DATA:
1017 /* validate that head is moving correctly */
1018 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1019 return FM10K_MBX_ERR_HEAD;
1020 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1021 return FM10K_MBX_ERR_HEAD;
1023 /* validate that tail is moving correctly */
1024 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
1025 return FM10K_MBX_ERR_TAIL;
1026 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1029 return FM10K_MBX_ERR_TAIL;
1030 case FM10K_MSG_CONNECT:
1031 /* validate size is in range and is power of 2 mask */
1032 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
1033 return FM10K_MBX_ERR_SIZE;
1036 case FM10K_MSG_ERROR:
1037 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1038 return FM10K_MBX_ERR_HEAD;
1039 /* neither create nor error include a tail offset */
1041 return FM10K_MBX_ERR_TAIL;
1045 return FM10K_MBX_ERR_TYPE;
1048 return FM10K_SUCCESS;
1052 * fm10k_mbx_create_reply - Generate reply based on state and remote head
1053 * @hw: pointer to hardware structure
1054 * @mbx: pointer to mailbox
1055 * @head: acknowledgement number
1057 * This function will generate an outgoing message based on the current
1058 * mailbox state and the remote FIFO head. It will return the length
1059 * of the outgoing message excluding header on success, and a negative value
1062 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1063 struct fm10k_mbx_info *mbx, u16 head)
1065 switch (mbx->state) {
1066 case FM10K_STATE_OPEN:
1067 case FM10K_STATE_DISCONNECT:
1068 /* update our checksum for the outgoing data */
1069 fm10k_mbx_update_local_crc(mbx, head);
1071 /* as long as other end recognizes us keep sending data */
1072 fm10k_mbx_pull_head(hw, mbx, head);
1074 /* generate new header based on data */
1075 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1076 fm10k_mbx_create_data_hdr(mbx);
1078 fm10k_mbx_create_disconnect_hdr(mbx);
1080 case FM10K_STATE_CONNECT:
1081 /* send disconnect even if we aren't connected */
1082 fm10k_mbx_create_connect_hdr(mbx);
1084 case FM10K_STATE_CLOSED:
1085 /* generate new header based on data */
1086 fm10k_mbx_create_disconnect_hdr(mbx);
1091 return FM10K_SUCCESS;
1095 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1096 * @mbx: pointer to mailbox
1098 * This function will reset all internal pointers so any work in progress
1099 * is dropped. This call should occur every time we transition from the
1100 * open state to the connect state.
1102 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1106 /* reset our outgoing max size back to Rx limits */
1107 mbx->max_size = mbx->rx.size - 1;
1109 /* update mbx->pulled to account for tail_len and ack */
1110 head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1111 ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1112 mbx->pulled += mbx->tail_len - ack;
1114 /* now drop any messages which have started or finished transmitting */
1115 while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1116 len = fm10k_fifo_head_drop(&mbx->tx);
1118 if (mbx->pulled >= len)
1124 /* just do a quick resysnc to start of message */
1134 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1135 * @mbx: pointer to mailbox
1136 * @size: new value for max_size
1138 * This function updates the max_size value and drops any outgoing messages
1139 * at the head of the Tx FIFO if they are larger than max_size. It does not
1140 * drop all messages, as this is too difficult to parse and remove them from
1141 * the FIFO. Instead, rely on the checking to ensure that messages larger
1142 * than max_size aren't pushed into the memory buffer.
1144 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1148 DEBUGFUNC("fm10k_mbx_update_max_size");
1150 mbx->max_size = size;
1152 /* flush any oversized messages from the queue */
1153 for (len = fm10k_fifo_head_len(&mbx->tx);
1155 len = fm10k_fifo_head_len(&mbx->tx)) {
1156 fm10k_fifo_head_drop(&mbx->tx);
1162 * fm10k_mbx_connect_reset - Reset following request for reset
1163 * @mbx: pointer to mailbox
1165 * This function resets the mailbox to either a disconnected state
1166 * or a connect state depending on the current mailbox state
1168 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1170 /* just do a quick resysnc to start of frame */
1171 fm10k_mbx_reset_work(mbx);
1173 /* reset CRC seeds */
1174 mbx->local = FM10K_MBX_CRC_SEED;
1175 mbx->remote = FM10K_MBX_CRC_SEED;
1177 /* we cannot exit connect until the size is good */
1178 if (mbx->state == FM10K_STATE_OPEN)
1179 mbx->state = FM10K_STATE_CONNECT;
1181 mbx->state = FM10K_STATE_CLOSED;
1185 * fm10k_mbx_process_connect - Process connect header
1186 * @hw: pointer to hardware structure
1187 * @mbx: pointer to mailbox
1189 * This function will read an incoming connect header and reply with the
1190 * appropriate message. It will return a value indicating the number of
1191 * data DWORDs on success, or will return a negative value on failure.
1193 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1194 struct fm10k_mbx_info *mbx)
1196 const enum fm10k_mbx_state state = mbx->state;
1197 const u32 *hdr = &mbx->mbx_hdr;
1200 /* we will need to pull all of the fields for verification */
1201 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1202 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1205 case FM10K_STATE_DISCONNECT:
1206 case FM10K_STATE_OPEN:
1207 /* reset any in-progress work */
1208 fm10k_mbx_connect_reset(mbx);
1210 case FM10K_STATE_CONNECT:
1211 /* we cannot exit connect until the size is good */
1212 if (size > mbx->rx.size) {
1213 mbx->max_size = mbx->rx.size - 1;
1215 /* record the remote system requesting connection */
1216 mbx->state = FM10K_STATE_OPEN;
1218 fm10k_mbx_update_max_size(mbx, size);
1225 /* align our tail index to remote head index */
1228 return fm10k_mbx_create_reply(hw, mbx, head);
1232 * fm10k_mbx_process_data - Process data header
1233 * @hw: pointer to hardware structure
1234 * @mbx: pointer to mailbox
1236 * This function will read an incoming data header and reply with the
1237 * appropriate message. It will return a value indicating the number of
1238 * data DWORDs on success, or will return a negative value on failure.
1240 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1241 struct fm10k_mbx_info *mbx)
1243 const u32 *hdr = &mbx->mbx_hdr;
1247 DEBUGFUNC("fm10k_mbx_process_data");
1249 /* we will need to pull all of the fields for verification */
1250 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1251 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1253 /* if we are in connect just update our data and go */
1254 if (mbx->state == FM10K_STATE_CONNECT) {
1256 mbx->state = FM10K_STATE_OPEN;
1259 /* abort on message size errors */
1260 err = fm10k_mbx_push_tail(hw, mbx, tail);
1264 /* verify the checksum on the incoming data */
1265 err = fm10k_mbx_verify_remote_crc(mbx);
1269 /* process messages if we have received any */
1270 fm10k_mbx_dequeue_rx(hw, mbx);
1272 return fm10k_mbx_create_reply(hw, mbx, head);
1276 * fm10k_mbx_process_disconnect - Process disconnect header
1277 * @hw: pointer to hardware structure
1278 * @mbx: pointer to mailbox
1280 * This function will read an incoming disconnect header and reply with the
1281 * appropriate message. It will return a value indicating the number of
1282 * data DWORDs on success, or will return a negative value on failure.
1284 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1285 struct fm10k_mbx_info *mbx)
1287 const enum fm10k_mbx_state state = mbx->state;
1288 const u32 *hdr = &mbx->mbx_hdr;
1292 /* we will need to pull the header field for verification */
1293 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1295 /* We should not be receiving disconnect if Rx is incomplete */
1297 return FM10K_MBX_ERR_TAIL;
1299 /* we have already verified mbx->head == tail so we know this is 0 */
1302 /* verify the checksum on the incoming header is correct */
1303 err = fm10k_mbx_verify_remote_crc(mbx);
1308 case FM10K_STATE_DISCONNECT:
1309 case FM10K_STATE_OPEN:
1310 /* state doesn't change if we still have work to do */
1311 if (!fm10k_mbx_tx_complete(mbx))
1314 /* verify the head indicates we completed all transmits */
1315 if (head != mbx->tail)
1316 return FM10K_MBX_ERR_HEAD;
1318 /* reset any in-progress work */
1319 fm10k_mbx_connect_reset(mbx);
1325 return fm10k_mbx_create_reply(hw, mbx, head);
1329 * fm10k_mbx_process_error - Process error header
1330 * @hw: pointer to hardware structure
1331 * @mbx: pointer to mailbox
1333 * This function will read an incoming error header and reply with the
1334 * appropriate message. It will return a value indicating the number of
1335 * data DWORDs on success, or will return a negative value on failure.
1337 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1338 struct fm10k_mbx_info *mbx)
1340 const u32 *hdr = &mbx->mbx_hdr;
1343 /* we will need to pull all of the fields for verification */
1344 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1346 switch (mbx->state) {
1347 case FM10K_STATE_OPEN:
1348 case FM10K_STATE_DISCONNECT:
1349 /* flush any uncompleted work */
1350 fm10k_mbx_reset_work(mbx);
1352 /* reset CRC seeds */
1353 mbx->local = FM10K_MBX_CRC_SEED;
1354 mbx->remote = FM10K_MBX_CRC_SEED;
1356 /* reset tail index and size to prepare for reconnect */
1359 /* if open then reset max_size and go back to connect */
1360 if (mbx->state == FM10K_STATE_OPEN) {
1361 mbx->state = FM10K_STATE_CONNECT;
1365 /* send a connect message to get data flowing again */
1366 fm10k_mbx_create_connect_hdr(mbx);
1367 return FM10K_SUCCESS;
1372 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1376 * fm10k_mbx_process - Process mailbox interrupt
1377 * @hw: pointer to hardware structure
1378 * @mbx: pointer to mailbox
1380 * This function will process incoming mailbox events and generate mailbox
1381 * replies. It will return a value indicating the number of DWORDs
1382 * transmitted excluding header on success or a negative value on error.
1384 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1385 struct fm10k_mbx_info *mbx)
1389 DEBUGFUNC("fm10k_mbx_process");
1391 /* we do not read mailbox if closed */
1392 if (mbx->state == FM10K_STATE_CLOSED)
1393 return FM10K_SUCCESS;
1395 /* copy data from mailbox */
1396 err = fm10k_mbx_read(hw, mbx);
1400 /* validate type, source, and destination */
1401 err = fm10k_mbx_validate_msg_hdr(mbx);
1405 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1406 case FM10K_MSG_CONNECT:
1407 err = fm10k_mbx_process_connect(hw, mbx);
1409 case FM10K_MSG_DATA:
1410 err = fm10k_mbx_process_data(hw, mbx);
1412 case FM10K_MSG_DISCONNECT:
1413 err = fm10k_mbx_process_disconnect(hw, mbx);
1415 case FM10K_MSG_ERROR:
1416 err = fm10k_mbx_process_error(hw, mbx);
1419 err = FM10K_MBX_ERR_TYPE;
1424 /* notify partner of errors on our end */
1426 fm10k_mbx_create_error_msg(mbx, err);
1428 /* copy data from mailbox */
1429 fm10k_mbx_write(hw, mbx);
1435 * fm10k_mbx_disconnect - Shutdown mailbox connection
1436 * @hw: pointer to hardware structure
1437 * @mbx: pointer to mailbox
1439 * This function will shut down the mailbox. It places the mailbox first
1440 * in the disconnect state, it then allows up to a predefined timeout for
1441 * the mailbox to transition to close on its own. If this does not occur
1442 * then the mailbox will be forced into the closed state.
1444 * Any mailbox transactions not completed before calling this function
1445 * are not guaranteed to complete and may be dropped.
1447 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1448 struct fm10k_mbx_info *mbx)
1450 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1452 DEBUGFUNC("fm10k_mbx_disconnect");
1454 /* Place mbx in ready to disconnect state */
1455 mbx->state = FM10K_STATE_DISCONNECT;
1457 /* trigger interrupt to start shutdown process */
1458 FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1459 FM10K_MBX_INTERRUPT_DISABLE);
1461 usec_delay(FM10K_MBX_POLL_DELAY);
1462 mbx->ops.process(hw, mbx);
1463 timeout -= FM10K_MBX_POLL_DELAY;
1464 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1466 /* in case we didn't close, just force the mailbox into shutdown and
1467 * drop all left over messages in the FIFO.
1469 fm10k_mbx_connect_reset(mbx);
1470 fm10k_fifo_drop_all(&mbx->tx);
1472 FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1476 * fm10k_mbx_connect - Start mailbox connection
1477 * @hw: pointer to hardware structure
1478 * @mbx: pointer to mailbox
1480 * This function will initiate a mailbox connection. It will populate the
1481 * mailbox with a broadcast connect message and then initialize the lock.
1482 * This is safe since the connect message is a single DWORD so the mailbox
1483 * transaction is guaranteed to be atomic.
1485 * This function will return an error if the mailbox has not been initiated
1486 * or is currently in use.
1488 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1490 DEBUGFUNC("fm10k_mbx_connect");
1492 /* we cannot connect an uninitialized mailbox */
1493 if (!mbx->rx.buffer)
1494 return FM10K_MBX_ERR_NO_SPACE;
1496 /* we cannot connect an already connected mailbox */
1497 if (mbx->state != FM10K_STATE_CLOSED)
1498 return FM10K_MBX_ERR_BUSY;
1500 /* mailbox timeout can now become active */
1501 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1503 /* Place mbx in ready to connect state */
1504 mbx->state = FM10K_STATE_CONNECT;
1506 fm10k_mbx_reset_work(mbx);
1508 /* initialize header of remote mailbox */
1509 fm10k_mbx_create_fake_disconnect_hdr(mbx);
1510 FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1512 /* enable interrupt and notify other party of new message */
1513 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1514 FM10K_MBX_INTERRUPT_ENABLE;
1516 /* generate and load connect header into mailbox */
1517 fm10k_mbx_create_connect_hdr(mbx);
1518 fm10k_mbx_write(hw, mbx);
1520 return FM10K_SUCCESS;
1524 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1525 * @msg_data: handlers for mailbox events
1527 * This function validates the layout of the message parsing data. This
1528 * should be mostly static, but it is important to catch any errors that
1529 * are made when constructing the parsers.
1531 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1533 const struct fm10k_tlv_attr *attr;
1536 DEBUGFUNC("fm10k_mbx_validate_handlers");
1538 /* Allow NULL mailboxes that transmit but don't receive */
1540 return FM10K_SUCCESS;
1542 while (msg_data->id != FM10K_TLV_ERROR) {
1543 /* all messages should have a function handler */
1544 if (!msg_data->func)
1545 return FM10K_ERR_PARAM;
1547 /* parser is optional */
1548 attr = msg_data->attr;
1550 while (attr->id != FM10K_TLV_ERROR) {
1553 /* ID should always be increasing */
1555 return FM10K_ERR_PARAM;
1556 /* ID should fit in results array */
1557 if (id >= FM10K_TLV_RESULTS_MAX)
1558 return FM10K_ERR_PARAM;
1561 /* verify terminator is in the list */
1562 if (attr->id != FM10K_TLV_ERROR)
1563 return FM10K_ERR_PARAM;
1568 /* ID should always be increasing */
1569 if (id >= msg_data->id)
1570 return FM10K_ERR_PARAM;
1573 /* verify terminator is in the list */
1574 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1575 return FM10K_ERR_PARAM;
1577 return FM10K_SUCCESS;
1581 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1582 * @mbx: pointer to mailbox
1583 * @msg_data: handlers for mailbox events
1585 * This function associates a set of message handling ops with a mailbox.
1587 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1588 const struct fm10k_msg_data *msg_data)
1590 DEBUGFUNC("fm10k_mbx_register_handlers");
1592 /* validate layout of handlers before assigning them */
1593 if (fm10k_mbx_validate_handlers(msg_data))
1594 return FM10K_ERR_PARAM;
1596 /* initialize the message handlers */
1597 mbx->msg_data = msg_data;
1599 return FM10K_SUCCESS;
1603 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1604 * @hw: pointer to hardware structure
1605 * @mbx: pointer to mailbox
1606 * @msg_data: handlers for mailbox events
1607 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1609 * This function initializes the mailbox for use. It will split the
1610 * buffer provided and use that to populate both the Tx and Rx FIFO by
1611 * evenly splitting it. In order to allow for easy masking of head/tail
1612 * the value reported in size must be a power of 2 and is reported in
1613 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1616 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1617 const struct fm10k_msg_data *msg_data, u8 id)
1619 DEBUGFUNC("fm10k_pfvf_mbx_init");
1621 /* initialize registers */
1622 switch (hw->mac.type) {
1624 mbx->mbx_reg = FM10K_VFMBX;
1625 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1628 /* there are only 64 VF <-> PF mailboxes */
1630 mbx->mbx_reg = FM10K_MBX(id);
1631 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1636 return FM10K_MBX_ERR_NO_MBX;
1639 /* start out in closed state */
1640 mbx->state = FM10K_STATE_CLOSED;
1642 /* validate layout of handlers before assigning them */
1643 if (fm10k_mbx_validate_handlers(msg_data))
1644 return FM10K_ERR_PARAM;
1646 /* initialize the message handlers */
1647 mbx->msg_data = msg_data;
1649 /* start mailbox as timed out and let the reset_hw call
1650 * set the timeout value to begin communications
1653 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1655 /* initialize tail and head */
1659 /* initialize CRC seeds */
1660 mbx->local = FM10K_MBX_CRC_SEED;
1661 mbx->remote = FM10K_MBX_CRC_SEED;
1663 /* Split buffer for use by Tx/Rx FIFOs */
1664 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1665 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1667 /* initialize the FIFOs, sizes are in 4 byte increments */
1668 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1669 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1670 FM10K_MBX_RX_BUFFER_SIZE);
1672 /* initialize function pointers */
1673 mbx->ops.connect = fm10k_mbx_connect;
1674 mbx->ops.disconnect = fm10k_mbx_disconnect;
1675 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1676 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1677 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1678 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1679 mbx->ops.process = fm10k_mbx_process;
1680 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1682 return FM10K_SUCCESS;
1686 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1687 * @mbx: pointer to mailbox
1689 * This function returns a data mailbox header
1691 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1694 mbx->mbx_lock |= FM10K_MBX_REQ;
1696 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1697 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1698 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1702 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1703 * @mbx: pointer to mailbox
1704 * @err: error flags to report if any
1706 * This function returns a connection mailbox header
1708 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1711 mbx->mbx_lock |= FM10K_MBX_REQ;
1713 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1714 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1715 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1716 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1720 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1721 * @mbx: pointer to mailbox
1723 * This function resets the mailbox to a just connected state
1725 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1727 /* flush any uncompleted work */
1728 fm10k_mbx_reset_work(mbx);
1730 /* set local version to max and remote version to 0 */
1731 mbx->local = FM10K_SM_MBX_VERSION;
1734 /* initialize tail and head */
1738 /* reset state back to connect */
1739 mbx->state = FM10K_STATE_CONNECT;
1743 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1744 * @hw: pointer to hardware structure
1745 * @mbx: pointer to mailbox
1747 * This function will initiate a mailbox connection with the switch
1748 * manager. To do this it will first disconnect the mailbox, and then
1749 * reconnect it in order to complete a reset of the mailbox.
1751 * This function will return an error if the mailbox has not been initiated
1752 * or is currently in use.
1754 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1756 DEBUGFUNC("fm10k_sm_mbx_connect");
1758 /* we cannot connect an uninitialized mailbox */
1759 if (!mbx->rx.buffer)
1760 return FM10K_MBX_ERR_NO_SPACE;
1762 /* we cannot connect an already connected mailbox */
1763 if (mbx->state != FM10K_STATE_CLOSED)
1764 return FM10K_MBX_ERR_BUSY;
1766 /* mailbox timeout can now become active */
1767 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1769 /* Place mbx in ready to connect state */
1770 mbx->state = FM10K_STATE_CONNECT;
1771 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1773 /* reset interface back to connect */
1774 fm10k_sm_mbx_connect_reset(mbx);
1776 /* enable interrupt and notify other party of new message */
1777 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1778 FM10K_MBX_INTERRUPT_ENABLE;
1780 /* generate and load connect header into mailbox */
1781 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1782 fm10k_mbx_write(hw, mbx);
1784 return FM10K_SUCCESS;
1788 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1789 * @hw: pointer to hardware structure
1790 * @mbx: pointer to mailbox
1792 * This function will shut down the mailbox. It places the mailbox first
1793 * in the disconnect state, it then allows up to a predefined timeout for
1794 * the mailbox to transition to close on its own. If this does not occur
1795 * then the mailbox will be forced into the closed state.
1797 * Any mailbox transactions not completed before calling this function
1798 * are not guaranteed to complete and may be dropped.
1800 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1801 struct fm10k_mbx_info *mbx)
1803 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1805 DEBUGFUNC("fm10k_sm_mbx_disconnect");
1807 /* Place mbx in ready to disconnect state */
1808 mbx->state = FM10K_STATE_DISCONNECT;
1810 /* trigger interrupt to start shutdown process */
1811 FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1812 FM10K_MBX_INTERRUPT_DISABLE);
1814 usec_delay(FM10K_MBX_POLL_DELAY);
1815 mbx->ops.process(hw, mbx);
1816 timeout -= FM10K_MBX_POLL_DELAY;
1817 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1819 /* in case we didn't close just force the mailbox into shutdown */
1820 mbx->state = FM10K_STATE_CLOSED;
1822 fm10k_mbx_reset_work(mbx);
1823 fm10k_fifo_drop_all(&mbx->tx);
1825 FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1829 * fm10k_sm_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1830 * @mbx: pointer to mailbox
1832 * This function will parse up the fields in the mailbox header and return
1833 * an error if the header contains any of a number of invalid configurations
1834 * including unrecognized offsets or version numbers.
1836 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1838 const u32 *hdr = &mbx->mbx_hdr;
1839 u16 tail, head, ver;
1841 DEBUGFUNC("fm10k_sm_mbx_validate_fifo_hdr");
1843 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1844 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1845 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1850 case FM10K_SM_MBX_VERSION:
1851 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1852 return FM10K_MBX_ERR_HEAD;
1853 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1854 return FM10K_MBX_ERR_TAIL;
1855 if (mbx->tail < head)
1856 head += mbx->mbmem_len - 1;
1857 if (tail < mbx->head)
1858 tail += mbx->mbmem_len - 1;
1859 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1860 return FM10K_MBX_ERR_HEAD;
1861 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1863 return FM10K_MBX_ERR_TAIL;
1865 return FM10K_MBX_ERR_SRC;
1868 return FM10K_SUCCESS;
1872 * fm10k_sm_mbx_process_error - Process header with error flag set
1873 * @mbx: pointer to mailbox
1875 * This function is meant to respond to a request where the error flag
1876 * is set. As a result we will terminate a connection if one is present
1877 * and fall back into the reset state with a connection header of version
1880 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1882 const enum fm10k_mbx_state state = mbx->state;
1885 case FM10K_STATE_DISCONNECT:
1886 /* if there is an error just disconnect */
1889 case FM10K_STATE_OPEN:
1890 /* flush any uncompleted work */
1891 fm10k_sm_mbx_connect_reset(mbx);
1893 case FM10K_STATE_CONNECT:
1894 /* try connnecting at lower version */
1896 while (mbx->local > 1)
1905 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1909 * fm10k_sm_mbx_create_error_msg - Process an error in FIFO header
1910 * @mbx: pointer to mailbox
1911 * @err: local error encountered
1913 * This function will interpret the error provided by err, and based on
1914 * that it may set the error bit in the local message header
1916 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1918 /* only generate an error message for these types */
1920 case FM10K_MBX_ERR_TAIL:
1921 case FM10K_MBX_ERR_HEAD:
1922 case FM10K_MBX_ERR_SRC:
1923 case FM10K_MBX_ERR_SIZE:
1924 case FM10K_MBX_ERR_RSVD0:
1930 /* process it as though we received an error, and send error reply */
1931 fm10k_sm_mbx_process_error(mbx);
1932 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1936 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1937 * @hw: pointer to hardware structure
1938 * @mbx: pointer to mailbox
1939 * @tail: tail index of message
1941 * This function will dequeue one message from the Rx switch manager mailbox
1942 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1944 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1945 struct fm10k_mbx_info *mbx,
1948 /* reduce length by 1 to convert to a mask */
1949 u16 mbmem_len = mbx->mbmem_len - 1;
1952 DEBUGFUNC("fm10k_sm_mbx_receive");
1954 /* push tail in front of head */
1955 if (tail < mbx->head)
1958 /* copy data to the Rx FIFO */
1959 err = fm10k_mbx_push_tail(hw, mbx, tail);
1963 /* process messages if we have received any */
1964 fm10k_mbx_dequeue_rx(hw, mbx);
1966 /* guarantee head aligns with the end of the last message */
1967 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1970 /* clear any extra bits left over since index adds 1 extra bit */
1971 if (mbx->head > mbmem_len)
1972 mbx->head -= mbmem_len;
1978 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1979 * @hw: pointer to hardware structure
1980 * @mbx: pointer to mailbox
1981 * @head: head index of message
1983 * This function will dequeue one message from the Tx mailbox FIFO and place
1984 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1986 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1987 struct fm10k_mbx_info *mbx, u16 head)
1989 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1990 /* reduce length by 1 to convert to a mask */
1991 u16 mbmem_len = mbx->mbmem_len - 1;
1992 u16 tail_len, len = 0;
1995 DEBUGFUNC("fm10k_sm_mbx_transmit");
1997 /* push head behind tail */
1998 if (mbx->tail < head)
2001 fm10k_mbx_pull_head(hw, mbx, head);
2003 /* determine msg aligned offset for end of buffer */
2005 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
2007 len += FM10K_TLV_DWORD_LEN(*msg);
2008 } while ((len <= mbx->tail_len) && (len < mbmem_len));
2010 /* guarantee we stop on a message boundary */
2011 if (mbx->tail_len > tail_len) {
2012 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
2013 mbx->tail_len = tail_len;
2016 /* clear any extra bits left over since index adds 1 extra bit */
2017 if (mbx->tail > mbmem_len)
2018 mbx->tail -= mbmem_len;
2022 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
2023 * @hw: pointer to hardware structure
2024 * @mbx: pointer to mailbox
2025 * @head: acknowledgement number
2027 * This function will generate an outgoing message based on the current
2028 * mailbox state and the remote FIFO head. It will return the length
2029 * of the outgoing message excluding header on success, and a negative value
2032 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
2033 struct fm10k_mbx_info *mbx, u16 head)
2035 switch (mbx->state) {
2036 case FM10K_STATE_OPEN:
2037 case FM10K_STATE_DISCONNECT:
2038 /* flush out Tx data */
2039 fm10k_sm_mbx_transmit(hw, mbx, head);
2041 /* generate new header based on data */
2042 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
2043 fm10k_sm_mbx_create_data_hdr(mbx);
2046 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2049 case FM10K_STATE_CONNECT:
2050 case FM10K_STATE_CLOSED:
2051 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2059 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2060 * @hw: pointer to hardware structure
2061 * @mbx: pointer to mailbox
2063 * This function is meant to respond to a request where the version data
2064 * is set to 0. As such we will either terminate the connection or go
2065 * into the connect state in order to re-establish the connection. This
2066 * function can also be used to respond to an error as the connection
2067 * resetting would also be a means of dealing with errors.
2069 STATIC s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2070 struct fm10k_mbx_info *mbx)
2072 s32 err = FM10K_SUCCESS;
2073 const enum fm10k_mbx_state state = mbx->state;
2076 case FM10K_STATE_DISCONNECT:
2077 /* drop remote connections and disconnect */
2078 mbx->state = FM10K_STATE_CLOSED;
2082 case FM10K_STATE_OPEN:
2083 /* flush any incomplete work */
2084 fm10k_sm_mbx_connect_reset(mbx);
2085 err = FM10K_ERR_RESET_REQUESTED;
2087 case FM10K_STATE_CONNECT:
2088 /* Update remote value to match local value */
2089 mbx->remote = mbx->local;
2094 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2100 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2101 * @hw: pointer to hardware structure
2102 * @mbx: pointer to mailbox
2104 * This function is meant to process messages received when the remote
2105 * mailbox is active.
2107 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2108 struct fm10k_mbx_info *mbx)
2110 const u32 *hdr = &mbx->mbx_hdr;
2114 /* pull all fields needed for verification */
2115 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2116 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2118 /* if we are in connect and wanting version 1 then start up and go */
2119 if (mbx->state == FM10K_STATE_CONNECT) {
2122 if (mbx->remote != 1)
2123 return FM10K_MBX_ERR_SRC;
2125 mbx->state = FM10K_STATE_OPEN;
2129 /* abort on message size errors */
2130 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2134 /* continue until we have flushed the Rx FIFO */
2138 fm10k_sm_mbx_create_reply(hw, mbx, head);
2140 return FM10K_SUCCESS;
2144 * fm10k_sm_mbx_process - Process switch manager mailbox interrupt
2145 * @hw: pointer to hardware structure
2146 * @mbx: pointer to mailbox
2148 * This function will process incoming mailbox events and generate mailbox
2149 * replies. It will return a value indicating the number of DWORDs
2150 * transmitted excluding header on success or a negative value on error.
2152 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2153 struct fm10k_mbx_info *mbx)
2157 DEBUGFUNC("fm10k_sm_mbx_process");
2159 /* we do not read mailbox if closed */
2160 if (mbx->state == FM10K_STATE_CLOSED)
2161 return FM10K_SUCCESS;
2163 /* retrieve data from switch manager */
2164 err = fm10k_mbx_read(hw, mbx);
2168 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2172 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2173 fm10k_sm_mbx_process_error(mbx);
2177 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2179 err = fm10k_sm_mbx_process_reset(hw, mbx);
2181 case FM10K_SM_MBX_VERSION:
2182 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2188 fm10k_sm_mbx_create_error_msg(mbx, err);
2190 /* report data to switch manager */
2191 fm10k_mbx_write(hw, mbx);
2197 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2198 * @hw: pointer to hardware structure
2199 * @mbx: pointer to mailbox
2200 * @msg_data: handlers for mailbox events
2202 * This function initializes the PF/SM mailbox for use. It will split the
2203 * buffer provided and use that to populate both the Tx and Rx FIFO by
2204 * evenly splitting it. In order to allow for easy masking of head/tail
2205 * the value reported in size must be a power of 2 and is reported in
2206 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
2209 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2210 const struct fm10k_msg_data *msg_data)
2212 DEBUGFUNC("fm10k_sm_mbx_init");
2213 UNREFERENCED_1PARAMETER(hw);
2215 mbx->mbx_reg = FM10K_GMBX;
2216 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2218 /* start out in closed state */
2219 mbx->state = FM10K_STATE_CLOSED;
2221 /* validate layout of handlers before assigning them */
2222 if (fm10k_mbx_validate_handlers(msg_data))
2223 return FM10K_ERR_PARAM;
2225 /* initialize the message handlers */
2226 mbx->msg_data = msg_data;
2228 /* start mailbox as timed out and let the reset_hw call
2229 * set the timeout value to begin communications
2232 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2234 /* Split buffer for use by Tx/Rx FIFOs */
2235 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2236 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2238 /* initialize the FIFOs, sizes are in 4 byte increments */
2239 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2240 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2241 FM10K_MBX_RX_BUFFER_SIZE);
2243 /* initialize function pointers */
2244 mbx->ops.connect = fm10k_sm_mbx_connect;
2245 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2246 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2247 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2248 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2249 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2250 mbx->ops.process = fm10k_sm_mbx_process;
2251 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2253 return FM10K_SUCCESS;