1 /* Intel Ethernet Switch Host Interface Driver
2 * Copyright(c) 2013 - 2014 Intel Corporation.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * The full GNU General Public License is included in this distribution in
14 * the file called "COPYING".
16 * Contact Information:
17 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
18 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
21 #include "fm10k_common.h"
24 * fm10k_fifo_init - Initialize a message FIFO
25 * @fifo: pointer to FIFO
26 * @buffer: pointer to memory to be used to store FIFO
27 * @size: maximum message size to store in FIFO, must be 2^n - 1
29 static void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
31 fifo->buffer = buffer;
38 * fm10k_fifo_used - Retrieve used space in FIFO
39 * @fifo: pointer to FIFO
41 * This function returns the number of DWORDs used in the FIFO
43 static u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
45 return fifo->tail - fifo->head;
49 * fm10k_fifo_unused - Retrieve unused space in FIFO
50 * @fifo: pointer to FIFO
52 * This function returns the number of unused DWORDs in the FIFO
54 static u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
56 return fifo->size + fifo->head - fifo->tail;
60 * fm10k_fifo_empty - Test to verify if fifo is empty
61 * @fifo: pointer to FIFO
63 * This function returns true if the FIFO is empty, else false
65 static bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
67 return fifo->head == fifo->tail;
71 * fm10k_fifo_head_offset - returns indices of head with given offset
72 * @fifo: pointer to FIFO
73 * @offset: offset to add to head
75 * This function returns the indicies into the fifo based on head + offset
77 static u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
79 return (fifo->head + offset) & (fifo->size - 1);
83 * fm10k_fifo_tail_offset - returns indices of tail with given offset
84 * @fifo: pointer to FIFO
85 * @offset: offset to add to tail
87 * This function returns the indicies into the fifo based on tail + offset
89 static u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
91 return (fifo->tail + offset) & (fifo->size - 1);
95 * fm10k_fifo_head_len - Retrieve length of first message in FIFO
96 * @fifo: pointer to FIFO
98 * This function returns the size of the first message in the FIFO
100 static u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
102 u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
104 /* verify there is at least 1 DWORD in the fifo so *head is valid */
105 if (fm10k_fifo_empty(fifo))
108 /* retieve the message length */
109 return FM10K_TLV_DWORD_LEN(*head);
113 * fm10k_fifo_head_drop - Drop the first message in FIFO
114 * @fifo: pointer to FIFO
116 * This function returns the size of the message dropped from the FIFO
118 static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
120 u16 len = fm10k_fifo_head_len(fifo);
122 /* update head so it is at the start of next frame */
129 * fm10k_mbx_index_len - Convert a head/tail index into a length value
130 * @mbx: pointer to mailbox
134 * This function takes the head and tail index and determines the length
135 * of the data indicated by this pair.
137 static u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
139 u16 len = tail - head;
141 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
145 return len & ((mbx->mbmem_len << 1) - 1);
149 * fm10k_mbx_tail_add - Determine new tail value with added offset
150 * @mbx: pointer to mailbox
151 * @offset: length to add to head offset
153 * This function takes the local tail index and recomputes it for
154 * a given length added as an offset.
156 static u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
158 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
160 /* add/sub 1 because we cannot have offset 0 or all 1s */
161 return (tail > mbx->tail) ? --tail : ++tail;
165 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
166 * @mbx: pointer to mailbox
167 * @offset: length to add to head offset
169 * This function takes the local tail index and recomputes it for
170 * a given length added as an offset.
172 static u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
174 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
176 /* sub/add 1 because we cannot have offset 0 or all 1s */
177 return (tail < mbx->tail) ? ++tail : --tail;
181 * fm10k_mbx_head_add - Determine new head value with added offset
182 * @mbx: pointer to mailbox
183 * @offset: length to add to head offset
185 * This function takes the local head index and recomputes it for
186 * a given length added as an offset.
188 static u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
190 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
192 /* add/sub 1 because we cannot have offset 0 or all 1s */
193 return (head > mbx->head) ? --head : ++head;
197 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
198 * @mbx: pointer to mailbox
199 * @offset: length to add to head offset
201 * This function takes the local head index and recomputes it for
202 * a given length added as an offset.
204 static u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
206 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
208 /* sub/add 1 because we cannot have offset 0 or all 1s */
209 return (head < mbx->head) ? ++head : --head;
213 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
214 * @mbx: pointer to mailbox
216 * This function will return the length of the message currently being
217 * pushed onto the tail of the Rx queue.
219 static u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
221 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
223 /* pushed tail is only valid if pushed is set */
227 return FM10K_TLV_DWORD_LEN(*tail);
231 * fm10k_fifo_write_copy - pulls data off of msg and places it in fifo
232 * @fifo: pointer to FIFO
233 * @msg: message array to populate
234 * @tail_offset: additional offset to add to tail pointer
235 * @len: length of FIFO to copy into message header
237 * This function will take a message and copy it into a section of the
238 * FIFO. In order to get something into a location other than just
239 * the tail you can use tail_offset to adjust the pointer.
241 static void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
242 const u32 *msg, u16 tail_offset, u16 len)
244 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
245 u32 *tail = fifo->buffer + end;
247 /* track when we should cross the end of the FIFO */
248 end = fifo->size - end;
250 /* copy end of message before start of message */
252 memcpy(fifo->buffer, msg + end, (len - end) << 2);
256 /* Copy remaining message into Tx FIFO */
257 memcpy(tail, msg, end << 2);
261 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
262 * @fifo: pointer to FIFO
263 * @msg: message array to read
265 * This function enqueues a message up to the size specified by the length
266 * contained in the first DWORD of the message and will place at the tail
267 * of the FIFO. It will return 0 on success, or a negative value on error.
269 static s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
271 u16 len = FM10K_TLV_DWORD_LEN(*msg);
273 /* verify parameters */
274 if (len > fifo->size)
275 return FM10K_MBX_ERR_SIZE;
277 /* verify there is room for the message */
278 if (len > fm10k_fifo_unused(fifo))
279 return FM10K_MBX_ERR_NO_SPACE;
281 /* Copy message into FIFO */
282 fm10k_fifo_write_copy(fifo, msg, 0, len);
284 /* memory barrier to guarantee FIFO is written before tail update */
287 /* Update Tx FIFO tail */
294 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
295 * @mbx: pointer to mailbox
296 * @len: length of data pushed onto buffer
298 * This function analyzes the frame and will return a non-zero value when
299 * the start of a message larger than the mailbox is detected.
301 static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
303 struct fm10k_mbx_fifo *fifo = &mbx->rx;
304 u16 total_len = 0, msg_len;
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->rx.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 * @mbx: pointer to mailbox
329 * This function will take a seciton of the Rx 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;
345 /* determine data length and mbmem tail index */
346 mask = mbx->mbmem_len - 1;
348 tail = fm10k_mbx_tail_sub(mbx, len);
352 /* determine offset in the ring */
353 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
356 /* memory barrier to guarantee data is ready to be read */
359 /* Copy message from Tx FIFO */
360 for (end = fifo->size - end; len; head = fifo->buffer) {
362 /* adjust tail to match offset for FIFO */
367 /* write message to hardware FIFO */
368 fm10k_write_reg(hw, mbmem + tail++, *(head++));
369 } while (--len && --end);
374 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
375 * @hw: pointer to hardware structure
376 * @mbx: pointer to mailbox
377 * @head: acknowledgement number last received
379 * This function will push the tail index forward based on the remote
380 * head index. It will then pull up to mbmem_len DWORDs off of the
381 * head of the FIFO and will place it in the MBMEM registers
382 * associated with the mailbox.
384 static void fm10k_mbx_pull_head(struct fm10k_hw *hw,
385 struct fm10k_mbx_info *mbx, u16 head)
387 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
388 struct fm10k_mbx_fifo *fifo = &mbx->tx;
390 /* update number of bytes pulled and update bytes in transit */
391 mbx->pulled += mbx->tail_len - ack;
393 /* determine length of data to pull, reserve space for mbmem header */
394 mbmem_len = mbx->mbmem_len - 1;
395 len = fm10k_fifo_used(fifo) - mbx->pulled;
399 /* update tail and record number of bytes in transit */
400 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
403 /* drop pulled messages from the FIFO */
404 for (len = fm10k_fifo_head_len(fifo);
405 len && (mbx->pulled >= len);
406 len = fm10k_fifo_head_len(fifo)) {
407 mbx->pulled -= fm10k_fifo_head_drop(fifo);
409 mbx->tx_dwords += len;
412 /* Copy message out from the Tx FIFO */
413 fm10k_mbx_write_copy(hw, mbx);
417 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
418 * @hw: pointer to hardware structure
419 * @mbx: pointer to mailbox
421 * This function will take a seciton of the mailbox memory and copy it
422 * into the Rx FIFO. The offset is based on the lower bits of the
423 * head and len determines the length to copy.
425 static void fm10k_mbx_read_copy(struct fm10k_hw *hw,
426 struct fm10k_mbx_info *mbx)
428 struct fm10k_mbx_fifo *fifo = &mbx->rx;
429 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
430 u32 *tail = fifo->buffer;
433 /* determine data length and mbmem head index */
435 head = fm10k_mbx_head_sub(mbx, len);
436 if (head >= mbx->mbmem_len)
439 /* determine offset in the ring */
440 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
443 /* Copy message into Rx FIFO */
444 for (end = fifo->size - end; len; tail = fifo->buffer) {
446 /* adjust head to match offset for FIFO */
447 head &= mbx->mbmem_len - 1;
451 /* read message from hardware FIFO */
452 *(tail++) = fm10k_read_reg(hw, mbmem + head++);
453 } while (--len && --end);
456 /* memory barrier to guarantee FIFO is written before tail update */
461 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
462 * @hw: pointer to hardware structure
463 * @mbx: pointer to mailbox
464 * @tail: tail index of message
466 * This function will first validate the tail index and size for the
467 * incoming message. It then updates the acknowlegment number and
468 * copies the data into the FIFO. It will return the number of messages
469 * dequeued on success and a negative value on error.
471 static s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
472 struct fm10k_mbx_info *mbx,
475 struct fm10k_mbx_fifo *fifo = &mbx->rx;
476 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
478 /* determine length of data to push */
479 len = fm10k_fifo_unused(fifo) - mbx->pushed;
483 /* update head and record bytes received */
484 mbx->head = fm10k_mbx_head_add(mbx, len);
487 /* nothing to do if there is no data */
491 /* Copy msg into Rx FIFO */
492 fm10k_mbx_read_copy(hw, mbx);
494 /* determine if there are any invalid lengths in message */
495 if (fm10k_mbx_validate_msg_size(mbx, len))
496 return FM10K_MBX_ERR_SIZE;
501 /* flush any completed messages */
502 for (len = fm10k_mbx_pushed_tail_len(mbx);
503 len && (mbx->pushed >= len);
504 len = fm10k_mbx_pushed_tail_len(mbx)) {
508 mbx->rx_dwords += len;
514 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
515 static const u16 fm10k_crc_16b_table[256] = {
516 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
517 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
518 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
519 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
520 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
521 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
522 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
523 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
524 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
525 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
526 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
527 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
528 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
529 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
530 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
531 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
532 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
533 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
534 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
535 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
536 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
537 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
538 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
539 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
540 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
541 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
542 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
543 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
544 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
545 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
546 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
547 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
550 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
551 * @data: pointer to data to process
552 * @seed: seed value for CRC
553 * @len: length measured in 16 bits words
555 * This function will generate a CRC based on the polynomial 0xAC9A and
556 * whatever value is stored in the seed variable. Note that this
557 * value inverts the local seed and the result in order to capture all
558 * leading and trailing zeros.
560 static u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
566 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
567 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
572 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
573 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
580 * fm10k_fifo_crc - generate a CRC based off of FIFO data
581 * @fifo: pointer to FIFO
582 * @offset: offset point for start of FIFO
583 * @len: number of DWORDS words to process
584 * @seed: seed value for CRC
586 * This function generates a CRC for some region of the FIFO
588 static u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
591 u32 *data = fifo->buffer + offset;
593 /* track when we should cross the end of the FIFO */
594 offset = fifo->size - offset;
596 /* if we are in 2 blocks process the end of the FIFO first */
598 seed = fm10k_crc_16b(data, seed, offset * 2);
603 /* process any remaining bits */
604 return fm10k_crc_16b(data, seed, len * 2);
608 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
609 * @mbx: pointer to mailbox
610 * @head: head index provided by remote mailbox
612 * This function will generate the CRC for all data from the end of the
613 * last head update to the current one. It uses the result of the
614 * previous CRC as the seed for this update. The result is stored in
617 static void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
619 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
621 /* determine the offset for the start of the region to be pulled */
622 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
624 /* update local CRC to include all of the pulled data */
625 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
629 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
630 * @mbx: pointer to mailbox
632 * This function will take all data that has been provided from the remote
633 * end and generate a CRC for it. This is stored in mbx->remote. The
634 * CRC for the header is then computed and if the result is non-zero this
635 * is an error and we signal an error dropping all data and resetting the
638 static s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
640 struct fm10k_mbx_fifo *fifo = &mbx->rx;
641 u16 len = mbx->head_len;
642 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
645 /* update the remote CRC if new data has been received */
647 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
649 /* process the full header as we have to validate the CRC */
650 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
652 /* notify other end if we have a problem */
653 return crc ? FM10K_MBX_ERR_CRC : 0;
657 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
658 * @mbx: pointer to mailbox
660 * This function returns true if there is a message in the Rx FIFO to dequeue.
662 static bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
664 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
666 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
670 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
671 * @mbx: pointer to mailbox
672 * @len: verify free space is >= this value
674 * This function returns true if the mailbox is in a state ready to transmit.
676 static bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
678 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
680 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
684 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
685 * @mbx: pointer to mailbox
687 * This function returns true if the Tx FIFO is empty.
689 static bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
691 return fm10k_fifo_empty(&mbx->tx);
695 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
696 * @hw: pointer to hardware structure
697 * @mbx: pointer to mailbox
699 * This function dequeues messages and hands them off to the tlv parser.
700 * It will return the number of messages processed when called.
702 static u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
703 struct fm10k_mbx_info *mbx)
705 struct fm10k_mbx_fifo *fifo = &mbx->rx;
709 /* parse Rx messages out of the Rx FIFO to empty it */
710 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
711 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
716 fm10k_fifo_head_drop(fifo);
719 /* shift remaining bytes back to start of FIFO */
720 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
722 /* shift head and tail based on the memory we moved */
723 fifo->tail -= fifo->head;
730 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
731 * @hw: pointer to hardware structure
732 * @mbx: pointer to mailbox
733 * @msg: message array to read
735 * This function enqueues a message up to the size specified by the length
736 * contained in the first DWORD of the message and will place at the tail
737 * of the FIFO. It will return 0 on success, or a negative value on error.
739 static s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
740 struct fm10k_mbx_info *mbx, const u32 *msg)
742 u32 countdown = mbx->timeout;
745 switch (mbx->state) {
746 case FM10K_STATE_CLOSED:
747 case FM10K_STATE_DISCONNECT:
748 return FM10K_MBX_ERR_NO_MBX;
753 /* enqueue the message on the Tx FIFO */
754 err = fm10k_fifo_enqueue(&mbx->tx, msg);
756 /* if it failed give the FIFO a chance to drain */
757 while (err && countdown) {
760 mbx->ops.process(hw, mbx);
761 err = fm10k_fifo_enqueue(&mbx->tx, msg);
764 /* if we failed trhead the error */
770 /* begin processing message, ignore errors as this is just meant
771 * to start the mailbox flow so we are not concerned if there
772 * is a bad error, or the mailbox is already busy with a request
775 mbx->ops.process(hw, mbx);
781 * fm10k_mbx_read - Copies the mbmem to local message buffer
782 * @hw: pointer to hardware structure
783 * @mbx: pointer to mailbox
785 * This function copies the message from the mbmem to the message array
787 static s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
789 /* only allow one reader in here at a time */
791 return FM10K_MBX_ERR_BUSY;
793 /* read to capture initial interrupt bits */
794 if (fm10k_read_reg(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
795 mbx->mbx_lock = FM10K_MBX_ACK;
797 /* write back interrupt bits to clear */
798 fm10k_write_reg(hw, mbx->mbx_reg,
799 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
801 /* read remote header */
802 mbx->mbx_hdr = fm10k_read_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
808 * fm10k_mbx_write - Copies the local message buffer to mbmem
809 * @hw: pointer to hardware structure
810 * @mbx: pointer to mailbox
812 * This function copies the message from the the message array to mbmem
814 static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
816 u32 mbmem = mbx->mbmem_reg;
818 /* write new msg header to notify recepient of change */
819 fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
821 /* write mailbox to sent interrupt */
823 fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock);
825 /* we no longer are using the header so free it */
831 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
832 * @mbx: pointer to mailbox
834 * This function returns a connection mailbox header
836 static void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
838 mbx->mbx_lock |= FM10K_MBX_REQ;
840 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
841 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
842 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
846 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
847 * @mbx: pointer to mailbox
849 * This function returns a data mailbox header
851 static void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
853 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
854 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
855 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
856 struct fm10k_mbx_fifo *fifo = &mbx->tx;
860 mbx->mbx_lock |= FM10K_MBX_REQ;
862 /* generate CRC for data in flight and header */
863 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
864 mbx->tail_len, mbx->local);
865 crc = fm10k_crc_16b(&hdr, crc, 1);
867 /* load header to memory to be written */
868 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
872 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
873 * @mbx: pointer to mailbox
875 * This function returns a disconnect mailbox header
877 static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
879 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
880 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
881 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
882 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
884 mbx->mbx_lock |= FM10K_MBX_ACK;
886 /* load header to memory to be written */
887 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
891 * fm10k_mbx_create_error_msg - Generate a error message
892 * @mbx: pointer to mailbox
893 * @err: local error encountered
895 * This function will interpret the error provided by err, and based on
896 * that it may shift the message by 1 DWORD and then place an error header
897 * at the start of the message.
899 static void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
901 /* only generate an error message for these types */
903 case FM10K_MBX_ERR_TAIL:
904 case FM10K_MBX_ERR_HEAD:
905 case FM10K_MBX_ERR_TYPE:
906 case FM10K_MBX_ERR_SIZE:
907 case FM10K_MBX_ERR_RSVD0:
908 case FM10K_MBX_ERR_CRC:
914 mbx->mbx_lock |= FM10K_MBX_REQ;
916 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
917 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
918 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
922 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
923 * @mbx: pointer to mailbox
924 * @msg: message array to read
926 * This function will parse up the fields in the mailbox header and return
927 * an error if the header contains any of a number of invalid configurations
928 * including unrecognized type, invalid route, or a malformed message.
930 static s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
932 u16 type, rsvd0, head, tail, size;
933 const u32 *hdr = &mbx->mbx_hdr;
935 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
936 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
937 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
938 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
939 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
942 return FM10K_MBX_ERR_RSVD0;
945 case FM10K_MSG_DISCONNECT:
946 /* validate that all data has been received */
947 if (tail != mbx->head)
948 return FM10K_MBX_ERR_TAIL;
952 /* validate that head is moving correctly */
953 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
954 return FM10K_MBX_ERR_HEAD;
955 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
956 return FM10K_MBX_ERR_HEAD;
958 /* validate that tail is moving correctly */
959 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
960 return FM10K_MBX_ERR_TAIL;
961 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
964 return FM10K_MBX_ERR_TAIL;
965 case FM10K_MSG_CONNECT:
966 /* validate size is in range and is power of 2 mask */
967 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
968 return FM10K_MBX_ERR_SIZE;
971 case FM10K_MSG_ERROR:
972 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
973 return FM10K_MBX_ERR_HEAD;
974 /* neither create nor error include a tail offset */
976 return FM10K_MBX_ERR_TAIL;
980 return FM10K_MBX_ERR_TYPE;
987 * fm10k_mbx_create_reply - Generate reply based on state and remote head
988 * @mbx: pointer to mailbox
989 * @head: acknowledgement number
991 * This function will generate an outgoing message based on the current
992 * mailbox state and the remote fifo head. It will return the length
993 * of the outgoing message excluding header on success, and a negative value
996 static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
997 struct fm10k_mbx_info *mbx, u16 head)
999 switch (mbx->state) {
1000 case FM10K_STATE_OPEN:
1001 case FM10K_STATE_DISCONNECT:
1002 /* update our checksum for the outgoing data */
1003 fm10k_mbx_update_local_crc(mbx, head);
1005 /* as long as other end recognizes us keep sending data */
1006 fm10k_mbx_pull_head(hw, mbx, head);
1008 /* generate new header based on data */
1009 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1010 fm10k_mbx_create_data_hdr(mbx);
1012 fm10k_mbx_create_disconnect_hdr(mbx);
1014 case FM10K_STATE_CONNECT:
1015 /* send disconnect even if we aren't connected */
1016 fm10k_mbx_create_connect_hdr(mbx);
1018 case FM10K_STATE_CLOSED:
1019 /* generate new header based on data */
1020 fm10k_mbx_create_disconnect_hdr(mbx);
1029 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1030 * @mbx: pointer to mailbox
1032 * This function will reset all internal pointers so any work in progress
1033 * is dropped. This call should occur every time we transition from the
1034 * open state to the connect state.
1036 static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1038 /* reset our outgoing max size back to Rx limits */
1039 mbx->max_size = mbx->rx.size - 1;
1041 /* just do a quick resysnc to start of message */
1051 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1052 * @mbx: pointer to mailbox
1053 * @size: new value for max_size
1055 * This function will update the max_size value and drop any outgoing messages
1056 * from the head of the Tx FIFO that are larger than max_size.
1058 static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1062 mbx->max_size = size;
1064 /* flush any oversized messages from the queue */
1065 for (len = fm10k_fifo_head_len(&mbx->tx);
1067 len = fm10k_fifo_head_len(&mbx->tx)) {
1068 fm10k_fifo_head_drop(&mbx->tx);
1074 * fm10k_mbx_connect_reset - Reset following request for reset
1075 * @mbx: pointer to mailbox
1077 * This function resets the mailbox to either a disconnected state
1078 * or a connect state depending on the current mailbox state
1080 static void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1082 /* just do a quick resysnc to start of frame */
1083 fm10k_mbx_reset_work(mbx);
1085 /* reset CRC seeds */
1086 mbx->local = FM10K_MBX_CRC_SEED;
1087 mbx->remote = FM10K_MBX_CRC_SEED;
1089 /* we cannot exit connect until the size is good */
1090 if (mbx->state == FM10K_STATE_OPEN)
1091 mbx->state = FM10K_STATE_CONNECT;
1093 mbx->state = FM10K_STATE_CLOSED;
1097 * fm10k_mbx_process_connect - Process connect header
1098 * @mbx: pointer to mailbox
1099 * @msg: message array to process
1101 * This function will read an incoming connect header and reply with the
1102 * appropriate message. It will return a value indicating the number of
1103 * data DWORDs on success, or will return a negative value on failure.
1105 static s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1106 struct fm10k_mbx_info *mbx)
1108 const enum fm10k_mbx_state state = mbx->state;
1109 const u32 *hdr = &mbx->mbx_hdr;
1112 /* we will need to pull all of the fields for verification */
1113 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1114 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1117 case FM10K_STATE_DISCONNECT:
1118 case FM10K_STATE_OPEN:
1119 /* reset any in-progress work */
1120 fm10k_mbx_connect_reset(mbx);
1122 case FM10K_STATE_CONNECT:
1123 /* we cannot exit connect until the size is good */
1124 if (size > mbx->rx.size) {
1125 mbx->max_size = mbx->rx.size - 1;
1127 /* record the remote system requesting connection */
1128 mbx->state = FM10K_STATE_OPEN;
1130 fm10k_mbx_update_max_size(mbx, size);
1137 /* align our tail index to remote head index */
1140 return fm10k_mbx_create_reply(hw, mbx, head);
1144 * fm10k_mbx_process_data - Process data header
1145 * @mbx: pointer to mailbox
1147 * This function will read an incoming data header and reply with the
1148 * appropriate message. It will return a value indicating the number of
1149 * data DWORDs on success, or will return a negative value on failure.
1151 static s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1152 struct fm10k_mbx_info *mbx)
1154 const u32 *hdr = &mbx->mbx_hdr;
1158 /* we will need to pull all of the fields for verification */
1159 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1160 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1162 /* if we are in connect just update our data and go */
1163 if (mbx->state == FM10K_STATE_CONNECT) {
1165 mbx->state = FM10K_STATE_OPEN;
1168 /* abort on message size errors */
1169 err = fm10k_mbx_push_tail(hw, mbx, tail);
1173 /* verify the checksum on the incoming data */
1174 err = fm10k_mbx_verify_remote_crc(mbx);
1178 /* process messages if we have received any */
1179 fm10k_mbx_dequeue_rx(hw, mbx);
1181 return fm10k_mbx_create_reply(hw, mbx, head);
1185 * fm10k_mbx_process_disconnect - Process disconnect header
1186 * @mbx: pointer to mailbox
1188 * This function will read an incoming disconnect header and reply with the
1189 * appropriate message. It will return a value indicating the number of
1190 * data DWORDs on success, or will return a negative value on failure.
1192 static s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1193 struct fm10k_mbx_info *mbx)
1195 const enum fm10k_mbx_state state = mbx->state;
1196 const u32 *hdr = &mbx->mbx_hdr;
1200 /* we will need to pull all of the fields for verification */
1201 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1202 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1204 /* We should not be receiving disconnect if Rx is incomplete */
1206 return FM10K_MBX_ERR_TAIL;
1208 /* we have already verified mbx->head == tail so we know this is 0 */
1211 /* verify the checksum on the incoming header is correct */
1212 err = fm10k_mbx_verify_remote_crc(mbx);
1217 case FM10K_STATE_DISCONNECT:
1218 case FM10K_STATE_OPEN:
1219 /* state doesn't change if we still have work to do */
1220 if (!fm10k_mbx_tx_complete(mbx))
1223 /* verify the head indicates we completed all transmits */
1224 if (head != mbx->tail)
1225 return FM10K_MBX_ERR_HEAD;
1227 /* reset any in-progress work */
1228 fm10k_mbx_connect_reset(mbx);
1234 return fm10k_mbx_create_reply(hw, mbx, head);
1238 * fm10k_mbx_process_error - Process error header
1239 * @mbx: pointer to mailbox
1241 * This function will read an incoming error header and reply with the
1242 * appropriate message. It will return a value indicating the number of
1243 * data DWORDs on success, or will return a negative value on failure.
1245 static s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1246 struct fm10k_mbx_info *mbx)
1248 const u32 *hdr = &mbx->mbx_hdr;
1252 /* we will need to pull all of the fields for verification */
1253 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1255 /* we only have lower 10 bits of error number os add upper bits */
1256 err_no = FM10K_MSG_HDR_FIELD_GET(*hdr, ERR_NO);
1257 err_no |= ~FM10K_MSG_HDR_MASK(ERR_NO);
1259 switch (mbx->state) {
1260 case FM10K_STATE_OPEN:
1261 case FM10K_STATE_DISCONNECT:
1262 /* flush any uncompleted work */
1263 fm10k_mbx_reset_work(mbx);
1265 /* reset CRC seeds */
1266 mbx->local = FM10K_MBX_CRC_SEED;
1267 mbx->remote = FM10K_MBX_CRC_SEED;
1269 /* reset tail index and size to prepare for reconnect */
1272 /* if open then reset max_size and go back to connect */
1273 if (mbx->state == FM10K_STATE_OPEN) {
1274 mbx->state = FM10K_STATE_CONNECT;
1278 /* send a connect message to get data flowing again */
1279 fm10k_mbx_create_connect_hdr(mbx);
1285 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1289 * fm10k_mbx_process - Process mailbox interrupt
1290 * @hw: pointer to hardware structure
1291 * @mbx: pointer to mailbox
1293 * This function will process incoming mailbox events and generate mailbox
1294 * replies. It will return a value indicating the number of DWORDs
1295 * transmitted excluding header on success or a negative value on error.
1297 static s32 fm10k_mbx_process(struct fm10k_hw *hw,
1298 struct fm10k_mbx_info *mbx)
1302 /* we do not read mailbox if closed */
1303 if (mbx->state == FM10K_STATE_CLOSED)
1306 /* copy data from mailbox */
1307 err = fm10k_mbx_read(hw, mbx);
1311 /* validate type, source, and destination */
1312 err = fm10k_mbx_validate_msg_hdr(mbx);
1316 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1317 case FM10K_MSG_CONNECT:
1318 err = fm10k_mbx_process_connect(hw, mbx);
1320 case FM10K_MSG_DATA:
1321 err = fm10k_mbx_process_data(hw, mbx);
1323 case FM10K_MSG_DISCONNECT:
1324 err = fm10k_mbx_process_disconnect(hw, mbx);
1326 case FM10K_MSG_ERROR:
1327 err = fm10k_mbx_process_error(hw, mbx);
1330 err = FM10K_MBX_ERR_TYPE;
1335 /* notify partner of errors on our end */
1337 fm10k_mbx_create_error_msg(mbx, err);
1339 /* copy data from mailbox */
1340 fm10k_mbx_write(hw, mbx);
1346 * fm10k_mbx_disconnect - Shutdown mailbox connection
1347 * @hw: pointer to hardware structure
1348 * @mbx: pointer to mailbox
1350 * This function will shut down the mailbox. It places the mailbox first
1351 * in the disconnect state, it then allows up to a predefined timeout for
1352 * the mailbox to transition to close on its own. If this does not occur
1353 * then the mailbox will be forced into the closed state.
1355 * Any mailbox transactions not completed before calling this function
1356 * are not guaranteed to complete and may be dropped.
1358 static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1359 struct fm10k_mbx_info *mbx)
1361 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1363 /* Place mbx in ready to disconnect state */
1364 mbx->state = FM10K_STATE_DISCONNECT;
1366 /* trigger interrupt to start shutdown process */
1367 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1368 FM10K_MBX_INTERRUPT_DISABLE);
1370 udelay(FM10K_MBX_POLL_DELAY);
1371 mbx->ops.process(hw, mbx);
1372 timeout -= FM10K_MBX_POLL_DELAY;
1373 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1375 /* in case we didn't close just force the mailbox into shutdown */
1376 fm10k_mbx_connect_reset(mbx);
1377 fm10k_mbx_update_max_size(mbx, 0);
1379 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1383 * fm10k_mbx_connect - Start mailbox connection
1384 * @hw: pointer to hardware structure
1385 * @mbx: pointer to mailbox
1387 * This function will initiate a mailbox connection. It will populate the
1388 * mailbox with a broadcast connect message and then initialize the lock.
1389 * This is safe since the connect message is a single DWORD so the mailbox
1390 * transaction is guaranteed to be atomic.
1392 * This function will return an error if the mailbox has not been initiated
1393 * or is currently in use.
1395 static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1397 /* we cannot connect an uninitialized mailbox */
1398 if (!mbx->rx.buffer)
1399 return FM10K_MBX_ERR_NO_SPACE;
1401 /* we cannot connect an already connected mailbox */
1402 if (mbx->state != FM10K_STATE_CLOSED)
1403 return FM10K_MBX_ERR_BUSY;
1405 /* mailbox timeout can now become active */
1406 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1408 /* Place mbx in ready to connect state */
1409 mbx->state = FM10K_STATE_CONNECT;
1411 /* initialize header of remote mailbox */
1412 fm10k_mbx_create_disconnect_hdr(mbx);
1413 fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1415 /* enable interrupt and notify other party of new message */
1416 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1417 FM10K_MBX_INTERRUPT_ENABLE;
1419 /* generate and load connect header into mailbox */
1420 fm10k_mbx_create_connect_hdr(mbx);
1421 fm10k_mbx_write(hw, mbx);
1427 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1428 * @msg_data: handlers for mailbox events
1430 * This function validates the layout of the message parsing data. This
1431 * should be mostly static, but it is important to catch any errors that
1432 * are made when constructing the parsers.
1434 static s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1436 const struct fm10k_tlv_attr *attr;
1439 /* Allow NULL mailboxes that transmit but don't receive */
1443 while (msg_data->id != FM10K_TLV_ERROR) {
1444 /* all messages should have a function handler */
1445 if (!msg_data->func)
1446 return FM10K_ERR_PARAM;
1448 /* parser is optional */
1449 attr = msg_data->attr;
1451 while (attr->id != FM10K_TLV_ERROR) {
1454 /* ID should always be increasing */
1456 return FM10K_ERR_PARAM;
1457 /* ID should fit in results array */
1458 if (id >= FM10K_TLV_RESULTS_MAX)
1459 return FM10K_ERR_PARAM;
1462 /* verify terminator is in the list */
1463 if (attr->id != FM10K_TLV_ERROR)
1464 return FM10K_ERR_PARAM;
1469 /* ID should always be increasing */
1470 if (id >= msg_data->id)
1471 return FM10K_ERR_PARAM;
1474 /* verify terminator is in the list */
1475 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1476 return FM10K_ERR_PARAM;
1482 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1483 * @mbx: pointer to mailbox
1484 * @msg_data: handlers for mailbox events
1486 * This function associates a set of message handling ops with a mailbox.
1488 static s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1489 const struct fm10k_msg_data *msg_data)
1491 /* validate layout of handlers before assigning them */
1492 if (fm10k_mbx_validate_handlers(msg_data))
1493 return FM10K_ERR_PARAM;
1495 /* initialize the message handlers */
1496 mbx->msg_data = msg_data;
1502 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1503 * @hw: pointer to hardware structure
1504 * @mbx: pointer to mailbox
1505 * @msg_data: handlers for mailbox events
1506 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1508 * This function initializes the mailbox for use. It will split the
1509 * buffer provided an use that th populate both the Tx and Rx FIFO by
1510 * evenly splitting it. In order to allow for easy masking of head/tail
1511 * the value reported in size must be a power of 2 and is reported in
1512 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1515 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1516 const struct fm10k_msg_data *msg_data, u8 id)
1518 /* initialize registers */
1519 switch (hw->mac.type) {
1521 mbx->mbx_reg = FM10K_VFMBX;
1522 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1525 /* there are only 64 VF <-> PF mailboxes */
1527 mbx->mbx_reg = FM10K_MBX(id);
1528 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1533 return FM10K_MBX_ERR_NO_MBX;
1536 /* start out in closed state */
1537 mbx->state = FM10K_STATE_CLOSED;
1539 /* validate layout of handlers before assigning them */
1540 if (fm10k_mbx_validate_handlers(msg_data))
1541 return FM10K_ERR_PARAM;
1543 /* initialize the message handlers */
1544 mbx->msg_data = msg_data;
1546 /* start mailbox as timed out and let the reset_hw call
1547 * set the timeout value to begin communications
1550 mbx->udelay = FM10K_MBX_INIT_DELAY;
1552 /* initalize tail and head */
1556 /* initialize CRC seeds */
1557 mbx->local = FM10K_MBX_CRC_SEED;
1558 mbx->remote = FM10K_MBX_CRC_SEED;
1560 /* Split buffer for use by Tx/Rx FIFOs */
1561 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1562 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1564 /* initialize the FIFOs, sizes are in 4 byte increments */
1565 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1566 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1567 FM10K_MBX_RX_BUFFER_SIZE);
1569 /* initialize function pointers */
1570 mbx->ops.connect = fm10k_mbx_connect;
1571 mbx->ops.disconnect = fm10k_mbx_disconnect;
1572 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1573 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1574 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1575 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1576 mbx->ops.process = fm10k_mbx_process;
1577 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1583 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1584 * @mbx: pointer to mailbox
1586 * This function returns a connection mailbox header
1588 static void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1591 mbx->mbx_lock |= FM10K_MBX_REQ;
1593 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1594 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1595 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1599 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1600 * @mbx: pointer to mailbox
1601 * @err: error flags to report if any
1603 * This function returns a connection mailbox header
1605 static void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1608 mbx->mbx_lock |= FM10K_MBX_REQ;
1610 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1611 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1612 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1613 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1617 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1618 * @mbx: pointer to mailbox
1620 * This function resets the mailbox to a just connected state
1622 static void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1624 /* flush any uncompleted work */
1625 fm10k_mbx_reset_work(mbx);
1627 /* set local version to max and remote version to 0 */
1628 mbx->local = FM10K_SM_MBX_VERSION;
1631 /* initalize tail and head */
1635 /* reset state back to connect */
1636 mbx->state = FM10K_STATE_CONNECT;
1640 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1641 * @hw: pointer to hardware structure
1642 * @mbx: pointer to mailbox
1644 * This function will initiate a mailbox connection with the switch
1645 * manager. To do this it will first disconnect the mailbox, and then
1646 * reconnect it in order to complete a reset of the mailbox.
1648 * This function will return an error if the mailbox has not been initiated
1649 * or is currently in use.
1651 static s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1653 /* we cannot connect an uninitialized mailbox */
1654 if (!mbx->rx.buffer)
1655 return FM10K_MBX_ERR_NO_SPACE;
1657 /* we cannot connect an already connected mailbox */
1658 if (mbx->state != FM10K_STATE_CLOSED)
1659 return FM10K_MBX_ERR_BUSY;
1661 /* mailbox timeout can now become active */
1662 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1664 /* Place mbx in ready to connect state */
1665 mbx->state = FM10K_STATE_CONNECT;
1666 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1668 /* reset interface back to connect */
1669 fm10k_sm_mbx_connect_reset(mbx);
1671 /* enable interrupt and notify other party of new message */
1672 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1673 FM10K_MBX_INTERRUPT_ENABLE;
1675 /* generate and load connect header into mailbox */
1676 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1677 fm10k_mbx_write(hw, mbx);
1679 /* enable interrupt and notify other party of new message */
1685 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1686 * @hw: pointer to hardware structure
1687 * @mbx: pointer to mailbox
1689 * This function will shut down the mailbox. It places the mailbox first
1690 * in the disconnect state, it then allows up to a predefined timeout for
1691 * the mailbox to transition to close on its own. If this does not occur
1692 * then the mailbox will be forced into the closed state.
1694 * Any mailbox transactions not completed before calling this function
1695 * are not guaranteed to complete and may be dropped.
1697 static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1698 struct fm10k_mbx_info *mbx)
1700 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1702 /* Place mbx in ready to disconnect state */
1703 mbx->state = FM10K_STATE_DISCONNECT;
1705 /* trigger interrupt to start shutdown process */
1706 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1707 FM10K_MBX_INTERRUPT_DISABLE);
1709 udelay(FM10K_MBX_POLL_DELAY);
1710 mbx->ops.process(hw, mbx);
1711 timeout -= FM10K_MBX_POLL_DELAY;
1712 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1714 /* in case we didn't close just force the mailbox into shutdown */
1715 mbx->state = FM10K_STATE_CLOSED;
1717 fm10k_mbx_reset_work(mbx);
1718 fm10k_mbx_update_max_size(mbx, 0);
1720 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1724 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1725 * @mbx: pointer to mailbox
1727 * This function will parse up the fields in the mailbox header and return
1728 * an error if the header contains any of a number of invalid configurations
1729 * including unrecognized offsets or version numbers.
1731 static s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1733 const u32 *hdr = &mbx->mbx_hdr;
1734 u16 tail, head, ver;
1736 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1737 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1738 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1743 case FM10K_SM_MBX_VERSION:
1744 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1745 return FM10K_MBX_ERR_HEAD;
1746 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1747 return FM10K_MBX_ERR_TAIL;
1748 if (mbx->tail < head)
1749 head += mbx->mbmem_len - 1;
1750 if (tail < mbx->head)
1751 tail += mbx->mbmem_len - 1;
1752 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1753 return FM10K_MBX_ERR_HEAD;
1754 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1756 return FM10K_MBX_ERR_TAIL;
1758 return FM10K_MBX_ERR_SRC;
1765 * fm10k_sm_mbx_process_error - Process header with error flag set
1766 * @mbx: pointer to mailbox
1768 * This function is meant to respond to a request where the error flag
1769 * is set. As a result we will terminate a connection if one is present
1770 * and fall back into the reset state with a connection header of version
1773 static void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1775 const enum fm10k_mbx_state state = mbx->state;
1778 case FM10K_STATE_DISCONNECT:
1779 /* if there is an error just disconnect */
1782 case FM10K_STATE_OPEN:
1783 /* flush any uncompleted work */
1784 fm10k_sm_mbx_connect_reset(mbx);
1786 case FM10K_STATE_CONNECT:
1787 /* try connnecting at lower version */
1789 while (mbx->local > 1)
1798 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1802 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1803 * @mbx: pointer to mailbox
1804 * @err: local error encountered
1806 * This function will interpret the error provided by err, and based on
1807 * that it may set the error bit in the local message header
1809 static void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1811 /* only generate an error message for these types */
1813 case FM10K_MBX_ERR_TAIL:
1814 case FM10K_MBX_ERR_HEAD:
1815 case FM10K_MBX_ERR_SRC:
1816 case FM10K_MBX_ERR_SIZE:
1817 case FM10K_MBX_ERR_RSVD0:
1823 /* process it as though we received an error, and send error reply */
1824 fm10k_sm_mbx_process_error(mbx);
1825 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1829 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1830 * @hw: pointer to hardware structure
1831 * @mbx: pointer to mailbox
1833 * This function will dequeue one message from the Rx switch manager mailbox
1834 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1836 static s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1837 struct fm10k_mbx_info *mbx,
1840 /* reduce length by 1 to convert to a mask */
1841 u16 mbmem_len = mbx->mbmem_len - 1;
1844 /* push tail in front of head */
1845 if (tail < mbx->head)
1848 /* copy data to the Rx FIFO */
1849 err = fm10k_mbx_push_tail(hw, mbx, tail);
1853 /* process messages if we have received any */
1854 fm10k_mbx_dequeue_rx(hw, mbx);
1856 /* guarantee head aligns with the end of the last message */
1857 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1860 /* clear any extra bits left over since index adds 1 extra bit */
1861 if (mbx->head > mbmem_len)
1862 mbx->head -= mbmem_len;
1868 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1869 * @hw: pointer to hardware structure
1870 * @mbx: pointer to mailbox
1872 * This function will dequeue one message from the Tx mailbox FIFO and place
1873 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1875 static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1876 struct fm10k_mbx_info *mbx, u16 head)
1878 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1879 /* reduce length by 1 to convert to a mask */
1880 u16 mbmem_len = mbx->mbmem_len - 1;
1881 u16 tail_len, len = 0;
1884 /* push head behind tail */
1885 if (mbx->tail < head)
1888 fm10k_mbx_pull_head(hw, mbx, head);
1890 /* determine msg aligned offset for end of buffer */
1892 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1894 len += FM10K_TLV_DWORD_LEN(*msg);
1895 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1897 /* guarantee we stop on a message boundary */
1898 if (mbx->tail_len > tail_len) {
1899 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1900 mbx->tail_len = tail_len;
1903 /* clear any extra bits left over since index adds 1 extra bit */
1904 if (mbx->tail > mbmem_len)
1905 mbx->tail -= mbmem_len;
1909 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1910 * @mbx: pointer to mailbox
1911 * @head: acknowledgement number
1913 * This function will generate an outgoing message based on the current
1914 * mailbox state and the remote fifo head. It will return the length
1915 * of the outgoing message excluding header on success, and a negative value
1918 static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1919 struct fm10k_mbx_info *mbx, u16 head)
1921 switch (mbx->state) {
1922 case FM10K_STATE_OPEN:
1923 case FM10K_STATE_DISCONNECT:
1924 /* flush out Tx data */
1925 fm10k_sm_mbx_transmit(hw, mbx, head);
1927 /* generate new header based on data */
1928 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1929 fm10k_sm_mbx_create_data_hdr(mbx);
1932 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1935 case FM10K_STATE_CONNECT:
1936 case FM10K_STATE_CLOSED:
1937 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1945 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
1946 * @hw: pointer to hardware structure
1947 * @mbx: pointer to mailbox
1949 * This function is meant to respond to a request where the version data
1950 * is set to 0. As such we will either terminate the connection or go
1951 * into the connect state in order to re-establish the connection. This
1952 * function can also be used to respond to an error as the connection
1953 * resetting would also be a means of dealing with errors.
1955 static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
1956 struct fm10k_mbx_info *mbx)
1958 const enum fm10k_mbx_state state = mbx->state;
1961 case FM10K_STATE_DISCONNECT:
1962 /* drop remote connections and disconnect */
1963 mbx->state = FM10K_STATE_CLOSED;
1967 case FM10K_STATE_OPEN:
1968 /* flush any incomplete work */
1969 fm10k_sm_mbx_connect_reset(mbx);
1971 case FM10K_STATE_CONNECT:
1972 /* Update remote value to match local value */
1973 mbx->remote = mbx->local;
1978 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
1982 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
1983 * @hw: pointer to hardware structure
1984 * @mbx: pointer to mailbox
1986 * This function is meant to process messages received when the remote
1987 * mailbox is active.
1989 static s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
1990 struct fm10k_mbx_info *mbx)
1992 const u32 *hdr = &mbx->mbx_hdr;
1996 /* pull all fields needed for verification */
1997 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1998 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2000 /* if we are in connect and wanting version 1 then start up and go */
2001 if (mbx->state == FM10K_STATE_CONNECT) {
2004 if (mbx->remote != 1)
2005 return FM10K_MBX_ERR_SRC;
2007 mbx->state = FM10K_STATE_OPEN;
2011 /* abort on message size errors */
2012 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2016 /* continue until we have flushed the Rx FIFO */
2020 fm10k_sm_mbx_create_reply(hw, mbx, head);
2026 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2027 * @hw: pointer to hardware structure
2028 * @mbx: pointer to mailbox
2030 * This function will process incoming mailbox events and generate mailbox
2031 * replies. It will return a value indicating the number of DWORDs
2032 * transmitted excluding header on success or a negative value on error.
2034 static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2035 struct fm10k_mbx_info *mbx)
2039 /* we do not read mailbox if closed */
2040 if (mbx->state == FM10K_STATE_CLOSED)
2043 /* retrieve data from switch manager */
2044 err = fm10k_mbx_read(hw, mbx);
2048 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2052 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2053 fm10k_sm_mbx_process_error(mbx);
2057 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2059 fm10k_sm_mbx_process_reset(hw, mbx);
2061 case FM10K_SM_MBX_VERSION:
2062 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2068 fm10k_sm_mbx_create_error_msg(mbx, err);
2070 /* report data to switch manager */
2071 fm10k_mbx_write(hw, mbx);
2077 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2078 * @hw: pointer to hardware structure
2079 * @mbx: pointer to mailbox
2080 * @msg_data: handlers for mailbox events
2082 * This function for now is used to stub out the PF/SM mailbox
2084 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2085 const struct fm10k_msg_data *msg_data)
2087 mbx->mbx_reg = FM10K_GMBX;
2088 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2089 /* start out in closed state */
2090 mbx->state = FM10K_STATE_CLOSED;
2092 /* validate layout of handlers before assigning them */
2093 if (fm10k_mbx_validate_handlers(msg_data))
2094 return FM10K_ERR_PARAM;
2096 /* initialize the message handlers */
2097 mbx->msg_data = msg_data;
2099 /* start mailbox as timed out and let the reset_hw call
2100 * set the timeout value to begin communications
2103 mbx->udelay = FM10K_MBX_INIT_DELAY;
2105 /* Split buffer for use by Tx/Rx FIFOs */
2106 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2107 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2109 /* initialize the FIFOs, sizes are in 4 byte increments */
2110 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2111 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2112 FM10K_MBX_RX_BUFFER_SIZE);
2114 /* initialize function pointers */
2115 mbx->ops.connect = fm10k_sm_mbx_connect;
2116 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2117 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2118 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2119 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2120 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2121 mbx->ops.process = fm10k_sm_mbx_process;
2122 mbx->ops.register_handlers = fm10k_mbx_register_handlers;