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 Rx FIFO and copy it into the
348 * mailbox memory. The offset in mbmem is based on the lower bits of the
349 * tail and len determines the length to copy.
351 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
352 struct fm10k_mbx_info *mbx)
354 struct fm10k_mbx_fifo *fifo = &mbx->tx;
355 u32 mbmem = mbx->mbmem_reg;
356 u32 *head = fifo->buffer;
357 u16 end, len, tail, mask;
359 DEBUGFUNC("fm10k_mbx_write_copy");
364 /* determine data length and mbmem tail index */
365 mask = mbx->mbmem_len - 1;
367 tail = fm10k_mbx_tail_sub(mbx, len);
371 /* determine offset in the ring */
372 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
375 /* memory barrier to guarantee data is ready to be read */
378 /* Copy message from Tx FIFO */
379 for (end = fifo->size - end; len; head = fifo->buffer) {
381 /* adjust tail to match offset for FIFO */
386 /* write message to hardware FIFO */
387 FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
388 } while (--len && --end);
393 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
394 * @hw: pointer to hardware structure
395 * @mbx: pointer to mailbox
396 * @head: acknowledgement number last received
398 * This function will push the tail index forward based on the remote
399 * head index. It will then pull up to mbmem_len DWORDs off of the
400 * head of the FIFO and will place it in the MBMEM registers
401 * associated with the mailbox.
403 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
404 struct fm10k_mbx_info *mbx, u16 head)
406 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
407 struct fm10k_mbx_fifo *fifo = &mbx->tx;
409 /* update number of bytes pulled and update bytes in transit */
410 mbx->pulled += mbx->tail_len - ack;
412 /* determine length of data to pull, reserve space for mbmem header */
413 mbmem_len = mbx->mbmem_len - 1;
414 len = fm10k_fifo_used(fifo) - mbx->pulled;
418 /* update tail and record number of bytes in transit */
419 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
422 /* drop pulled messages from the FIFO */
423 for (len = fm10k_fifo_head_len(fifo);
424 len && (mbx->pulled >= len);
425 len = fm10k_fifo_head_len(fifo)) {
426 mbx->pulled -= fm10k_fifo_head_drop(fifo);
428 mbx->tx_dwords += len;
431 /* Copy message out from the Tx FIFO */
432 fm10k_mbx_write_copy(hw, mbx);
436 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
437 * @hw: pointer to hardware structure
438 * @mbx: pointer to mailbox
440 * This function will take a section of the mailbox memory and copy it
441 * into the Rx FIFO. The offset is based on the lower bits of the
442 * head and len determines the length to copy.
444 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
445 struct fm10k_mbx_info *mbx)
447 struct fm10k_mbx_fifo *fifo = &mbx->rx;
448 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
449 u32 *tail = fifo->buffer;
452 DEBUGFUNC("fm10k_mbx_read_copy");
454 /* determine data length and mbmem head index */
456 head = fm10k_mbx_head_sub(mbx, len);
457 if (head >= mbx->mbmem_len)
460 /* determine offset in the ring */
461 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
464 /* Copy message into Rx FIFO */
465 for (end = fifo->size - end; len; tail = fifo->buffer) {
467 /* adjust head to match offset for FIFO */
468 head &= mbx->mbmem_len - 1;
472 /* read message from hardware FIFO */
473 *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
474 } while (--len && --end);
477 /* memory barrier to guarantee FIFO is written before tail update */
482 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
483 * @hw: pointer to hardware structure
484 * @mbx: pointer to mailbox
485 * @tail: tail index of message
487 * This function will first validate the tail index and size for the
488 * incoming message. It then updates the acknowledgment number and
489 * copies the data into the FIFO. It will return the number of messages
490 * dequeued on success and a negative value on error.
492 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
493 struct fm10k_mbx_info *mbx,
496 struct fm10k_mbx_fifo *fifo = &mbx->rx;
497 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
499 DEBUGFUNC("fm10k_mbx_push_tail");
501 /* determine length of data to push */
502 len = fm10k_fifo_unused(fifo) - mbx->pushed;
506 /* update head and record bytes received */
507 mbx->head = fm10k_mbx_head_add(mbx, len);
510 /* nothing to do if there is no data */
512 return FM10K_SUCCESS;
514 /* Copy msg into Rx FIFO */
515 fm10k_mbx_read_copy(hw, mbx);
517 /* determine if there are any invalid lengths in message */
518 if (fm10k_mbx_validate_msg_size(mbx, len))
519 return FM10K_MBX_ERR_SIZE;
524 /* flush any completed messages */
525 for (len = fm10k_mbx_pushed_tail_len(mbx);
526 len && (mbx->pushed >= len);
527 len = fm10k_mbx_pushed_tail_len(mbx)) {
531 mbx->rx_dwords += len;
534 return FM10K_SUCCESS;
537 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
538 static const u16 fm10k_crc_16b_table[256] = {
539 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
540 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
541 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
542 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
543 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
544 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
545 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
546 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
547 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
548 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
549 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
550 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
551 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
552 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
553 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
554 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
555 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
556 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
557 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
558 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
559 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
560 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
561 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
562 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
563 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
564 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
565 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
566 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
567 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
568 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
569 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
570 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
573 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
574 * @data: pointer to data to process
575 * @seed: seed value for CRC
576 * @len: length measured in 16 bits words
578 * This function will generate a CRC based on the polynomial 0xAC9A and
579 * whatever value is stored in the seed variable. Note that this
580 * value inverts the local seed and the result in order to capture all
581 * leading and trailing zeros.
583 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
589 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
590 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
595 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
596 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
603 * fm10k_fifo_crc - generate a CRC based off of FIFO data
604 * @fifo: pointer to FIFO
605 * @offset: offset point for start of FIFO
606 * @len: number of DWORDS words to process
607 * @seed: seed value for CRC
609 * This function generates a CRC for some region of the FIFO
611 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
614 u32 *data = fifo->buffer + offset;
616 /* track when we should cross the end of the FIFO */
617 offset = fifo->size - offset;
619 /* if we are in 2 blocks process the end of the FIFO first */
621 seed = fm10k_crc_16b(data, seed, offset * 2);
626 /* process any remaining bits */
627 return fm10k_crc_16b(data, seed, len * 2);
631 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
632 * @mbx: pointer to mailbox
633 * @head: head index provided by remote mailbox
635 * This function will generate the CRC for all data from the end of the
636 * last head update to the current one. It uses the result of the
637 * previous CRC as the seed for this update. The result is stored in
640 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
642 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
644 /* determine the offset for the start of the region to be pulled */
645 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
647 /* update local CRC to include all of the pulled data */
648 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
652 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
653 * @mbx: pointer to mailbox
655 * This function will take all data that has been provided from the remote
656 * end and generate a CRC for it. This is stored in mbx->remote. The
657 * CRC for the header is then computed and if the result is non-zero this
658 * is an error and we signal an error dropping all data and resetting the
661 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
663 struct fm10k_mbx_fifo *fifo = &mbx->rx;
664 u16 len = mbx->head_len;
665 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
668 /* update the remote CRC if new data has been received */
670 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
672 /* process the full header as we have to validate the CRC */
673 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
675 /* notify other end if we have a problem */
676 return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
680 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
681 * @mbx: pointer to mailbox
683 * This function returns true if there is a message in the Rx FIFO to dequeue.
685 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
687 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
689 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
693 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
694 * @mbx: pointer to mailbox
695 * @len: verify free space is >= this value
697 * This function returns true if the mailbox is in a state ready to transmit.
699 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
701 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
703 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
707 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
708 * @mbx: pointer to mailbox
710 * This function returns true if the Tx FIFO is empty.
712 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
714 return fm10k_fifo_empty(&mbx->tx);
718 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
719 * @hw: pointer to hardware structure
720 * @mbx: pointer to mailbox
722 * This function dequeues messages and hands them off to the tlv parser.
723 * It will return the number of messages processed when called.
725 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
726 struct fm10k_mbx_info *mbx)
728 struct fm10k_mbx_fifo *fifo = &mbx->rx;
732 /* parse Rx messages out of the Rx FIFO to empty it */
733 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
734 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
739 fm10k_fifo_head_drop(fifo);
742 /* shift remaining bytes back to start of FIFO */
743 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
745 /* shift head and tail based on the memory we moved */
746 fifo->tail -= fifo->head;
753 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
754 * @hw: pointer to hardware structure
755 * @mbx: pointer to mailbox
756 * @msg: message array to read
758 * This function enqueues a message up to the size specified by the length
759 * contained in the first DWORD of the message and will place at the tail
760 * of the FIFO. It will return 0 on success, or a negative value on error.
762 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
763 struct fm10k_mbx_info *mbx, const u32 *msg)
765 u32 countdown = mbx->timeout;
768 switch (mbx->state) {
769 case FM10K_STATE_CLOSED:
770 case FM10K_STATE_DISCONNECT:
771 return FM10K_MBX_ERR_NO_MBX;
776 /* enqueue the message on the Tx FIFO */
777 err = fm10k_fifo_enqueue(&mbx->tx, msg);
779 /* if it failed give the FIFO a chance to drain */
780 while (err && countdown) {
782 usec_delay(mbx->usec_delay);
783 mbx->ops.process(hw, mbx);
784 err = fm10k_fifo_enqueue(&mbx->tx, msg);
787 /* if we failed treat the error */
793 /* begin processing message, ignore errors as this is just meant
794 * to start the mailbox flow so we are not concerned if there
795 * is a bad error, or the mailbox is already busy with a request
798 mbx->ops.process(hw, mbx);
800 return FM10K_SUCCESS;
804 * fm10k_mbx_read - Copies the mbmem to local message buffer
805 * @hw: pointer to hardware structure
806 * @mbx: pointer to mailbox
808 * This function copies the message from the mbmem to the message array
810 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
812 DEBUGFUNC("fm10k_mbx_read");
814 /* only allow one reader in here at a time */
816 return FM10K_MBX_ERR_BUSY;
818 /* read to capture initial interrupt bits */
819 if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
820 mbx->mbx_lock = FM10K_MBX_ACK;
822 /* write back interrupt bits to clear */
823 FM10K_WRITE_MBX(hw, mbx->mbx_reg,
824 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
826 /* read remote header */
827 mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
829 return FM10K_SUCCESS;
833 * fm10k_mbx_write - Copies the local message buffer to mbmem
834 * @hw: pointer to hardware structure
835 * @mbx: pointer to mailbox
837 * This function copies the message from the the message array to mbmem
839 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
841 u32 mbmem = mbx->mbmem_reg;
843 DEBUGFUNC("fm10k_mbx_write");
845 /* write new msg header to notify recipient of change */
846 FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
848 /* write mailbox to send interrupt */
850 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
852 /* we no longer are using the header so free it */
858 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
859 * @mbx: pointer to mailbox
861 * This function returns a connection mailbox header
863 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
865 mbx->mbx_lock |= FM10K_MBX_REQ;
867 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
868 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
869 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
873 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
874 * @mbx: pointer to mailbox
876 * This function returns a data mailbox header
878 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
880 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
881 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
882 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
883 struct fm10k_mbx_fifo *fifo = &mbx->tx;
887 mbx->mbx_lock |= FM10K_MBX_REQ;
889 /* generate CRC for data in flight and header */
890 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
891 mbx->tail_len, mbx->local);
892 crc = fm10k_crc_16b(&hdr, crc, 1);
894 /* load header to memory to be written */
895 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
899 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
900 * @mbx: pointer to mailbox
902 * This function returns a disconnect mailbox header
904 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
906 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
907 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
908 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
909 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
911 mbx->mbx_lock |= FM10K_MBX_ACK;
913 /* load header to memory to be written */
914 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
918 * fm10k_mbx_create_error_msg - Generate a error message
919 * @mbx: pointer to mailbox
920 * @err: local error encountered
922 * This function will interpret the error provided by err, and based on
923 * that it may shift the message by 1 DWORD and then place an error header
924 * at the start of the message.
926 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
928 /* only generate an error message for these types */
930 case FM10K_MBX_ERR_TAIL:
931 case FM10K_MBX_ERR_HEAD:
932 case FM10K_MBX_ERR_TYPE:
933 case FM10K_MBX_ERR_SIZE:
934 case FM10K_MBX_ERR_RSVD0:
935 case FM10K_MBX_ERR_CRC:
941 mbx->mbx_lock |= FM10K_MBX_REQ;
943 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
944 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
945 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
949 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
950 * @mbx: pointer to mailbox
951 * @msg: message array to read
953 * This function will parse up the fields in the mailbox header and return
954 * an error if the header contains any of a number of invalid configurations
955 * including unrecognized type, invalid route, or a malformed message.
957 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
959 u16 type, rsvd0, head, tail, size;
960 const u32 *hdr = &mbx->mbx_hdr;
962 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
964 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
965 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
966 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
967 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
968 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
971 return FM10K_MBX_ERR_RSVD0;
974 case FM10K_MSG_DISCONNECT:
975 /* validate that all data has been received */
976 if (tail != mbx->head)
977 return FM10K_MBX_ERR_TAIL;
981 /* validate that head is moving correctly */
982 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
983 return FM10K_MBX_ERR_HEAD;
984 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
985 return FM10K_MBX_ERR_HEAD;
987 /* validate that tail is moving correctly */
988 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
989 return FM10K_MBX_ERR_TAIL;
990 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
993 return FM10K_MBX_ERR_TAIL;
994 case FM10K_MSG_CONNECT:
995 /* validate size is in range and is power of 2 mask */
996 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
997 return FM10K_MBX_ERR_SIZE;
1000 case FM10K_MSG_ERROR:
1001 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1002 return FM10K_MBX_ERR_HEAD;
1003 /* neither create nor error include a tail offset */
1005 return FM10K_MBX_ERR_TAIL;
1009 return FM10K_MBX_ERR_TYPE;
1012 return FM10K_SUCCESS;
1016 * fm10k_mbx_create_reply - Generate reply based on state and remote head
1017 * @mbx: pointer to mailbox
1018 * @head: acknowledgement number
1020 * This function will generate an outgoing message based on the current
1021 * mailbox state and the remote fifo head. It will return the length
1022 * of the outgoing message excluding header on success, and a negative value
1025 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1026 struct fm10k_mbx_info *mbx, u16 head)
1028 switch (mbx->state) {
1029 case FM10K_STATE_OPEN:
1030 case FM10K_STATE_DISCONNECT:
1031 /* update our checksum for the outgoing data */
1032 fm10k_mbx_update_local_crc(mbx, head);
1034 /* as long as other end recognizes us keep sending data */
1035 fm10k_mbx_pull_head(hw, mbx, head);
1037 /* generate new header based on data */
1038 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1039 fm10k_mbx_create_data_hdr(mbx);
1041 fm10k_mbx_create_disconnect_hdr(mbx);
1043 case FM10K_STATE_CONNECT:
1044 /* send disconnect even if we aren't connected */
1045 fm10k_mbx_create_connect_hdr(mbx);
1047 case FM10K_STATE_CLOSED:
1048 /* generate new header based on data */
1049 fm10k_mbx_create_disconnect_hdr(mbx);
1054 return FM10K_SUCCESS;
1058 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1059 * @mbx: pointer to mailbox
1061 * This function will reset all internal pointers so any work in progress
1062 * is dropped. This call should occur every time we transition from the
1063 * open state to the connect state.
1065 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1067 /* reset our outgoing max size back to Rx limits */
1068 mbx->max_size = mbx->rx.size - 1;
1070 /* just do a quick resysnc to start of message */
1080 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1081 * @mbx: pointer to mailbox
1082 * @size: new value for max_size
1084 * This function will update the max_size value and drop any outgoing messages
1085 * from the head of the Tx FIFO that are larger than max_size.
1087 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1091 DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1093 mbx->max_size = size;
1095 /* flush any oversized messages from the queue */
1096 for (len = fm10k_fifo_head_len(&mbx->tx);
1098 len = fm10k_fifo_head_len(&mbx->tx)) {
1099 fm10k_fifo_head_drop(&mbx->tx);
1105 * fm10k_mbx_connect_reset - Reset following request for reset
1106 * @mbx: pointer to mailbox
1108 * This function resets the mailbox to either a disconnected state
1109 * or a connect state depending on the current mailbox state
1111 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1113 /* just do a quick resysnc to start of frame */
1114 fm10k_mbx_reset_work(mbx);
1116 /* reset CRC seeds */
1117 mbx->local = FM10K_MBX_CRC_SEED;
1118 mbx->remote = FM10K_MBX_CRC_SEED;
1120 /* we cannot exit connect until the size is good */
1121 if (mbx->state == FM10K_STATE_OPEN)
1122 mbx->state = FM10K_STATE_CONNECT;
1124 mbx->state = FM10K_STATE_CLOSED;
1128 * fm10k_mbx_process_connect - Process connect header
1129 * @mbx: pointer to mailbox
1130 * @msg: message array to process
1132 * This function will read an incoming connect header and reply with the
1133 * appropriate message. It will return a value indicating the number of
1134 * data DWORDs on success, or will return a negative value on failure.
1136 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1137 struct fm10k_mbx_info *mbx)
1139 const enum fm10k_mbx_state state = mbx->state;
1140 const u32 *hdr = &mbx->mbx_hdr;
1143 /* we will need to pull all of the fields for verification */
1144 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1145 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1148 case FM10K_STATE_DISCONNECT:
1149 case FM10K_STATE_OPEN:
1150 /* reset any in-progress work */
1151 fm10k_mbx_connect_reset(mbx);
1153 case FM10K_STATE_CONNECT:
1154 /* we cannot exit connect until the size is good */
1155 if (size > mbx->rx.size) {
1156 mbx->max_size = mbx->rx.size - 1;
1158 /* record the remote system requesting connection */
1159 mbx->state = FM10K_STATE_OPEN;
1161 fm10k_mbx_update_max_size(mbx, size);
1168 /* align our tail index to remote head index */
1171 return fm10k_mbx_create_reply(hw, mbx, head);
1175 * fm10k_mbx_process_data - Process data header
1176 * @mbx: pointer to mailbox
1178 * This function will read an incoming data header and reply with the
1179 * appropriate message. It will return a value indicating the number of
1180 * data DWORDs on success, or will return a negative value on failure.
1182 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1183 struct fm10k_mbx_info *mbx)
1185 const u32 *hdr = &mbx->mbx_hdr;
1189 DEBUGFUNC("fm10k_mbx_process_data");
1191 /* we will need to pull all of the fields for verification */
1192 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1193 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1195 /* if we are in connect just update our data and go */
1196 if (mbx->state == FM10K_STATE_CONNECT) {
1198 mbx->state = FM10K_STATE_OPEN;
1201 /* abort on message size errors */
1202 err = fm10k_mbx_push_tail(hw, mbx, tail);
1206 /* verify the checksum on the incoming data */
1207 err = fm10k_mbx_verify_remote_crc(mbx);
1211 /* process messages if we have received any */
1212 fm10k_mbx_dequeue_rx(hw, mbx);
1214 return fm10k_mbx_create_reply(hw, mbx, head);
1218 * fm10k_mbx_process_disconnect - Process disconnect header
1219 * @mbx: pointer to mailbox
1221 * This function will read an incoming disconnect header and reply with the
1222 * appropriate message. It will return a value indicating the number of
1223 * data DWORDs on success, or will return a negative value on failure.
1225 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1226 struct fm10k_mbx_info *mbx)
1228 const enum fm10k_mbx_state state = mbx->state;
1229 const u32 *hdr = &mbx->mbx_hdr;
1233 /* we will need to pull the header field for verification */
1234 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1236 /* We should not be receiving disconnect if Rx is incomplete */
1238 return FM10K_MBX_ERR_TAIL;
1240 /* we have already verified mbx->head == tail so we know this is 0 */
1243 /* verify the checksum on the incoming header is correct */
1244 err = fm10k_mbx_verify_remote_crc(mbx);
1249 case FM10K_STATE_DISCONNECT:
1250 case FM10K_STATE_OPEN:
1251 /* state doesn't change if we still have work to do */
1252 if (!fm10k_mbx_tx_complete(mbx))
1255 /* verify the head indicates we completed all transmits */
1256 if (head != mbx->tail)
1257 return FM10K_MBX_ERR_HEAD;
1259 /* reset any in-progress work */
1260 fm10k_mbx_connect_reset(mbx);
1266 return fm10k_mbx_create_reply(hw, mbx, head);
1270 * fm10k_mbx_process_error - Process error header
1271 * @mbx: pointer to mailbox
1273 * This function will read an incoming error header and reply with the
1274 * appropriate message. It will return a value indicating the number of
1275 * data DWORDs on success, or will return a negative value on failure.
1277 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1278 struct fm10k_mbx_info *mbx)
1280 const u32 *hdr = &mbx->mbx_hdr;
1284 /* we will need to pull all of the fields for verification */
1285 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1287 /* we only have lower 10 bits of error number so add upper bits */
1288 err_no = FM10K_MSG_HDR_FIELD_GET(*hdr, ERR_NO);
1289 err_no |= ~FM10K_MSG_HDR_MASK(ERR_NO);
1291 switch (mbx->state) {
1292 case FM10K_STATE_OPEN:
1293 case FM10K_STATE_DISCONNECT:
1294 /* flush any uncompleted work */
1295 fm10k_mbx_reset_work(mbx);
1297 /* reset CRC seeds */
1298 mbx->local = FM10K_MBX_CRC_SEED;
1299 mbx->remote = FM10K_MBX_CRC_SEED;
1301 /* reset tail index and size to prepare for reconnect */
1304 /* if open then reset max_size and go back to connect */
1305 if (mbx->state == FM10K_STATE_OPEN) {
1306 mbx->state = FM10K_STATE_CONNECT;
1310 /* send a connect message to get data flowing again */
1311 fm10k_mbx_create_connect_hdr(mbx);
1312 return FM10K_SUCCESS;
1317 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1321 * fm10k_mbx_process - Process mailbox interrupt
1322 * @hw: pointer to hardware structure
1323 * @mbx: pointer to mailbox
1325 * This function will process incoming mailbox events and generate mailbox
1326 * replies. It will return a value indicating the number of DWORDs
1327 * transmitted excluding header on success or a negative value on error.
1329 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1330 struct fm10k_mbx_info *mbx)
1334 DEBUGFUNC("fm10k_mbx_process");
1336 /* we do not read mailbox if closed */
1337 if (mbx->state == FM10K_STATE_CLOSED)
1338 return FM10K_SUCCESS;
1340 /* copy data from mailbox */
1341 err = fm10k_mbx_read(hw, mbx);
1345 /* validate type, source, and destination */
1346 err = fm10k_mbx_validate_msg_hdr(mbx);
1350 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1351 case FM10K_MSG_CONNECT:
1352 err = fm10k_mbx_process_connect(hw, mbx);
1354 case FM10K_MSG_DATA:
1355 err = fm10k_mbx_process_data(hw, mbx);
1357 case FM10K_MSG_DISCONNECT:
1358 err = fm10k_mbx_process_disconnect(hw, mbx);
1360 case FM10K_MSG_ERROR:
1361 err = fm10k_mbx_process_error(hw, mbx);
1364 err = FM10K_MBX_ERR_TYPE;
1369 /* notify partner of errors on our end */
1371 fm10k_mbx_create_error_msg(mbx, err);
1373 /* copy data from mailbox */
1374 fm10k_mbx_write(hw, mbx);
1380 * fm10k_mbx_disconnect - Shutdown mailbox connection
1381 * @hw: pointer to hardware structure
1382 * @mbx: pointer to mailbox
1384 * This function will shut down the mailbox. It places the mailbox first
1385 * in the disconnect state, it then allows up to a predefined timeout for
1386 * the mailbox to transition to close on its own. If this does not occur
1387 * then the mailbox will be forced into the closed state.
1389 * Any mailbox transactions not completed before calling this function
1390 * are not guaranteed to complete and may be dropped.
1392 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1393 struct fm10k_mbx_info *mbx)
1395 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1397 DEBUGFUNC("fm10k_mbx_disconnect");
1399 /* Place mbx in ready to disconnect state */
1400 mbx->state = FM10K_STATE_DISCONNECT;
1402 /* trigger interrupt to start shutdown process */
1403 FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1404 FM10K_MBX_INTERRUPT_DISABLE);
1406 usec_delay(FM10K_MBX_POLL_DELAY);
1407 mbx->ops.process(hw, mbx);
1408 timeout -= FM10K_MBX_POLL_DELAY;
1409 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1411 /* in case we didn't close just force the mailbox into shutdown */
1412 fm10k_mbx_connect_reset(mbx);
1413 fm10k_mbx_update_max_size(mbx, 0);
1415 FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1419 * fm10k_mbx_connect - Start mailbox connection
1420 * @hw: pointer to hardware structure
1421 * @mbx: pointer to mailbox
1423 * This function will initiate a mailbox connection. It will populate the
1424 * mailbox with a broadcast connect message and then initialize the lock.
1425 * This is safe since the connect message is a single DWORD so the mailbox
1426 * transaction is guaranteed to be atomic.
1428 * This function will return an error if the mailbox has not been initiated
1429 * or is currently in use.
1431 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1433 DEBUGFUNC("fm10k_mbx_connect");
1435 /* we cannot connect an uninitialized mailbox */
1436 if (!mbx->rx.buffer)
1437 return FM10K_MBX_ERR_NO_SPACE;
1439 /* we cannot connect an already connected mailbox */
1440 if (mbx->state != FM10K_STATE_CLOSED)
1441 return FM10K_MBX_ERR_BUSY;
1443 /* mailbox timeout can now become active */
1444 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1446 /* Place mbx in ready to connect state */
1447 mbx->state = FM10K_STATE_CONNECT;
1449 /* initialize header of remote mailbox */
1450 fm10k_mbx_create_disconnect_hdr(mbx);
1451 FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1453 /* enable interrupt and notify other party of new message */
1454 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1455 FM10K_MBX_INTERRUPT_ENABLE;
1457 /* generate and load connect header into mailbox */
1458 fm10k_mbx_create_connect_hdr(mbx);
1459 fm10k_mbx_write(hw, mbx);
1461 return FM10K_SUCCESS;
1465 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1466 * @msg_data: handlers for mailbox events
1468 * This function validates the layout of the message parsing data. This
1469 * should be mostly static, but it is important to catch any errors that
1470 * are made when constructing the parsers.
1472 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1474 const struct fm10k_tlv_attr *attr;
1477 DEBUGFUNC("fm10k_mbx_validate_handlers");
1479 /* Allow NULL mailboxes that transmit but don't receive */
1481 return FM10K_SUCCESS;
1483 while (msg_data->id != FM10K_TLV_ERROR) {
1484 /* all messages should have a function handler */
1485 if (!msg_data->func)
1486 return FM10K_ERR_PARAM;
1488 /* parser is optional */
1489 attr = msg_data->attr;
1491 while (attr->id != FM10K_TLV_ERROR) {
1494 /* ID should always be increasing */
1496 return FM10K_ERR_PARAM;
1497 /* ID should fit in results array */
1498 if (id >= FM10K_TLV_RESULTS_MAX)
1499 return FM10K_ERR_PARAM;
1502 /* verify terminator is in the list */
1503 if (attr->id != FM10K_TLV_ERROR)
1504 return FM10K_ERR_PARAM;
1509 /* ID should always be increasing */
1510 if (id >= msg_data->id)
1511 return FM10K_ERR_PARAM;
1514 /* verify terminator is in the list */
1515 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1516 return FM10K_ERR_PARAM;
1518 return FM10K_SUCCESS;
1522 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1523 * @mbx: pointer to mailbox
1524 * @msg_data: handlers for mailbox events
1526 * This function associates a set of message handling ops with a mailbox.
1528 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1529 const struct fm10k_msg_data *msg_data)
1531 DEBUGFUNC("fm10k_mbx_register_handlers");
1533 /* validate layout of handlers before assigning them */
1534 if (fm10k_mbx_validate_handlers(msg_data))
1535 return FM10K_ERR_PARAM;
1537 /* initialize the message handlers */
1538 mbx->msg_data = msg_data;
1540 return FM10K_SUCCESS;
1544 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1545 * @hw: pointer to hardware structure
1546 * @mbx: pointer to mailbox
1547 * @msg_data: handlers for mailbox events
1548 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1550 * This function initializes the mailbox for use. It will split the
1551 * buffer provided an use that th populate both the Tx and Rx FIFO by
1552 * evenly splitting it. In order to allow for easy masking of head/tail
1553 * the value reported in size must be a power of 2 and is reported in
1554 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1557 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1558 const struct fm10k_msg_data *msg_data, u8 id)
1560 DEBUGFUNC("fm10k_pfvf_mbx_init");
1562 /* initialize registers */
1563 switch (hw->mac.type) {
1565 mbx->mbx_reg = FM10K_VFMBX;
1566 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1569 /* there are only 64 VF <-> PF mailboxes */
1571 mbx->mbx_reg = FM10K_MBX(id);
1572 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1577 return FM10K_MBX_ERR_NO_MBX;
1580 /* start out in closed state */
1581 mbx->state = FM10K_STATE_CLOSED;
1583 /* validate layout of handlers before assigning them */
1584 if (fm10k_mbx_validate_handlers(msg_data))
1585 return FM10K_ERR_PARAM;
1587 /* initialize the message handlers */
1588 mbx->msg_data = msg_data;
1590 /* start mailbox as timed out and let the reset_hw call
1591 * set the timeout value to begin communications
1594 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1596 /* initialize tail and head */
1600 /* initialize CRC seeds */
1601 mbx->local = FM10K_MBX_CRC_SEED;
1602 mbx->remote = FM10K_MBX_CRC_SEED;
1604 /* Split buffer for use by Tx/Rx FIFOs */
1605 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1606 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1608 /* initialize the FIFOs, sizes are in 4 byte increments */
1609 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1610 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1611 FM10K_MBX_RX_BUFFER_SIZE);
1613 /* initialize function pointers */
1614 mbx->ops.connect = fm10k_mbx_connect;
1615 mbx->ops.disconnect = fm10k_mbx_disconnect;
1616 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1617 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1618 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1619 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1620 mbx->ops.process = fm10k_mbx_process;
1621 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1623 return FM10K_SUCCESS;
1627 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1628 * @mbx: pointer to mailbox
1630 * This function returns a connection mailbox header
1632 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1635 mbx->mbx_lock |= FM10K_MBX_REQ;
1637 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1638 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1639 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1643 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1644 * @mbx: pointer to mailbox
1645 * @err: error flags to report if any
1647 * This function returns a connection mailbox header
1649 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1652 mbx->mbx_lock |= FM10K_MBX_REQ;
1654 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1655 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1656 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1657 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1661 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1662 * @mbx: pointer to mailbox
1664 * This function resets the mailbox to a just connected state
1666 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1668 /* flush any uncompleted work */
1669 fm10k_mbx_reset_work(mbx);
1671 /* set local version to max and remote version to 0 */
1672 mbx->local = FM10K_SM_MBX_VERSION;
1675 /* initialize tail and head */
1679 /* reset state back to connect */
1680 mbx->state = FM10K_STATE_CONNECT;
1684 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1685 * @hw: pointer to hardware structure
1686 * @mbx: pointer to mailbox
1688 * This function will initiate a mailbox connection with the switch
1689 * manager. To do this it will first disconnect the mailbox, and then
1690 * reconnect it in order to complete a reset of the mailbox.
1692 * This function will return an error if the mailbox has not been initiated
1693 * or is currently in use.
1695 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1697 DEBUGFUNC("fm10k_mbx_connect");
1699 /* we cannot connect an uninitialized mailbox */
1700 if (!mbx->rx.buffer)
1701 return FM10K_MBX_ERR_NO_SPACE;
1703 /* we cannot connect an already connected mailbox */
1704 if (mbx->state != FM10K_STATE_CLOSED)
1705 return FM10K_MBX_ERR_BUSY;
1707 /* mailbox timeout can now become active */
1708 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1710 /* Place mbx in ready to connect state */
1711 mbx->state = FM10K_STATE_CONNECT;
1712 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1714 /* reset interface back to connect */
1715 fm10k_sm_mbx_connect_reset(mbx);
1717 /* enable interrupt and notify other party of new message */
1718 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1719 FM10K_MBX_INTERRUPT_ENABLE;
1721 /* generate and load connect header into mailbox */
1722 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1723 fm10k_mbx_write(hw, mbx);
1725 /* enable interrupt and notify other party of new message */
1727 return FM10K_SUCCESS;
1731 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1732 * @hw: pointer to hardware structure
1733 * @mbx: pointer to mailbox
1735 * This function will shut down the mailbox. It places the mailbox first
1736 * in the disconnect state, it then allows up to a predefined timeout for
1737 * the mailbox to transition to close on its own. If this does not occur
1738 * then the mailbox will be forced into the closed state.
1740 * Any mailbox transactions not completed before calling this function
1741 * are not guaranteed to complete and may be dropped.
1743 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1744 struct fm10k_mbx_info *mbx)
1746 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1748 DEBUGFUNC("fm10k_sm_mbx_disconnect");
1750 /* Place mbx in ready to disconnect state */
1751 mbx->state = FM10K_STATE_DISCONNECT;
1753 /* trigger interrupt to start shutdown process */
1754 FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1755 FM10K_MBX_INTERRUPT_DISABLE);
1757 usec_delay(FM10K_MBX_POLL_DELAY);
1758 mbx->ops.process(hw, mbx);
1759 timeout -= FM10K_MBX_POLL_DELAY;
1760 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1762 /* in case we didn't close just force the mailbox into shutdown */
1763 mbx->state = FM10K_STATE_CLOSED;
1765 fm10k_mbx_reset_work(mbx);
1766 fm10k_mbx_update_max_size(mbx, 0);
1768 FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1772 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1773 * @mbx: pointer to mailbox
1775 * This function will parse up the fields in the mailbox header and return
1776 * an error if the header contains any of a number of invalid configurations
1777 * including unrecognized offsets or version numbers.
1779 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1781 const u32 *hdr = &mbx->mbx_hdr;
1782 u16 tail, head, ver;
1784 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1786 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1787 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1788 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1793 case FM10K_SM_MBX_VERSION:
1794 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1795 return FM10K_MBX_ERR_HEAD;
1796 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1797 return FM10K_MBX_ERR_TAIL;
1798 if (mbx->tail < head)
1799 head += mbx->mbmem_len - 1;
1800 if (tail < mbx->head)
1801 tail += mbx->mbmem_len - 1;
1802 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1803 return FM10K_MBX_ERR_HEAD;
1804 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1806 return FM10K_MBX_ERR_TAIL;
1808 return FM10K_MBX_ERR_SRC;
1811 return FM10K_SUCCESS;
1815 * fm10k_sm_mbx_process_error - Process header with error flag set
1816 * @mbx: pointer to mailbox
1818 * This function is meant to respond to a request where the error flag
1819 * is set. As a result we will terminate a connection if one is present
1820 * and fall back into the reset state with a connection header of version
1823 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1825 const enum fm10k_mbx_state state = mbx->state;
1828 case FM10K_STATE_DISCONNECT:
1829 /* if there is an error just disconnect */
1832 case FM10K_STATE_OPEN:
1833 /* flush any uncompleted work */
1834 fm10k_sm_mbx_connect_reset(mbx);
1836 case FM10K_STATE_CONNECT:
1837 /* try connnecting at lower version */
1839 while (mbx->local > 1)
1848 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1852 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1853 * @mbx: pointer to mailbox
1854 * @err: local error encountered
1856 * This function will interpret the error provided by err, and based on
1857 * that it may set the error bit in the local message header
1859 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1861 /* only generate an error message for these types */
1863 case FM10K_MBX_ERR_TAIL:
1864 case FM10K_MBX_ERR_HEAD:
1865 case FM10K_MBX_ERR_SRC:
1866 case FM10K_MBX_ERR_SIZE:
1867 case FM10K_MBX_ERR_RSVD0:
1873 /* process it as though we received an error, and send error reply */
1874 fm10k_sm_mbx_process_error(mbx);
1875 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1879 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1880 * @hw: pointer to hardware structure
1881 * @mbx: pointer to mailbox
1883 * This function will dequeue one message from the Rx switch manager mailbox
1884 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1886 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1887 struct fm10k_mbx_info *mbx,
1890 /* reduce length by 1 to convert to a mask */
1891 u16 mbmem_len = mbx->mbmem_len - 1;
1894 DEBUGFUNC("fm10k_sm_mbx_receive");
1896 /* push tail in front of head */
1897 if (tail < mbx->head)
1900 /* copy data to the Rx FIFO */
1901 err = fm10k_mbx_push_tail(hw, mbx, tail);
1905 /* process messages if we have received any */
1906 fm10k_mbx_dequeue_rx(hw, mbx);
1908 /* guarantee head aligns with the end of the last message */
1909 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1912 /* clear any extra bits left over since index adds 1 extra bit */
1913 if (mbx->head > mbmem_len)
1914 mbx->head -= mbmem_len;
1920 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1921 * @hw: pointer to hardware structure
1922 * @mbx: pointer to mailbox
1924 * This function will dequeue one message from the Tx mailbox FIFO and place
1925 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1927 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1928 struct fm10k_mbx_info *mbx, u16 head)
1930 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1931 /* reduce length by 1 to convert to a mask */
1932 u16 mbmem_len = mbx->mbmem_len - 1;
1933 u16 tail_len, len = 0;
1936 DEBUGFUNC("fm10k_sm_mbx_transmit");
1938 /* push head behind tail */
1939 if (mbx->tail < head)
1942 fm10k_mbx_pull_head(hw, mbx, head);
1944 /* determine msg aligned offset for end of buffer */
1946 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1948 len += FM10K_TLV_DWORD_LEN(*msg);
1949 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1951 /* guarantee we stop on a message boundary */
1952 if (mbx->tail_len > tail_len) {
1953 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1954 mbx->tail_len = tail_len;
1957 /* clear any extra bits left over since index adds 1 extra bit */
1958 if (mbx->tail > mbmem_len)
1959 mbx->tail -= mbmem_len;
1963 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1964 * @mbx: pointer to mailbox
1965 * @head: acknowledgement number
1967 * This function will generate an outgoing message based on the current
1968 * mailbox state and the remote fifo head. It will return the length
1969 * of the outgoing message excluding header on success, and a negative value
1972 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1973 struct fm10k_mbx_info *mbx, u16 head)
1975 switch (mbx->state) {
1976 case FM10K_STATE_OPEN:
1977 case FM10K_STATE_DISCONNECT:
1978 /* flush out Tx data */
1979 fm10k_sm_mbx_transmit(hw, mbx, head);
1981 /* generate new header based on data */
1982 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1983 fm10k_sm_mbx_create_data_hdr(mbx);
1986 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1989 case FM10K_STATE_CONNECT:
1990 case FM10K_STATE_CLOSED:
1991 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1999 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2000 * @hw: pointer to hardware structure
2001 * @mbx: pointer to mailbox
2003 * This function is meant to respond to a request where the version data
2004 * is set to 0. As such we will either terminate the connection or go
2005 * into the connect state in order to re-establish the connection. This
2006 * function can also be used to respond to an error as the connection
2007 * resetting would also be a means of dealing with errors.
2009 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2010 struct fm10k_mbx_info *mbx)
2012 const enum fm10k_mbx_state state = mbx->state;
2015 case FM10K_STATE_DISCONNECT:
2016 /* drop remote connections and disconnect */
2017 mbx->state = FM10K_STATE_CLOSED;
2021 case FM10K_STATE_OPEN:
2022 /* flush any incomplete work */
2023 fm10k_sm_mbx_connect_reset(mbx);
2025 case FM10K_STATE_CONNECT:
2026 /* Update remote value to match local value */
2027 mbx->remote = mbx->local;
2032 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2036 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2037 * @hw: pointer to hardware structure
2038 * @mbx: pointer to mailbox
2040 * This function is meant to process messages received when the remote
2041 * mailbox is active.
2043 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2044 struct fm10k_mbx_info *mbx)
2046 const u32 *hdr = &mbx->mbx_hdr;
2050 /* pull all fields needed for verification */
2051 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2052 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2054 /* if we are in connect and wanting version 1 then start up and go */
2055 if (mbx->state == FM10K_STATE_CONNECT) {
2058 if (mbx->remote != 1)
2059 return FM10K_MBX_ERR_SRC;
2061 mbx->state = FM10K_STATE_OPEN;
2065 /* abort on message size errors */
2066 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2070 /* continue until we have flushed the Rx FIFO */
2074 fm10k_sm_mbx_create_reply(hw, mbx, head);
2076 return FM10K_SUCCESS;
2080 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2081 * @hw: pointer to hardware structure
2082 * @mbx: pointer to mailbox
2084 * This function will process incoming mailbox events and generate mailbox
2085 * replies. It will return a value indicating the number of DWORDs
2086 * transmitted excluding header on success or a negative value on error.
2088 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2089 struct fm10k_mbx_info *mbx)
2093 DEBUGFUNC("fm10k_sm_mbx_process");
2095 /* we do not read mailbox if closed */
2096 if (mbx->state == FM10K_STATE_CLOSED)
2097 return FM10K_SUCCESS;
2099 /* retrieve data from switch manager */
2100 err = fm10k_mbx_read(hw, mbx);
2104 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2108 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2109 fm10k_sm_mbx_process_error(mbx);
2113 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2115 fm10k_sm_mbx_process_reset(hw, mbx);
2117 case FM10K_SM_MBX_VERSION:
2118 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2124 fm10k_sm_mbx_create_error_msg(mbx, err);
2126 /* report data to switch manager */
2127 fm10k_mbx_write(hw, mbx);
2133 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2134 * @hw: pointer to hardware structure
2135 * @mbx: pointer to mailbox
2136 * @msg_data: handlers for mailbox events
2138 * This function for now is used to stub out the PF/SM mailbox
2140 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2141 const struct fm10k_msg_data *msg_data)
2143 DEBUGFUNC("fm10k_sm_mbx_init");
2144 UNREFERENCED_1PARAMETER(hw);
2146 mbx->mbx_reg = FM10K_GMBX;
2147 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2149 /* start out in closed state */
2150 mbx->state = FM10K_STATE_CLOSED;
2152 /* validate layout of handlers before assigning them */
2153 if (fm10k_mbx_validate_handlers(msg_data))
2154 return FM10K_ERR_PARAM;
2156 /* initialize the message handlers */
2157 mbx->msg_data = msg_data;
2159 /* start mailbox as timed out and let the reset_hw call
2160 * set the timeout value to begin communications
2163 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2165 /* Split buffer for use by Tx/Rx FIFOs */
2166 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2167 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2169 /* initialize the FIFOs, sizes are in 4 byte increments */
2170 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2171 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2172 FM10K_MBX_RX_BUFFER_SIZE);
2174 /* initialize function pointers */
2175 mbx->ops.connect = fm10k_sm_mbx_connect;
2176 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2177 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2178 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2179 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2180 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2181 mbx->ops.process = fm10k_sm_mbx_process;
2182 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2184 return FM10K_SUCCESS;