1 /*******************************************************************************
3 Copyright (c) 2013 - 2015, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 ***************************************************************************/
34 #include "fm10k_common.h"
37 * fm10k_fifo_init - Initialize a message FIFO
38 * @fifo: pointer to FIFO
39 * @buffer: pointer to memory to be used to store FIFO
40 * @size: maximum message size to store in FIFO, must be 2^n - 1
42 STATIC void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
44 fifo->buffer = buffer;
51 * fm10k_fifo_used - Retrieve used space in FIFO
52 * @fifo: pointer to FIFO
54 * This function returns the number of DWORDs used in the FIFO
56 STATIC u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
58 return fifo->tail - fifo->head;
62 * fm10k_fifo_unused - Retrieve unused space in FIFO
63 * @fifo: pointer to FIFO
65 * This function returns the number of unused DWORDs in the FIFO
67 STATIC u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
69 return fifo->size + fifo->head - fifo->tail;
73 * fm10k_fifo_empty - Test to verify if fifo is empty
74 * @fifo: pointer to FIFO
76 * This function returns true if the FIFO is empty, else false
78 STATIC bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
80 return fifo->head == fifo->tail;
84 * fm10k_fifo_head_offset - returns indices of head with given offset
85 * @fifo: pointer to FIFO
86 * @offset: offset to add to head
88 * This function returns the indices into the fifo based on head + offset
90 STATIC u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
92 return (fifo->head + offset) & (fifo->size - 1);
96 * fm10k_fifo_tail_offset - returns indices of tail with given offset
97 * @fifo: pointer to FIFO
98 * @offset: offset to add to tail
100 * This function returns the indices into the fifo based on tail + offset
102 STATIC u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
104 return (fifo->tail + offset) & (fifo->size - 1);
108 * fm10k_fifo_head_len - Retrieve length of first message in FIFO
109 * @fifo: pointer to FIFO
111 * This function returns the size of the first message in the FIFO
113 STATIC u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
115 u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
117 /* verify there is at least 1 DWORD in the fifo so *head is valid */
118 if (fm10k_fifo_empty(fifo))
121 /* retieve the message length */
122 return FM10K_TLV_DWORD_LEN(*head);
126 * fm10k_fifo_head_drop - Drop the first message in FIFO
127 * @fifo: pointer to FIFO
129 * This function returns the size of the message dropped from the FIFO
131 STATIC u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
133 u16 len = fm10k_fifo_head_len(fifo);
135 /* update head so it is at the start of next frame */
142 * fm10k_fifo_drop_all - Drop all messages in FIFO
143 * @fifo: pointer to FIFO
145 * This function resets the head pointer to drop all messages in the FIFO and
146 * ensure the FIFO is empty.
148 STATIC void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
150 fifo->head = fifo->tail;
154 * fm10k_mbx_index_len - Convert a head/tail index into a length value
155 * @mbx: pointer to mailbox
159 * This function takes the head and tail index and determines the length
160 * of the data indicated by this pair.
162 STATIC u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
164 u16 len = tail - head;
166 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
170 return len & ((mbx->mbmem_len << 1) - 1);
174 * fm10k_mbx_tail_add - Determine new tail value with added offset
175 * @mbx: pointer to mailbox
176 * @offset: length to add to head offset
178 * This function takes the local tail index and recomputes it for
179 * a given length added as an offset.
181 STATIC u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
183 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
185 /* add/sub 1 because we cannot have offset 0 or all 1s */
186 return (tail > mbx->tail) ? --tail : ++tail;
190 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
191 * @mbx: pointer to mailbox
192 * @offset: length to add to head offset
194 * This function takes the local tail index and recomputes it for
195 * a given length added as an offset.
197 STATIC u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
199 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
201 /* sub/add 1 because we cannot have offset 0 or all 1s */
202 return (tail < mbx->tail) ? ++tail : --tail;
206 * fm10k_mbx_head_add - Determine new head value with added offset
207 * @mbx: pointer to mailbox
208 * @offset: length to add to head offset
210 * This function takes the local head index and recomputes it for
211 * a given length added as an offset.
213 STATIC u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
215 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
217 /* add/sub 1 because we cannot have offset 0 or all 1s */
218 return (head > mbx->head) ? --head : ++head;
222 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
223 * @mbx: pointer to mailbox
224 * @offset: length to add to head offset
226 * This function takes the local head index and recomputes it for
227 * a given length added as an offset.
229 STATIC u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
231 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
233 /* sub/add 1 because we cannot have offset 0 or all 1s */
234 return (head < mbx->head) ? ++head : --head;
238 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
239 * @mbx: pointer to mailbox
241 * This function will return the length of the message currently being
242 * pushed onto the tail of the Rx queue.
244 STATIC u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
246 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
248 /* pushed tail is only valid if pushed is set */
252 return FM10K_TLV_DWORD_LEN(*tail);
256 * fm10k_fifo_write_copy - pulls data off of msg and places it in fifo
257 * @fifo: pointer to FIFO
258 * @msg: message array to populate
259 * @tail_offset: additional offset to add to tail pointer
260 * @len: length of FIFO to copy into message header
262 * This function will take a message and copy it into a section of the
263 * FIFO. In order to get something into a location other than just
264 * the tail you can use tail_offset to adjust the pointer.
266 STATIC void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
267 const u32 *msg, u16 tail_offset, u16 len)
269 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
270 u32 *tail = fifo->buffer + end;
272 /* track when we should cross the end of the FIFO */
273 end = fifo->size - end;
275 /* copy end of message before start of message */
277 memcpy(fifo->buffer, msg + end, (len - end) << 2);
281 /* Copy remaining message into Tx FIFO */
282 memcpy(tail, msg, end << 2);
286 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
287 * @fifo: pointer to FIFO
288 * @msg: message array to read
290 * This function enqueues a message up to the size specified by the length
291 * contained in the first DWORD of the message and will place at the tail
292 * of the FIFO. It will return 0 on success, or a negative value on error.
294 STATIC s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
296 u16 len = FM10K_TLV_DWORD_LEN(*msg);
298 DEBUGFUNC("fm10k_fifo_enqueue");
300 /* verify parameters */
301 if (len > fifo->size)
302 return FM10K_MBX_ERR_SIZE;
304 /* verify there is room for the message */
305 if (len > fm10k_fifo_unused(fifo))
306 return FM10K_MBX_ERR_NO_SPACE;
308 /* Copy message into FIFO */
309 fm10k_fifo_write_copy(fifo, msg, 0, len);
311 /* memory barrier to guarantee FIFO is written before tail update */
314 /* Update Tx FIFO tail */
317 return FM10K_SUCCESS;
321 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
322 * @mbx: pointer to mailbox
323 * @len: length of data pushed onto buffer
325 * This function analyzes the frame and will return a non-zero value when
326 * the start of a message larger than the mailbox is detected.
328 STATIC u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
330 struct fm10k_mbx_fifo *fifo = &mbx->rx;
331 u16 total_len = 0, msg_len;
334 DEBUGFUNC("fm10k_mbx_validate_msg");
336 /* length should include previous amounts pushed */
339 /* offset in message is based off of current message size */
341 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
342 msg_len = FM10K_TLV_DWORD_LEN(*msg);
343 total_len += msg_len;
344 } while (total_len < len);
346 /* message extends out of pushed section, but fits in FIFO */
347 if ((len < total_len) && (msg_len <= mbx->max_size))
350 /* return length of invalid section */
351 return (len < total_len) ? len : (len - total_len);
355 * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
356 * @mbx: pointer to mailbox
358 * This function will take a section of the Tx FIFO and copy it into the
359 * mailbox memory. The offset in mbmem is based on the lower bits of the
360 * tail and len determines the length to copy.
362 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
363 struct fm10k_mbx_info *mbx)
365 struct fm10k_mbx_fifo *fifo = &mbx->tx;
366 u32 mbmem = mbx->mbmem_reg;
367 u32 *head = fifo->buffer;
368 u16 end, len, tail, mask;
370 DEBUGFUNC("fm10k_mbx_write_copy");
375 /* determine data length and mbmem tail index */
376 mask = mbx->mbmem_len - 1;
378 tail = fm10k_mbx_tail_sub(mbx, len);
382 /* determine offset in the ring */
383 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
386 /* memory barrier to guarantee data is ready to be read */
389 /* Copy message from Tx FIFO */
390 for (end = fifo->size - end; len; head = fifo->buffer) {
392 /* adjust tail to match offset for FIFO */
397 /* write message to hardware FIFO */
398 FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
399 } while (--len && --end);
404 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
405 * @hw: pointer to hardware structure
406 * @mbx: pointer to mailbox
407 * @head: acknowledgement number last received
409 * This function will push the tail index forward based on the remote
410 * head index. It will then pull up to mbmem_len DWORDs off of the
411 * head of the FIFO and will place it in the MBMEM registers
412 * associated with the mailbox.
414 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
415 struct fm10k_mbx_info *mbx, u16 head)
417 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
418 struct fm10k_mbx_fifo *fifo = &mbx->tx;
420 /* update number of bytes pulled and update bytes in transit */
421 mbx->pulled += mbx->tail_len - ack;
423 /* determine length of data to pull, reserve space for mbmem header */
424 mbmem_len = mbx->mbmem_len - 1;
425 len = fm10k_fifo_used(fifo) - mbx->pulled;
429 /* update tail and record number of bytes in transit */
430 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
433 /* drop pulled messages from the FIFO */
434 for (len = fm10k_fifo_head_len(fifo);
435 len && (mbx->pulled >= len);
436 len = fm10k_fifo_head_len(fifo)) {
437 mbx->pulled -= fm10k_fifo_head_drop(fifo);
439 mbx->tx_dwords += len;
442 /* Copy message out from the Tx FIFO */
443 fm10k_mbx_write_copy(hw, mbx);
447 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
448 * @hw: pointer to hardware structure
449 * @mbx: pointer to mailbox
451 * This function will take a section of the mailbox memory and copy it
452 * into the Rx FIFO. The offset is based on the lower bits of the
453 * head and len determines the length to copy.
455 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
456 struct fm10k_mbx_info *mbx)
458 struct fm10k_mbx_fifo *fifo = &mbx->rx;
459 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
460 u32 *tail = fifo->buffer;
463 DEBUGFUNC("fm10k_mbx_read_copy");
465 /* determine data length and mbmem head index */
467 head = fm10k_mbx_head_sub(mbx, len);
468 if (head >= mbx->mbmem_len)
471 /* determine offset in the ring */
472 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
475 /* Copy message into Rx FIFO */
476 for (end = fifo->size - end; len; tail = fifo->buffer) {
478 /* adjust head to match offset for FIFO */
479 head &= mbx->mbmem_len - 1;
483 /* read message from hardware FIFO */
484 *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
485 } while (--len && --end);
488 /* memory barrier to guarantee FIFO is written before tail update */
493 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
494 * @hw: pointer to hardware structure
495 * @mbx: pointer to mailbox
496 * @tail: tail index of message
498 * This function will first validate the tail index and size for the
499 * incoming message. It then updates the acknowledgment number and
500 * copies the data into the FIFO. It will return the number of messages
501 * dequeued on success and a negative value on error.
503 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
504 struct fm10k_mbx_info *mbx,
507 struct fm10k_mbx_fifo *fifo = &mbx->rx;
508 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
510 DEBUGFUNC("fm10k_mbx_push_tail");
512 /* determine length of data to push */
513 len = fm10k_fifo_unused(fifo) - mbx->pushed;
517 /* update head and record bytes received */
518 mbx->head = fm10k_mbx_head_add(mbx, len);
521 /* nothing to do if there is no data */
523 return FM10K_SUCCESS;
525 /* Copy msg into Rx FIFO */
526 fm10k_mbx_read_copy(hw, mbx);
528 /* determine if there are any invalid lengths in message */
529 if (fm10k_mbx_validate_msg_size(mbx, len))
530 return FM10K_MBX_ERR_SIZE;
535 /* flush any completed messages */
536 for (len = fm10k_mbx_pushed_tail_len(mbx);
537 len && (mbx->pushed >= len);
538 len = fm10k_mbx_pushed_tail_len(mbx)) {
542 mbx->rx_dwords += len;
545 return FM10K_SUCCESS;
548 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
549 static const u16 fm10k_crc_16b_table[256] = {
550 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
551 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
552 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
553 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
554 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
555 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
556 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
557 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
558 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
559 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
560 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
561 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
562 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
563 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
564 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
565 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
566 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
567 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
568 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
569 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
570 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
571 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
572 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
573 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
574 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
575 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
576 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
577 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
578 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
579 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
580 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
581 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
584 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
585 * @data: pointer to data to process
586 * @seed: seed value for CRC
587 * @len: length measured in 16 bits words
589 * This function will generate a CRC based on the polynomial 0xAC9A and
590 * whatever value is stored in the seed variable. Note that this
591 * value inverts the local seed and the result in order to capture all
592 * leading and trailing zeros.
594 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
600 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
601 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
606 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
607 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
614 * fm10k_fifo_crc - generate a CRC based off of FIFO data
615 * @fifo: pointer to FIFO
616 * @offset: offset point for start of FIFO
617 * @len: number of DWORDS words to process
618 * @seed: seed value for CRC
620 * This function generates a CRC for some region of the FIFO
622 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
625 u32 *data = fifo->buffer + offset;
627 /* track when we should cross the end of the FIFO */
628 offset = fifo->size - offset;
630 /* if we are in 2 blocks process the end of the FIFO first */
632 seed = fm10k_crc_16b(data, seed, offset * 2);
637 /* process any remaining bits */
638 return fm10k_crc_16b(data, seed, len * 2);
642 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
643 * @mbx: pointer to mailbox
644 * @head: head index provided by remote mailbox
646 * This function will generate the CRC for all data from the end of the
647 * last head update to the current one. It uses the result of the
648 * previous CRC as the seed for this update. The result is stored in
651 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
653 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
655 /* determine the offset for the start of the region to be pulled */
656 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
658 /* update local CRC to include all of the pulled data */
659 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
663 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
664 * @mbx: pointer to mailbox
666 * This function will take all data that has been provided from the remote
667 * end and generate a CRC for it. This is stored in mbx->remote. The
668 * CRC for the header is then computed and if the result is non-zero this
669 * is an error and we signal an error dropping all data and resetting the
672 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
674 struct fm10k_mbx_fifo *fifo = &mbx->rx;
675 u16 len = mbx->head_len;
676 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
679 /* update the remote CRC if new data has been received */
681 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
683 /* process the full header as we have to validate the CRC */
684 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
686 /* notify other end if we have a problem */
687 return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
691 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
692 * @mbx: pointer to mailbox
694 * This function returns true if there is a message in the Rx FIFO to dequeue.
696 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
698 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
700 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
704 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
705 * @mbx: pointer to mailbox
706 * @len: verify free space is >= this value
708 * This function returns true if the mailbox is in a state ready to transmit.
710 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
712 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
714 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
718 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
719 * @mbx: pointer to mailbox
721 * This function returns true if the Tx FIFO is empty.
723 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
725 return fm10k_fifo_empty(&mbx->tx);
729 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
730 * @hw: pointer to hardware structure
731 * @mbx: pointer to mailbox
733 * This function dequeues messages and hands them off to the tlv parser.
734 * It will return the number of messages processed when called.
736 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
737 struct fm10k_mbx_info *mbx)
739 struct fm10k_mbx_fifo *fifo = &mbx->rx;
743 /* parse Rx messages out of the Rx FIFO to empty it */
744 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
745 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
750 fm10k_fifo_head_drop(fifo);
753 /* shift remaining bytes back to start of FIFO */
754 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
756 /* shift head and tail based on the memory we moved */
757 fifo->tail -= fifo->head;
764 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
765 * @hw: pointer to hardware structure
766 * @mbx: pointer to mailbox
767 * @msg: message array to read
769 * This function enqueues a message up to the size specified by the length
770 * contained in the first DWORD of the message and will place at the tail
771 * of the FIFO. It will return 0 on success, or a negative value on error.
773 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
774 struct fm10k_mbx_info *mbx, const u32 *msg)
776 u32 countdown = mbx->timeout;
779 switch (mbx->state) {
780 case FM10K_STATE_CLOSED:
781 case FM10K_STATE_DISCONNECT:
782 return FM10K_MBX_ERR_NO_MBX;
787 /* enqueue the message on the Tx FIFO */
788 err = fm10k_fifo_enqueue(&mbx->tx, msg);
790 /* if it failed give the FIFO a chance to drain */
791 while (err && countdown) {
793 usec_delay(mbx->usec_delay);
794 mbx->ops.process(hw, mbx);
795 err = fm10k_fifo_enqueue(&mbx->tx, msg);
798 /* if we failed treat the error */
804 /* begin processing message, ignore errors as this is just meant
805 * to start the mailbox flow so we are not concerned if there
806 * is a bad error, or the mailbox is already busy with a request
809 mbx->ops.process(hw, mbx);
811 return FM10K_SUCCESS;
815 * fm10k_mbx_read - Copies the mbmem to local message buffer
816 * @hw: pointer to hardware structure
817 * @mbx: pointer to mailbox
819 * This function copies the message from the mbmem to the message array
821 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
823 DEBUGFUNC("fm10k_mbx_read");
825 /* only allow one reader in here at a time */
827 return FM10K_MBX_ERR_BUSY;
829 /* read to capture initial interrupt bits */
830 if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
831 mbx->mbx_lock = FM10K_MBX_ACK;
833 /* write back interrupt bits to clear */
834 FM10K_WRITE_MBX(hw, mbx->mbx_reg,
835 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
837 /* read remote header */
838 mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
840 return FM10K_SUCCESS;
844 * fm10k_mbx_write - Copies the local message buffer to mbmem
845 * @hw: pointer to hardware structure
846 * @mbx: pointer to mailbox
848 * This function copies the message from the the message array to mbmem
850 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
852 u32 mbmem = mbx->mbmem_reg;
854 DEBUGFUNC("fm10k_mbx_write");
856 /* write new msg header to notify recipient of change */
857 FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
859 /* write mailbox to send interrupt */
861 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
863 /* we no longer are using the header so free it */
869 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
870 * @mbx: pointer to mailbox
872 * This function returns a connection mailbox header
874 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
876 mbx->mbx_lock |= FM10K_MBX_REQ;
878 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
879 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
880 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
884 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
885 * @mbx: pointer to mailbox
887 * This function returns a data mailbox header
889 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
891 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
892 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
893 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
894 struct fm10k_mbx_fifo *fifo = &mbx->tx;
898 mbx->mbx_lock |= FM10K_MBX_REQ;
900 /* generate CRC for data in flight and header */
901 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
902 mbx->tail_len, mbx->local);
903 crc = fm10k_crc_16b(&hdr, crc, 1);
905 /* load header to memory to be written */
906 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
910 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
911 * @mbx: pointer to mailbox
913 * This function returns a disconnect mailbox header
915 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
917 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
918 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
919 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
920 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
922 mbx->mbx_lock |= FM10K_MBX_ACK;
924 /* load header to memory to be written */
925 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
929 * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mailbox header
930 * @mbx: pointer to mailbox
932 * This function creates a fake disconnect header for loading into remote
933 * mailbox header. The primary purpose is to prevent errors on immediate
934 * start up after mbx->connect.
936 STATIC void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
938 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
939 FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
940 FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
941 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
943 mbx->mbx_lock |= FM10K_MBX_ACK;
945 /* load header to memory to be written */
946 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
950 * fm10k_mbx_create_error_msg - Generate a error message
951 * @mbx: pointer to mailbox
952 * @err: local error encountered
954 * This function will interpret the error provided by err, and based on
955 * that it may shift the message by 1 DWORD and then place an error header
956 * at the start of the message.
958 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
960 /* only generate an error message for these types */
962 case FM10K_MBX_ERR_TAIL:
963 case FM10K_MBX_ERR_HEAD:
964 case FM10K_MBX_ERR_TYPE:
965 case FM10K_MBX_ERR_SIZE:
966 case FM10K_MBX_ERR_RSVD0:
967 case FM10K_MBX_ERR_CRC:
973 mbx->mbx_lock |= FM10K_MBX_REQ;
975 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
976 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
977 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
981 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
982 * @mbx: pointer to mailbox
983 * @msg: message array to read
985 * This function will parse up the fields in the mailbox header and return
986 * an error if the header contains any of a number of invalid configurations
987 * including unrecognized type, invalid route, or a malformed message.
989 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
991 u16 type, rsvd0, head, tail, size;
992 const u32 *hdr = &mbx->mbx_hdr;
994 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
996 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
997 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
998 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
999 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1000 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1003 return FM10K_MBX_ERR_RSVD0;
1006 case FM10K_MSG_DISCONNECT:
1007 /* validate that all data has been received */
1008 if (tail != mbx->head)
1009 return FM10K_MBX_ERR_TAIL;
1012 case FM10K_MSG_DATA:
1013 /* validate that head is moving correctly */
1014 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1015 return FM10K_MBX_ERR_HEAD;
1016 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1017 return FM10K_MBX_ERR_HEAD;
1019 /* validate that tail is moving correctly */
1020 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
1021 return FM10K_MBX_ERR_TAIL;
1022 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1025 return FM10K_MBX_ERR_TAIL;
1026 case FM10K_MSG_CONNECT:
1027 /* validate size is in range and is power of 2 mask */
1028 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
1029 return FM10K_MBX_ERR_SIZE;
1032 case FM10K_MSG_ERROR:
1033 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1034 return FM10K_MBX_ERR_HEAD;
1035 /* neither create nor error include a tail offset */
1037 return FM10K_MBX_ERR_TAIL;
1041 return FM10K_MBX_ERR_TYPE;
1044 return FM10K_SUCCESS;
1048 * fm10k_mbx_create_reply - Generate reply based on state and remote head
1049 * @mbx: pointer to mailbox
1050 * @head: acknowledgement number
1052 * This function will generate an outgoing message based on the current
1053 * mailbox state and the remote fifo head. It will return the length
1054 * of the outgoing message excluding header on success, and a negative value
1057 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1058 struct fm10k_mbx_info *mbx, u16 head)
1060 switch (mbx->state) {
1061 case FM10K_STATE_OPEN:
1062 case FM10K_STATE_DISCONNECT:
1063 /* update our checksum for the outgoing data */
1064 fm10k_mbx_update_local_crc(mbx, head);
1066 /* as long as other end recognizes us keep sending data */
1067 fm10k_mbx_pull_head(hw, mbx, head);
1069 /* generate new header based on data */
1070 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1071 fm10k_mbx_create_data_hdr(mbx);
1073 fm10k_mbx_create_disconnect_hdr(mbx);
1075 case FM10K_STATE_CONNECT:
1076 /* send disconnect even if we aren't connected */
1077 fm10k_mbx_create_connect_hdr(mbx);
1079 case FM10K_STATE_CLOSED:
1080 /* generate new header based on data */
1081 fm10k_mbx_create_disconnect_hdr(mbx);
1086 return FM10K_SUCCESS;
1090 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1091 * @mbx: pointer to mailbox
1093 * This function will reset all internal pointers so any work in progress
1094 * is dropped. This call should occur every time we transition from the
1095 * open state to the connect state.
1097 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1101 /* reset our outgoing max size back to Rx limits */
1102 mbx->max_size = mbx->rx.size - 1;
1104 /* update mbx->pulled to account for tail_len and ack */
1105 head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1106 ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1107 mbx->pulled += mbx->tail_len - ack;
1109 /* now drop any messages which have started or finished transmitting */
1110 while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1111 len = fm10k_fifo_head_drop(&mbx->tx);
1113 if (mbx->pulled >= len)
1119 /* just do a quick resysnc to start of message */
1129 * fm10k_mbx_update_max_size - Update the max_size and drop large messages
1130 * @mbx: pointer to mailbox
1131 * @size: new value for max_size
1133 * This function updates the max_size value and drops any outgoing messages
1134 * at the head of the Tx FIFO if they are larger than max_size. It does not
1135 * drop all messages, as this is too difficult to parse and remove them from
1136 * the FIFO. Instead, rely on the checking to ensure that messages larger
1137 * than max_size aren't pushed into the memory buffer.
1139 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1143 DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1145 mbx->max_size = size;
1147 /* flush any oversized messages from the queue */
1148 for (len = fm10k_fifo_head_len(&mbx->tx);
1150 len = fm10k_fifo_head_len(&mbx->tx)) {
1151 fm10k_fifo_head_drop(&mbx->tx);
1157 * fm10k_mbx_connect_reset - Reset following request for reset
1158 * @mbx: pointer to mailbox
1160 * This function resets the mailbox to either a disconnected state
1161 * or a connect state depending on the current mailbox state
1163 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1165 /* just do a quick resysnc to start of frame */
1166 fm10k_mbx_reset_work(mbx);
1168 /* reset CRC seeds */
1169 mbx->local = FM10K_MBX_CRC_SEED;
1170 mbx->remote = FM10K_MBX_CRC_SEED;
1172 /* we cannot exit connect until the size is good */
1173 if (mbx->state == FM10K_STATE_OPEN)
1174 mbx->state = FM10K_STATE_CONNECT;
1176 mbx->state = FM10K_STATE_CLOSED;
1180 * fm10k_mbx_process_connect - Process connect header
1181 * @mbx: pointer to mailbox
1182 * @msg: message array to process
1184 * This function will read an incoming connect header and reply with the
1185 * appropriate message. It will return a value indicating the number of
1186 * data DWORDs on success, or will return a negative value on failure.
1188 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1189 struct fm10k_mbx_info *mbx)
1191 const enum fm10k_mbx_state state = mbx->state;
1192 const u32 *hdr = &mbx->mbx_hdr;
1195 /* we will need to pull all of the fields for verification */
1196 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1197 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1200 case FM10K_STATE_DISCONNECT:
1201 case FM10K_STATE_OPEN:
1202 /* reset any in-progress work */
1203 fm10k_mbx_connect_reset(mbx);
1205 case FM10K_STATE_CONNECT:
1206 /* we cannot exit connect until the size is good */
1207 if (size > mbx->rx.size) {
1208 mbx->max_size = mbx->rx.size - 1;
1210 /* record the remote system requesting connection */
1211 mbx->state = FM10K_STATE_OPEN;
1213 fm10k_mbx_update_max_size(mbx, size);
1220 /* align our tail index to remote head index */
1223 return fm10k_mbx_create_reply(hw, mbx, head);
1227 * fm10k_mbx_process_data - Process data header
1228 * @mbx: pointer to mailbox
1230 * This function will read an incoming data header and reply with the
1231 * appropriate message. It will return a value indicating the number of
1232 * data DWORDs on success, or will return a negative value on failure.
1234 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1235 struct fm10k_mbx_info *mbx)
1237 const u32 *hdr = &mbx->mbx_hdr;
1241 DEBUGFUNC("fm10k_mbx_process_data");
1243 /* we will need to pull all of the fields for verification */
1244 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1245 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1247 /* if we are in connect just update our data and go */
1248 if (mbx->state == FM10K_STATE_CONNECT) {
1250 mbx->state = FM10K_STATE_OPEN;
1253 /* abort on message size errors */
1254 err = fm10k_mbx_push_tail(hw, mbx, tail);
1258 /* verify the checksum on the incoming data */
1259 err = fm10k_mbx_verify_remote_crc(mbx);
1263 /* process messages if we have received any */
1264 fm10k_mbx_dequeue_rx(hw, mbx);
1266 return fm10k_mbx_create_reply(hw, mbx, head);
1270 * fm10k_mbx_process_disconnect - Process disconnect header
1271 * @mbx: pointer to mailbox
1273 * This function will read an incoming disconnect 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_disconnect(struct fm10k_hw *hw,
1278 struct fm10k_mbx_info *mbx)
1280 const enum fm10k_mbx_state state = mbx->state;
1281 const u32 *hdr = &mbx->mbx_hdr;
1285 /* we will need to pull the header field for verification */
1286 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1288 /* We should not be receiving disconnect if Rx is incomplete */
1290 return FM10K_MBX_ERR_TAIL;
1292 /* we have already verified mbx->head == tail so we know this is 0 */
1295 /* verify the checksum on the incoming header is correct */
1296 err = fm10k_mbx_verify_remote_crc(mbx);
1301 case FM10K_STATE_DISCONNECT:
1302 case FM10K_STATE_OPEN:
1303 /* state doesn't change if we still have work to do */
1304 if (!fm10k_mbx_tx_complete(mbx))
1307 /* verify the head indicates we completed all transmits */
1308 if (head != mbx->tail)
1309 return FM10K_MBX_ERR_HEAD;
1311 /* reset any in-progress work */
1312 fm10k_mbx_connect_reset(mbx);
1318 return fm10k_mbx_create_reply(hw, mbx, head);
1322 * fm10k_mbx_process_error - Process error header
1323 * @mbx: pointer to mailbox
1325 * This function will read an incoming error header and reply with the
1326 * appropriate message. It will return a value indicating the number of
1327 * data DWORDs on success, or will return a negative value on failure.
1329 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1330 struct fm10k_mbx_info *mbx)
1332 const u32 *hdr = &mbx->mbx_hdr;
1335 /* we will need to pull all of the fields for verification */
1336 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1338 switch (mbx->state) {
1339 case FM10K_STATE_OPEN:
1340 case FM10K_STATE_DISCONNECT:
1341 /* flush any uncompleted work */
1342 fm10k_mbx_reset_work(mbx);
1344 /* reset CRC seeds */
1345 mbx->local = FM10K_MBX_CRC_SEED;
1346 mbx->remote = FM10K_MBX_CRC_SEED;
1348 /* reset tail index and size to prepare for reconnect */
1351 /* if open then reset max_size and go back to connect */
1352 if (mbx->state == FM10K_STATE_OPEN) {
1353 mbx->state = FM10K_STATE_CONNECT;
1357 /* send a connect message to get data flowing again */
1358 fm10k_mbx_create_connect_hdr(mbx);
1359 return FM10K_SUCCESS;
1364 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1368 * fm10k_mbx_process - Process mailbox interrupt
1369 * @hw: pointer to hardware structure
1370 * @mbx: pointer to mailbox
1372 * This function will process incoming mailbox events and generate mailbox
1373 * replies. It will return a value indicating the number of DWORDs
1374 * transmitted excluding header on success or a negative value on error.
1376 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1377 struct fm10k_mbx_info *mbx)
1381 DEBUGFUNC("fm10k_mbx_process");
1383 /* we do not read mailbox if closed */
1384 if (mbx->state == FM10K_STATE_CLOSED)
1385 return FM10K_SUCCESS;
1387 /* copy data from mailbox */
1388 err = fm10k_mbx_read(hw, mbx);
1392 /* validate type, source, and destination */
1393 err = fm10k_mbx_validate_msg_hdr(mbx);
1397 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1398 case FM10K_MSG_CONNECT:
1399 err = fm10k_mbx_process_connect(hw, mbx);
1401 case FM10K_MSG_DATA:
1402 err = fm10k_mbx_process_data(hw, mbx);
1404 case FM10K_MSG_DISCONNECT:
1405 err = fm10k_mbx_process_disconnect(hw, mbx);
1407 case FM10K_MSG_ERROR:
1408 err = fm10k_mbx_process_error(hw, mbx);
1411 err = FM10K_MBX_ERR_TYPE;
1416 /* notify partner of errors on our end */
1418 fm10k_mbx_create_error_msg(mbx, err);
1420 /* copy data from mailbox */
1421 fm10k_mbx_write(hw, mbx);
1427 * fm10k_mbx_disconnect - Shutdown mailbox connection
1428 * @hw: pointer to hardware structure
1429 * @mbx: pointer to mailbox
1431 * This function will shut down the mailbox. It places the mailbox first
1432 * in the disconnect state, it then allows up to a predefined timeout for
1433 * the mailbox to transition to close on its own. If this does not occur
1434 * then the mailbox will be forced into the closed state.
1436 * Any mailbox transactions not completed before calling this function
1437 * are not guaranteed to complete and may be dropped.
1439 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1440 struct fm10k_mbx_info *mbx)
1442 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1444 DEBUGFUNC("fm10k_mbx_disconnect");
1446 /* Place mbx in ready to disconnect state */
1447 mbx->state = FM10K_STATE_DISCONNECT;
1449 /* trigger interrupt to start shutdown process */
1450 FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1451 FM10K_MBX_INTERRUPT_DISABLE);
1453 usec_delay(FM10K_MBX_POLL_DELAY);
1454 mbx->ops.process(hw, mbx);
1455 timeout -= FM10K_MBX_POLL_DELAY;
1456 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1458 /* in case we didn't close, just force the mailbox into shutdown and
1459 * drop all left over messages in the FIFO.
1461 fm10k_mbx_connect_reset(mbx);
1462 fm10k_fifo_drop_all(&mbx->tx);
1464 FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1468 * fm10k_mbx_connect - Start mailbox connection
1469 * @hw: pointer to hardware structure
1470 * @mbx: pointer to mailbox
1472 * This function will initiate a mailbox connection. It will populate the
1473 * mailbox with a broadcast connect message and then initialize the lock.
1474 * This is safe since the connect message is a single DWORD so the mailbox
1475 * transaction is guaranteed to be atomic.
1477 * This function will return an error if the mailbox has not been initiated
1478 * or is currently in use.
1480 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1482 DEBUGFUNC("fm10k_mbx_connect");
1484 /* we cannot connect an uninitialized mailbox */
1485 if (!mbx->rx.buffer)
1486 return FM10K_MBX_ERR_NO_SPACE;
1488 /* we cannot connect an already connected mailbox */
1489 if (mbx->state != FM10K_STATE_CLOSED)
1490 return FM10K_MBX_ERR_BUSY;
1492 /* mailbox timeout can now become active */
1493 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1495 /* Place mbx in ready to connect state */
1496 mbx->state = FM10K_STATE_CONNECT;
1498 fm10k_mbx_reset_work(mbx);
1500 fm10k_mbx_create_fake_disconnect_hdr(mbx);
1501 FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1503 /* enable interrupt and notify other party of new message */
1504 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1505 FM10K_MBX_INTERRUPT_ENABLE;
1507 /* generate and load connect header into mailbox */
1508 fm10k_mbx_create_connect_hdr(mbx);
1509 fm10k_mbx_write(hw, mbx);
1511 return FM10K_SUCCESS;
1515 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1516 * @msg_data: handlers for mailbox events
1518 * This function validates the layout of the message parsing data. This
1519 * should be mostly static, but it is important to catch any errors that
1520 * are made when constructing the parsers.
1522 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1524 const struct fm10k_tlv_attr *attr;
1527 DEBUGFUNC("fm10k_mbx_validate_handlers");
1529 /* Allow NULL mailboxes that transmit but don't receive */
1531 return FM10K_SUCCESS;
1533 while (msg_data->id != FM10K_TLV_ERROR) {
1534 /* all messages should have a function handler */
1535 if (!msg_data->func)
1536 return FM10K_ERR_PARAM;
1538 /* parser is optional */
1539 attr = msg_data->attr;
1541 while (attr->id != FM10K_TLV_ERROR) {
1544 /* ID should always be increasing */
1546 return FM10K_ERR_PARAM;
1547 /* ID should fit in results array */
1548 if (id >= FM10K_TLV_RESULTS_MAX)
1549 return FM10K_ERR_PARAM;
1552 /* verify terminator is in the list */
1553 if (attr->id != FM10K_TLV_ERROR)
1554 return FM10K_ERR_PARAM;
1559 /* ID should always be increasing */
1560 if (id >= msg_data->id)
1561 return FM10K_ERR_PARAM;
1564 /* verify terminator is in the list */
1565 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1566 return FM10K_ERR_PARAM;
1568 return FM10K_SUCCESS;
1572 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1573 * @mbx: pointer to mailbox
1574 * @msg_data: handlers for mailbox events
1576 * This function associates a set of message handling ops with a mailbox.
1578 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1579 const struct fm10k_msg_data *msg_data)
1581 DEBUGFUNC("fm10k_mbx_register_handlers");
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 return FM10K_SUCCESS;
1594 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1595 * @hw: pointer to hardware structure
1596 * @mbx: pointer to mailbox
1597 * @msg_data: handlers for mailbox events
1598 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1600 * This function initializes the mailbox for use. It will split the
1601 * buffer provided an use that th populate both the Tx and Rx FIFO by
1602 * evenly splitting it. In order to allow for easy masking of head/tail
1603 * the value reported in size must be a power of 2 and is reported in
1604 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1607 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1608 const struct fm10k_msg_data *msg_data, u8 id)
1610 DEBUGFUNC("fm10k_pfvf_mbx_init");
1612 /* initialize registers */
1613 switch (hw->mac.type) {
1615 mbx->mbx_reg = FM10K_VFMBX;
1616 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1619 /* there are only 64 VF <-> PF mailboxes */
1621 mbx->mbx_reg = FM10K_MBX(id);
1622 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1627 return FM10K_MBX_ERR_NO_MBX;
1630 /* start out in closed state */
1631 mbx->state = FM10K_STATE_CLOSED;
1633 /* validate layout of handlers before assigning them */
1634 if (fm10k_mbx_validate_handlers(msg_data))
1635 return FM10K_ERR_PARAM;
1637 /* initialize the message handlers */
1638 mbx->msg_data = msg_data;
1640 /* start mailbox as timed out and let the reset_hw call
1641 * set the timeout value to begin communications
1644 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1646 /* initialize tail and head */
1650 /* initialize CRC seeds */
1651 mbx->local = FM10K_MBX_CRC_SEED;
1652 mbx->remote = FM10K_MBX_CRC_SEED;
1654 /* Split buffer for use by Tx/Rx FIFOs */
1655 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1656 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1658 /* initialize the FIFOs, sizes are in 4 byte increments */
1659 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1660 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1661 FM10K_MBX_RX_BUFFER_SIZE);
1663 /* initialize function pointers */
1664 mbx->ops.connect = fm10k_mbx_connect;
1665 mbx->ops.disconnect = fm10k_mbx_disconnect;
1666 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1667 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1668 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1669 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1670 mbx->ops.process = fm10k_mbx_process;
1671 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1673 return FM10K_SUCCESS;
1677 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1678 * @mbx: pointer to mailbox
1680 * This function returns a connection mailbox header
1682 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1685 mbx->mbx_lock |= FM10K_MBX_REQ;
1687 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1688 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1689 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1693 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1694 * @mbx: pointer to mailbox
1695 * @err: error flags to report if any
1697 * This function returns a connection mailbox header
1699 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1702 mbx->mbx_lock |= FM10K_MBX_REQ;
1704 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1705 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1706 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1707 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1711 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1712 * @mbx: pointer to mailbox
1714 * This function resets the mailbox to a just connected state
1716 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1718 /* flush any uncompleted work */
1719 fm10k_mbx_reset_work(mbx);
1721 /* set local version to max and remote version to 0 */
1722 mbx->local = FM10K_SM_MBX_VERSION;
1725 /* initialize tail and head */
1729 /* reset state back to connect */
1730 mbx->state = FM10K_STATE_CONNECT;
1734 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1735 * @hw: pointer to hardware structure
1736 * @mbx: pointer to mailbox
1738 * This function will initiate a mailbox connection with the switch
1739 * manager. To do this it will first disconnect the mailbox, and then
1740 * reconnect it in order to complete a reset of the mailbox.
1742 * This function will return an error if the mailbox has not been initiated
1743 * or is currently in use.
1745 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1747 DEBUGFUNC("fm10k_mbx_connect");
1749 /* we cannot connect an uninitialized mailbox */
1750 if (!mbx->rx.buffer)
1751 return FM10K_MBX_ERR_NO_SPACE;
1753 /* we cannot connect an already connected mailbox */
1754 if (mbx->state != FM10K_STATE_CLOSED)
1755 return FM10K_MBX_ERR_BUSY;
1757 /* mailbox timeout can now become active */
1758 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1760 /* Place mbx in ready to connect state */
1761 mbx->state = FM10K_STATE_CONNECT;
1762 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1764 /* reset interface back to connect */
1765 fm10k_sm_mbx_connect_reset(mbx);
1767 /* enable interrupt and notify other party of new message */
1768 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1769 FM10K_MBX_INTERRUPT_ENABLE;
1771 /* generate and load connect header into mailbox */
1772 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1773 fm10k_mbx_write(hw, mbx);
1775 /* enable interrupt and notify other party of new message */
1777 return FM10K_SUCCESS;
1781 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1782 * @hw: pointer to hardware structure
1783 * @mbx: pointer to mailbox
1785 * This function will shut down the mailbox. It places the mailbox first
1786 * in the disconnect state, it then allows up to a predefined timeout for
1787 * the mailbox to transition to close on its own. If this does not occur
1788 * then the mailbox will be forced into the closed state.
1790 * Any mailbox transactions not completed before calling this function
1791 * are not guaranteed to complete and may be dropped.
1793 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1794 struct fm10k_mbx_info *mbx)
1796 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1798 DEBUGFUNC("fm10k_sm_mbx_disconnect");
1800 /* Place mbx in ready to disconnect state */
1801 mbx->state = FM10K_STATE_DISCONNECT;
1803 /* trigger interrupt to start shutdown process */
1804 FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1805 FM10K_MBX_INTERRUPT_DISABLE);
1807 usec_delay(FM10K_MBX_POLL_DELAY);
1808 mbx->ops.process(hw, mbx);
1809 timeout -= FM10K_MBX_POLL_DELAY;
1810 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1812 /* in case we didn't close just force the mailbox into shutdown */
1813 mbx->state = FM10K_STATE_CLOSED;
1815 fm10k_mbx_reset_work(mbx);
1816 fm10k_fifo_drop_all(&mbx->tx);
1818 FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1822 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1823 * @mbx: pointer to mailbox
1825 * This function will parse up the fields in the mailbox header and return
1826 * an error if the header contains any of a number of invalid configurations
1827 * including unrecognized offsets or version numbers.
1829 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1831 const u32 *hdr = &mbx->mbx_hdr;
1832 u16 tail, head, ver;
1834 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1836 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1837 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1838 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1843 case FM10K_SM_MBX_VERSION:
1844 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1845 return FM10K_MBX_ERR_HEAD;
1846 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1847 return FM10K_MBX_ERR_TAIL;
1848 if (mbx->tail < head)
1849 head += mbx->mbmem_len - 1;
1850 if (tail < mbx->head)
1851 tail += mbx->mbmem_len - 1;
1852 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1853 return FM10K_MBX_ERR_HEAD;
1854 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1856 return FM10K_MBX_ERR_TAIL;
1858 return FM10K_MBX_ERR_SRC;
1861 return FM10K_SUCCESS;
1865 * fm10k_sm_mbx_process_error - Process header with error flag set
1866 * @mbx: pointer to mailbox
1868 * This function is meant to respond to a request where the error flag
1869 * is set. As a result we will terminate a connection if one is present
1870 * and fall back into the reset state with a connection header of version
1873 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1875 const enum fm10k_mbx_state state = mbx->state;
1878 case FM10K_STATE_DISCONNECT:
1879 /* if there is an error just disconnect */
1882 case FM10K_STATE_OPEN:
1883 /* flush any uncompleted work */
1884 fm10k_sm_mbx_connect_reset(mbx);
1886 case FM10K_STATE_CONNECT:
1887 /* try connnecting at lower version */
1889 while (mbx->local > 1)
1898 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1902 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1903 * @mbx: pointer to mailbox
1904 * @err: local error encountered
1906 * This function will interpret the error provided by err, and based on
1907 * that it may set the error bit in the local message header
1909 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1911 /* only generate an error message for these types */
1913 case FM10K_MBX_ERR_TAIL:
1914 case FM10K_MBX_ERR_HEAD:
1915 case FM10K_MBX_ERR_SRC:
1916 case FM10K_MBX_ERR_SIZE:
1917 case FM10K_MBX_ERR_RSVD0:
1923 /* process it as though we received an error, and send error reply */
1924 fm10k_sm_mbx_process_error(mbx);
1925 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1929 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1930 * @hw: pointer to hardware structure
1931 * @mbx: pointer to mailbox
1933 * This function will dequeue one message from the Rx switch manager mailbox
1934 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1936 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1937 struct fm10k_mbx_info *mbx,
1940 /* reduce length by 1 to convert to a mask */
1941 u16 mbmem_len = mbx->mbmem_len - 1;
1944 DEBUGFUNC("fm10k_sm_mbx_receive");
1946 /* push tail in front of head */
1947 if (tail < mbx->head)
1950 /* copy data to the Rx FIFO */
1951 err = fm10k_mbx_push_tail(hw, mbx, tail);
1955 /* process messages if we have received any */
1956 fm10k_mbx_dequeue_rx(hw, mbx);
1958 /* guarantee head aligns with the end of the last message */
1959 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1962 /* clear any extra bits left over since index adds 1 extra bit */
1963 if (mbx->head > mbmem_len)
1964 mbx->head -= mbmem_len;
1970 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1971 * @hw: pointer to hardware structure
1972 * @mbx: pointer to mailbox
1974 * This function will dequeue one message from the Tx mailbox FIFO and place
1975 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1977 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1978 struct fm10k_mbx_info *mbx, u16 head)
1980 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1981 /* reduce length by 1 to convert to a mask */
1982 u16 mbmem_len = mbx->mbmem_len - 1;
1983 u16 tail_len, len = 0;
1986 DEBUGFUNC("fm10k_sm_mbx_transmit");
1988 /* push head behind tail */
1989 if (mbx->tail < head)
1992 fm10k_mbx_pull_head(hw, mbx, head);
1994 /* determine msg aligned offset for end of buffer */
1996 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1998 len += FM10K_TLV_DWORD_LEN(*msg);
1999 } while ((len <= mbx->tail_len) && (len < mbmem_len));
2001 /* guarantee we stop on a message boundary */
2002 if (mbx->tail_len > tail_len) {
2003 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
2004 mbx->tail_len = tail_len;
2007 /* clear any extra bits left over since index adds 1 extra bit */
2008 if (mbx->tail > mbmem_len)
2009 mbx->tail -= mbmem_len;
2013 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
2014 * @mbx: pointer to mailbox
2015 * @head: acknowledgement number
2017 * This function will generate an outgoing message based on the current
2018 * mailbox state and the remote fifo head. It will return the length
2019 * of the outgoing message excluding header on success, and a negative value
2022 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
2023 struct fm10k_mbx_info *mbx, u16 head)
2025 switch (mbx->state) {
2026 case FM10K_STATE_OPEN:
2027 case FM10K_STATE_DISCONNECT:
2028 /* flush out Tx data */
2029 fm10k_sm_mbx_transmit(hw, mbx, head);
2031 /* generate new header based on data */
2032 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
2033 fm10k_sm_mbx_create_data_hdr(mbx);
2036 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2039 case FM10K_STATE_CONNECT:
2040 case FM10K_STATE_CLOSED:
2041 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2049 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2050 * @hw: pointer to hardware structure
2051 * @mbx: pointer to mailbox
2053 * This function is meant to respond to a request where the version data
2054 * is set to 0. As such we will either terminate the connection or go
2055 * into the connect state in order to re-establish the connection. This
2056 * function can also be used to respond to an error as the connection
2057 * resetting would also be a means of dealing with errors.
2059 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2060 struct fm10k_mbx_info *mbx)
2062 const enum fm10k_mbx_state state = mbx->state;
2065 case FM10K_STATE_DISCONNECT:
2066 /* drop remote connections and disconnect */
2067 mbx->state = FM10K_STATE_CLOSED;
2071 case FM10K_STATE_OPEN:
2072 /* flush any incomplete work */
2073 fm10k_sm_mbx_connect_reset(mbx);
2075 case FM10K_STATE_CONNECT:
2076 /* Update remote value to match local value */
2077 mbx->remote = mbx->local;
2082 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2086 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2087 * @hw: pointer to hardware structure
2088 * @mbx: pointer to mailbox
2090 * This function is meant to process messages received when the remote
2091 * mailbox is active.
2093 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2094 struct fm10k_mbx_info *mbx)
2096 const u32 *hdr = &mbx->mbx_hdr;
2100 /* pull all fields needed for verification */
2101 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2102 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2104 /* if we are in connect and wanting version 1 then start up and go */
2105 if (mbx->state == FM10K_STATE_CONNECT) {
2108 if (mbx->remote != 1)
2109 return FM10K_MBX_ERR_SRC;
2111 mbx->state = FM10K_STATE_OPEN;
2115 /* abort on message size errors */
2116 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2120 /* continue until we have flushed the Rx FIFO */
2124 fm10k_sm_mbx_create_reply(hw, mbx, head);
2126 return FM10K_SUCCESS;
2130 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2131 * @hw: pointer to hardware structure
2132 * @mbx: pointer to mailbox
2134 * This function will process incoming mailbox events and generate mailbox
2135 * replies. It will return a value indicating the number of DWORDs
2136 * transmitted excluding header on success or a negative value on error.
2138 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2139 struct fm10k_mbx_info *mbx)
2143 DEBUGFUNC("fm10k_sm_mbx_process");
2145 /* we do not read mailbox if closed */
2146 if (mbx->state == FM10K_STATE_CLOSED)
2147 return FM10K_SUCCESS;
2149 /* retrieve data from switch manager */
2150 err = fm10k_mbx_read(hw, mbx);
2154 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2158 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2159 fm10k_sm_mbx_process_error(mbx);
2163 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2165 fm10k_sm_mbx_process_reset(hw, mbx);
2167 case FM10K_SM_MBX_VERSION:
2168 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2174 fm10k_sm_mbx_create_error_msg(mbx, err);
2176 /* report data to switch manager */
2177 fm10k_mbx_write(hw, mbx);
2183 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2184 * @hw: pointer to hardware structure
2185 * @mbx: pointer to mailbox
2186 * @msg_data: handlers for mailbox events
2188 * This function for now is used to stub out the PF/SM mailbox
2190 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2191 const struct fm10k_msg_data *msg_data)
2193 DEBUGFUNC("fm10k_sm_mbx_init");
2194 UNREFERENCED_1PARAMETER(hw);
2196 mbx->mbx_reg = FM10K_GMBX;
2197 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2199 /* start out in closed state */
2200 mbx->state = FM10K_STATE_CLOSED;
2202 /* validate layout of handlers before assigning them */
2203 if (fm10k_mbx_validate_handlers(msg_data))
2204 return FM10K_ERR_PARAM;
2206 /* initialize the message handlers */
2207 mbx->msg_data = msg_data;
2209 /* start mailbox as timed out and let the reset_hw call
2210 * set the timeout value to begin communications
2213 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2215 /* Split buffer for use by Tx/Rx FIFOs */
2216 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2217 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2219 /* initialize the FIFOs, sizes are in 4 byte increments */
2220 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2221 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2222 FM10K_MBX_RX_BUFFER_SIZE);
2224 /* initialize function pointers */
2225 mbx->ops.connect = fm10k_sm_mbx_connect;
2226 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2227 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2228 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2229 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2230 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2231 mbx->ops.process = fm10k_sm_mbx_process;
2232 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2234 return FM10K_SUCCESS;