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 head 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 head 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");
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 * @mbx: pointer to mailbox
358 * This function will take a section of the Tx FIFO and copy it into the
359 * mailbox memory. The offset in mbmem is based on the lower bits of the
360 * tail and len determines the length to copy.
362 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
363 struct fm10k_mbx_info *mbx)
365 struct fm10k_mbx_fifo *fifo = &mbx->tx;
366 u32 mbmem = mbx->mbmem_reg;
367 u32 *head = fifo->buffer;
368 u16 end, len, tail, mask;
370 DEBUGFUNC("fm10k_mbx_write_copy");
375 /* determine data length and mbmem tail index */
376 mask = mbx->mbmem_len - 1;
378 tail = fm10k_mbx_tail_sub(mbx, len);
382 /* determine offset in the ring */
383 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
386 /* memory barrier to guarantee data is ready to be read */
389 /* Copy message from Tx FIFO */
390 for (end = fifo->size - end; len; head = fifo->buffer) {
392 /* adjust tail to match offset for FIFO */
397 mbx->tx_mbmem_pulled++;
399 /* write message to hardware FIFO */
400 FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
401 } while (--len && --end);
406 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
407 * @hw: pointer to hardware structure
408 * @mbx: pointer to mailbox
409 * @head: acknowledgement number last received
411 * This function will push the tail index forward based on the remote
412 * head index. It will then pull up to mbmem_len DWORDs off of the
413 * head of the FIFO and will place it in the MBMEM registers
414 * associated with the mailbox.
416 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
417 struct fm10k_mbx_info *mbx, u16 head)
419 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
420 struct fm10k_mbx_fifo *fifo = &mbx->tx;
422 /* update number of bytes pulled and update bytes in transit */
423 mbx->pulled += mbx->tail_len - ack;
425 /* determine length of data to pull, reserve space for mbmem header */
426 mbmem_len = mbx->mbmem_len - 1;
427 len = fm10k_fifo_used(fifo) - mbx->pulled;
431 /* update tail and record number of bytes in transit */
432 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
435 /* drop pulled messages from the FIFO */
436 for (len = fm10k_fifo_head_len(fifo);
437 len && (mbx->pulled >= len);
438 len = fm10k_fifo_head_len(fifo)) {
439 mbx->pulled -= fm10k_fifo_head_drop(fifo);
441 mbx->tx_dwords += len;
444 /* Copy message out from the Tx FIFO */
445 fm10k_mbx_write_copy(hw, mbx);
449 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
450 * @hw: pointer to hardware structure
451 * @mbx: pointer to mailbox
453 * This function will take a section of the mailbox memory and copy it
454 * into the Rx FIFO. The offset is based on the lower bits of the
455 * head and len determines the length to copy.
457 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
458 struct fm10k_mbx_info *mbx)
460 struct fm10k_mbx_fifo *fifo = &mbx->rx;
461 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
462 u32 *tail = fifo->buffer;
465 DEBUGFUNC("fm10k_mbx_read_copy");
467 /* determine data length and mbmem head index */
469 head = fm10k_mbx_head_sub(mbx, len);
470 if (head >= mbx->mbmem_len)
473 /* determine offset in the ring */
474 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
477 /* Copy message into Rx FIFO */
478 for (end = fifo->size - end; len; tail = fifo->buffer) {
480 /* adjust head to match offset for FIFO */
481 head &= mbx->mbmem_len - 1;
485 mbx->rx_mbmem_pushed++;
487 /* read message from hardware FIFO */
488 *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
489 } while (--len && --end);
492 /* memory barrier to guarantee FIFO is written before tail update */
497 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
498 * @hw: pointer to hardware structure
499 * @mbx: pointer to mailbox
500 * @tail: tail index of message
502 * This function will first validate the tail index and size for the
503 * incoming message. It then updates the acknowledgment number and
504 * copies the data into the FIFO. It will return the number of messages
505 * dequeued on success and a negative value on error.
507 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
508 struct fm10k_mbx_info *mbx,
511 struct fm10k_mbx_fifo *fifo = &mbx->rx;
512 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
514 DEBUGFUNC("fm10k_mbx_push_tail");
516 /* determine length of data to push */
517 len = fm10k_fifo_unused(fifo) - mbx->pushed;
521 /* update head and record bytes received */
522 mbx->head = fm10k_mbx_head_add(mbx, len);
525 /* nothing to do if there is no data */
527 return FM10K_SUCCESS;
529 /* Copy msg into Rx FIFO */
530 fm10k_mbx_read_copy(hw, mbx);
532 /* determine if there are any invalid lengths in message */
533 if (fm10k_mbx_validate_msg_size(mbx, len))
534 return FM10K_MBX_ERR_SIZE;
539 /* flush any completed messages */
540 for (len = fm10k_mbx_pushed_tail_len(mbx);
541 len && (mbx->pushed >= len);
542 len = fm10k_mbx_pushed_tail_len(mbx)) {
546 mbx->rx_dwords += len;
549 return FM10K_SUCCESS;
552 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
553 static const u16 fm10k_crc_16b_table[256] = {
554 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
555 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
556 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
557 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
558 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
559 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
560 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
561 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
562 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
563 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
564 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
565 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
566 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
567 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
568 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
569 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
570 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
571 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
572 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
573 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
574 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
575 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
576 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
577 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
578 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
579 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
580 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
581 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
582 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
583 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
584 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
585 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
588 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
589 * @data: pointer to data to process
590 * @seed: seed value for CRC
591 * @len: length measured in 16 bits words
593 * This function will generate a CRC based on the polynomial 0xAC9A and
594 * whatever value is stored in the seed variable. Note that this
595 * value inverts the local seed and the result in order to capture all
596 * leading and trailing zeros.
598 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
604 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
605 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
610 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
611 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
618 * fm10k_fifo_crc - generate a CRC based off of FIFO data
619 * @fifo: pointer to FIFO
620 * @offset: offset point for start of FIFO
621 * @len: number of DWORDS words to process
622 * @seed: seed value for CRC
624 * This function generates a CRC for some region of the FIFO
626 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
629 u32 *data = fifo->buffer + offset;
631 /* track when we should cross the end of the FIFO */
632 offset = fifo->size - offset;
634 /* if we are in 2 blocks process the end of the FIFO first */
636 seed = fm10k_crc_16b(data, seed, offset * 2);
641 /* process any remaining bits */
642 return fm10k_crc_16b(data, seed, len * 2);
646 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
647 * @mbx: pointer to mailbox
648 * @head: head index provided by remote mailbox
650 * This function will generate the CRC for all data from the end of the
651 * last head update to the current one. It uses the result of the
652 * previous CRC as the seed for this update. The result is stored in
655 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
657 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
659 /* determine the offset for the start of the region to be pulled */
660 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
662 /* update local CRC to include all of the pulled data */
663 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
667 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
668 * @mbx: pointer to mailbox
670 * This function will take all data that has been provided from the remote
671 * end and generate a CRC for it. This is stored in mbx->remote. The
672 * CRC for the header is then computed and if the result is non-zero this
673 * is an error and we signal an error dropping all data and resetting the
676 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
678 struct fm10k_mbx_fifo *fifo = &mbx->rx;
679 u16 len = mbx->head_len;
680 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
683 /* update the remote CRC if new data has been received */
685 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
687 /* process the full header as we have to validate the CRC */
688 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
690 /* notify other end if we have a problem */
691 return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
695 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
696 * @mbx: pointer to mailbox
698 * This function returns true if there is a message in the Rx FIFO to dequeue.
700 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
702 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
704 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
708 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
709 * @mbx: pointer to mailbox
710 * @len: verify free space is >= this value
712 * This function returns true if the mailbox is in a state ready to transmit.
714 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
716 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
718 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
722 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
723 * @mbx: pointer to mailbox
725 * This function returns true if the Tx FIFO is empty.
727 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
729 return fm10k_fifo_empty(&mbx->tx);
733 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
734 * @hw: pointer to hardware structure
735 * @mbx: pointer to mailbox
737 * This function dequeues messages and hands them off to the tlv parser.
738 * It will return the number of messages processed when called.
740 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
741 struct fm10k_mbx_info *mbx)
743 struct fm10k_mbx_fifo *fifo = &mbx->rx;
747 /* parse Rx messages out of the Rx FIFO to empty it */
748 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
749 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
754 fm10k_fifo_head_drop(fifo);
757 /* shift remaining bytes back to start of FIFO */
758 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
760 /* shift head and tail based on the memory we moved */
761 fifo->tail -= fifo->head;
768 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
769 * @hw: pointer to hardware structure
770 * @mbx: pointer to mailbox
771 * @msg: message array to read
773 * This function enqueues a message up to the size specified by the length
774 * contained in the first DWORD of the message and will place at the tail
775 * of the FIFO. It will return 0 on success, or a negative value on error.
777 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
778 struct fm10k_mbx_info *mbx, const u32 *msg)
780 u32 countdown = mbx->timeout;
783 switch (mbx->state) {
784 case FM10K_STATE_CLOSED:
785 case FM10K_STATE_DISCONNECT:
786 return FM10K_MBX_ERR_NO_MBX;
791 /* enqueue the message on the Tx FIFO */
792 err = fm10k_fifo_enqueue(&mbx->tx, msg);
794 /* if it failed give the FIFO a chance to drain */
795 while (err && countdown) {
797 usec_delay(mbx->usec_delay);
798 mbx->ops.process(hw, mbx);
799 err = fm10k_fifo_enqueue(&mbx->tx, msg);
802 /* if we failed treat the error */
808 /* begin processing message, ignore errors as this is just meant
809 * to start the mailbox flow so we are not concerned if there
810 * is a bad error, or the mailbox is already busy with a request
813 mbx->ops.process(hw, mbx);
815 return FM10K_SUCCESS;
819 * fm10k_mbx_read - Copies the mbmem to local message buffer
820 * @hw: pointer to hardware structure
821 * @mbx: pointer to mailbox
823 * This function copies the message from the mbmem to the message array
825 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
827 DEBUGFUNC("fm10k_mbx_read");
829 /* only allow one reader in here at a time */
831 return FM10K_MBX_ERR_BUSY;
833 /* read to capture initial interrupt bits */
834 if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
835 mbx->mbx_lock = FM10K_MBX_ACK;
837 /* write back interrupt bits to clear */
838 FM10K_WRITE_MBX(hw, mbx->mbx_reg,
839 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
841 /* read remote header */
842 mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
844 return FM10K_SUCCESS;
848 * fm10k_mbx_write - Copies the local message buffer to mbmem
849 * @hw: pointer to hardware structure
850 * @mbx: pointer to mailbox
852 * This function copies the message from the the message array to mbmem
854 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
856 u32 mbmem = mbx->mbmem_reg;
858 DEBUGFUNC("fm10k_mbx_write");
860 /* write new msg header to notify recipient of change */
861 FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
863 /* write mailbox to send interrupt */
865 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
867 /* we no longer are using the header so free it */
873 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
874 * @mbx: pointer to mailbox
876 * This function returns a connection mailbox header
878 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
880 mbx->mbx_lock |= FM10K_MBX_REQ;
882 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
883 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
884 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
888 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
889 * @mbx: pointer to mailbox
891 * This function returns a data mailbox header
893 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
895 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
896 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
897 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
898 struct fm10k_mbx_fifo *fifo = &mbx->tx;
902 mbx->mbx_lock |= FM10K_MBX_REQ;
904 /* generate CRC for data in flight and header */
905 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
906 mbx->tail_len, mbx->local);
907 crc = fm10k_crc_16b(&hdr, crc, 1);
909 /* load header to memory to be written */
910 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
914 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
915 * @mbx: pointer to mailbox
917 * This function returns a disconnect mailbox header
919 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
921 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
922 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
923 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
924 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
926 mbx->mbx_lock |= FM10K_MBX_ACK;
928 /* load header to memory to be written */
929 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
933 * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mbox hdr
934 * @mbx: pointer to mailbox
936 * This function creates a fake disconnect header for loading into remote
937 * mailbox header. The primary purpose is to prevent errors on immediate
938 * start up after mbx->connect.
940 STATIC void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
942 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
943 FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
944 FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
945 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
947 mbx->mbx_lock |= FM10K_MBX_ACK;
949 /* load header to memory to be written */
950 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
954 * fm10k_mbx_create_error_msg - Generate a error message
955 * @mbx: pointer to mailbox
956 * @err: local error encountered
958 * This function will interpret the error provided by err, and based on
959 * that it may shift the message by 1 DWORD and then place an error header
960 * at the start of the message.
962 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
964 /* only generate an error message for these types */
966 case FM10K_MBX_ERR_TAIL:
967 case FM10K_MBX_ERR_HEAD:
968 case FM10K_MBX_ERR_TYPE:
969 case FM10K_MBX_ERR_SIZE:
970 case FM10K_MBX_ERR_RSVD0:
971 case FM10K_MBX_ERR_CRC:
977 mbx->mbx_lock |= FM10K_MBX_REQ;
979 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
980 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
981 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
985 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
986 * @mbx: pointer to mailbox
987 * @msg: message array to read
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 * @mbx: pointer to mailbox
1054 * @head: acknowledgement number
1056 * This function will generate an outgoing message based on the current
1057 * mailbox state and the remote fifo head. It will return the length
1058 * of the outgoing message excluding header on success, and a negative value
1061 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1062 struct fm10k_mbx_info *mbx, u16 head)
1064 switch (mbx->state) {
1065 case FM10K_STATE_OPEN:
1066 case FM10K_STATE_DISCONNECT:
1067 /* update our checksum for the outgoing data */
1068 fm10k_mbx_update_local_crc(mbx, head);
1070 /* as long as other end recognizes us keep sending data */
1071 fm10k_mbx_pull_head(hw, mbx, head);
1073 /* generate new header based on data */
1074 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1075 fm10k_mbx_create_data_hdr(mbx);
1077 fm10k_mbx_create_disconnect_hdr(mbx);
1079 case FM10K_STATE_CONNECT:
1080 /* send disconnect even if we aren't connected */
1081 fm10k_mbx_create_connect_hdr(mbx);
1083 case FM10K_STATE_CLOSED:
1084 /* generate new header based on data */
1085 fm10k_mbx_create_disconnect_hdr(mbx);
1090 return FM10K_SUCCESS;
1094 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1095 * @mbx: pointer to mailbox
1097 * This function will reset all internal pointers so any work in progress
1098 * is dropped. This call should occur every time we transition from the
1099 * open state to the connect state.
1101 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1105 /* reset our outgoing max size back to Rx limits */
1106 mbx->max_size = mbx->rx.size - 1;
1108 /* update mbx->pulled to account for tail_len and ack */
1109 head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1110 ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1111 mbx->pulled += mbx->tail_len - ack;
1113 /* now drop any messages which have started or finished transmitting */
1114 while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1115 len = fm10k_fifo_head_drop(&mbx->tx);
1117 if (mbx->pulled >= len)
1123 /* just do a quick resysnc to start of message */
1133 * fm10k_mbx_update_max_size - Update the max_size and drop large messages
1134 * @mbx: pointer to mailbox
1135 * @size: new value for max_size
1137 * This function updates the max_size value and drops any outgoing messages
1138 * at the head of the Tx FIFO if they are larger than max_size. It does not
1139 * drop all messages, as this is too difficult to parse and remove them from
1140 * the FIFO. Instead, rely on the checking to ensure that messages larger
1141 * than max_size aren't pushed into the memory buffer.
1143 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1147 DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1149 mbx->max_size = size;
1151 /* flush any oversized messages from the queue */
1152 for (len = fm10k_fifo_head_len(&mbx->tx);
1154 len = fm10k_fifo_head_len(&mbx->tx)) {
1155 fm10k_fifo_head_drop(&mbx->tx);
1161 * fm10k_mbx_connect_reset - Reset following request for reset
1162 * @mbx: pointer to mailbox
1164 * This function resets the mailbox to either a disconnected state
1165 * or a connect state depending on the current mailbox state
1167 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1169 /* just do a quick resysnc to start of frame */
1170 fm10k_mbx_reset_work(mbx);
1172 /* reset CRC seeds */
1173 mbx->local = FM10K_MBX_CRC_SEED;
1174 mbx->remote = FM10K_MBX_CRC_SEED;
1176 /* we cannot exit connect until the size is good */
1177 if (mbx->state == FM10K_STATE_OPEN)
1178 mbx->state = FM10K_STATE_CONNECT;
1180 mbx->state = FM10K_STATE_CLOSED;
1184 * fm10k_mbx_process_connect - Process connect header
1185 * @mbx: pointer to mailbox
1186 * @msg: message array to process
1188 * This function will read an incoming connect header and reply with the
1189 * appropriate message. It will return a value indicating the number of
1190 * data DWORDs on success, or will return a negative value on failure.
1192 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1193 struct fm10k_mbx_info *mbx)
1195 const enum fm10k_mbx_state state = mbx->state;
1196 const u32 *hdr = &mbx->mbx_hdr;
1199 /* we will need to pull all of the fields for verification */
1200 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1201 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1204 case FM10K_STATE_DISCONNECT:
1205 case FM10K_STATE_OPEN:
1206 /* reset any in-progress work */
1207 fm10k_mbx_connect_reset(mbx);
1209 case FM10K_STATE_CONNECT:
1210 /* we cannot exit connect until the size is good */
1211 if (size > mbx->rx.size) {
1212 mbx->max_size = mbx->rx.size - 1;
1214 /* record the remote system requesting connection */
1215 mbx->state = FM10K_STATE_OPEN;
1217 fm10k_mbx_update_max_size(mbx, size);
1224 /* align our tail index to remote head index */
1227 return fm10k_mbx_create_reply(hw, mbx, head);
1231 * fm10k_mbx_process_data - Process data header
1232 * @mbx: pointer to mailbox
1234 * This function will read an incoming data header and reply with the
1235 * appropriate message. It will return a value indicating the number of
1236 * data DWORDs on success, or will return a negative value on failure.
1238 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1239 struct fm10k_mbx_info *mbx)
1241 const u32 *hdr = &mbx->mbx_hdr;
1245 DEBUGFUNC("fm10k_mbx_process_data");
1247 /* we will need to pull all of the fields for verification */
1248 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1249 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1251 /* if we are in connect just update our data and go */
1252 if (mbx->state == FM10K_STATE_CONNECT) {
1254 mbx->state = FM10K_STATE_OPEN;
1257 /* abort on message size errors */
1258 err = fm10k_mbx_push_tail(hw, mbx, tail);
1262 /* verify the checksum on the incoming data */
1263 err = fm10k_mbx_verify_remote_crc(mbx);
1267 /* process messages if we have received any */
1268 fm10k_mbx_dequeue_rx(hw, mbx);
1270 return fm10k_mbx_create_reply(hw, mbx, head);
1274 * fm10k_mbx_process_disconnect - Process disconnect header
1275 * @mbx: pointer to mailbox
1277 * This function will read an incoming disconnect header and reply with the
1278 * appropriate message. It will return a value indicating the number of
1279 * data DWORDs on success, or will return a negative value on failure.
1281 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1282 struct fm10k_mbx_info *mbx)
1284 const enum fm10k_mbx_state state = mbx->state;
1285 const u32 *hdr = &mbx->mbx_hdr;
1289 /* we will need to pull the header field for verification */
1290 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1292 /* We should not be receiving disconnect if Rx is incomplete */
1294 return FM10K_MBX_ERR_TAIL;
1296 /* we have already verified mbx->head == tail so we know this is 0 */
1299 /* verify the checksum on the incoming header is correct */
1300 err = fm10k_mbx_verify_remote_crc(mbx);
1305 case FM10K_STATE_DISCONNECT:
1306 case FM10K_STATE_OPEN:
1307 /* state doesn't change if we still have work to do */
1308 if (!fm10k_mbx_tx_complete(mbx))
1311 /* verify the head indicates we completed all transmits */
1312 if (head != mbx->tail)
1313 return FM10K_MBX_ERR_HEAD;
1315 /* reset any in-progress work */
1316 fm10k_mbx_connect_reset(mbx);
1322 return fm10k_mbx_create_reply(hw, mbx, head);
1326 * fm10k_mbx_process_error - Process error header
1327 * @mbx: pointer to mailbox
1329 * This function will read an incoming error header and reply with the
1330 * appropriate message. It will return a value indicating the number of
1331 * data DWORDs on success, or will return a negative value on failure.
1333 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1334 struct fm10k_mbx_info *mbx)
1336 const u32 *hdr = &mbx->mbx_hdr;
1339 /* we will need to pull all of the fields for verification */
1340 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1342 switch (mbx->state) {
1343 case FM10K_STATE_OPEN:
1344 case FM10K_STATE_DISCONNECT:
1345 /* flush any uncompleted work */
1346 fm10k_mbx_reset_work(mbx);
1348 /* reset CRC seeds */
1349 mbx->local = FM10K_MBX_CRC_SEED;
1350 mbx->remote = FM10K_MBX_CRC_SEED;
1352 /* reset tail index and size to prepare for reconnect */
1355 /* if open then reset max_size and go back to connect */
1356 if (mbx->state == FM10K_STATE_OPEN) {
1357 mbx->state = FM10K_STATE_CONNECT;
1361 /* send a connect message to get data flowing again */
1362 fm10k_mbx_create_connect_hdr(mbx);
1363 return FM10K_SUCCESS;
1368 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1372 * fm10k_mbx_process - Process mailbox interrupt
1373 * @hw: pointer to hardware structure
1374 * @mbx: pointer to mailbox
1376 * This function will process incoming mailbox events and generate mailbox
1377 * replies. It will return a value indicating the number of DWORDs
1378 * transmitted excluding header on success or a negative value on error.
1380 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1381 struct fm10k_mbx_info *mbx)
1385 DEBUGFUNC("fm10k_mbx_process");
1387 /* we do not read mailbox if closed */
1388 if (mbx->state == FM10K_STATE_CLOSED)
1389 return FM10K_SUCCESS;
1391 /* copy data from mailbox */
1392 err = fm10k_mbx_read(hw, mbx);
1396 /* validate type, source, and destination */
1397 err = fm10k_mbx_validate_msg_hdr(mbx);
1401 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1402 case FM10K_MSG_CONNECT:
1403 err = fm10k_mbx_process_connect(hw, mbx);
1405 case FM10K_MSG_DATA:
1406 err = fm10k_mbx_process_data(hw, mbx);
1408 case FM10K_MSG_DISCONNECT:
1409 err = fm10k_mbx_process_disconnect(hw, mbx);
1411 case FM10K_MSG_ERROR:
1412 err = fm10k_mbx_process_error(hw, mbx);
1415 err = FM10K_MBX_ERR_TYPE;
1420 /* notify partner of errors on our end */
1422 fm10k_mbx_create_error_msg(mbx, err);
1424 /* copy data from mailbox */
1425 fm10k_mbx_write(hw, mbx);
1431 * fm10k_mbx_disconnect - Shutdown mailbox connection
1432 * @hw: pointer to hardware structure
1433 * @mbx: pointer to mailbox
1435 * This function will shut down the mailbox. It places the mailbox first
1436 * in the disconnect state, it then allows up to a predefined timeout for
1437 * the mailbox to transition to close on its own. If this does not occur
1438 * then the mailbox will be forced into the closed state.
1440 * Any mailbox transactions not completed before calling this function
1441 * are not guaranteed to complete and may be dropped.
1443 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1444 struct fm10k_mbx_info *mbx)
1446 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1448 DEBUGFUNC("fm10k_mbx_disconnect");
1450 /* Place mbx in ready to disconnect state */
1451 mbx->state = FM10K_STATE_DISCONNECT;
1453 /* trigger interrupt to start shutdown process */
1454 FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1455 FM10K_MBX_INTERRUPT_DISABLE);
1457 usec_delay(FM10K_MBX_POLL_DELAY);
1458 mbx->ops.process(hw, mbx);
1459 timeout -= FM10K_MBX_POLL_DELAY;
1460 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1462 /* in case we didn't close, just force the mailbox into shutdown and
1463 * drop all left over messages in the FIFO.
1465 fm10k_mbx_connect_reset(mbx);
1466 fm10k_fifo_drop_all(&mbx->tx);
1468 FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1472 * fm10k_mbx_connect - Start mailbox connection
1473 * @hw: pointer to hardware structure
1474 * @mbx: pointer to mailbox
1476 * This function will initiate a mailbox connection. It will populate the
1477 * mailbox with a broadcast connect message and then initialize the lock.
1478 * This is safe since the connect message is a single DWORD so the mailbox
1479 * transaction is guaranteed to be atomic.
1481 * This function will return an error if the mailbox has not been initiated
1482 * or is currently in use.
1484 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1486 DEBUGFUNC("fm10k_mbx_connect");
1488 /* we cannot connect an uninitialized mailbox */
1489 if (!mbx->rx.buffer)
1490 return FM10K_MBX_ERR_NO_SPACE;
1492 /* we cannot connect an already connected mailbox */
1493 if (mbx->state != FM10K_STATE_CLOSED)
1494 return FM10K_MBX_ERR_BUSY;
1496 /* mailbox timeout can now become active */
1497 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1499 /* Place mbx in ready to connect state */
1500 mbx->state = FM10K_STATE_CONNECT;
1502 fm10k_mbx_reset_work(mbx);
1504 fm10k_mbx_create_fake_disconnect_hdr(mbx);
1505 FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1507 /* enable interrupt and notify other party of new message */
1508 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1509 FM10K_MBX_INTERRUPT_ENABLE;
1511 /* generate and load connect header into mailbox */
1512 fm10k_mbx_create_connect_hdr(mbx);
1513 fm10k_mbx_write(hw, mbx);
1515 return FM10K_SUCCESS;
1519 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1520 * @msg_data: handlers for mailbox events
1522 * This function validates the layout of the message parsing data. This
1523 * should be mostly static, but it is important to catch any errors that
1524 * are made when constructing the parsers.
1526 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1528 const struct fm10k_tlv_attr *attr;
1531 DEBUGFUNC("fm10k_mbx_validate_handlers");
1533 /* Allow NULL mailboxes that transmit but don't receive */
1535 return FM10K_SUCCESS;
1537 while (msg_data->id != FM10K_TLV_ERROR) {
1538 /* all messages should have a function handler */
1539 if (!msg_data->func)
1540 return FM10K_ERR_PARAM;
1542 /* parser is optional */
1543 attr = msg_data->attr;
1545 while (attr->id != FM10K_TLV_ERROR) {
1548 /* ID should always be increasing */
1550 return FM10K_ERR_PARAM;
1551 /* ID should fit in results array */
1552 if (id >= FM10K_TLV_RESULTS_MAX)
1553 return FM10K_ERR_PARAM;
1556 /* verify terminator is in the list */
1557 if (attr->id != FM10K_TLV_ERROR)
1558 return FM10K_ERR_PARAM;
1563 /* ID should always be increasing */
1564 if (id >= msg_data->id)
1565 return FM10K_ERR_PARAM;
1568 /* verify terminator is in the list */
1569 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1570 return FM10K_ERR_PARAM;
1572 return FM10K_SUCCESS;
1576 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1577 * @mbx: pointer to mailbox
1578 * @msg_data: handlers for mailbox events
1580 * This function associates a set of message handling ops with a mailbox.
1582 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1583 const struct fm10k_msg_data *msg_data)
1585 DEBUGFUNC("fm10k_mbx_register_handlers");
1587 /* validate layout of handlers before assigning them */
1588 if (fm10k_mbx_validate_handlers(msg_data))
1589 return FM10K_ERR_PARAM;
1591 /* initialize the message handlers */
1592 mbx->msg_data = msg_data;
1594 return FM10K_SUCCESS;
1598 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1599 * @hw: pointer to hardware structure
1600 * @mbx: pointer to mailbox
1601 * @msg_data: handlers for mailbox events
1602 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1604 * This function initializes the mailbox for use. It will split the
1605 * buffer provided an use that th populate both the Tx and Rx FIFO by
1606 * evenly splitting it. In order to allow for easy masking of head/tail
1607 * the value reported in size must be a power of 2 and is reported in
1608 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1611 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1612 const struct fm10k_msg_data *msg_data, u8 id)
1614 DEBUGFUNC("fm10k_pfvf_mbx_init");
1616 /* initialize registers */
1617 switch (hw->mac.type) {
1619 mbx->mbx_reg = FM10K_VFMBX;
1620 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1623 /* there are only 64 VF <-> PF mailboxes */
1625 mbx->mbx_reg = FM10K_MBX(id);
1626 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1631 return FM10K_MBX_ERR_NO_MBX;
1634 /* start out in closed state */
1635 mbx->state = FM10K_STATE_CLOSED;
1637 /* validate layout of handlers before assigning them */
1638 if (fm10k_mbx_validate_handlers(msg_data))
1639 return FM10K_ERR_PARAM;
1641 /* initialize the message handlers */
1642 mbx->msg_data = msg_data;
1644 /* start mailbox as timed out and let the reset_hw call
1645 * set the timeout value to begin communications
1648 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1650 /* initialize tail and head */
1654 /* initialize CRC seeds */
1655 mbx->local = FM10K_MBX_CRC_SEED;
1656 mbx->remote = FM10K_MBX_CRC_SEED;
1658 /* Split buffer for use by Tx/Rx FIFOs */
1659 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1660 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1662 /* initialize the FIFOs, sizes are in 4 byte increments */
1663 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1664 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1665 FM10K_MBX_RX_BUFFER_SIZE);
1667 /* initialize function pointers */
1668 mbx->ops.connect = fm10k_mbx_connect;
1669 mbx->ops.disconnect = fm10k_mbx_disconnect;
1670 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1671 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1672 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1673 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1674 mbx->ops.process = fm10k_mbx_process;
1675 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1677 return FM10K_SUCCESS;
1681 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1682 * @mbx: pointer to mailbox
1684 * This function returns a connection mailbox header
1686 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1689 mbx->mbx_lock |= FM10K_MBX_REQ;
1691 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1692 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1693 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1697 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1698 * @mbx: pointer to mailbox
1699 * @err: error flags to report if any
1701 * This function returns a connection mailbox header
1703 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1706 mbx->mbx_lock |= FM10K_MBX_REQ;
1708 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1709 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1710 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1711 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1715 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1716 * @mbx: pointer to mailbox
1718 * This function resets the mailbox to a just connected state
1720 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1722 /* flush any uncompleted work */
1723 fm10k_mbx_reset_work(mbx);
1725 /* set local version to max and remote version to 0 */
1726 mbx->local = FM10K_SM_MBX_VERSION;
1729 /* initialize tail and head */
1733 /* reset state back to connect */
1734 mbx->state = FM10K_STATE_CONNECT;
1738 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1739 * @hw: pointer to hardware structure
1740 * @mbx: pointer to mailbox
1742 * This function will initiate a mailbox connection with the switch
1743 * manager. To do this it will first disconnect the mailbox, and then
1744 * reconnect it in order to complete a reset of the mailbox.
1746 * This function will return an error if the mailbox has not been initiated
1747 * or is currently in use.
1749 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1751 DEBUGFUNC("fm10k_mbx_connect");
1753 /* we cannot connect an uninitialized mailbox */
1754 if (!mbx->rx.buffer)
1755 return FM10K_MBX_ERR_NO_SPACE;
1757 /* we cannot connect an already connected mailbox */
1758 if (mbx->state != FM10K_STATE_CLOSED)
1759 return FM10K_MBX_ERR_BUSY;
1761 /* mailbox timeout can now become active */
1762 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1764 /* Place mbx in ready to connect state */
1765 mbx->state = FM10K_STATE_CONNECT;
1766 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1768 /* reset interface back to connect */
1769 fm10k_sm_mbx_connect_reset(mbx);
1771 /* enable interrupt and notify other party of new message */
1772 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1773 FM10K_MBX_INTERRUPT_ENABLE;
1775 /* generate and load connect header into mailbox */
1776 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1777 fm10k_mbx_write(hw, mbx);
1779 /* enable interrupt and notify other party of new message */
1781 return FM10K_SUCCESS;
1785 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1786 * @hw: pointer to hardware structure
1787 * @mbx: pointer to mailbox
1789 * This function will shut down the mailbox. It places the mailbox first
1790 * in the disconnect state, it then allows up to a predefined timeout for
1791 * the mailbox to transition to close on its own. If this does not occur
1792 * then the mailbox will be forced into the closed state.
1794 * Any mailbox transactions not completed before calling this function
1795 * are not guaranteed to complete and may be dropped.
1797 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1798 struct fm10k_mbx_info *mbx)
1800 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1802 DEBUGFUNC("fm10k_sm_mbx_disconnect");
1804 /* Place mbx in ready to disconnect state */
1805 mbx->state = FM10K_STATE_DISCONNECT;
1807 /* trigger interrupt to start shutdown process */
1808 FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1809 FM10K_MBX_INTERRUPT_DISABLE);
1811 usec_delay(FM10K_MBX_POLL_DELAY);
1812 mbx->ops.process(hw, mbx);
1813 timeout -= FM10K_MBX_POLL_DELAY;
1814 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1816 /* in case we didn't close just force the mailbox into shutdown */
1817 mbx->state = FM10K_STATE_CLOSED;
1819 fm10k_mbx_reset_work(mbx);
1820 fm10k_fifo_drop_all(&mbx->tx);
1822 FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1826 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1827 * @mbx: pointer to mailbox
1829 * This function will parse up the fields in the mailbox header and return
1830 * an error if the header contains any of a number of invalid configurations
1831 * including unrecognized offsets or version numbers.
1833 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1835 const u32 *hdr = &mbx->mbx_hdr;
1836 u16 tail, head, ver;
1838 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1840 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1841 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1842 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1847 case FM10K_SM_MBX_VERSION:
1848 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1849 return FM10K_MBX_ERR_HEAD;
1850 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1851 return FM10K_MBX_ERR_TAIL;
1852 if (mbx->tail < head)
1853 head += mbx->mbmem_len - 1;
1854 if (tail < mbx->head)
1855 tail += mbx->mbmem_len - 1;
1856 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1857 return FM10K_MBX_ERR_HEAD;
1858 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1860 return FM10K_MBX_ERR_TAIL;
1862 return FM10K_MBX_ERR_SRC;
1865 return FM10K_SUCCESS;
1869 * fm10k_sm_mbx_process_error - Process header with error flag set
1870 * @mbx: pointer to mailbox
1872 * This function is meant to respond to a request where the error flag
1873 * is set. As a result we will terminate a connection if one is present
1874 * and fall back into the reset state with a connection header of version
1877 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1879 const enum fm10k_mbx_state state = mbx->state;
1882 case FM10K_STATE_DISCONNECT:
1883 /* if there is an error just disconnect */
1886 case FM10K_STATE_OPEN:
1887 /* flush any uncompleted work */
1888 fm10k_sm_mbx_connect_reset(mbx);
1890 case FM10K_STATE_CONNECT:
1891 /* try connnecting at lower version */
1893 while (mbx->local > 1)
1902 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1906 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1907 * @mbx: pointer to mailbox
1908 * @err: local error encountered
1910 * This function will interpret the error provided by err, and based on
1911 * that it may set the error bit in the local message header
1913 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1915 /* only generate an error message for these types */
1917 case FM10K_MBX_ERR_TAIL:
1918 case FM10K_MBX_ERR_HEAD:
1919 case FM10K_MBX_ERR_SRC:
1920 case FM10K_MBX_ERR_SIZE:
1921 case FM10K_MBX_ERR_RSVD0:
1927 /* process it as though we received an error, and send error reply */
1928 fm10k_sm_mbx_process_error(mbx);
1929 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1933 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1934 * @hw: pointer to hardware structure
1935 * @mbx: pointer to mailbox
1937 * This function will dequeue one message from the Rx switch manager mailbox
1938 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1940 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1941 struct fm10k_mbx_info *mbx,
1944 /* reduce length by 1 to convert to a mask */
1945 u16 mbmem_len = mbx->mbmem_len - 1;
1948 DEBUGFUNC("fm10k_sm_mbx_receive");
1950 /* push tail in front of head */
1951 if (tail < mbx->head)
1954 /* copy data to the Rx FIFO */
1955 err = fm10k_mbx_push_tail(hw, mbx, tail);
1959 /* process messages if we have received any */
1960 fm10k_mbx_dequeue_rx(hw, mbx);
1962 /* guarantee head aligns with the end of the last message */
1963 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1966 /* clear any extra bits left over since index adds 1 extra bit */
1967 if (mbx->head > mbmem_len)
1968 mbx->head -= mbmem_len;
1974 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1975 * @hw: pointer to hardware structure
1976 * @mbx: pointer to mailbox
1978 * This function will dequeue one message from the Tx mailbox FIFO and place
1979 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1981 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1982 struct fm10k_mbx_info *mbx, u16 head)
1984 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1985 /* reduce length by 1 to convert to a mask */
1986 u16 mbmem_len = mbx->mbmem_len - 1;
1987 u16 tail_len, len = 0;
1990 DEBUGFUNC("fm10k_sm_mbx_transmit");
1992 /* push head behind tail */
1993 if (mbx->tail < head)
1996 fm10k_mbx_pull_head(hw, mbx, head);
1998 /* determine msg aligned offset for end of buffer */
2000 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
2002 len += FM10K_TLV_DWORD_LEN(*msg);
2003 } while ((len <= mbx->tail_len) && (len < mbmem_len));
2005 /* guarantee we stop on a message boundary */
2006 if (mbx->tail_len > tail_len) {
2007 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
2008 mbx->tail_len = tail_len;
2011 /* clear any extra bits left over since index adds 1 extra bit */
2012 if (mbx->tail > mbmem_len)
2013 mbx->tail -= mbmem_len;
2017 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
2018 * @mbx: pointer to mailbox
2019 * @head: acknowledgement number
2021 * This function will generate an outgoing message based on the current
2022 * mailbox state and the remote fifo head. It will return the length
2023 * of the outgoing message excluding header on success, and a negative value
2026 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
2027 struct fm10k_mbx_info *mbx, u16 head)
2029 switch (mbx->state) {
2030 case FM10K_STATE_OPEN:
2031 case FM10K_STATE_DISCONNECT:
2032 /* flush out Tx data */
2033 fm10k_sm_mbx_transmit(hw, mbx, head);
2035 /* generate new header based on data */
2036 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
2037 fm10k_sm_mbx_create_data_hdr(mbx);
2040 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2043 case FM10K_STATE_CONNECT:
2044 case FM10K_STATE_CLOSED:
2045 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2053 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2054 * @hw: pointer to hardware structure
2055 * @mbx: pointer to mailbox
2057 * This function is meant to respond to a request where the version data
2058 * is set to 0. As such we will either terminate the connection or go
2059 * into the connect state in order to re-establish the connection. This
2060 * function can also be used to respond to an error as the connection
2061 * resetting would also be a means of dealing with errors.
2063 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2064 struct fm10k_mbx_info *mbx)
2066 const enum fm10k_mbx_state state = mbx->state;
2069 case FM10K_STATE_DISCONNECT:
2070 /* drop remote connections and disconnect */
2071 mbx->state = FM10K_STATE_CLOSED;
2075 case FM10K_STATE_OPEN:
2076 /* flush any incomplete work */
2077 fm10k_sm_mbx_connect_reset(mbx);
2079 case FM10K_STATE_CONNECT:
2080 /* Update remote value to match local value */
2081 mbx->remote = mbx->local;
2086 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2090 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2091 * @hw: pointer to hardware structure
2092 * @mbx: pointer to mailbox
2094 * This function is meant to process messages received when the remote
2095 * mailbox is active.
2097 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2098 struct fm10k_mbx_info *mbx)
2100 const u32 *hdr = &mbx->mbx_hdr;
2104 /* pull all fields needed for verification */
2105 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2106 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2108 /* if we are in connect and wanting version 1 then start up and go */
2109 if (mbx->state == FM10K_STATE_CONNECT) {
2112 if (mbx->remote != 1)
2113 return FM10K_MBX_ERR_SRC;
2115 mbx->state = FM10K_STATE_OPEN;
2119 /* abort on message size errors */
2120 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2124 /* continue until we have flushed the Rx FIFO */
2128 fm10k_sm_mbx_create_reply(hw, mbx, head);
2130 return FM10K_SUCCESS;
2134 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2135 * @hw: pointer to hardware structure
2136 * @mbx: pointer to mailbox
2138 * This function will process incoming mailbox events and generate mailbox
2139 * replies. It will return a value indicating the number of DWORDs
2140 * transmitted excluding header on success or a negative value on error.
2142 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2143 struct fm10k_mbx_info *mbx)
2147 DEBUGFUNC("fm10k_sm_mbx_process");
2149 /* we do not read mailbox if closed */
2150 if (mbx->state == FM10K_STATE_CLOSED)
2151 return FM10K_SUCCESS;
2153 /* retrieve data from switch manager */
2154 err = fm10k_mbx_read(hw, mbx);
2158 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2162 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2163 fm10k_sm_mbx_process_error(mbx);
2167 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2169 fm10k_sm_mbx_process_reset(hw, mbx);
2171 case FM10K_SM_MBX_VERSION:
2172 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2178 fm10k_sm_mbx_create_error_msg(mbx, err);
2180 /* report data to switch manager */
2181 fm10k_mbx_write(hw, mbx);
2187 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2188 * @hw: pointer to hardware structure
2189 * @mbx: pointer to mailbox
2190 * @msg_data: handlers for mailbox events
2192 * This function for now is used to stub out the PF/SM mailbox
2194 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2195 const struct fm10k_msg_data *msg_data)
2197 DEBUGFUNC("fm10k_sm_mbx_init");
2198 UNREFERENCED_1PARAMETER(hw);
2200 mbx->mbx_reg = FM10K_GMBX;
2201 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2203 /* start out in closed state */
2204 mbx->state = FM10K_STATE_CLOSED;
2206 /* validate layout of handlers before assigning them */
2207 if (fm10k_mbx_validate_handlers(msg_data))
2208 return FM10K_ERR_PARAM;
2210 /* initialize the message handlers */
2211 mbx->msg_data = msg_data;
2213 /* start mailbox as timed out and let the reset_hw call
2214 * set the timeout value to begin communications
2217 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2219 /* Split buffer for use by Tx/Rx FIFOs */
2220 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2221 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2223 /* initialize the FIFOs, sizes are in 4 byte increments */
2224 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2225 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2226 FM10K_MBX_RX_BUFFER_SIZE);
2228 /* initialize function pointers */
2229 mbx->ops.connect = fm10k_sm_mbx_connect;
2230 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2231 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2232 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2233 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2234 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2235 mbx->ops.process = fm10k_sm_mbx_process;
2236 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2238 return FM10K_SUCCESS;