1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2013 - 2015 Intel Corporation
5 #include "fm10k_common.h"
8 * fm10k_fifo_init - Initialize a message FIFO
9 * @fifo: pointer to FIFO
10 * @buffer: pointer to memory to be used to store FIFO
11 * @size: maximum message size to store in FIFO, must be 2^n - 1
13 STATIC void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
15 fifo->buffer = buffer;
22 * fm10k_fifo_used - Retrieve used space in FIFO
23 * @fifo: pointer to FIFO
25 * This function returns the number of DWORDs used in the FIFO
27 STATIC u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
29 return fifo->tail - fifo->head;
33 * fm10k_fifo_unused - Retrieve unused space in FIFO
34 * @fifo: pointer to FIFO
36 * This function returns the number of unused DWORDs in the FIFO
38 STATIC u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
40 return fifo->size + fifo->head - fifo->tail;
44 * fm10k_fifo_empty - Test to verify if FIFO is empty
45 * @fifo: pointer to FIFO
47 * This function returns true if the FIFO is empty, else false
49 STATIC bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
51 return fifo->head == fifo->tail;
55 * fm10k_fifo_head_offset - returns indices of head with given offset
56 * @fifo: pointer to FIFO
57 * @offset: offset to add to head
59 * This function returns the indices into the FIFO based on head + offset
61 STATIC u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
63 return (fifo->head + offset) & (fifo->size - 1);
67 * fm10k_fifo_tail_offset - returns indices of tail with given offset
68 * @fifo: pointer to FIFO
69 * @offset: offset to add to tail
71 * This function returns the indices into the FIFO based on tail + offset
73 STATIC u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
75 return (fifo->tail + offset) & (fifo->size - 1);
79 * fm10k_fifo_head_len - Retrieve length of first message in FIFO
80 * @fifo: pointer to FIFO
82 * This function returns the size of the first message in the FIFO
84 STATIC u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
86 u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
88 /* verify there is at least 1 DWORD in the fifo so *head is valid */
89 if (fm10k_fifo_empty(fifo))
92 /* retieve the message length */
93 return FM10K_TLV_DWORD_LEN(*head);
97 * fm10k_fifo_head_drop - Drop the first message in FIFO
98 * @fifo: pointer to FIFO
100 * This function returns the size of the message dropped from the FIFO
102 STATIC u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
104 u16 len = fm10k_fifo_head_len(fifo);
106 /* update head so it is at the start of next frame */
113 * fm10k_fifo_drop_all - Drop all messages in FIFO
114 * @fifo: pointer to FIFO
116 * This function resets the head pointer to drop all messages in the FIFO and
117 * ensure the FIFO is empty.
119 STATIC void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
121 fifo->head = fifo->tail;
125 * fm10k_mbx_index_len - Convert a head/tail index into a length value
126 * @mbx: pointer to mailbox
130 * This function takes the head and tail index and determines the length
131 * of the data indicated by this pair.
133 STATIC u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
135 u16 len = tail - head;
137 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
141 return len & ((mbx->mbmem_len << 1) - 1);
145 * fm10k_mbx_tail_add - Determine new tail value with added offset
146 * @mbx: pointer to mailbox
147 * @offset: length to add to tail offset
149 * This function takes the local tail index and recomputes it for
150 * a given length added as an offset.
152 STATIC u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
154 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
156 /* add/sub 1 because we cannot have offset 0 or all 1s */
157 return (tail > mbx->tail) ? --tail : ++tail;
161 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
162 * @mbx: pointer to mailbox
163 * @offset: length to add to tail offset
165 * This function takes the local tail index and recomputes it for
166 * a given length added as an offset.
168 STATIC u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
170 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
172 /* sub/add 1 because we cannot have offset 0 or all 1s */
173 return (tail < mbx->tail) ? ++tail : --tail;
177 * fm10k_mbx_head_add - Determine new head value with added offset
178 * @mbx: pointer to mailbox
179 * @offset: length to add to head offset
181 * This function takes the local head index and recomputes it for
182 * a given length added as an offset.
184 STATIC u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
186 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
188 /* add/sub 1 because we cannot have offset 0 or all 1s */
189 return (head > mbx->head) ? --head : ++head;
193 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
194 * @mbx: pointer to mailbox
195 * @offset: length to add to head offset
197 * This function takes the local head index and recomputes it for
198 * a given length added as an offset.
200 STATIC u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
202 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
204 /* sub/add 1 because we cannot have offset 0 or all 1s */
205 return (head < mbx->head) ? ++head : --head;
209 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
210 * @mbx: pointer to mailbox
212 * This function will return the length of the message currently being
213 * pushed onto the tail of the Rx queue.
215 STATIC u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
217 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
219 /* pushed tail is only valid if pushed is set */
223 return FM10K_TLV_DWORD_LEN(*tail);
227 * fm10k_fifo_write_copy - pulls data off of msg and places it in FIFO
228 * @fifo: pointer to FIFO
229 * @msg: message array to populate
230 * @tail_offset: additional offset to add to tail pointer
231 * @len: length of FIFO to copy into message header
233 * This function will take a message and copy it into a section of the
234 * FIFO. In order to get something into a location other than just
235 * the tail you can use tail_offset to adjust the pointer.
237 STATIC void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
238 const u32 *msg, u16 tail_offset, u16 len)
240 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
241 u32 *tail = fifo->buffer + end;
243 /* track when we should cross the end of the FIFO */
244 end = fifo->size - end;
246 /* copy end of message before start of message */
248 memcpy(fifo->buffer, msg + end, (len - end) << 2);
252 /* Copy remaining message into Tx FIFO */
253 memcpy(tail, msg, end << 2);
257 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
258 * @fifo: pointer to FIFO
259 * @msg: message array to read
261 * This function enqueues a message up to the size specified by the length
262 * contained in the first DWORD of the message and will place at the tail
263 * of the FIFO. It will return 0 on success, or a negative value on error.
265 STATIC s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
267 u16 len = FM10K_TLV_DWORD_LEN(*msg);
269 DEBUGFUNC("fm10k_fifo_enqueue");
271 /* verify parameters */
272 if (len > fifo->size)
273 return FM10K_MBX_ERR_SIZE;
275 /* verify there is room for the message */
276 if (len > fm10k_fifo_unused(fifo))
277 return FM10K_MBX_ERR_NO_SPACE;
279 /* Copy message into FIFO */
280 fm10k_fifo_write_copy(fifo, msg, 0, len);
282 /* memory barrier to guarantee FIFO is written before tail update */
285 /* Update Tx FIFO tail */
288 return FM10K_SUCCESS;
292 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
293 * @mbx: pointer to mailbox
294 * @len: length of data pushed onto buffer
296 * This function analyzes the frame and will return a non-zero value when
297 * the start of a message larger than the mailbox is detected.
299 STATIC u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
301 struct fm10k_mbx_fifo *fifo = &mbx->rx;
302 u16 total_len = 0, msg_len;
305 DEBUGFUNC("fm10k_mbx_validate_msg_size");
307 /* length should include previous amounts pushed */
310 /* offset in message is based off of current message size */
312 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
313 msg_len = FM10K_TLV_DWORD_LEN(*msg);
314 total_len += msg_len;
315 } while (total_len < len);
317 /* message extends out of pushed section, but fits in FIFO */
318 if ((len < total_len) && (msg_len <= mbx->max_size))
321 /* return length of invalid section */
322 return (len < total_len) ? len : (len - total_len);
326 * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
327 * @hw: pointer to hardware structure
328 * @mbx: pointer to mailbox
330 * This function will take a section of the Tx FIFO and copy it into the
331 * mailbox memory. The offset in mbmem is based on the lower bits of the
332 * tail and len determines the length to copy.
334 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
335 struct fm10k_mbx_info *mbx)
337 struct fm10k_mbx_fifo *fifo = &mbx->tx;
338 u32 mbmem = mbx->mbmem_reg;
339 u32 *head = fifo->buffer;
340 u16 end, len, tail, mask;
342 DEBUGFUNC("fm10k_mbx_write_copy");
347 /* determine data length and mbmem tail index */
348 mask = mbx->mbmem_len - 1;
350 tail = fm10k_mbx_tail_sub(mbx, len);
354 /* determine offset in the ring */
355 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
358 /* memory barrier to guarantee data is ready to be read */
361 /* Copy message from Tx FIFO */
362 for (end = fifo->size - end; len; head = fifo->buffer) {
364 /* adjust tail to match offset for FIFO */
369 mbx->tx_mbmem_pulled++;
371 /* write message to hardware FIFO */
372 FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
373 } while (--len && --end);
378 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
379 * @hw: pointer to hardware structure
380 * @mbx: pointer to mailbox
381 * @head: acknowledgement number last received
383 * This function will push the tail index forward based on the remote
384 * head index. It will then pull up to mbmem_len DWORDs off of the
385 * head of the FIFO and will place it in the MBMEM registers
386 * associated with the mailbox.
388 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
389 struct fm10k_mbx_info *mbx, u16 head)
391 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
392 struct fm10k_mbx_fifo *fifo = &mbx->tx;
394 /* update number of bytes pulled and update bytes in transit */
395 mbx->pulled += mbx->tail_len - ack;
397 /* determine length of data to pull, reserve space for mbmem header */
398 mbmem_len = mbx->mbmem_len - 1;
399 len = fm10k_fifo_used(fifo) - mbx->pulled;
403 /* update tail and record number of bytes in transit */
404 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
407 /* drop pulled messages from the FIFO */
408 for (len = fm10k_fifo_head_len(fifo);
409 len && (mbx->pulled >= len);
410 len = fm10k_fifo_head_len(fifo)) {
411 mbx->pulled -= fm10k_fifo_head_drop(fifo);
413 mbx->tx_dwords += len;
416 /* Copy message out from the Tx FIFO */
417 fm10k_mbx_write_copy(hw, mbx);
421 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
422 * @hw: pointer to hardware structure
423 * @mbx: pointer to mailbox
425 * This function will take a section of the mailbox memory and copy it
426 * into the Rx FIFO. The offset is based on the lower bits of the
427 * head and len determines the length to copy.
429 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
430 struct fm10k_mbx_info *mbx)
432 struct fm10k_mbx_fifo *fifo = &mbx->rx;
433 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
434 u32 *tail = fifo->buffer;
437 DEBUGFUNC("fm10k_mbx_read_copy");
439 /* determine data length and mbmem head index */
441 head = fm10k_mbx_head_sub(mbx, len);
442 if (head >= mbx->mbmem_len)
445 /* determine offset in the ring */
446 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
449 /* Copy message into Rx FIFO */
450 for (end = fifo->size - end; len; tail = fifo->buffer) {
452 /* adjust head to match offset for FIFO */
453 head &= mbx->mbmem_len - 1;
457 mbx->rx_mbmem_pushed++;
459 /* read message from hardware FIFO */
460 *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
461 } while (--len && --end);
464 /* memory barrier to guarantee FIFO is written before tail update */
469 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
470 * @hw: pointer to hardware structure
471 * @mbx: pointer to mailbox
472 * @tail: tail index of message
474 * This function will first validate the tail index and size for the
475 * incoming message. It then updates the acknowledgment number and
476 * copies the data into the FIFO. It will return the number of messages
477 * dequeued on success and a negative value on error.
479 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
480 struct fm10k_mbx_info *mbx,
483 struct fm10k_mbx_fifo *fifo = &mbx->rx;
484 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
486 DEBUGFUNC("fm10k_mbx_push_tail");
488 /* determine length of data to push */
489 len = fm10k_fifo_unused(fifo) - mbx->pushed;
493 /* update head and record bytes received */
494 mbx->head = fm10k_mbx_head_add(mbx, len);
497 /* nothing to do if there is no data */
499 return FM10K_SUCCESS;
501 /* Copy msg into Rx FIFO */
502 fm10k_mbx_read_copy(hw, mbx);
504 /* determine if there are any invalid lengths in message */
505 if (fm10k_mbx_validate_msg_size(mbx, len))
506 return FM10K_MBX_ERR_SIZE;
511 /* flush any completed messages */
512 for (len = fm10k_mbx_pushed_tail_len(mbx);
513 len && (mbx->pushed >= len);
514 len = fm10k_mbx_pushed_tail_len(mbx)) {
518 mbx->rx_dwords += len;
521 return FM10K_SUCCESS;
524 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
525 static const u16 fm10k_crc_16b_table[256] = {
526 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
527 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
528 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
529 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
530 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
531 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
532 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
533 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
534 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
535 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
536 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
537 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
538 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
539 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
540 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
541 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
542 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
543 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
544 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
545 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
546 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
547 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
548 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
549 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
550 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
551 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
552 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
553 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
554 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
555 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
556 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
557 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
560 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
561 * @data: pointer to data to process
562 * @seed: seed value for CRC
563 * @len: length measured in 16 bits words
565 * This function will generate a CRC based on the polynomial 0xAC9A and
566 * whatever value is stored in the seed variable. Note that this
567 * value inverts the local seed and the result in order to capture all
568 * leading and trailing zeros.
570 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
576 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
577 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
582 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
583 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
590 * fm10k_fifo_crc - generate a CRC based off of FIFO data
591 * @fifo: pointer to FIFO
592 * @offset: offset point for start of FIFO
593 * @len: number of DWORDS words to process
594 * @seed: seed value for CRC
596 * This function generates a CRC for some region of the FIFO
598 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
601 u32 *data = fifo->buffer + offset;
603 /* track when we should cross the end of the FIFO */
604 offset = fifo->size - offset;
606 /* if we are in 2 blocks process the end of the FIFO first */
608 seed = fm10k_crc_16b(data, seed, offset * 2);
613 /* process any remaining bits */
614 return fm10k_crc_16b(data, seed, len * 2);
618 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
619 * @mbx: pointer to mailbox
620 * @head: head index provided by remote mailbox
622 * This function will generate the CRC for all data from the end of the
623 * last head update to the current one. It uses the result of the
624 * previous CRC as the seed for this update. The result is stored in
627 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
629 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
631 /* determine the offset for the start of the region to be pulled */
632 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
634 /* update local CRC to include all of the pulled data */
635 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
639 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
640 * @mbx: pointer to mailbox
642 * This function will take all data that has been provided from the remote
643 * end and generate a CRC for it. This is stored in mbx->remote. The
644 * CRC for the header is then computed and if the result is non-zero this
645 * is an error and we signal an error dropping all data and resetting the
648 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
650 struct fm10k_mbx_fifo *fifo = &mbx->rx;
651 u16 len = mbx->head_len;
652 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
655 /* update the remote CRC if new data has been received */
657 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
659 /* process the full header as we have to validate the CRC */
660 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
662 /* notify other end if we have a problem */
663 return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
667 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
668 * @mbx: pointer to mailbox
670 * This function returns true if there is a message in the Rx FIFO to dequeue.
672 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
674 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
676 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
680 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
681 * @mbx: pointer to mailbox
682 * @len: verify free space is >= this value
684 * This function returns true if the mailbox is in a state ready to transmit.
686 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
688 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
690 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
694 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
695 * @mbx: pointer to mailbox
697 * This function returns true if the Tx FIFO is empty.
699 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
701 return fm10k_fifo_empty(&mbx->tx);
705 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
706 * @hw: pointer to hardware structure
707 * @mbx: pointer to mailbox
709 * This function dequeues messages and hands them off to the TLV parser.
710 * It will return the number of messages processed when called.
712 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
713 struct fm10k_mbx_info *mbx)
715 struct fm10k_mbx_fifo *fifo = &mbx->rx;
719 /* parse Rx messages out of the Rx FIFO to empty it */
720 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
721 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
726 fm10k_fifo_head_drop(fifo);
729 /* shift remaining bytes back to start of FIFO */
730 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
732 /* shift head and tail based on the memory we moved */
733 fifo->tail -= fifo->head;
740 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
741 * @hw: pointer to hardware structure
742 * @mbx: pointer to mailbox
743 * @msg: message array to read
745 * This function enqueues a message up to the size specified by the length
746 * contained in the first DWORD of the message and will place at the tail
747 * of the FIFO. It will return 0 on success, or a negative value on error.
749 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
750 struct fm10k_mbx_info *mbx, const u32 *msg)
752 u32 countdown = mbx->timeout;
755 switch (mbx->state) {
756 case FM10K_STATE_CLOSED:
757 case FM10K_STATE_DISCONNECT:
758 return FM10K_MBX_ERR_NO_MBX;
763 /* enqueue the message on the Tx FIFO */
764 err = fm10k_fifo_enqueue(&mbx->tx, msg);
766 /* if it failed give the FIFO a chance to drain */
767 while (err && countdown) {
769 usec_delay(mbx->usec_delay);
770 mbx->ops.process(hw, mbx);
771 err = fm10k_fifo_enqueue(&mbx->tx, msg);
774 /* if we failed treat the error */
780 /* begin processing message, ignore errors as this is just meant
781 * to start the mailbox flow so we are not concerned if there
782 * is a bad error, or the mailbox is already busy with a request
785 mbx->ops.process(hw, mbx);
787 return FM10K_SUCCESS;
791 * fm10k_mbx_read - Copies the mbmem to local message buffer
792 * @hw: pointer to hardware structure
793 * @mbx: pointer to mailbox
795 * This function copies the message from the mbmem to the message array
797 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
799 DEBUGFUNC("fm10k_mbx_read");
801 /* only allow one reader in here at a time */
803 return FM10K_MBX_ERR_BUSY;
805 /* read to capture initial interrupt bits */
806 if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
807 mbx->mbx_lock = FM10K_MBX_ACK;
809 /* write back interrupt bits to clear */
810 FM10K_WRITE_MBX(hw, mbx->mbx_reg,
811 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
813 /* read remote header */
814 mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
816 return FM10K_SUCCESS;
820 * fm10k_mbx_write - Copies the local message buffer to mbmem
821 * @hw: pointer to hardware structure
822 * @mbx: pointer to mailbox
824 * This function copies the message from the message array to mbmem
826 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
828 u32 mbmem = mbx->mbmem_reg;
830 DEBUGFUNC("fm10k_mbx_write");
832 /* write new msg header to notify recipient of change */
833 FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
835 /* write mailbox to send interrupt */
837 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
839 /* we no longer are using the header so free it */
845 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
846 * @mbx: pointer to mailbox
848 * This function returns a connection mailbox header
850 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
852 mbx->mbx_lock |= FM10K_MBX_REQ;
854 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
855 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
856 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
860 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
861 * @mbx: pointer to mailbox
863 * This function returns a data mailbox header
865 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
867 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
868 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
869 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
870 struct fm10k_mbx_fifo *fifo = &mbx->tx;
874 mbx->mbx_lock |= FM10K_MBX_REQ;
876 /* generate CRC for data in flight and header */
877 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
878 mbx->tail_len, mbx->local);
879 crc = fm10k_crc_16b(&hdr, crc, 1);
881 /* load header to memory to be written */
882 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
886 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
887 * @mbx: pointer to mailbox
889 * This function returns a disconnect mailbox header
891 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
893 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
894 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
895 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
896 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
898 mbx->mbx_lock |= FM10K_MBX_ACK;
900 /* load header to memory to be written */
901 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
905 * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mbox hdr
906 * @mbx: pointer to mailbox
908 * This function creates a fake disconnect header for loading into remote
909 * mailbox header. The primary purpose is to prevent errors on immediate
910 * start up after mbx->connect.
912 STATIC void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
914 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
915 FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
916 FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
917 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
919 mbx->mbx_lock |= FM10K_MBX_ACK;
921 /* load header to memory to be written */
922 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
926 * fm10k_mbx_create_error_msg - Generate an error message
927 * @mbx: pointer to mailbox
928 * @err: local error encountered
930 * This function will interpret the error provided by err, and based on
931 * that it may shift the message by 1 DWORD and then place an error header
932 * at the start of the message.
934 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
936 /* only generate an error message for these types */
938 case FM10K_MBX_ERR_TAIL:
939 case FM10K_MBX_ERR_HEAD:
940 case FM10K_MBX_ERR_TYPE:
941 case FM10K_MBX_ERR_SIZE:
942 case FM10K_MBX_ERR_RSVD0:
943 case FM10K_MBX_ERR_CRC:
949 mbx->mbx_lock |= FM10K_MBX_REQ;
951 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
952 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
953 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
957 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
958 * @mbx: pointer to mailbox
960 * This function will parse up the fields in the mailbox header and return
961 * an error if the header contains any of a number of invalid configurations
962 * including unrecognized type, invalid route, or a malformed message.
964 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
966 u16 type, rsvd0, head, tail, size;
967 const u32 *hdr = &mbx->mbx_hdr;
969 DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
971 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
972 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
973 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
974 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
975 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
978 return FM10K_MBX_ERR_RSVD0;
981 case FM10K_MSG_DISCONNECT:
982 /* validate that all data has been received */
983 if (tail != mbx->head)
984 return FM10K_MBX_ERR_TAIL;
988 /* validate that head is moving correctly */
989 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
990 return FM10K_MBX_ERR_HEAD;
991 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
992 return FM10K_MBX_ERR_HEAD;
994 /* validate that tail is moving correctly */
995 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
996 return FM10K_MBX_ERR_TAIL;
997 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1000 return FM10K_MBX_ERR_TAIL;
1001 case FM10K_MSG_CONNECT:
1002 /* validate size is in range and is power of 2 mask */
1003 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
1004 return FM10K_MBX_ERR_SIZE;
1007 case FM10K_MSG_ERROR:
1008 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1009 return FM10K_MBX_ERR_HEAD;
1010 /* neither create nor error include a tail offset */
1012 return FM10K_MBX_ERR_TAIL;
1016 return FM10K_MBX_ERR_TYPE;
1019 return FM10K_SUCCESS;
1023 * fm10k_mbx_create_reply - Generate reply based on state and remote head
1024 * @hw: pointer to hardware structure
1025 * @mbx: pointer to mailbox
1026 * @head: acknowledgement number
1028 * This function will generate an outgoing message based on the current
1029 * mailbox state and the remote FIFO head. It will return the length
1030 * of the outgoing message excluding header on success, and a negative value
1033 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1034 struct fm10k_mbx_info *mbx, u16 head)
1036 switch (mbx->state) {
1037 case FM10K_STATE_OPEN:
1038 case FM10K_STATE_DISCONNECT:
1039 /* update our checksum for the outgoing data */
1040 fm10k_mbx_update_local_crc(mbx, head);
1042 /* as long as other end recognizes us keep sending data */
1043 fm10k_mbx_pull_head(hw, mbx, head);
1045 /* generate new header based on data */
1046 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1047 fm10k_mbx_create_data_hdr(mbx);
1049 fm10k_mbx_create_disconnect_hdr(mbx);
1051 case FM10K_STATE_CONNECT:
1052 /* send disconnect even if we aren't connected */
1053 fm10k_mbx_create_connect_hdr(mbx);
1055 case FM10K_STATE_CLOSED:
1056 /* generate new header based on data */
1057 fm10k_mbx_create_disconnect_hdr(mbx);
1062 return FM10K_SUCCESS;
1066 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1067 * @mbx: pointer to mailbox
1069 * This function will reset all internal pointers so any work in progress
1070 * is dropped. This call should occur every time we transition from the
1071 * open state to the connect state.
1073 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1077 /* reset our outgoing max size back to Rx limits */
1078 mbx->max_size = mbx->rx.size - 1;
1080 /* update mbx->pulled to account for tail_len and ack */
1081 head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1082 ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1083 mbx->pulled += mbx->tail_len - ack;
1085 /* now drop any messages which have started or finished transmitting */
1086 while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1087 len = fm10k_fifo_head_drop(&mbx->tx);
1089 if (mbx->pulled >= len)
1095 /* just do a quick resysnc to start of message */
1105 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1106 * @mbx: pointer to mailbox
1107 * @size: new value for max_size
1109 * This function updates the max_size value and drops any outgoing messages
1110 * at the head of the Tx FIFO if they are larger than max_size. It does not
1111 * drop all messages, as this is too difficult to parse and remove them from
1112 * the FIFO. Instead, rely on the checking to ensure that messages larger
1113 * than max_size aren't pushed into the memory buffer.
1115 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1119 DEBUGFUNC("fm10k_mbx_update_max_size");
1121 mbx->max_size = size;
1123 /* flush any oversized messages from the queue */
1124 for (len = fm10k_fifo_head_len(&mbx->tx);
1126 len = fm10k_fifo_head_len(&mbx->tx)) {
1127 fm10k_fifo_head_drop(&mbx->tx);
1133 * fm10k_mbx_connect_reset - Reset following request for reset
1134 * @mbx: pointer to mailbox
1136 * This function resets the mailbox to either a disconnected state
1137 * or a connect state depending on the current mailbox state
1139 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1141 /* just do a quick resysnc to start of frame */
1142 fm10k_mbx_reset_work(mbx);
1144 /* reset CRC seeds */
1145 mbx->local = FM10K_MBX_CRC_SEED;
1146 mbx->remote = FM10K_MBX_CRC_SEED;
1148 /* we cannot exit connect until the size is good */
1149 if (mbx->state == FM10K_STATE_OPEN)
1150 mbx->state = FM10K_STATE_CONNECT;
1152 mbx->state = FM10K_STATE_CLOSED;
1156 * fm10k_mbx_process_connect - Process connect header
1157 * @hw: pointer to hardware structure
1158 * @mbx: pointer to mailbox
1160 * This function will read an incoming connect header and reply with the
1161 * appropriate message. It will return a value indicating the number of
1162 * data DWORDs on success, or will return a negative value on failure.
1164 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1165 struct fm10k_mbx_info *mbx)
1167 const enum fm10k_mbx_state state = mbx->state;
1168 const u32 *hdr = &mbx->mbx_hdr;
1171 /* we will need to pull all of the fields for verification */
1172 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1173 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1176 case FM10K_STATE_DISCONNECT:
1177 case FM10K_STATE_OPEN:
1178 /* reset any in-progress work */
1179 fm10k_mbx_connect_reset(mbx);
1181 case FM10K_STATE_CONNECT:
1182 /* we cannot exit connect until the size is good */
1183 if (size > mbx->rx.size) {
1184 mbx->max_size = mbx->rx.size - 1;
1186 /* record the remote system requesting connection */
1187 mbx->state = FM10K_STATE_OPEN;
1189 fm10k_mbx_update_max_size(mbx, size);
1196 /* align our tail index to remote head index */
1199 return fm10k_mbx_create_reply(hw, mbx, head);
1203 * fm10k_mbx_process_data - Process data header
1204 * @hw: pointer to hardware structure
1205 * @mbx: pointer to mailbox
1207 * This function will read an incoming data header and reply with the
1208 * appropriate message. It will return a value indicating the number of
1209 * data DWORDs on success, or will return a negative value on failure.
1211 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1212 struct fm10k_mbx_info *mbx)
1214 const u32 *hdr = &mbx->mbx_hdr;
1218 DEBUGFUNC("fm10k_mbx_process_data");
1220 /* we will need to pull all of the fields for verification */
1221 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1222 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1224 /* if we are in connect just update our data and go */
1225 if (mbx->state == FM10K_STATE_CONNECT) {
1227 mbx->state = FM10K_STATE_OPEN;
1230 /* abort on message size errors */
1231 err = fm10k_mbx_push_tail(hw, mbx, tail);
1235 /* verify the checksum on the incoming data */
1236 err = fm10k_mbx_verify_remote_crc(mbx);
1240 /* process messages if we have received any */
1241 fm10k_mbx_dequeue_rx(hw, mbx);
1243 return fm10k_mbx_create_reply(hw, mbx, head);
1247 * fm10k_mbx_process_disconnect - Process disconnect header
1248 * @hw: pointer to hardware structure
1249 * @mbx: pointer to mailbox
1251 * This function will read an incoming disconnect header and reply with the
1252 * appropriate message. It will return a value indicating the number of
1253 * data DWORDs on success, or will return a negative value on failure.
1255 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1256 struct fm10k_mbx_info *mbx)
1258 const enum fm10k_mbx_state state = mbx->state;
1259 const u32 *hdr = &mbx->mbx_hdr;
1263 /* we will need to pull the header field for verification */
1264 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1266 /* We should not be receiving disconnect if Rx is incomplete */
1268 return FM10K_MBX_ERR_TAIL;
1270 /* we have already verified mbx->head == tail so we know this is 0 */
1273 /* verify the checksum on the incoming header is correct */
1274 err = fm10k_mbx_verify_remote_crc(mbx);
1279 case FM10K_STATE_DISCONNECT:
1280 case FM10K_STATE_OPEN:
1281 /* state doesn't change if we still have work to do */
1282 if (!fm10k_mbx_tx_complete(mbx))
1285 /* verify the head indicates we completed all transmits */
1286 if (head != mbx->tail)
1287 return FM10K_MBX_ERR_HEAD;
1289 /* reset any in-progress work */
1290 fm10k_mbx_connect_reset(mbx);
1296 return fm10k_mbx_create_reply(hw, mbx, head);
1300 * fm10k_mbx_process_error - Process error header
1301 * @hw: pointer to hardware structure
1302 * @mbx: pointer to mailbox
1304 * This function will read an incoming error header and reply with the
1305 * appropriate message. It will return a value indicating the number of
1306 * data DWORDs on success, or will return a negative value on failure.
1308 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1309 struct fm10k_mbx_info *mbx)
1311 const u32 *hdr = &mbx->mbx_hdr;
1314 /* we will need to pull all of the fields for verification */
1315 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1317 switch (mbx->state) {
1318 case FM10K_STATE_OPEN:
1319 case FM10K_STATE_DISCONNECT:
1320 /* flush any uncompleted work */
1321 fm10k_mbx_reset_work(mbx);
1323 /* reset CRC seeds */
1324 mbx->local = FM10K_MBX_CRC_SEED;
1325 mbx->remote = FM10K_MBX_CRC_SEED;
1327 /* reset tail index and size to prepare for reconnect */
1330 /* if open then reset max_size and go back to connect */
1331 if (mbx->state == FM10K_STATE_OPEN) {
1332 mbx->state = FM10K_STATE_CONNECT;
1336 /* send a connect message to get data flowing again */
1337 fm10k_mbx_create_connect_hdr(mbx);
1338 return FM10K_SUCCESS;
1343 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1347 * fm10k_mbx_process - Process mailbox interrupt
1348 * @hw: pointer to hardware structure
1349 * @mbx: pointer to mailbox
1351 * This function will process incoming mailbox events and generate mailbox
1352 * replies. It will return a value indicating the number of DWORDs
1353 * transmitted excluding header on success or a negative value on error.
1355 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1356 struct fm10k_mbx_info *mbx)
1360 DEBUGFUNC("fm10k_mbx_process");
1362 /* we do not read mailbox if closed */
1363 if (mbx->state == FM10K_STATE_CLOSED)
1364 return FM10K_SUCCESS;
1366 /* copy data from mailbox */
1367 err = fm10k_mbx_read(hw, mbx);
1371 /* validate type, source, and destination */
1372 err = fm10k_mbx_validate_msg_hdr(mbx);
1376 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1377 case FM10K_MSG_CONNECT:
1378 err = fm10k_mbx_process_connect(hw, mbx);
1380 case FM10K_MSG_DATA:
1381 err = fm10k_mbx_process_data(hw, mbx);
1383 case FM10K_MSG_DISCONNECT:
1384 err = fm10k_mbx_process_disconnect(hw, mbx);
1386 case FM10K_MSG_ERROR:
1387 err = fm10k_mbx_process_error(hw, mbx);
1390 err = FM10K_MBX_ERR_TYPE;
1395 /* notify partner of errors on our end */
1397 fm10k_mbx_create_error_msg(mbx, err);
1399 /* copy data from mailbox */
1400 fm10k_mbx_write(hw, mbx);
1406 * fm10k_mbx_disconnect - Shutdown mailbox connection
1407 * @hw: pointer to hardware structure
1408 * @mbx: pointer to mailbox
1410 * This function will shut down the mailbox. It places the mailbox first
1411 * in the disconnect state, it then allows up to a predefined timeout for
1412 * the mailbox to transition to close on its own. If this does not occur
1413 * then the mailbox will be forced into the closed state.
1415 * Any mailbox transactions not completed before calling this function
1416 * are not guaranteed to complete and may be dropped.
1418 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1419 struct fm10k_mbx_info *mbx)
1421 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1423 DEBUGFUNC("fm10k_mbx_disconnect");
1425 /* Place mbx in ready to disconnect state */
1426 mbx->state = FM10K_STATE_DISCONNECT;
1428 /* trigger interrupt to start shutdown process */
1429 FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1430 FM10K_MBX_INTERRUPT_DISABLE);
1432 usec_delay(FM10K_MBX_POLL_DELAY);
1433 mbx->ops.process(hw, mbx);
1434 timeout -= FM10K_MBX_POLL_DELAY;
1435 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1437 /* in case we didn't close, just force the mailbox into shutdown and
1438 * drop all left over messages in the FIFO.
1440 fm10k_mbx_connect_reset(mbx);
1441 fm10k_fifo_drop_all(&mbx->tx);
1443 FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1447 * fm10k_mbx_connect - Start mailbox connection
1448 * @hw: pointer to hardware structure
1449 * @mbx: pointer to mailbox
1451 * This function will initiate a mailbox connection. It will populate the
1452 * mailbox with a broadcast connect message and then initialize the lock.
1453 * This is safe since the connect message is a single DWORD so the mailbox
1454 * transaction is guaranteed to be atomic.
1456 * This function will return an error if the mailbox has not been initiated
1457 * or is currently in use.
1459 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1461 DEBUGFUNC("fm10k_mbx_connect");
1463 /* we cannot connect an uninitialized mailbox */
1464 if (!mbx->rx.buffer)
1465 return FM10K_MBX_ERR_NO_SPACE;
1467 /* we cannot connect an already connected mailbox */
1468 if (mbx->state != FM10K_STATE_CLOSED)
1469 return FM10K_MBX_ERR_BUSY;
1471 /* mailbox timeout can now become active */
1472 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1474 /* Place mbx in ready to connect state */
1475 mbx->state = FM10K_STATE_CONNECT;
1477 fm10k_mbx_reset_work(mbx);
1479 /* initialize header of remote mailbox */
1480 fm10k_mbx_create_fake_disconnect_hdr(mbx);
1481 FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1483 /* enable interrupt and notify other party of new message */
1484 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1485 FM10K_MBX_INTERRUPT_ENABLE;
1487 /* generate and load connect header into mailbox */
1488 fm10k_mbx_create_connect_hdr(mbx);
1489 fm10k_mbx_write(hw, mbx);
1491 return FM10K_SUCCESS;
1495 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1496 * @msg_data: handlers for mailbox events
1498 * This function validates the layout of the message parsing data. This
1499 * should be mostly static, but it is important to catch any errors that
1500 * are made when constructing the parsers.
1502 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1504 const struct fm10k_tlv_attr *attr;
1507 DEBUGFUNC("fm10k_mbx_validate_handlers");
1509 /* Allow NULL mailboxes that transmit but don't receive */
1511 return FM10K_SUCCESS;
1513 while (msg_data->id != FM10K_TLV_ERROR) {
1514 /* all messages should have a function handler */
1515 if (!msg_data->func)
1516 return FM10K_ERR_PARAM;
1518 /* parser is optional */
1519 attr = msg_data->attr;
1521 while (attr->id != FM10K_TLV_ERROR) {
1524 /* ID should always be increasing */
1526 return FM10K_ERR_PARAM;
1527 /* ID should fit in results array */
1528 if (id >= FM10K_TLV_RESULTS_MAX)
1529 return FM10K_ERR_PARAM;
1532 /* verify terminator is in the list */
1533 if (attr->id != FM10K_TLV_ERROR)
1534 return FM10K_ERR_PARAM;
1539 /* ID should always be increasing */
1540 if (id >= msg_data->id)
1541 return FM10K_ERR_PARAM;
1544 /* verify terminator is in the list */
1545 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1546 return FM10K_ERR_PARAM;
1548 return FM10K_SUCCESS;
1552 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1553 * @mbx: pointer to mailbox
1554 * @msg_data: handlers for mailbox events
1556 * This function associates a set of message handling ops with a mailbox.
1558 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1559 const struct fm10k_msg_data *msg_data)
1561 DEBUGFUNC("fm10k_mbx_register_handlers");
1563 /* validate layout of handlers before assigning them */
1564 if (fm10k_mbx_validate_handlers(msg_data))
1565 return FM10K_ERR_PARAM;
1567 /* initialize the message handlers */
1568 mbx->msg_data = msg_data;
1570 return FM10K_SUCCESS;
1574 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1575 * @hw: pointer to hardware structure
1576 * @mbx: pointer to mailbox
1577 * @msg_data: handlers for mailbox events
1578 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1580 * This function initializes the mailbox for use. It will split the
1581 * buffer provided and use that to populate both the Tx and Rx FIFO by
1582 * evenly splitting it. In order to allow for easy masking of head/tail
1583 * the value reported in size must be a power of 2 and is reported in
1584 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1587 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1588 const struct fm10k_msg_data *msg_data, u8 id)
1590 DEBUGFUNC("fm10k_pfvf_mbx_init");
1592 /* initialize registers */
1593 switch (hw->mac.type) {
1595 mbx->mbx_reg = FM10K_VFMBX;
1596 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1599 /* there are only 64 VF <-> PF mailboxes */
1601 mbx->mbx_reg = FM10K_MBX(id);
1602 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1607 return FM10K_MBX_ERR_NO_MBX;
1610 /* start out in closed state */
1611 mbx->state = FM10K_STATE_CLOSED;
1613 /* validate layout of handlers before assigning them */
1614 if (fm10k_mbx_validate_handlers(msg_data))
1615 return FM10K_ERR_PARAM;
1617 /* initialize the message handlers */
1618 mbx->msg_data = msg_data;
1620 /* start mailbox as timed out and let the reset_hw call
1621 * set the timeout value to begin communications
1624 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1626 /* initialize tail and head */
1630 /* initialize CRC seeds */
1631 mbx->local = FM10K_MBX_CRC_SEED;
1632 mbx->remote = FM10K_MBX_CRC_SEED;
1634 /* Split buffer for use by Tx/Rx FIFOs */
1635 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1636 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1638 /* initialize the FIFOs, sizes are in 4 byte increments */
1639 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1640 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1641 FM10K_MBX_RX_BUFFER_SIZE);
1643 /* initialize function pointers */
1644 mbx->ops.connect = fm10k_mbx_connect;
1645 mbx->ops.disconnect = fm10k_mbx_disconnect;
1646 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1647 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1648 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1649 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1650 mbx->ops.process = fm10k_mbx_process;
1651 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1653 return FM10K_SUCCESS;
1657 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1658 * @mbx: pointer to mailbox
1660 * This function returns a data mailbox header
1662 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1665 mbx->mbx_lock |= FM10K_MBX_REQ;
1667 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1668 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1669 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1673 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1674 * @mbx: pointer to mailbox
1675 * @err: error flags to report if any
1677 * This function returns a connection mailbox header
1679 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1682 mbx->mbx_lock |= FM10K_MBX_REQ;
1684 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1685 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1686 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1687 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1691 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1692 * @mbx: pointer to mailbox
1694 * This function resets the mailbox to a just connected state
1696 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1698 /* flush any uncompleted work */
1699 fm10k_mbx_reset_work(mbx);
1701 /* set local version to max and remote version to 0 */
1702 mbx->local = FM10K_SM_MBX_VERSION;
1705 /* initialize tail and head */
1709 /* reset state back to connect */
1710 mbx->state = FM10K_STATE_CONNECT;
1714 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1715 * @hw: pointer to hardware structure
1716 * @mbx: pointer to mailbox
1718 * This function will initiate a mailbox connection with the switch
1719 * manager. To do this it will first disconnect the mailbox, and then
1720 * reconnect it in order to complete a reset of the mailbox.
1722 * This function will return an error if the mailbox has not been initiated
1723 * or is currently in use.
1725 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1727 DEBUGFUNC("fm10k_sm_mbx_connect");
1729 /* we cannot connect an uninitialized mailbox */
1730 if (!mbx->rx.buffer)
1731 return FM10K_MBX_ERR_NO_SPACE;
1733 /* we cannot connect an already connected mailbox */
1734 if (mbx->state != FM10K_STATE_CLOSED)
1735 return FM10K_MBX_ERR_BUSY;
1737 /* mailbox timeout can now become active */
1738 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1740 /* Place mbx in ready to connect state */
1741 mbx->state = FM10K_STATE_CONNECT;
1742 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1744 /* reset interface back to connect */
1745 fm10k_sm_mbx_connect_reset(mbx);
1747 /* enable interrupt and notify other party of new message */
1748 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1749 FM10K_MBX_INTERRUPT_ENABLE;
1751 /* generate and load connect header into mailbox */
1752 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1753 fm10k_mbx_write(hw, mbx);
1755 return FM10K_SUCCESS;
1759 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1760 * @hw: pointer to hardware structure
1761 * @mbx: pointer to mailbox
1763 * This function will shut down the mailbox. It places the mailbox first
1764 * in the disconnect state, it then allows up to a predefined timeout for
1765 * the mailbox to transition to close on its own. If this does not occur
1766 * then the mailbox will be forced into the closed state.
1768 * Any mailbox transactions not completed before calling this function
1769 * are not guaranteed to complete and may be dropped.
1771 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1772 struct fm10k_mbx_info *mbx)
1774 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1776 DEBUGFUNC("fm10k_sm_mbx_disconnect");
1778 /* Place mbx in ready to disconnect state */
1779 mbx->state = FM10K_STATE_DISCONNECT;
1781 /* trigger interrupt to start shutdown process */
1782 FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1783 FM10K_MBX_INTERRUPT_DISABLE);
1785 usec_delay(FM10K_MBX_POLL_DELAY);
1786 mbx->ops.process(hw, mbx);
1787 timeout -= FM10K_MBX_POLL_DELAY;
1788 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1790 /* in case we didn't close just force the mailbox into shutdown */
1791 mbx->state = FM10K_STATE_CLOSED;
1793 fm10k_mbx_reset_work(mbx);
1794 fm10k_fifo_drop_all(&mbx->tx);
1796 FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1800 * fm10k_sm_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1801 * @mbx: pointer to mailbox
1803 * This function will parse up the fields in the mailbox header and return
1804 * an error if the header contains any of a number of invalid configurations
1805 * including unrecognized offsets or version numbers.
1807 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1809 const u32 *hdr = &mbx->mbx_hdr;
1810 u16 tail, head, ver;
1812 DEBUGFUNC("fm10k_sm_mbx_validate_fifo_hdr");
1814 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1815 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1816 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1821 case FM10K_SM_MBX_VERSION:
1822 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1823 return FM10K_MBX_ERR_HEAD;
1824 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1825 return FM10K_MBX_ERR_TAIL;
1826 if (mbx->tail < head)
1827 head += mbx->mbmem_len - 1;
1828 if (tail < mbx->head)
1829 tail += mbx->mbmem_len - 1;
1830 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1831 return FM10K_MBX_ERR_HEAD;
1832 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1834 return FM10K_MBX_ERR_TAIL;
1836 return FM10K_MBX_ERR_SRC;
1839 return FM10K_SUCCESS;
1843 * fm10k_sm_mbx_process_error - Process header with error flag set
1844 * @mbx: pointer to mailbox
1846 * This function is meant to respond to a request where the error flag
1847 * is set. As a result we will terminate a connection if one is present
1848 * and fall back into the reset state with a connection header of version
1851 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1853 const enum fm10k_mbx_state state = mbx->state;
1856 case FM10K_STATE_DISCONNECT:
1857 /* if there is an error just disconnect */
1860 case FM10K_STATE_OPEN:
1861 /* flush any uncompleted work */
1862 fm10k_sm_mbx_connect_reset(mbx);
1864 case FM10K_STATE_CONNECT:
1865 /* try connnecting at lower version */
1867 while (mbx->local > 1)
1876 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1880 * fm10k_sm_mbx_create_error_msg - Process an error in FIFO header
1881 * @mbx: pointer to mailbox
1882 * @err: local error encountered
1884 * This function will interpret the error provided by err, and based on
1885 * that it may set the error bit in the local message header
1887 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1889 /* only generate an error message for these types */
1891 case FM10K_MBX_ERR_TAIL:
1892 case FM10K_MBX_ERR_HEAD:
1893 case FM10K_MBX_ERR_SRC:
1894 case FM10K_MBX_ERR_SIZE:
1895 case FM10K_MBX_ERR_RSVD0:
1901 /* process it as though we received an error, and send error reply */
1902 fm10k_sm_mbx_process_error(mbx);
1903 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1907 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1908 * @hw: pointer to hardware structure
1909 * @mbx: pointer to mailbox
1910 * @tail: tail index of message
1912 * This function will dequeue one message from the Rx switch manager mailbox
1913 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1915 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1916 struct fm10k_mbx_info *mbx,
1919 /* reduce length by 1 to convert to a mask */
1920 u16 mbmem_len = mbx->mbmem_len - 1;
1923 DEBUGFUNC("fm10k_sm_mbx_receive");
1925 /* push tail in front of head */
1926 if (tail < mbx->head)
1929 /* copy data to the Rx FIFO */
1930 err = fm10k_mbx_push_tail(hw, mbx, tail);
1934 /* process messages if we have received any */
1935 fm10k_mbx_dequeue_rx(hw, mbx);
1937 /* guarantee head aligns with the end of the last message */
1938 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1941 /* clear any extra bits left over since index adds 1 extra bit */
1942 if (mbx->head > mbmem_len)
1943 mbx->head -= mbmem_len;
1949 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1950 * @hw: pointer to hardware structure
1951 * @mbx: pointer to mailbox
1952 * @head: head index of message
1954 * This function will dequeue one message from the Tx mailbox FIFO and place
1955 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1957 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1958 struct fm10k_mbx_info *mbx, u16 head)
1960 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1961 /* reduce length by 1 to convert to a mask */
1962 u16 mbmem_len = mbx->mbmem_len - 1;
1963 u16 tail_len, len = 0;
1966 DEBUGFUNC("fm10k_sm_mbx_transmit");
1968 /* push head behind tail */
1969 if (mbx->tail < head)
1972 fm10k_mbx_pull_head(hw, mbx, head);
1974 /* determine msg aligned offset for end of buffer */
1976 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1978 len += FM10K_TLV_DWORD_LEN(*msg);
1979 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1981 /* guarantee we stop on a message boundary */
1982 if (mbx->tail_len > tail_len) {
1983 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1984 mbx->tail_len = tail_len;
1987 /* clear any extra bits left over since index adds 1 extra bit */
1988 if (mbx->tail > mbmem_len)
1989 mbx->tail -= mbmem_len;
1993 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1994 * @hw: pointer to hardware structure
1995 * @mbx: pointer to mailbox
1996 * @head: acknowledgement number
1998 * This function will generate an outgoing message based on the current
1999 * mailbox state and the remote FIFO head. It will return the length
2000 * of the outgoing message excluding header on success, and a negative value
2003 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
2004 struct fm10k_mbx_info *mbx, u16 head)
2006 switch (mbx->state) {
2007 case FM10K_STATE_OPEN:
2008 case FM10K_STATE_DISCONNECT:
2009 /* flush out Tx data */
2010 fm10k_sm_mbx_transmit(hw, mbx, head);
2012 /* generate new header based on data */
2013 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
2014 fm10k_sm_mbx_create_data_hdr(mbx);
2017 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2020 case FM10K_STATE_CONNECT:
2021 case FM10K_STATE_CLOSED:
2022 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2030 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2031 * @hw: pointer to hardware structure
2032 * @mbx: pointer to mailbox
2034 * This function is meant to respond to a request where the version data
2035 * is set to 0. As such we will either terminate the connection or go
2036 * into the connect state in order to re-establish the connection. This
2037 * function can also be used to respond to an error as the connection
2038 * resetting would also be a means of dealing with errors.
2040 STATIC s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2041 struct fm10k_mbx_info *mbx)
2043 s32 err = FM10K_SUCCESS;
2044 const enum fm10k_mbx_state state = mbx->state;
2047 case FM10K_STATE_DISCONNECT:
2048 /* drop remote connections and disconnect */
2049 mbx->state = FM10K_STATE_CLOSED;
2053 case FM10K_STATE_OPEN:
2054 /* flush any incomplete work */
2055 fm10k_sm_mbx_connect_reset(mbx);
2056 err = FM10K_ERR_RESET_REQUESTED;
2058 case FM10K_STATE_CONNECT:
2059 /* Update remote value to match local value */
2060 mbx->remote = mbx->local;
2065 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2071 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
2072 * @hw: pointer to hardware structure
2073 * @mbx: pointer to mailbox
2075 * This function is meant to process messages received when the remote
2076 * mailbox is active.
2078 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2079 struct fm10k_mbx_info *mbx)
2081 const u32 *hdr = &mbx->mbx_hdr;
2085 /* pull all fields needed for verification */
2086 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2087 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2089 /* if we are in connect and wanting version 1 then start up and go */
2090 if (mbx->state == FM10K_STATE_CONNECT) {
2093 if (mbx->remote != 1)
2094 return FM10K_MBX_ERR_SRC;
2096 mbx->state = FM10K_STATE_OPEN;
2100 /* abort on message size errors */
2101 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2105 /* continue until we have flushed the Rx FIFO */
2109 fm10k_sm_mbx_create_reply(hw, mbx, head);
2111 return FM10K_SUCCESS;
2115 * fm10k_sm_mbx_process - Process switch manager mailbox interrupt
2116 * @hw: pointer to hardware structure
2117 * @mbx: pointer to mailbox
2119 * This function will process incoming mailbox events and generate mailbox
2120 * replies. It will return a value indicating the number of DWORDs
2121 * transmitted excluding header on success or a negative value on error.
2123 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2124 struct fm10k_mbx_info *mbx)
2128 DEBUGFUNC("fm10k_sm_mbx_process");
2130 /* we do not read mailbox if closed */
2131 if (mbx->state == FM10K_STATE_CLOSED)
2132 return FM10K_SUCCESS;
2134 /* retrieve data from switch manager */
2135 err = fm10k_mbx_read(hw, mbx);
2139 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2143 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2144 fm10k_sm_mbx_process_error(mbx);
2148 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2150 err = fm10k_sm_mbx_process_reset(hw, mbx);
2152 case FM10K_SM_MBX_VERSION:
2153 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2159 fm10k_sm_mbx_create_error_msg(mbx, err);
2161 /* report data to switch manager */
2162 fm10k_mbx_write(hw, mbx);
2168 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2169 * @hw: pointer to hardware structure
2170 * @mbx: pointer to mailbox
2171 * @msg_data: handlers for mailbox events
2173 * This function initializes the PF/SM mailbox for use. It will split the
2174 * buffer provided and use that to populate both the Tx and Rx FIFO by
2175 * evenly splitting it. In order to allow for easy masking of head/tail
2176 * the value reported in size must be a power of 2 and is reported in
2177 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
2180 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2181 const struct fm10k_msg_data *msg_data)
2183 DEBUGFUNC("fm10k_sm_mbx_init");
2184 UNREFERENCED_1PARAMETER(hw);
2186 mbx->mbx_reg = FM10K_GMBX;
2187 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2189 /* start out in closed state */
2190 mbx->state = FM10K_STATE_CLOSED;
2192 /* validate layout of handlers before assigning them */
2193 if (fm10k_mbx_validate_handlers(msg_data))
2194 return FM10K_ERR_PARAM;
2196 /* initialize the message handlers */
2197 mbx->msg_data = msg_data;
2199 /* start mailbox as timed out and let the reset_hw call
2200 * set the timeout value to begin communications
2203 mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2205 /* Split buffer for use by Tx/Rx FIFOs */
2206 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2207 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2209 /* initialize the FIFOs, sizes are in 4 byte increments */
2210 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2211 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2212 FM10K_MBX_RX_BUFFER_SIZE);
2214 /* initialize function pointers */
2215 mbx->ops.connect = fm10k_sm_mbx_connect;
2216 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2217 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2218 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2219 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2220 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2221 mbx->ops.process = fm10k_sm_mbx_process;
2222 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2224 return FM10K_SUCCESS;