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_mbx_index_len - Convert a head/tail index into a length value
143 * @mbx: pointer to mailbox
147 * This function takes the head and tail index and determines the length
148 * of the data indicated by this pair.
150 STATIC u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
152 u16 len = tail - head;
154 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
158 return len & ((mbx->mbmem_len << 1) - 1);
162 * fm10k_mbx_tail_add - Determine new tail value with added offset
163 * @mbx: pointer to mailbox
164 * @offset: length to add to head offset
166 * This function takes the local tail index and recomputes it for
167 * a given length added as an offset.
169 STATIC u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
171 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
173 /* add/sub 1 because we cannot have offset 0 or all 1s */
174 return (tail > mbx->tail) ? --tail : ++tail;
178 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
179 * @mbx: pointer to mailbox
180 * @offset: length to add to head offset
182 * This function takes the local tail index and recomputes it for
183 * a given length added as an offset.
185 STATIC u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
187 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
189 /* sub/add 1 because we cannot have offset 0 or all 1s */
190 return (tail < mbx->tail) ? ++tail : --tail;
194 * fm10k_mbx_head_add - Determine new head value with added offset
195 * @mbx: pointer to mailbox
196 * @offset: length to add to head offset
198 * This function takes the local head index and recomputes it for
199 * a given length added as an offset.
201 STATIC u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
203 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
205 /* add/sub 1 because we cannot have offset 0 or all 1s */
206 return (head > mbx->head) ? --head : ++head;
210 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
211 * @mbx: pointer to mailbox
212 * @offset: length to add to head offset
214 * This function takes the local head index and recomputes it for
215 * a given length added as an offset.
217 STATIC u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
219 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
221 /* sub/add 1 because we cannot have offset 0 or all 1s */
222 return (head < mbx->head) ? ++head : --head;
226 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
227 * @mbx: pointer to mailbox
229 * This function will return the length of the message currently being
230 * pushed onto the tail of the Rx queue.
232 STATIC u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
234 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
236 /* pushed tail is only valid if pushed is set */
240 return FM10K_TLV_DWORD_LEN(*tail);
244 * fm10k_fifo_write_copy - pulls data off of msg and places it in fifo
245 * @fifo: pointer to FIFO
246 * @msg: message array to populate
247 * @tail_offset: additional offset to add to tail pointer
248 * @len: length of FIFO to copy into message header
250 * This function will take a message and copy it into a section of the
251 * FIFO. In order to get something into a location other than just
252 * the tail you can use tail_offset to adjust the pointer.
254 STATIC void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
255 const u32 *msg, u16 tail_offset, u16 len)
257 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
258 u32 *tail = fifo->buffer + end;
260 /* track when we should cross the end of the FIFO */
261 end = fifo->size - end;
263 /* copy end of message before start of message */
265 memcpy(fifo->buffer, msg + end, (len - end) << 2);
269 /* Copy remaining message into Tx FIFO */
270 memcpy(tail, msg, end << 2);
274 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
275 * @fifo: pointer to FIFO
276 * @msg: message array to read
278 * This function enqueues a message up to the size specified by the length
279 * contained in the first DWORD of the message and will place at the tail
280 * of the FIFO. It will return 0 on success, or a negative value on error.
282 STATIC s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
284 u16 len = FM10K_TLV_DWORD_LEN(*msg);
286 DEBUGFUNC("fm10k_fifo_enqueue");
288 /* verify parameters */
289 if (len > fifo->size)
290 return FM10K_MBX_ERR_SIZE;
292 /* verify there is room for the message */
293 if (len > fm10k_fifo_unused(fifo))
294 return FM10K_MBX_ERR_NO_SPACE;
296 /* Copy message into FIFO */
297 fm10k_fifo_write_copy(fifo, msg, 0, len);
299 /* memory barrier to guarantee FIFO is written before tail update */
302 /* Update Tx FIFO tail */
305 return FM10K_SUCCESS;
309 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
310 * @mbx: pointer to mailbox
311 * @len: length of data pushed onto buffer
313 * This function analyzes the frame and will return a non-zero value when
314 * the start of a message larger than the mailbox is detected.
316 STATIC u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
318 struct fm10k_mbx_fifo *fifo = &mbx->rx;
319 u16 total_len = 0, msg_len;
322 DEBUGFUNC("fm10k_mbx_validate_msg");
324 /* length should include previous amounts pushed */
327 /* offset in message is based off of current message size */
329 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
330 msg_len = FM10K_TLV_DWORD_LEN(*msg);
331 total_len += msg_len;
332 } while (total_len < len);
334 /* message extends out of pushed section, but fits in FIFO */
335 if ((len < total_len) && (msg_len <= mbx->rx.size))
338 /* return length of invalid section */
339 return (len < total_len) ? len : (len - total_len);
343 * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
344 * @mbx: pointer to mailbox
346 * This function will take a section of the Tx FIFO and copy it into the
347 * mailbox memory. The offset in mbmem is based on the lower bits of the
348 * tail and len determines the length to copy.
350 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
351 struct fm10k_mbx_info *mbx)
353 struct fm10k_mbx_fifo *fifo = &mbx->tx;
354 u32 mbmem = mbx->mbmem_reg;
355 u32 *head = fifo->buffer;
356 u16 end, len, tail, mask;
358 DEBUGFUNC("fm10k_mbx_write_copy");
363 /* determine data length and mbmem tail index */
364 mask = mbx->mbmem_len - 1;
366 tail = fm10k_mbx_tail_sub(mbx, len);
370 /* determine offset in the ring */
371 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
374 /* memory barrier to guarantee data is ready to be read */
377 /* Copy message from Tx FIFO */
378 for (end = fifo->size - end; len; head = fifo->buffer) {
380 /* adjust tail to match offset for FIFO */
385 /* write message to hardware FIFO */
386 FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
387 } while (--len && --end);
392 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
393 * @hw: pointer to hardware structure
394 * @mbx: pointer to mailbox
395 * @head: acknowledgement number last received
397 * This function will push the tail index forward based on the remote
398 * head index. It will then pull up to mbmem_len DWORDs off of the
399 * head of the FIFO and will place it in the MBMEM registers
400 * associated with the mailbox.
402 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
403 struct fm10k_mbx_info *mbx, u16 head)
405 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
406 struct fm10k_mbx_fifo *fifo = &mbx->tx;
408 /* update number of bytes pulled and update bytes in transit */
409 mbx->pulled += mbx->tail_len - ack;
411 /* determine length of data to pull, reserve space for mbmem header */
412 mbmem_len = mbx->mbmem_len - 1;
413 len = fm10k_fifo_used(fifo) - mbx->pulled;
417 /* update tail and record number of bytes in transit */
418 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
421 /* drop pulled messages from the FIFO */
422 for (len = fm10k_fifo_head_len(fifo);
423 len && (mbx->pulled >= len);
424 len = fm10k_fifo_head_len(fifo)) {
425 mbx->pulled -= fm10k_fifo_head_drop(fifo);
427 mbx->tx_dwords += len;
430 /* Copy message out from the Tx FIFO */
431 fm10k_mbx_write_copy(hw, mbx);
435 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
436 * @hw: pointer to hardware structure
437 * @mbx: pointer to mailbox
439 * This function will take a section of the mailbox memory and copy it
440 * into the Rx FIFO. The offset is based on the lower bits of the
441 * head and len determines the length to copy.
443 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
444 struct fm10k_mbx_info *mbx)
446 struct fm10k_mbx_fifo *fifo = &mbx->rx;
447 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
448 u32 *tail = fifo->buffer;
451 DEBUGFUNC("fm10k_mbx_read_copy");
453 /* determine data length and mbmem head index */
455 head = fm10k_mbx_head_sub(mbx, len);
456 if (head >= mbx->mbmem_len)
459 /* determine offset in the ring */
460 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
463 /* Copy message into Rx FIFO */
464 for (end = fifo->size - end; len; tail = fifo->buffer) {
466 /* adjust head to match offset for FIFO */
467 head &= mbx->mbmem_len - 1;
471 /* read message from hardware FIFO */
472 *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
473 } while (--len && --end);
476 /* memory barrier to guarantee FIFO is written before tail update */
481 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
482 * @hw: pointer to hardware structure
483 * @mbx: pointer to mailbox
484 * @tail: tail index of message
486 * This function will first validate the tail index and size for the
487 * incoming message. It then updates the acknowledgment number and
488 * copies the data into the FIFO. It will return the number of messages
489 * dequeued on success and a negative value on error.
491 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
492 struct fm10k_mbx_info *mbx,
495 struct fm10k_mbx_fifo *fifo = &mbx->rx;
496 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
498 DEBUGFUNC("fm10k_mbx_push_tail");
500 /* determine length of data to push */
501 len = fm10k_fifo_unused(fifo) - mbx->pushed;
505 /* update head and record bytes received */
506 mbx->head = fm10k_mbx_head_add(mbx, len);
509 /* nothing to do if there is no data */
511 return FM10K_SUCCESS;
513 /* Copy msg into Rx FIFO */
514 fm10k_mbx_read_copy(hw, mbx);
516 /* determine if there are any invalid lengths in message */
517 if (fm10k_mbx_validate_msg_size(mbx, len))
518 return FM10K_MBX_ERR_SIZE;
523 /* flush any completed messages */
524 for (len = fm10k_mbx_pushed_tail_len(mbx);
525 len && (mbx->pushed >= len);
526 len = fm10k_mbx_pushed_tail_len(mbx)) {
530 mbx->rx_dwords += len;
533 return FM10K_SUCCESS;
536 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
537 static const u16 fm10k_crc_16b_table[256] = {
538 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
539 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
540 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
541 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
542 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
543 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
544 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
545 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
546 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
547 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
548 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
549 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
550 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
551 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
552 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
553 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
554 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
555 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
556 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
557 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
558 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
559 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
560 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
561 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
562 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
563 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
564 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
565 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
566 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
567 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
568 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
569 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
572 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
573 * @data: pointer to data to process
574 * @seed: seed value for CRC
575 * @len: length measured in 16 bits words
577 * This function will generate a CRC based on the polynomial 0xAC9A and
578 * whatever value is stored in the seed variable. Note that this
579 * value inverts the local seed and the result in order to capture all
580 * leading and trailing zeros.
582 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
588 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
589 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
594 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
595 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
602 * fm10k_fifo_crc - generate a CRC based off of FIFO data
603 * @fifo: pointer to FIFO
604 * @offset: offset point for start of FIFO
605 * @len: number of DWORDS words to process
606 * @seed: seed value for CRC
608 * This function generates a CRC for some region of the FIFO
610 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
613 u32 *data = fifo->buffer + offset;
615 /* track when we should cross the end of the FIFO */
616 offset = fifo->size - offset;
618 /* if we are in 2 blocks process the end of the FIFO first */
620 seed = fm10k_crc_16b(data, seed, offset * 2);
625 /* process any remaining bits */
626 return fm10k_crc_16b(data, seed, len * 2);
630 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
631 * @mbx: pointer to mailbox
632 * @head: head index provided by remote mailbox
634 * This function will generate the CRC for all data from the end of the
635 * last head update to the current one. It uses the result of the
636 * previous CRC as the seed for this update. The result is stored in
639 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
641 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
643 /* determine the offset for the start of the region to be pulled */
644 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
646 /* update local CRC to include all of the pulled data */
647 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
651 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
652 * @mbx: pointer to mailbox
654 * This function will take all data that has been provided from the remote
655 * end and generate a CRC for it. This is stored in mbx->remote. The
656 * CRC for the header is then computed and if the result is non-zero this
657 * is an error and we signal an error dropping all data and resetting the
660 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
662 struct fm10k_mbx_fifo *fifo = &mbx->rx;
663 u16 len = mbx->head_len;
664 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
667 /* update the remote CRC if new data has been received */
669 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
671 /* process the full header as we have to validate the CRC */
672 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
674 /* notify other end if we have a problem */
675 return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
679 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
680 * @mbx: pointer to mailbox
682 * This function returns true if there is a message in the Rx FIFO to dequeue.
684 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
686 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
688 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
692 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
693 * @mbx: pointer to mailbox
694 * @len: verify free space is >= this value
696 * This function returns true if the mailbox is in a state ready to transmit.
698 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
700 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
702 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
706 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
707 * @mbx: pointer to mailbox
709 * This function returns true if the Tx FIFO is empty.
711 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
713 return fm10k_fifo_empty(&mbx->tx);
717 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
718 * @hw: pointer to hardware structure
719 * @mbx: pointer to mailbox
721 * This function dequeues messages and hands them off to the tlv parser.
722 * It will return the number of messages processed when called.
724 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
725 struct fm10k_mbx_info *mbx)
727 struct fm10k_mbx_fifo *fifo = &mbx->rx;
731 /* parse Rx messages out of the Rx FIFO to empty it */
732 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
733 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
738 fm10k_fifo_head_drop(fifo);
741 /* shift remaining bytes back to start of FIFO */
742 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
744 /* shift head and tail based on the memory we moved */
745 fifo->tail -= fifo->head;
752 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
753 * @hw: pointer to hardware structure
754 * @mbx: pointer to mailbox
755 * @msg: message array to read
757 * This function enqueues a message up to the size specified by the length
758 * contained in the first DWORD of the message and will place at the tail
759 * of the FIFO. It will return 0 on success, or a negative value on error.
761 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
762 struct fm10k_mbx_info *mbx, const u32 *msg)
764 u32 countdown = mbx->timeout;
767 switch (mbx->state) {
768 case FM10K_STATE_CLOSED:
769 case FM10K_STATE_DISCONNECT:
770 return FM10K_MBX_ERR_NO_MBX;
775 /* enqueue the message on the Tx FIFO */
776 err = fm10k_fifo_enqueue(&mbx->tx, msg);
778 /* if it failed give the FIFO a chance to drain */
779 while (err && countdown) {
781 usec_delay(mbx->usec_delay);
782 mbx->ops.process(hw, mbx);
783 err = fm10k_fifo_enqueue(&mbx->tx, msg);
786 /* if we failed treat the error */
792 /* begin processing message, ignore errors as this is just meant
793 * to start the mailbox flow so we are not concerned if there
794 * is a bad error, or the mailbox is already busy with a request
797 mbx->ops.process(hw, mbx);
799 return FM10K_SUCCESS;
803 * fm10k_mbx_read - Copies the mbmem to local message buffer
804 * @hw: pointer to hardware structure
805 * @mbx: pointer to mailbox
807 * This function copies the message from the mbmem to the message array
809 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
811 DEBUGFUNC("fm10k_mbx_read");
813 /* only allow one reader in here at a time */
815 return FM10K_MBX_ERR_BUSY;
817 /* read to capture initial interrupt bits */
818 if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
819 mbx->mbx_lock = FM10K_MBX_ACK;
821 /* write back interrupt bits to clear */
822 FM10K_WRITE_MBX(hw, mbx->mbx_reg,
823 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
825 /* read remote header */
826 mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
828 return FM10K_SUCCESS;
832 * fm10k_mbx_write - Copies the local message buffer to mbmem
833 * @hw: pointer to hardware structure
834 * @mbx: pointer to mailbox
836 * This function copies the message from the the message array to mbmem
838 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
840 u32 mbmem = mbx->mbmem_reg;
842 DEBUGFUNC("fm10k_mbx_write");
844 /* write new msg header to notify recipient of change */
845 FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
847 /* write mailbox to send interrupt */
849 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
851 /* we no longer are using the header so free it */
857 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
858 * @mbx: pointer to mailbox
860 * This function returns a connection mailbox header
862 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
864 mbx->mbx_lock |= FM10K_MBX_REQ;
866 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
867 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
868 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
872 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
873 * @mbx: pointer to mailbox
875 * This function returns a data mailbox header
877 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
879 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
880 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
881 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
882 struct fm10k_mbx_fifo *fifo = &mbx->tx;
886 mbx->mbx_lock |= FM10K_MBX_REQ;
888 /* generate CRC for data in flight and header */
889 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
890 mbx->tail_len, mbx->local);
891 crc = fm10k_crc_16b(&hdr, crc, 1);
893 /* load header to memory to be written */
894 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
898 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
899 * @mbx: pointer to mailbox
901 * This function returns a disconnect mailbox header
903 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
905 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
906 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
907 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
908 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
910 mbx->mbx_lock |= FM10K_MBX_ACK;
912 /* load header to memory to be written */
913 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
917 * fm10k_mbx_create_error_msg - Generate a error message
918 * @mbx: pointer to mailbox
919 * @err: local error encountered
921 * This function will interpret the error provided by err, and based on
922 * that it may shift the message by 1 DWORD and then place an error header
923 * at the start of the message.
925 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
927 /* only generate an error message for these types */
929 case FM10K_MBX_ERR_TAIL:
930 case FM10K_MBX_ERR_HEAD:
931 case FM10K_MBX_ERR_TYPE:
932 case FM10K_MBX_ERR_SIZE:
933 case FM10K_MBX_ERR_RSVD0:
934 case FM10K_MBX_ERR_CRC:
940 mbx->mbx_lock |= FM10K_MBX_REQ;
942 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
943 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
944 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
948 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
949 * @mbx: pointer to mailbox
950 * @msg: message array to read
952 * This function will parse up the fields in the mailbox header and return
953 * an error if the header contains any of a number of invalid configurations
954 * including unrecognized type, invalid route, or a malformed message.
956 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
958 u16 type, rsvd0, head, tail, size;
959 const u32 *hdr = &mbx->mbx_hdr;
961 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
963 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
964 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
965 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
966 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
967 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
970 return FM10K_MBX_ERR_RSVD0;
973 case FM10K_MSG_DISCONNECT:
974 /* validate that all data has been received */
975 if (tail != mbx->head)
976 return FM10K_MBX_ERR_TAIL;
980 /* validate that head is moving correctly */
981 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
982 return FM10K_MBX_ERR_HEAD;
983 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
984 return FM10K_MBX_ERR_HEAD;
986 /* validate that tail is moving correctly */
987 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
988 return FM10K_MBX_ERR_TAIL;
989 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
992 return FM10K_MBX_ERR_TAIL;
993 case FM10K_MSG_CONNECT:
994 /* validate size is in range and is power of 2 mask */
995 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
996 return FM10K_MBX_ERR_SIZE;
999 case FM10K_MSG_ERROR:
1000 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1001 return FM10K_MBX_ERR_HEAD;
1002 /* neither create nor error include a tail offset */
1004 return FM10K_MBX_ERR_TAIL;
1008 return FM10K_MBX_ERR_TYPE;
1011 return FM10K_SUCCESS;
1015 * fm10k_mbx_create_reply - Generate reply based on state and remote head
1016 * @mbx: pointer to mailbox
1017 * @head: acknowledgement number
1019 * This function will generate an outgoing message based on the current
1020 * mailbox state and the remote fifo head. It will return the length
1021 * of the outgoing message excluding header on success, and a negative value
1024 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1025 struct fm10k_mbx_info *mbx, u16 head)
1027 switch (mbx->state) {
1028 case FM10K_STATE_OPEN:
1029 case FM10K_STATE_DISCONNECT:
1030 /* update our checksum for the outgoing data */
1031 fm10k_mbx_update_local_crc(mbx, head);
1033 /* as long as other end recognizes us keep sending data */
1034 fm10k_mbx_pull_head(hw, mbx, head);
1036 /* generate new header based on data */
1037 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1038 fm10k_mbx_create_data_hdr(mbx);
1040 fm10k_mbx_create_disconnect_hdr(mbx);
1042 case FM10K_STATE_CONNECT:
1043 /* send disconnect even if we aren't connected */
1044 fm10k_mbx_create_connect_hdr(mbx);
1046 case FM10K_STATE_CLOSED:
1047 /* generate new header based on data */
1048 fm10k_mbx_create_disconnect_hdr(mbx);
1053 return FM10K_SUCCESS;
1057 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1058 * @mbx: pointer to mailbox
1060 * This function will reset all internal pointers so any work in progress
1061 * is dropped. This call should occur every time we transition from the
1062 * open state to the connect state.
1064 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1066 /* reset our outgoing max size back to Rx limits */
1067 mbx->max_size = mbx->rx.size - 1;
1069 /* just do a quick resysnc to start of message */
1079 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1080 * @mbx: pointer to mailbox
1081 * @size: new value for max_size
1083 * This function will update the max_size value and drop any outgoing messages
1084 * from the head of the Tx FIFO that are larger than max_size.
1086 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1090 DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1092 mbx->max_size = size;
1094 /* flush any oversized messages from the queue */
1095 for (len = fm10k_fifo_head_len(&mbx->tx);
1097 len = fm10k_fifo_head_len(&mbx->tx)) {
1098 fm10k_fifo_head_drop(&mbx->tx);
1104 * fm10k_mbx_connect_reset - Reset following request for reset
1105 * @mbx: pointer to mailbox
1107 * This function resets the mailbox to either a disconnected state
1108 * or a connect state depending on the current mailbox state
1110 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1112 /* just do a quick resysnc to start of frame */
1113 fm10k_mbx_reset_work(mbx);
1115 /* reset CRC seeds */
1116 mbx->local = FM10K_MBX_CRC_SEED;
1117 mbx->remote = FM10K_MBX_CRC_SEED;
1119 /* we cannot exit connect until the size is good */
1120 if (mbx->state == FM10K_STATE_OPEN)
1121 mbx->state = FM10K_STATE_CONNECT;
1123 mbx->state = FM10K_STATE_CLOSED;
1127 * fm10k_mbx_process_connect - Process connect header
1128 * @mbx: pointer to mailbox
1129 * @msg: message array to process
1131 * This function will read an incoming connect header and reply with the
1132 * appropriate message. It will return a value indicating the number of
1133 * data DWORDs on success, or will return a negative value on failure.
1135 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1136 struct fm10k_mbx_info *mbx)
1138 const enum fm10k_mbx_state state = mbx->state;
1139 const u32 *hdr = &mbx->mbx_hdr;
1142 /* we will need to pull all of the fields for verification */
1143 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1144 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1147 case FM10K_STATE_DISCONNECT:
1148 case FM10K_STATE_OPEN:
1149 /* reset any in-progress work */
1150 fm10k_mbx_connect_reset(mbx);
1152 case FM10K_STATE_CONNECT:
1153 /* we cannot exit connect until the size is good */
1154 if (size > mbx->rx.size) {
1155 mbx->max_size = mbx->rx.size - 1;
1157 /* record the remote system requesting connection */
1158 mbx->state = FM10K_STATE_OPEN;
1160 fm10k_mbx_update_max_size(mbx, size);
1167 /* align our tail index to remote head index */
1170 return fm10k_mbx_create_reply(hw, mbx, head);
1174 * fm10k_mbx_process_data - Process data header
1175 * @mbx: pointer to mailbox
1177 * This function will read an incoming data header and reply with the
1178 * appropriate message. It will return a value indicating the number of
1179 * data DWORDs on success, or will return a negative value on failure.
1181 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1182 struct fm10k_mbx_info *mbx)
1184 const u32 *hdr = &mbx->mbx_hdr;
1188 DEBUGFUNC("fm10k_mbx_process_data");
1190 /* we will need to pull all of the fields for verification */
1191 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1192 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1194 /* if we are in connect just update our data and go */
1195 if (mbx->state == FM10K_STATE_CONNECT) {
1197 mbx->state = FM10K_STATE_OPEN;
1200 /* abort on message size errors */
1201 err = fm10k_mbx_push_tail(hw, mbx, tail);
1205 /* verify the checksum on the incoming data */
1206 err = fm10k_mbx_verify_remote_crc(mbx);
1210 /* process messages if we have received any */
1211 fm10k_mbx_dequeue_rx(hw, mbx);
1213 return fm10k_mbx_create_reply(hw, mbx, head);
1217 * fm10k_mbx_process_disconnect - Process disconnect header
1218 * @mbx: pointer to mailbox
1220 * This function will read an incoming disconnect header and reply with the
1221 * appropriate message. It will return a value indicating the number of
1222 * data DWORDs on success, or will return a negative value on failure.
1224 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1225 struct fm10k_mbx_info *mbx)
1227 const enum fm10k_mbx_state state = mbx->state;
1228 const u32 *hdr = &mbx->mbx_hdr;
1232 /* we will need to pull the header field for verification */
1233 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1235 /* We should not be receiving disconnect if Rx is incomplete */
1237 return FM10K_MBX_ERR_TAIL;
1239 /* we have already verified mbx->head == tail so we know this is 0 */
1242 /* verify the checksum on the incoming header is correct */
1243 err = fm10k_mbx_verify_remote_crc(mbx);
1248 case FM10K_STATE_DISCONNECT:
1249 case FM10K_STATE_OPEN:
1250 /* state doesn't change if we still have work to do */
1251 if (!fm10k_mbx_tx_complete(mbx))
1254 /* verify the head indicates we completed all transmits */
1255 if (head != mbx->tail)
1256 return FM10K_MBX_ERR_HEAD;
1258 /* reset any in-progress work */
1259 fm10k_mbx_connect_reset(mbx);
1265 return fm10k_mbx_create_reply(hw, mbx, head);
1269 * fm10k_mbx_process_error - Process error header
1270 * @mbx: pointer to mailbox
1272 * This function will read an incoming error header and reply with the
1273 * appropriate message. It will return a value indicating the number of
1274 * data DWORDs on success, or will return a negative value on failure.
1276 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1277 struct fm10k_mbx_info *mbx)
1279 const u32 *hdr = &mbx->mbx_hdr;
1283 /* we will need to pull all of the fields for verification */
1284 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1286 /* we only have lower 10 bits of error number so add upper bits */
1287 err_no = FM10K_MSG_HDR_FIELD_GET(*hdr, ERR_NO);
1288 err_no |= ~FM10K_MSG_HDR_MASK(ERR_NO);
1290 switch (mbx->state) {
1291 case FM10K_STATE_OPEN:
1292 case FM10K_STATE_DISCONNECT:
1293 /* flush any uncompleted work */
1294 fm10k_mbx_reset_work(mbx);
1296 /* reset CRC seeds */
1297 mbx->local = FM10K_MBX_CRC_SEED;
1298 mbx->remote = FM10K_MBX_CRC_SEED;
1300 /* reset tail index and size to prepare for reconnect */
1303 /* if open then reset max_size and go back to connect */
1304 if (mbx->state == FM10K_STATE_OPEN) {
1305 mbx->state = FM10K_STATE_CONNECT;
1309 /* send a connect message to get data flowing again */
1310 fm10k_mbx_create_connect_hdr(mbx);
1311 return FM10K_SUCCESS;
1316 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1320 * fm10k_mbx_process - Process mailbox interrupt
1321 * @hw: pointer to hardware structure
1322 * @mbx: pointer to mailbox
1324 * This function will process incoming mailbox events and generate mailbox
1325 * replies. It will return a value indicating the number of DWORDs
1326 * transmitted excluding header on success or a negative value on error.
1328 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1329 struct fm10k_mbx_info *mbx)
1333 DEBUGFUNC("fm10k_mbx_process");
1335 /* we do not read mailbox if closed */
1336 if (mbx->state == FM10K_STATE_CLOSED)
1337 return FM10K_SUCCESS;
1339 /* copy data from mailbox */
1340 err = fm10k_mbx_read(hw, mbx);
1344 /* validate type, source, and destination */
1345 err = fm10k_mbx_validate_msg_hdr(mbx);
1349 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1350 case FM10K_MSG_CONNECT:
1351 err = fm10k_mbx_process_connect(hw, mbx);
1353 case FM10K_MSG_DATA:
1354 err = fm10k_mbx_process_data(hw, mbx);
1356 case FM10K_MSG_DISCONNECT:
1357 err = fm10k_mbx_process_disconnect(hw, mbx);
1359 case FM10K_MSG_ERROR:
1360 err = fm10k_mbx_process_error(hw, mbx);
1363 err = FM10K_MBX_ERR_TYPE;
1368 /* notify partner of errors on our end */
1370 fm10k_mbx_create_error_msg(mbx, err);
1372 /* copy data from mailbox */
1373 fm10k_mbx_write(hw, mbx);
1379 * fm10k_mbx_disconnect - Shutdown mailbox connection
1380 * @hw: pointer to hardware structure
1381 * @mbx: pointer to mailbox
1383 * This function will shut down the mailbox. It places the mailbox first
1384 * in the disconnect state, it then allows up to a predefined timeout for
1385 * the mailbox to transition to close on its own. If this does not occur
1386 * then the mailbox will be forced into the closed state.
1388 * Any mailbox transactions not completed before calling this function
1389 * are not guaranteed to complete and may be dropped.
1391 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1392 struct fm10k_mbx_info *mbx)
1394 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1396 DEBUGFUNC("fm10k_mbx_disconnect");
1398 /* Place mbx in ready to disconnect state */
1399 mbx->state = FM10K_STATE_DISCONNECT;
1401 /* trigger interrupt to start shutdown process */
1402 FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1403 FM10K_MBX_INTERRUPT_DISABLE);
1405 usec_delay(FM10K_MBX_POLL_DELAY);
1406 mbx->ops.process(hw, mbx);
1407 timeout -= FM10K_MBX_POLL_DELAY;
1408 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1410 /* in case we didn't close just force the mailbox into shutdown */
1411 fm10k_mbx_connect_reset(mbx);
1412 fm10k_mbx_update_max_size(mbx, 0);
1414 FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1418 * fm10k_mbx_connect - Start mailbox connection
1419 * @hw: pointer to hardware structure
1420 * @mbx: pointer to mailbox
1422 * This function will initiate a mailbox connection. It will populate the
1423 * mailbox with a broadcast connect message and then initialize the lock.
1424 * This is safe since the connect message is a single DWORD so the mailbox
1425 * transaction is guaranteed to be atomic.
1427 * This function will return an error if the mailbox has not been initiated
1428 * or is currently in use.
1430 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1432 DEBUGFUNC("fm10k_mbx_connect");
1434 /* we cannot connect an uninitialized mailbox */
1435 if (!mbx->rx.buffer)
1436 return FM10K_MBX_ERR_NO_SPACE;
1438 /* we cannot connect an already connected mailbox */
1439 if (mbx->state != FM10K_STATE_CLOSED)
1440 return FM10K_MBX_ERR_BUSY;
1442 /* mailbox timeout can now become active */
1443 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1445 /* Place mbx in ready to connect state */
1446 mbx->state = FM10K_STATE_CONNECT;
1448 /* initialize header of remote mailbox */
1449 fm10k_mbx_create_disconnect_hdr(mbx);
1450 FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1452 /* enable interrupt and notify other party of new message */
1453 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1454 FM10K_MBX_INTERRUPT_ENABLE;
1456 /* generate and load connect header into mailbox */
1457 fm10k_mbx_create_connect_hdr(mbx);
1458 fm10k_mbx_write(hw, mbx);
1460 return FM10K_SUCCESS;
1464 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1465 * @msg_data: handlers for mailbox events
1467 * This function validates the layout of the message parsing data. This
1468 * should be mostly static, but it is important to catch any errors that
1469 * are made when constructing the parsers.
1471 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1473 const struct fm10k_tlv_attr *attr;
1476 DEBUGFUNC("fm10k_mbx_validate_handlers");
1478 /* Allow NULL mailboxes that transmit but don't receive */
1480 return FM10K_SUCCESS;
1482 while (msg_data->id != FM10K_TLV_ERROR) {
1483 /* all messages should have a function handler */
1484 if (!msg_data->func)
1485 return FM10K_ERR_PARAM;
1487 /* parser is optional */
1488 attr = msg_data->attr;
1490 while (attr->id != FM10K_TLV_ERROR) {
1493 /* ID should always be increasing */
1495 return FM10K_ERR_PARAM;
1496 /* ID should fit in results array */
1497 if (id >= FM10K_TLV_RESULTS_MAX)
1498 return FM10K_ERR_PARAM;
1501 /* verify terminator is in the list */
1502 if (attr->id != FM10K_TLV_ERROR)
1503 return FM10K_ERR_PARAM;
1508 /* ID should always be increasing */
1509 if (id >= msg_data->id)
1510 return FM10K_ERR_PARAM;
1513 /* verify terminator is in the list */
1514 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1515 return FM10K_ERR_PARAM;
1517 return FM10K_SUCCESS;
1521 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1522 * @mbx: pointer to mailbox
1523 * @msg_data: handlers for mailbox events
1525 * This function associates a set of message handling ops with a mailbox.
1527 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1528 const struct fm10k_msg_data *msg_data)
1530 DEBUGFUNC("fm10k_mbx_register_handlers");
1532 /* validate layout of handlers before assigning them */
1533 if (fm10k_mbx_validate_handlers(msg_data))
1534 return FM10K_ERR_PARAM;
1536 /* initialize the message handlers */
1537 mbx->msg_data = msg_data;
1539 return FM10K_SUCCESS;
1543 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1544 * @hw: pointer to hardware structure
1545 * @mbx: pointer to mailbox
1546 * @msg_data: handlers for mailbox events
1547 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1549 * This function initializes the mailbox for use. It will split the
1550 * buffer provided an use that th populate both the Tx and Rx FIFO by
1551 * evenly splitting it. In order to allow for easy masking of head/tail
1552 * the value reported in size must be a power of 2 and is reported in
1553 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1556 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1557 const struct fm10k_msg_data *msg_data, u8 id)
1559 DEBUGFUNC("fm10k_pfvf_mbx_init");
1561 /* initialize registers */
1562 switch (hw->mac.type) {
1564 mbx->mbx_reg = FM10K_VFMBX;
1565 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1568 /* there are only 64 VF <-> PF mailboxes */
1570 mbx->mbx_reg = FM10K_MBX(id);
1571 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1576 return FM10K_MBX_ERR_NO_MBX;
1579 /* start out in closed state */
1580 mbx->state = FM10K_STATE_CLOSED;
1582 /* validate layout of handlers before assigning them */
1583 if (fm10k_mbx_validate_handlers(msg_data))
1584 return FM10K_ERR_PARAM;
1586 /* initialize the message handlers */
1587 mbx->msg_data = msg_data;
1589 /* start mailbox as timed out and let the reset_hw call
1590 * set the timeout value to begin communications
1593 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1595 /* initialize tail and head */
1599 /* initialize CRC seeds */
1600 mbx->local = FM10K_MBX_CRC_SEED;
1601 mbx->remote = FM10K_MBX_CRC_SEED;
1603 /* Split buffer for use by Tx/Rx FIFOs */
1604 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1605 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1607 /* initialize the FIFOs, sizes are in 4 byte increments */
1608 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1609 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1610 FM10K_MBX_RX_BUFFER_SIZE);
1612 /* initialize function pointers */
1613 mbx->ops.connect = fm10k_mbx_connect;
1614 mbx->ops.disconnect = fm10k_mbx_disconnect;
1615 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1616 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1617 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1618 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1619 mbx->ops.process = fm10k_mbx_process;
1620 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1622 return FM10K_SUCCESS;
1626 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1627 * @mbx: pointer to mailbox
1629 * This function returns a connection mailbox header
1631 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1634 mbx->mbx_lock |= FM10K_MBX_REQ;
1636 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1637 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1638 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1642 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1643 * @mbx: pointer to mailbox
1644 * @err: error flags to report if any
1646 * This function returns a connection mailbox header
1648 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1651 mbx->mbx_lock |= FM10K_MBX_REQ;
1653 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1654 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1655 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1656 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1660 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1661 * @mbx: pointer to mailbox
1663 * This function resets the mailbox to a just connected state
1665 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1667 /* flush any uncompleted work */
1668 fm10k_mbx_reset_work(mbx);
1670 /* set local version to max and remote version to 0 */
1671 mbx->local = FM10K_SM_MBX_VERSION;
1674 /* initialize tail and head */
1678 /* reset state back to connect */
1679 mbx->state = FM10K_STATE_CONNECT;
1683 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1684 * @hw: pointer to hardware structure
1685 * @mbx: pointer to mailbox
1687 * This function will initiate a mailbox connection with the switch
1688 * manager. To do this it will first disconnect the mailbox, and then
1689 * reconnect it in order to complete a reset of the mailbox.
1691 * This function will return an error if the mailbox has not been initiated
1692 * or is currently in use.
1694 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1696 DEBUGFUNC("fm10k_mbx_connect");
1698 /* we cannot connect an uninitialized mailbox */
1699 if (!mbx->rx.buffer)
1700 return FM10K_MBX_ERR_NO_SPACE;
1702 /* we cannot connect an already connected mailbox */
1703 if (mbx->state != FM10K_STATE_CLOSED)
1704 return FM10K_MBX_ERR_BUSY;
1706 /* mailbox timeout can now become active */
1707 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1709 /* Place mbx in ready to connect state */
1710 mbx->state = FM10K_STATE_CONNECT;
1711 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1713 /* reset interface back to connect */
1714 fm10k_sm_mbx_connect_reset(mbx);
1716 /* enable interrupt and notify other party of new message */
1717 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1718 FM10K_MBX_INTERRUPT_ENABLE;
1720 /* generate and load connect header into mailbox */
1721 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1722 fm10k_mbx_write(hw, mbx);
1724 /* enable interrupt and notify other party of new message */
1726 return FM10K_SUCCESS;
1730 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1731 * @hw: pointer to hardware structure
1732 * @mbx: pointer to mailbox
1734 * This function will shut down the mailbox. It places the mailbox first
1735 * in the disconnect state, it then allows up to a predefined timeout for
1736 * the mailbox to transition to close on its own. If this does not occur
1737 * then the mailbox will be forced into the closed state.
1739 * Any mailbox transactions not completed before calling this function
1740 * are not guaranteed to complete and may be dropped.
1742 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1743 struct fm10k_mbx_info *mbx)
1745 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1747 DEBUGFUNC("fm10k_sm_mbx_disconnect");
1749 /* Place mbx in ready to disconnect state */
1750 mbx->state = FM10K_STATE_DISCONNECT;
1752 /* trigger interrupt to start shutdown process */
1753 FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1754 FM10K_MBX_INTERRUPT_DISABLE);
1756 usec_delay(FM10K_MBX_POLL_DELAY);
1757 mbx->ops.process(hw, mbx);
1758 timeout -= FM10K_MBX_POLL_DELAY;
1759 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1761 /* in case we didn't close just force the mailbox into shutdown */
1762 mbx->state = FM10K_STATE_CLOSED;
1764 fm10k_mbx_reset_work(mbx);
1765 fm10k_mbx_update_max_size(mbx, 0);
1767 FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1771 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1772 * @mbx: pointer to mailbox
1774 * This function will parse up the fields in the mailbox header and return
1775 * an error if the header contains any of a number of invalid configurations
1776 * including unrecognized offsets or version numbers.
1778 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1780 const u32 *hdr = &mbx->mbx_hdr;
1781 u16 tail, head, ver;
1783 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1785 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1786 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1787 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1792 case FM10K_SM_MBX_VERSION:
1793 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1794 return FM10K_MBX_ERR_HEAD;
1795 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1796 return FM10K_MBX_ERR_TAIL;
1797 if (mbx->tail < head)
1798 head += mbx->mbmem_len - 1;
1799 if (tail < mbx->head)
1800 tail += mbx->mbmem_len - 1;
1801 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1802 return FM10K_MBX_ERR_HEAD;
1803 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1805 return FM10K_MBX_ERR_TAIL;
1807 return FM10K_MBX_ERR_SRC;
1810 return FM10K_SUCCESS;
1814 * fm10k_sm_mbx_process_error - Process header with error flag set
1815 * @mbx: pointer to mailbox
1817 * This function is meant to respond to a request where the error flag
1818 * is set. As a result we will terminate a connection if one is present
1819 * and fall back into the reset state with a connection header of version
1822 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1824 const enum fm10k_mbx_state state = mbx->state;
1827 case FM10K_STATE_DISCONNECT:
1828 /* if there is an error just disconnect */
1831 case FM10K_STATE_OPEN:
1832 /* flush any uncompleted work */
1833 fm10k_sm_mbx_connect_reset(mbx);
1835 case FM10K_STATE_CONNECT:
1836 /* try connnecting at lower version */
1838 while (mbx->local > 1)
1847 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1851 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1852 * @mbx: pointer to mailbox
1853 * @err: local error encountered
1855 * This function will interpret the error provided by err, and based on
1856 * that it may set the error bit in the local message header
1858 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1860 /* only generate an error message for these types */
1862 case FM10K_MBX_ERR_TAIL:
1863 case FM10K_MBX_ERR_HEAD:
1864 case FM10K_MBX_ERR_SRC:
1865 case FM10K_MBX_ERR_SIZE:
1866 case FM10K_MBX_ERR_RSVD0:
1872 /* process it as though we received an error, and send error reply */
1873 fm10k_sm_mbx_process_error(mbx);
1874 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1878 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1879 * @hw: pointer to hardware structure
1880 * @mbx: pointer to mailbox
1882 * This function will dequeue one message from the Rx switch manager mailbox
1883 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1885 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1886 struct fm10k_mbx_info *mbx,
1889 /* reduce length by 1 to convert to a mask */
1890 u16 mbmem_len = mbx->mbmem_len - 1;
1893 DEBUGFUNC("fm10k_sm_mbx_receive");
1895 /* push tail in front of head */
1896 if (tail < mbx->head)
1899 /* copy data to the Rx FIFO */
1900 err = fm10k_mbx_push_tail(hw, mbx, tail);
1904 /* process messages if we have received any */
1905 fm10k_mbx_dequeue_rx(hw, mbx);
1907 /* guarantee head aligns with the end of the last message */
1908 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1911 /* clear any extra bits left over since index adds 1 extra bit */
1912 if (mbx->head > mbmem_len)
1913 mbx->head -= mbmem_len;
1919 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1920 * @hw: pointer to hardware structure
1921 * @mbx: pointer to mailbox
1923 * This function will dequeue one message from the Tx mailbox FIFO and place
1924 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1926 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1927 struct fm10k_mbx_info *mbx, u16 head)
1929 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1930 /* reduce length by 1 to convert to a mask */
1931 u16 mbmem_len = mbx->mbmem_len - 1;
1932 u16 tail_len, len = 0;
1935 DEBUGFUNC("fm10k_sm_mbx_transmit");
1937 /* push head behind tail */
1938 if (mbx->tail < head)
1941 fm10k_mbx_pull_head(hw, mbx, head);
1943 /* determine msg aligned offset for end of buffer */
1945 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1947 len += FM10K_TLV_DWORD_LEN(*msg);
1948 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1950 /* guarantee we stop on a message boundary */
1951 if (mbx->tail_len > tail_len) {
1952 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1953 mbx->tail_len = tail_len;
1956 /* clear any extra bits left over since index adds 1 extra bit */
1957 if (mbx->tail > mbmem_len)
1958 mbx->tail -= mbmem_len;
1962 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1963 * @mbx: pointer to mailbox
1964 * @head: acknowledgement number
1966 * This function will generate an outgoing message based on the current
1967 * mailbox state and the remote fifo head. It will return the length
1968 * of the outgoing message excluding header on success, and a negative value
1971 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1972 struct fm10k_mbx_info *mbx, u16 head)
1974 switch (mbx->state) {
1975 case FM10K_STATE_OPEN:
1976 case FM10K_STATE_DISCONNECT:
1977 /* flush out Tx data */
1978 fm10k_sm_mbx_transmit(hw, mbx, head);
1980 /* generate new header based on data */
1981 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1982 fm10k_sm_mbx_create_data_hdr(mbx);
1985 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1988 case FM10K_STATE_CONNECT:
1989 case FM10K_STATE_CLOSED:
1990 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1998 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
1999 * @hw: pointer to hardware structure
2000 * @mbx: pointer to mailbox
2002 * This function is meant to respond to a request where the version data
2003 * is set to 0. As such we will either terminate the connection or go
2004 * into the connect state in order to re-establish the connection. This
2005 * function can also be used to respond to an error as the connection
2006 * resetting would also be a means of dealing with errors.
2008 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2009 struct fm10k_mbx_info *mbx)
2011 const enum fm10k_mbx_state state = mbx->state;
2014 case FM10K_STATE_DISCONNECT:
2015 /* drop remote connections and disconnect */
2016 mbx->state = FM10K_STATE_CLOSED;
2020 case FM10K_STATE_OPEN:
2021 /* flush any incomplete work */
2022 fm10k_sm_mbx_connect_reset(mbx);
2024 case FM10K_STATE_CONNECT:
2025 /* Update remote value to match local value */
2026 mbx->remote = mbx->local;
2031 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2035 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2036 * @hw: pointer to hardware structure
2037 * @mbx: pointer to mailbox
2039 * This function is meant to process messages received when the remote
2040 * mailbox is active.
2042 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2043 struct fm10k_mbx_info *mbx)
2045 const u32 *hdr = &mbx->mbx_hdr;
2049 /* pull all fields needed for verification */
2050 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2051 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2053 /* if we are in connect and wanting version 1 then start up and go */
2054 if (mbx->state == FM10K_STATE_CONNECT) {
2057 if (mbx->remote != 1)
2058 return FM10K_MBX_ERR_SRC;
2060 mbx->state = FM10K_STATE_OPEN;
2064 /* abort on message size errors */
2065 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2069 /* continue until we have flushed the Rx FIFO */
2073 fm10k_sm_mbx_create_reply(hw, mbx, head);
2075 return FM10K_SUCCESS;
2079 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2080 * @hw: pointer to hardware structure
2081 * @mbx: pointer to mailbox
2083 * This function will process incoming mailbox events and generate mailbox
2084 * replies. It will return a value indicating the number of DWORDs
2085 * transmitted excluding header on success or a negative value on error.
2087 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2088 struct fm10k_mbx_info *mbx)
2092 DEBUGFUNC("fm10k_sm_mbx_process");
2094 /* we do not read mailbox if closed */
2095 if (mbx->state == FM10K_STATE_CLOSED)
2096 return FM10K_SUCCESS;
2098 /* retrieve data from switch manager */
2099 err = fm10k_mbx_read(hw, mbx);
2103 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2107 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2108 fm10k_sm_mbx_process_error(mbx);
2112 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2114 fm10k_sm_mbx_process_reset(hw, mbx);
2116 case FM10K_SM_MBX_VERSION:
2117 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2123 fm10k_sm_mbx_create_error_msg(mbx, err);
2125 /* report data to switch manager */
2126 fm10k_mbx_write(hw, mbx);
2132 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2133 * @hw: pointer to hardware structure
2134 * @mbx: pointer to mailbox
2135 * @msg_data: handlers for mailbox events
2137 * This function for now is used to stub out the PF/SM mailbox
2139 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2140 const struct fm10k_msg_data *msg_data)
2142 DEBUGFUNC("fm10k_sm_mbx_init");
2143 UNREFERENCED_1PARAMETER(hw);
2145 mbx->mbx_reg = FM10K_GMBX;
2146 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2148 /* start out in closed state */
2149 mbx->state = FM10K_STATE_CLOSED;
2151 /* validate layout of handlers before assigning them */
2152 if (fm10k_mbx_validate_handlers(msg_data))
2153 return FM10K_ERR_PARAM;
2155 /* initialize the message handlers */
2156 mbx->msg_data = msg_data;
2158 /* start mailbox as timed out and let the reset_hw call
2159 * set the timeout value to begin communications
2162 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2164 /* Split buffer for use by Tx/Rx FIFOs */
2165 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2166 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2168 /* initialize the FIFOs, sizes are in 4 byte increments */
2169 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2170 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2171 FM10K_MBX_RX_BUFFER_SIZE);
2173 /* initialize function pointers */
2174 mbx->ops.connect = fm10k_sm_mbx_connect;
2175 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2176 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2177 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2178 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2179 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2180 mbx->ops.process = fm10k_sm_mbx_process;
2181 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2183 return FM10K_SUCCESS;