x86/ldt: Further fix FPU emulation
[linux/fpc-iii.git] / drivers / net / ethernet / intel / fm10k / fm10k_mbx.c
blob1a4b52637de9123d900f7362b54b985e46e345de
1 /* Intel Ethernet Switch Host Interface Driver
2 * Copyright(c) 2013 - 2015 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
11 * more details.
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"
23 /**
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
28 **/
29 static void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
31 fifo->buffer = buffer;
32 fifo->size = size;
33 fifo->head = 0;
34 fifo->tail = 0;
37 /**
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
42 **/
43 static u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
45 return fifo->tail - fifo->head;
48 /**
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
53 **/
54 static u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
56 return fifo->size + fifo->head - fifo->tail;
59 /**
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
64 **/
65 static bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
67 return fifo->head == fifo->tail;
70 /**
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 indices into the fifo based on head + offset
76 **/
77 static u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
79 return (fifo->head + offset) & (fifo->size - 1);
82 /**
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 indices into the fifo based on tail + offset
88 **/
89 static u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
91 return (fifo->tail + offset) & (fifo->size - 1);
94 /**
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
99 **/
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))
106 return 0;
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 */
123 fifo->head += len;
125 return len;
129 * fm10k_fifo_drop_all - Drop all messages in FIFO
130 * @fifo: pointer to FIFO
132 * This function resets the head pointer to drop all messages in the FIFO,
133 * and ensure the FIFO is empty.
135 static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
137 fifo->head = fifo->tail;
141 * fm10k_mbx_index_len - Convert a head/tail index into a length value
142 * @mbx: pointer to mailbox
143 * @head: head index
144 * @tail: head index
146 * This function takes the head and tail index and determines the length
147 * of the data indicated by this pair.
149 static u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
151 u16 len = tail - head;
153 /* we wrapped so subtract 2, one for index 0, one for all 1s index */
154 if (len > tail)
155 len -= 2;
157 return len & ((mbx->mbmem_len << 1) - 1);
161 * fm10k_mbx_tail_add - Determine new tail value with added offset
162 * @mbx: pointer to mailbox
163 * @offset: length to add to head 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_add(struct fm10k_mbx_info *mbx, u16 offset)
170 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
172 /* add/sub 1 because we cannot have offset 0 or all 1s */
173 return (tail > mbx->tail) ? --tail : ++tail;
177 * fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
178 * @mbx: pointer to mailbox
179 * @offset: length to add to head offset
181 * This function takes the local tail index and recomputes it for
182 * a given length added as an offset.
184 static u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
186 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
188 /* sub/add 1 because we cannot have offset 0 or all 1s */
189 return (tail < mbx->tail) ? ++tail : --tail;
193 * fm10k_mbx_head_add - Determine new head value with added 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_add(struct fm10k_mbx_info *mbx, u16 offset)
202 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
204 /* add/sub 1 because we cannot have offset 0 or all 1s */
205 return (head > mbx->head) ? --head : ++head;
209 * fm10k_mbx_head_sub - Determine new head value with subtracted offset
210 * @mbx: pointer to mailbox
211 * @offset: length to add to head offset
213 * This function takes the local head index and recomputes it for
214 * a given length added as an offset.
216 static u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
218 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
220 /* sub/add 1 because we cannot have offset 0 or all 1s */
221 return (head < mbx->head) ? ++head : --head;
225 * fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
226 * @mbx: pointer to mailbox
228 * This function will return the length of the message currently being
229 * pushed onto the tail of the Rx queue.
231 static u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
233 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
235 /* pushed tail is only valid if pushed is set */
236 if (!mbx->pushed)
237 return 0;
239 return FM10K_TLV_DWORD_LEN(*tail);
243 * fm10k_fifo_write_copy - pulls data off of msg and places it in fifo
244 * @fifo: pointer to FIFO
245 * @msg: message array to populate
246 * @tail_offset: additional offset to add to tail pointer
247 * @len: length of FIFO to copy into message header
249 * This function will take a message and copy it into a section of the
250 * FIFO. In order to get something into a location other than just
251 * the tail you can use tail_offset to adjust the pointer.
253 static void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
254 const u32 *msg, u16 tail_offset, u16 len)
256 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
257 u32 *tail = fifo->buffer + end;
259 /* track when we should cross the end of the FIFO */
260 end = fifo->size - end;
262 /* copy end of message before start of message */
263 if (end < len)
264 memcpy(fifo->buffer, msg + end, (len - end) << 2);
265 else
266 end = len;
268 /* Copy remaining message into Tx FIFO */
269 memcpy(tail, msg, end << 2);
273 * fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
274 * @fifo: pointer to FIFO
275 * @msg: message array to read
277 * This function enqueues a message up to the size specified by the length
278 * contained in the first DWORD of the message and will place at the tail
279 * of the FIFO. It will return 0 on success, or a negative value on error.
281 static s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
283 u16 len = FM10K_TLV_DWORD_LEN(*msg);
285 /* verify parameters */
286 if (len > fifo->size)
287 return FM10K_MBX_ERR_SIZE;
289 /* verify there is room for the message */
290 if (len > fm10k_fifo_unused(fifo))
291 return FM10K_MBX_ERR_NO_SPACE;
293 /* Copy message into FIFO */
294 fm10k_fifo_write_copy(fifo, msg, 0, len);
296 /* memory barrier to guarantee FIFO is written before tail update */
297 wmb();
299 /* Update Tx FIFO tail */
300 fifo->tail += len;
302 return 0;
306 * fm10k_mbx_validate_msg_size - Validate incoming message based on size
307 * @mbx: pointer to mailbox
308 * @len: length of data pushed onto buffer
310 * This function analyzes the frame and will return a non-zero value when
311 * the start of a message larger than the mailbox is detected.
313 static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
315 struct fm10k_mbx_fifo *fifo = &mbx->rx;
316 u16 total_len = 0, msg_len;
317 u32 *msg;
319 /* length should include previous amounts pushed */
320 len += mbx->pushed;
322 /* offset in message is based off of current message size */
323 do {
324 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
325 msg_len = FM10K_TLV_DWORD_LEN(*msg);
326 total_len += msg_len;
327 } while (total_len < len);
329 /* message extends out of pushed section, but fits in FIFO */
330 if ((len < total_len) && (msg_len <= mbx->max_size))
331 return 0;
333 /* return length of invalid section */
334 return (len < total_len) ? len : (len - total_len);
338 * fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
339 * @mbx: pointer to mailbox
341 * This function will take a section of the Tx FIFO and copy it into the
342 * mailbox memory. The offset in mbmem is based on the lower bits of the
343 * tail and len determines the length to copy.
345 static void fm10k_mbx_write_copy(struct fm10k_hw *hw,
346 struct fm10k_mbx_info *mbx)
348 struct fm10k_mbx_fifo *fifo = &mbx->tx;
349 u32 mbmem = mbx->mbmem_reg;
350 u32 *head = fifo->buffer;
351 u16 end, len, tail, mask;
353 if (!mbx->tail_len)
354 return;
356 /* determine data length and mbmem tail index */
357 mask = mbx->mbmem_len - 1;
358 len = mbx->tail_len;
359 tail = fm10k_mbx_tail_sub(mbx, len);
360 if (tail > mask)
361 tail++;
363 /* determine offset in the ring */
364 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
365 head += end;
367 /* memory barrier to guarantee data is ready to be read */
368 rmb();
370 /* Copy message from Tx FIFO */
371 for (end = fifo->size - end; len; head = fifo->buffer) {
372 do {
373 /* adjust tail to match offset for FIFO */
374 tail &= mask;
375 if (!tail)
376 tail++;
378 /* write message to hardware FIFO */
379 fm10k_write_reg(hw, mbmem + tail++, *(head++));
380 } while (--len && --end);
385 * fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
386 * @hw: pointer to hardware structure
387 * @mbx: pointer to mailbox
388 * @head: acknowledgement number last received
390 * This function will push the tail index forward based on the remote
391 * head index. It will then pull up to mbmem_len DWORDs off of the
392 * head of the FIFO and will place it in the MBMEM registers
393 * associated with the mailbox.
395 static void fm10k_mbx_pull_head(struct fm10k_hw *hw,
396 struct fm10k_mbx_info *mbx, u16 head)
398 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
399 struct fm10k_mbx_fifo *fifo = &mbx->tx;
401 /* update number of bytes pulled and update bytes in transit */
402 mbx->pulled += mbx->tail_len - ack;
404 /* determine length of data to pull, reserve space for mbmem header */
405 mbmem_len = mbx->mbmem_len - 1;
406 len = fm10k_fifo_used(fifo) - mbx->pulled;
407 if (len > mbmem_len)
408 len = mbmem_len;
410 /* update tail and record number of bytes in transit */
411 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
412 mbx->tail_len = len;
414 /* drop pulled messages from the FIFO */
415 for (len = fm10k_fifo_head_len(fifo);
416 len && (mbx->pulled >= len);
417 len = fm10k_fifo_head_len(fifo)) {
418 mbx->pulled -= fm10k_fifo_head_drop(fifo);
419 mbx->tx_messages++;
420 mbx->tx_dwords += len;
423 /* Copy message out from the Tx FIFO */
424 fm10k_mbx_write_copy(hw, mbx);
428 * fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
429 * @hw: pointer to hardware structure
430 * @mbx: pointer to mailbox
432 * This function will take a section of the mailbox memory and copy it
433 * into the Rx FIFO. The offset is based on the lower bits of the
434 * head and len determines the length to copy.
436 static void fm10k_mbx_read_copy(struct fm10k_hw *hw,
437 struct fm10k_mbx_info *mbx)
439 struct fm10k_mbx_fifo *fifo = &mbx->rx;
440 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
441 u32 *tail = fifo->buffer;
442 u16 end, len, head;
444 /* determine data length and mbmem head index */
445 len = mbx->head_len;
446 head = fm10k_mbx_head_sub(mbx, len);
447 if (head >= mbx->mbmem_len)
448 head++;
450 /* determine offset in the ring */
451 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
452 tail += end;
454 /* Copy message into Rx FIFO */
455 for (end = fifo->size - end; len; tail = fifo->buffer) {
456 do {
457 /* adjust head to match offset for FIFO */
458 head &= mbx->mbmem_len - 1;
459 if (!head)
460 head++;
462 /* read message from hardware FIFO */
463 *(tail++) = fm10k_read_reg(hw, mbmem + head++);
464 } while (--len && --end);
467 /* memory barrier to guarantee FIFO is written before tail update */
468 wmb();
472 * fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
473 * @hw: pointer to hardware structure
474 * @mbx: pointer to mailbox
475 * @tail: tail index of message
477 * This function will first validate the tail index and size for the
478 * incoming message. It then updates the acknowledgment number and
479 * copies the data into the FIFO. It will return the number of messages
480 * dequeued on success and a negative value on error.
482 static s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
483 struct fm10k_mbx_info *mbx,
484 u16 tail)
486 struct fm10k_mbx_fifo *fifo = &mbx->rx;
487 u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
489 /* determine length of data to push */
490 len = fm10k_fifo_unused(fifo) - mbx->pushed;
491 if (len > seq)
492 len = seq;
494 /* update head and record bytes received */
495 mbx->head = fm10k_mbx_head_add(mbx, len);
496 mbx->head_len = len;
498 /* nothing to do if there is no data */
499 if (!len)
500 return 0;
502 /* Copy msg into Rx FIFO */
503 fm10k_mbx_read_copy(hw, mbx);
505 /* determine if there are any invalid lengths in message */
506 if (fm10k_mbx_validate_msg_size(mbx, len))
507 return FM10K_MBX_ERR_SIZE;
509 /* Update pushed */
510 mbx->pushed += len;
512 /* flush any completed messages */
513 for (len = fm10k_mbx_pushed_tail_len(mbx);
514 len && (mbx->pushed >= len);
515 len = fm10k_mbx_pushed_tail_len(mbx)) {
516 fifo->tail += len;
517 mbx->pushed -= len;
518 mbx->rx_messages++;
519 mbx->rx_dwords += len;
522 return 0;
525 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
526 static const u16 fm10k_crc_16b_table[256] = {
527 0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
528 0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
529 0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
530 0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
531 0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
532 0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
533 0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
534 0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
535 0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
536 0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
537 0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
538 0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
539 0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
540 0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
541 0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
542 0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
543 0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
544 0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
545 0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
546 0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
547 0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
548 0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
549 0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
550 0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
551 0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
552 0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
553 0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
554 0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
555 0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
556 0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
557 0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
558 0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
561 * fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
562 * @data: pointer to data to process
563 * @seed: seed value for CRC
564 * @len: length measured in 16 bits words
566 * This function will generate a CRC based on the polynomial 0xAC9A and
567 * whatever value is stored in the seed variable. Note that this
568 * value inverts the local seed and the result in order to capture all
569 * leading and trailing zeros.
571 static u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
573 u32 result = seed;
575 while (len--) {
576 result ^= *(data++);
577 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
578 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
580 if (!(len--))
581 break;
583 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
584 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
587 return (u16)result;
591 * fm10k_fifo_crc - generate a CRC based off of FIFO data
592 * @fifo: pointer to FIFO
593 * @offset: offset point for start of FIFO
594 * @len: number of DWORDS words to process
595 * @seed: seed value for CRC
597 * This function generates a CRC for some region of the FIFO
599 static u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
600 u16 len, u16 seed)
602 u32 *data = fifo->buffer + offset;
604 /* track when we should cross the end of the FIFO */
605 offset = fifo->size - offset;
607 /* if we are in 2 blocks process the end of the FIFO first */
608 if (offset < len) {
609 seed = fm10k_crc_16b(data, seed, offset * 2);
610 data = fifo->buffer;
611 len -= offset;
614 /* process any remaining bits */
615 return fm10k_crc_16b(data, seed, len * 2);
619 * fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
620 * @mbx: pointer to mailbox
621 * @head: head index provided by remote mailbox
623 * This function will generate the CRC for all data from the end of the
624 * last head update to the current one. It uses the result of the
625 * previous CRC as the seed for this update. The result is stored in
626 * mbx->local.
628 static void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
630 u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
632 /* determine the offset for the start of the region to be pulled */
633 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
635 /* update local CRC to include all of the pulled data */
636 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
640 * fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
641 * @mbx: pointer to mailbox
643 * This function will take all data that has been provided from the remote
644 * end and generate a CRC for it. This is stored in mbx->remote. The
645 * CRC for the header is then computed and if the result is non-zero this
646 * is an error and we signal an error dropping all data and resetting the
647 * connection.
649 static s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
651 struct fm10k_mbx_fifo *fifo = &mbx->rx;
652 u16 len = mbx->head_len;
653 u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
654 u16 crc;
656 /* update the remote CRC if new data has been received */
657 if (len)
658 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
660 /* process the full header as we have to validate the CRC */
661 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
663 /* notify other end if we have a problem */
664 return crc ? FM10K_MBX_ERR_CRC : 0;
668 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
669 * @mbx: pointer to mailbox
671 * This function returns true if there is a message in the Rx FIFO to dequeue.
673 static bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
675 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
677 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
681 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
682 * @mbx: pointer to mailbox
683 * @len: verify free space is >= this value
685 * This function returns true if the mailbox is in a state ready to transmit.
687 static bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
689 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
691 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
695 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
696 * @mbx: pointer to mailbox
698 * This function returns true if the Tx FIFO is empty.
700 static bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
702 return fm10k_fifo_empty(&mbx->tx);
706 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
707 * @hw: pointer to hardware structure
708 * @mbx: pointer to mailbox
710 * This function dequeues messages and hands them off to the tlv parser.
711 * It will return the number of messages processed when called.
713 static u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
714 struct fm10k_mbx_info *mbx)
716 struct fm10k_mbx_fifo *fifo = &mbx->rx;
717 s32 err;
718 u16 cnt;
720 /* parse Rx messages out of the Rx FIFO to empty it */
721 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
722 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
723 mbx, mbx->msg_data);
724 if (err < 0)
725 mbx->rx_parse_err++;
727 fm10k_fifo_head_drop(fifo);
730 /* shift remaining bytes back to start of FIFO */
731 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
733 /* shift head and tail based on the memory we moved */
734 fifo->tail -= fifo->head;
735 fifo->head = 0;
737 return cnt;
741 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
742 * @hw: pointer to hardware structure
743 * @mbx: pointer to mailbox
744 * @msg: message array to read
746 * This function enqueues a message up to the size specified by the length
747 * contained in the first DWORD of the message and will place at the tail
748 * of the FIFO. It will return 0 on success, or a negative value on error.
750 static s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
751 struct fm10k_mbx_info *mbx, const u32 *msg)
753 u32 countdown = mbx->timeout;
754 s32 err;
756 switch (mbx->state) {
757 case FM10K_STATE_CLOSED:
758 case FM10K_STATE_DISCONNECT:
759 return FM10K_MBX_ERR_NO_MBX;
760 default:
761 break;
764 /* enqueue the message on the Tx FIFO */
765 err = fm10k_fifo_enqueue(&mbx->tx, msg);
767 /* if it failed give the FIFO a chance to drain */
768 while (err && countdown) {
769 countdown--;
770 udelay(mbx->udelay);
771 mbx->ops.process(hw, mbx);
772 err = fm10k_fifo_enqueue(&mbx->tx, msg);
775 /* if we failed treat the error */
776 if (err) {
777 mbx->timeout = 0;
778 mbx->tx_busy++;
781 /* begin processing message, ignore errors as this is just meant
782 * to start the mailbox flow so we are not concerned if there
783 * is a bad error, or the mailbox is already busy with a request
785 if (!mbx->tail_len)
786 mbx->ops.process(hw, mbx);
788 return 0;
792 * fm10k_mbx_read - Copies the mbmem to local message buffer
793 * @hw: pointer to hardware structure
794 * @mbx: pointer to mailbox
796 * This function copies the message from the mbmem to the message array
798 static s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
800 /* only allow one reader in here at a time */
801 if (mbx->mbx_hdr)
802 return FM10K_MBX_ERR_BUSY;
804 /* read to capture initial interrupt bits */
805 if (fm10k_read_reg(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
806 mbx->mbx_lock = FM10K_MBX_ACK;
808 /* write back interrupt bits to clear */
809 fm10k_write_reg(hw, mbx->mbx_reg,
810 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
812 /* read remote header */
813 mbx->mbx_hdr = fm10k_read_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
815 return 0;
819 * fm10k_mbx_write - Copies the local message buffer to mbmem
820 * @hw: pointer to hardware structure
821 * @mbx: pointer to mailbox
823 * This function copies the message from the the message array to mbmem
825 static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
827 u32 mbmem = mbx->mbmem_reg;
829 /* write new msg header to notify recipient of change */
830 fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
832 /* write mailbox to send interrupt */
833 if (mbx->mbx_lock)
834 fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock);
836 /* we no longer are using the header so free it */
837 mbx->mbx_hdr = 0;
838 mbx->mbx_lock = 0;
842 * fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
843 * @mbx: pointer to mailbox
845 * This function returns a connection mailbox header
847 static void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
849 mbx->mbx_lock |= FM10K_MBX_REQ;
851 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
852 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
853 FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
857 * fm10k_mbx_create_data_hdr - Generate a data mailbox header
858 * @mbx: pointer to mailbox
860 * This function returns a data mailbox header
862 static void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
864 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
865 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
866 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
867 struct fm10k_mbx_fifo *fifo = &mbx->tx;
868 u16 crc;
870 if (mbx->tail_len)
871 mbx->mbx_lock |= FM10K_MBX_REQ;
873 /* generate CRC for data in flight and header */
874 crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
875 mbx->tail_len, mbx->local);
876 crc = fm10k_crc_16b(&hdr, crc, 1);
878 /* load header to memory to be written */
879 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
883 * fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
884 * @mbx: pointer to mailbox
886 * This function returns a disconnect mailbox header
888 static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
890 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
891 FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
892 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
893 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
895 mbx->mbx_lock |= FM10K_MBX_ACK;
897 /* load header to memory to be written */
898 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
902 * fm10k_mbx_create_error_msg - Generate a error message
903 * @mbx: pointer to mailbox
904 * @err: local error encountered
906 * This function will interpret the error provided by err, and based on
907 * that it may shift the message by 1 DWORD and then place an error header
908 * at the start of the message.
910 static void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
912 /* only generate an error message for these types */
913 switch (err) {
914 case FM10K_MBX_ERR_TAIL:
915 case FM10K_MBX_ERR_HEAD:
916 case FM10K_MBX_ERR_TYPE:
917 case FM10K_MBX_ERR_SIZE:
918 case FM10K_MBX_ERR_RSVD0:
919 case FM10K_MBX_ERR_CRC:
920 break;
921 default:
922 return;
925 mbx->mbx_lock |= FM10K_MBX_REQ;
927 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
928 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
929 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
933 * fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
934 * @mbx: pointer to mailbox
935 * @msg: message array to read
937 * This function will parse up the fields in the mailbox header and return
938 * an error if the header contains any of a number of invalid configurations
939 * including unrecognized type, invalid route, or a malformed message.
941 static s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
943 u16 type, rsvd0, head, tail, size;
944 const u32 *hdr = &mbx->mbx_hdr;
946 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
947 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
948 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
949 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
950 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
952 if (rsvd0)
953 return FM10K_MBX_ERR_RSVD0;
955 switch (type) {
956 case FM10K_MSG_DISCONNECT:
957 /* validate that all data has been received */
958 if (tail != mbx->head)
959 return FM10K_MBX_ERR_TAIL;
961 /* fall through */
962 case FM10K_MSG_DATA:
963 /* validate that head is moving correctly */
964 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
965 return FM10K_MBX_ERR_HEAD;
966 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
967 return FM10K_MBX_ERR_HEAD;
969 /* validate that tail is moving correctly */
970 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
971 return FM10K_MBX_ERR_TAIL;
972 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
973 break;
975 return FM10K_MBX_ERR_TAIL;
976 case FM10K_MSG_CONNECT:
977 /* validate size is in range and is power of 2 mask */
978 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
979 return FM10K_MBX_ERR_SIZE;
981 /* fall through */
982 case FM10K_MSG_ERROR:
983 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
984 return FM10K_MBX_ERR_HEAD;
985 /* neither create nor error include a tail offset */
986 if (tail)
987 return FM10K_MBX_ERR_TAIL;
989 break;
990 default:
991 return FM10K_MBX_ERR_TYPE;
994 return 0;
998 * fm10k_mbx_create_reply - Generate reply based on state and remote head
999 * @mbx: pointer to mailbox
1000 * @head: acknowledgement number
1002 * This function will generate an outgoing message based on the current
1003 * mailbox state and the remote fifo head. It will return the length
1004 * of the outgoing message excluding header on success, and a negative value
1005 * on error.
1007 static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1008 struct fm10k_mbx_info *mbx, u16 head)
1010 switch (mbx->state) {
1011 case FM10K_STATE_OPEN:
1012 case FM10K_STATE_DISCONNECT:
1013 /* update our checksum for the outgoing data */
1014 fm10k_mbx_update_local_crc(mbx, head);
1016 /* as long as other end recognizes us keep sending data */
1017 fm10k_mbx_pull_head(hw, mbx, head);
1019 /* generate new header based on data */
1020 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1021 fm10k_mbx_create_data_hdr(mbx);
1022 else
1023 fm10k_mbx_create_disconnect_hdr(mbx);
1024 break;
1025 case FM10K_STATE_CONNECT:
1026 /* send disconnect even if we aren't connected */
1027 fm10k_mbx_create_connect_hdr(mbx);
1028 break;
1029 case FM10K_STATE_CLOSED:
1030 /* generate new header based on data */
1031 fm10k_mbx_create_disconnect_hdr(mbx);
1032 default:
1033 break;
1036 return 0;
1040 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
1041 * @mbx: pointer to mailbox
1043 * This function will reset all internal pointers so any work in progress
1044 * is dropped. This call should occur every time we transition from the
1045 * open state to the connect state.
1047 static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1049 /* reset our outgoing max size back to Rx limits */
1050 mbx->max_size = mbx->rx.size - 1;
1052 /* just do a quick resysnc to start of message */
1053 mbx->pushed = 0;
1054 mbx->pulled = 0;
1055 mbx->tail_len = 0;
1056 mbx->head_len = 0;
1057 mbx->rx.tail = 0;
1058 mbx->rx.head = 0;
1062 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
1063 * @mbx: pointer to mailbox
1064 * @size: new value for max_size
1066 * This function updates the max_size value and drops any outgoing messages
1067 * at the head of the Tx FIFO if they are larger than max_size. It does not
1068 * drop all messages, as this is too difficult to parse and remove them from
1069 * the FIFO. Instead, rely on the checking to ensure that messages larger
1070 * than max_size aren't pushed into the memory buffer.
1072 static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1074 u16 len;
1076 mbx->max_size = size;
1078 /* flush any oversized messages from the queue */
1079 for (len = fm10k_fifo_head_len(&mbx->tx);
1080 len > size;
1081 len = fm10k_fifo_head_len(&mbx->tx)) {
1082 fm10k_fifo_head_drop(&mbx->tx);
1083 mbx->tx_dropped++;
1088 * fm10k_mbx_connect_reset - Reset following request for reset
1089 * @mbx: pointer to mailbox
1091 * This function resets the mailbox to either a disconnected state
1092 * or a connect state depending on the current mailbox state
1094 static void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1096 /* just do a quick resysnc to start of frame */
1097 fm10k_mbx_reset_work(mbx);
1099 /* reset CRC seeds */
1100 mbx->local = FM10K_MBX_CRC_SEED;
1101 mbx->remote = FM10K_MBX_CRC_SEED;
1103 /* we cannot exit connect until the size is good */
1104 if (mbx->state == FM10K_STATE_OPEN)
1105 mbx->state = FM10K_STATE_CONNECT;
1106 else
1107 mbx->state = FM10K_STATE_CLOSED;
1111 * fm10k_mbx_process_connect - Process connect header
1112 * @mbx: pointer to mailbox
1113 * @msg: message array to process
1115 * This function will read an incoming connect header and reply with the
1116 * appropriate message. It will return a value indicating the number of
1117 * data DWORDs on success, or will return a negative value on failure.
1119 static s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1120 struct fm10k_mbx_info *mbx)
1122 const enum fm10k_mbx_state state = mbx->state;
1123 const u32 *hdr = &mbx->mbx_hdr;
1124 u16 size, head;
1126 /* we will need to pull all of the fields for verification */
1127 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1128 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1130 switch (state) {
1131 case FM10K_STATE_DISCONNECT:
1132 case FM10K_STATE_OPEN:
1133 /* reset any in-progress work */
1134 fm10k_mbx_connect_reset(mbx);
1135 break;
1136 case FM10K_STATE_CONNECT:
1137 /* we cannot exit connect until the size is good */
1138 if (size > mbx->rx.size) {
1139 mbx->max_size = mbx->rx.size - 1;
1140 } else {
1141 /* record the remote system requesting connection */
1142 mbx->state = FM10K_STATE_OPEN;
1144 fm10k_mbx_update_max_size(mbx, size);
1146 break;
1147 default:
1148 break;
1151 /* align our tail index to remote head index */
1152 mbx->tail = head;
1154 return fm10k_mbx_create_reply(hw, mbx, head);
1158 * fm10k_mbx_process_data - Process data header
1159 * @mbx: pointer to mailbox
1161 * This function will read an incoming data header and reply with the
1162 * appropriate message. It will return a value indicating the number of
1163 * data DWORDs on success, or will return a negative value on failure.
1165 static s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1166 struct fm10k_mbx_info *mbx)
1168 const u32 *hdr = &mbx->mbx_hdr;
1169 u16 head, tail;
1170 s32 err;
1172 /* we will need to pull all of the fields for verification */
1173 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1174 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1176 /* if we are in connect just update our data and go */
1177 if (mbx->state == FM10K_STATE_CONNECT) {
1178 mbx->tail = head;
1179 mbx->state = FM10K_STATE_OPEN;
1182 /* abort on message size errors */
1183 err = fm10k_mbx_push_tail(hw, mbx, tail);
1184 if (err < 0)
1185 return err;
1187 /* verify the checksum on the incoming data */
1188 err = fm10k_mbx_verify_remote_crc(mbx);
1189 if (err)
1190 return err;
1192 /* process messages if we have received any */
1193 fm10k_mbx_dequeue_rx(hw, mbx);
1195 return fm10k_mbx_create_reply(hw, mbx, head);
1199 * fm10k_mbx_process_disconnect - Process disconnect header
1200 * @mbx: pointer to mailbox
1202 * This function will read an incoming disconnect header and reply with the
1203 * appropriate message. It will return a value indicating the number of
1204 * data DWORDs on success, or will return a negative value on failure.
1206 static s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1207 struct fm10k_mbx_info *mbx)
1209 const enum fm10k_mbx_state state = mbx->state;
1210 const u32 *hdr = &mbx->mbx_hdr;
1211 u16 head;
1212 s32 err;
1214 /* we will need to pull the header field for verification */
1215 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1217 /* We should not be receiving disconnect if Rx is incomplete */
1218 if (mbx->pushed)
1219 return FM10K_MBX_ERR_TAIL;
1221 /* we have already verified mbx->head == tail so we know this is 0 */
1222 mbx->head_len = 0;
1224 /* verify the checksum on the incoming header is correct */
1225 err = fm10k_mbx_verify_remote_crc(mbx);
1226 if (err)
1227 return err;
1229 switch (state) {
1230 case FM10K_STATE_DISCONNECT:
1231 case FM10K_STATE_OPEN:
1232 /* state doesn't change if we still have work to do */
1233 if (!fm10k_mbx_tx_complete(mbx))
1234 break;
1236 /* verify the head indicates we completed all transmits */
1237 if (head != mbx->tail)
1238 return FM10K_MBX_ERR_HEAD;
1240 /* reset any in-progress work */
1241 fm10k_mbx_connect_reset(mbx);
1242 break;
1243 default:
1244 break;
1247 return fm10k_mbx_create_reply(hw, mbx, head);
1251 * fm10k_mbx_process_error - Process error header
1252 * @mbx: pointer to mailbox
1254 * This function will read an incoming error header and reply with the
1255 * appropriate message. It will return a value indicating the number of
1256 * data DWORDs on success, or will return a negative value on failure.
1258 static s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1259 struct fm10k_mbx_info *mbx)
1261 const u32 *hdr = &mbx->mbx_hdr;
1262 u16 head;
1264 /* we will need to pull all of the fields for verification */
1265 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1267 switch (mbx->state) {
1268 case FM10K_STATE_OPEN:
1269 case FM10K_STATE_DISCONNECT:
1270 /* flush any uncompleted work */
1271 fm10k_mbx_reset_work(mbx);
1273 /* reset CRC seeds */
1274 mbx->local = FM10K_MBX_CRC_SEED;
1275 mbx->remote = FM10K_MBX_CRC_SEED;
1277 /* reset tail index and size to prepare for reconnect */
1278 mbx->tail = head;
1280 /* if open then reset max_size and go back to connect */
1281 if (mbx->state == FM10K_STATE_OPEN) {
1282 mbx->state = FM10K_STATE_CONNECT;
1283 break;
1286 /* send a connect message to get data flowing again */
1287 fm10k_mbx_create_connect_hdr(mbx);
1288 return 0;
1289 default:
1290 break;
1293 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1297 * fm10k_mbx_process - Process mailbox interrupt
1298 * @hw: pointer to hardware structure
1299 * @mbx: pointer to mailbox
1301 * This function will process incoming mailbox events and generate mailbox
1302 * replies. It will return a value indicating the number of DWORDs
1303 * transmitted excluding header on success or a negative value on error.
1305 static s32 fm10k_mbx_process(struct fm10k_hw *hw,
1306 struct fm10k_mbx_info *mbx)
1308 s32 err;
1310 /* we do not read mailbox if closed */
1311 if (mbx->state == FM10K_STATE_CLOSED)
1312 return 0;
1314 /* copy data from mailbox */
1315 err = fm10k_mbx_read(hw, mbx);
1316 if (err)
1317 return err;
1319 /* validate type, source, and destination */
1320 err = fm10k_mbx_validate_msg_hdr(mbx);
1321 if (err < 0)
1322 goto msg_err;
1324 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1325 case FM10K_MSG_CONNECT:
1326 err = fm10k_mbx_process_connect(hw, mbx);
1327 break;
1328 case FM10K_MSG_DATA:
1329 err = fm10k_mbx_process_data(hw, mbx);
1330 break;
1331 case FM10K_MSG_DISCONNECT:
1332 err = fm10k_mbx_process_disconnect(hw, mbx);
1333 break;
1334 case FM10K_MSG_ERROR:
1335 err = fm10k_mbx_process_error(hw, mbx);
1336 break;
1337 default:
1338 err = FM10K_MBX_ERR_TYPE;
1339 break;
1342 msg_err:
1343 /* notify partner of errors on our end */
1344 if (err < 0)
1345 fm10k_mbx_create_error_msg(mbx, err);
1347 /* copy data from mailbox */
1348 fm10k_mbx_write(hw, mbx);
1350 return err;
1354 * fm10k_mbx_disconnect - Shutdown mailbox connection
1355 * @hw: pointer to hardware structure
1356 * @mbx: pointer to mailbox
1358 * This function will shut down the mailbox. It places the mailbox first
1359 * in the disconnect state, it then allows up to a predefined timeout for
1360 * the mailbox to transition to close on its own. If this does not occur
1361 * then the mailbox will be forced into the closed state.
1363 * Any mailbox transactions not completed before calling this function
1364 * are not guaranteed to complete and may be dropped.
1366 static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1367 struct fm10k_mbx_info *mbx)
1369 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1371 /* Place mbx in ready to disconnect state */
1372 mbx->state = FM10K_STATE_DISCONNECT;
1374 /* trigger interrupt to start shutdown process */
1375 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1376 FM10K_MBX_INTERRUPT_DISABLE);
1377 do {
1378 udelay(FM10K_MBX_POLL_DELAY);
1379 mbx->ops.process(hw, mbx);
1380 timeout -= FM10K_MBX_POLL_DELAY;
1381 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1383 /* in case we didn't close, just force the mailbox into shutdown and
1384 * drop all left over messages in the FIFO.
1386 fm10k_mbx_connect_reset(mbx);
1387 fm10k_fifo_drop_all(&mbx->tx);
1389 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1393 * fm10k_mbx_connect - Start mailbox connection
1394 * @hw: pointer to hardware structure
1395 * @mbx: pointer to mailbox
1397 * This function will initiate a mailbox connection. It will populate the
1398 * mailbox with a broadcast connect message and then initialize the lock.
1399 * This is safe since the connect message is a single DWORD so the mailbox
1400 * transaction is guaranteed to be atomic.
1402 * This function will return an error if the mailbox has not been initiated
1403 * or is currently in use.
1405 static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1407 /* we cannot connect an uninitialized mailbox */
1408 if (!mbx->rx.buffer)
1409 return FM10K_MBX_ERR_NO_SPACE;
1411 /* we cannot connect an already connected mailbox */
1412 if (mbx->state != FM10K_STATE_CLOSED)
1413 return FM10K_MBX_ERR_BUSY;
1415 /* mailbox timeout can now become active */
1416 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1418 /* Place mbx in ready to connect state */
1419 mbx->state = FM10K_STATE_CONNECT;
1421 /* initialize header of remote mailbox */
1422 fm10k_mbx_create_disconnect_hdr(mbx);
1423 fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1425 /* enable interrupt and notify other party of new message */
1426 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1427 FM10K_MBX_INTERRUPT_ENABLE;
1429 /* generate and load connect header into mailbox */
1430 fm10k_mbx_create_connect_hdr(mbx);
1431 fm10k_mbx_write(hw, mbx);
1433 return 0;
1437 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
1438 * @msg_data: handlers for mailbox events
1440 * This function validates the layout of the message parsing data. This
1441 * should be mostly static, but it is important to catch any errors that
1442 * are made when constructing the parsers.
1444 static s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1446 const struct fm10k_tlv_attr *attr;
1447 unsigned int id;
1449 /* Allow NULL mailboxes that transmit but don't receive */
1450 if (!msg_data)
1451 return 0;
1453 while (msg_data->id != FM10K_TLV_ERROR) {
1454 /* all messages should have a function handler */
1455 if (!msg_data->func)
1456 return FM10K_ERR_PARAM;
1458 /* parser is optional */
1459 attr = msg_data->attr;
1460 if (attr) {
1461 while (attr->id != FM10K_TLV_ERROR) {
1462 id = attr->id;
1463 attr++;
1464 /* ID should always be increasing */
1465 if (id >= attr->id)
1466 return FM10K_ERR_PARAM;
1467 /* ID should fit in results array */
1468 if (id >= FM10K_TLV_RESULTS_MAX)
1469 return FM10K_ERR_PARAM;
1472 /* verify terminator is in the list */
1473 if (attr->id != FM10K_TLV_ERROR)
1474 return FM10K_ERR_PARAM;
1477 id = msg_data->id;
1478 msg_data++;
1479 /* ID should always be increasing */
1480 if (id >= msg_data->id)
1481 return FM10K_ERR_PARAM;
1484 /* verify terminator is in the list */
1485 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1486 return FM10K_ERR_PARAM;
1488 return 0;
1492 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1493 * @mbx: pointer to mailbox
1494 * @msg_data: handlers for mailbox events
1496 * This function associates a set of message handling ops with a mailbox.
1498 static s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1499 const struct fm10k_msg_data *msg_data)
1501 /* validate layout of handlers before assigning them */
1502 if (fm10k_mbx_validate_handlers(msg_data))
1503 return FM10K_ERR_PARAM;
1505 /* initialize the message handlers */
1506 mbx->msg_data = msg_data;
1508 return 0;
1512 * fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1513 * @hw: pointer to hardware structure
1514 * @mbx: pointer to mailbox
1515 * @msg_data: handlers for mailbox events
1516 * @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1518 * This function initializes the mailbox for use. It will split the
1519 * buffer provided an use that th populate both the Tx and Rx FIFO by
1520 * evenly splitting it. In order to allow for easy masking of head/tail
1521 * the value reported in size must be a power of 2 and is reported in
1522 * DWORDs, not bytes. Any invalid values will cause the mailbox to return
1523 * error.
1525 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1526 const struct fm10k_msg_data *msg_data, u8 id)
1528 /* initialize registers */
1529 switch (hw->mac.type) {
1530 case fm10k_mac_vf:
1531 mbx->mbx_reg = FM10K_VFMBX;
1532 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1533 break;
1534 case fm10k_mac_pf:
1535 /* there are only 64 VF <-> PF mailboxes */
1536 if (id < 64) {
1537 mbx->mbx_reg = FM10K_MBX(id);
1538 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1539 break;
1541 /* fallthough */
1542 default:
1543 return FM10K_MBX_ERR_NO_MBX;
1546 /* start out in closed state */
1547 mbx->state = FM10K_STATE_CLOSED;
1549 /* validate layout of handlers before assigning them */
1550 if (fm10k_mbx_validate_handlers(msg_data))
1551 return FM10K_ERR_PARAM;
1553 /* initialize the message handlers */
1554 mbx->msg_data = msg_data;
1556 /* start mailbox as timed out and let the reset_hw call
1557 * set the timeout value to begin communications
1559 mbx->timeout = 0;
1560 mbx->udelay = FM10K_MBX_INIT_DELAY;
1562 /* initialize tail and head */
1563 mbx->tail = 1;
1564 mbx->head = 1;
1566 /* initialize CRC seeds */
1567 mbx->local = FM10K_MBX_CRC_SEED;
1568 mbx->remote = FM10K_MBX_CRC_SEED;
1570 /* Split buffer for use by Tx/Rx FIFOs */
1571 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1572 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1574 /* initialize the FIFOs, sizes are in 4 byte increments */
1575 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1576 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1577 FM10K_MBX_RX_BUFFER_SIZE);
1579 /* initialize function pointers */
1580 mbx->ops.connect = fm10k_mbx_connect;
1581 mbx->ops.disconnect = fm10k_mbx_disconnect;
1582 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1583 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1584 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1585 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1586 mbx->ops.process = fm10k_mbx_process;
1587 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1589 return 0;
1593 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1594 * @mbx: pointer to mailbox
1596 * This function returns a connection mailbox header
1598 static void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1600 if (mbx->tail_len)
1601 mbx->mbx_lock |= FM10K_MBX_REQ;
1603 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1604 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1605 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1609 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1610 * @mbx: pointer to mailbox
1611 * @err: error flags to report if any
1613 * This function returns a connection mailbox header
1615 static void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1617 if (mbx->local)
1618 mbx->mbx_lock |= FM10K_MBX_REQ;
1620 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1621 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1622 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1623 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1627 * fm10k_sm_mbx_connect_reset - Reset following request for reset
1628 * @mbx: pointer to mailbox
1630 * This function resets the mailbox to a just connected state
1632 static void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1634 /* flush any uncompleted work */
1635 fm10k_mbx_reset_work(mbx);
1637 /* set local version to max and remote version to 0 */
1638 mbx->local = FM10K_SM_MBX_VERSION;
1639 mbx->remote = 0;
1641 /* initialize tail and head */
1642 mbx->tail = 1;
1643 mbx->head = 1;
1645 /* reset state back to connect */
1646 mbx->state = FM10K_STATE_CONNECT;
1650 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
1651 * @hw: pointer to hardware structure
1652 * @mbx: pointer to mailbox
1654 * This function will initiate a mailbox connection with the switch
1655 * manager. To do this it will first disconnect the mailbox, and then
1656 * reconnect it in order to complete a reset of the mailbox.
1658 * This function will return an error if the mailbox has not been initiated
1659 * or is currently in use.
1661 static s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1663 /* we cannot connect an uninitialized mailbox */
1664 if (!mbx->rx.buffer)
1665 return FM10K_MBX_ERR_NO_SPACE;
1667 /* we cannot connect an already connected mailbox */
1668 if (mbx->state != FM10K_STATE_CLOSED)
1669 return FM10K_MBX_ERR_BUSY;
1671 /* mailbox timeout can now become active */
1672 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1674 /* Place mbx in ready to connect state */
1675 mbx->state = FM10K_STATE_CONNECT;
1676 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1678 /* reset interface back to connect */
1679 fm10k_sm_mbx_connect_reset(mbx);
1681 /* enable interrupt and notify other party of new message */
1682 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1683 FM10K_MBX_INTERRUPT_ENABLE;
1685 /* generate and load connect header into mailbox */
1686 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1687 fm10k_mbx_write(hw, mbx);
1689 /* enable interrupt and notify other party of new message */
1691 return 0;
1695 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1696 * @hw: pointer to hardware structure
1697 * @mbx: pointer to mailbox
1699 * This function will shut down the mailbox. It places the mailbox first
1700 * in the disconnect state, it then allows up to a predefined timeout for
1701 * the mailbox to transition to close on its own. If this does not occur
1702 * then the mailbox will be forced into the closed state.
1704 * Any mailbox transactions not completed before calling this function
1705 * are not guaranteed to complete and may be dropped.
1707 static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1708 struct fm10k_mbx_info *mbx)
1710 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1712 /* Place mbx in ready to disconnect state */
1713 mbx->state = FM10K_STATE_DISCONNECT;
1715 /* trigger interrupt to start shutdown process */
1716 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1717 FM10K_MBX_INTERRUPT_DISABLE);
1718 do {
1719 udelay(FM10K_MBX_POLL_DELAY);
1720 mbx->ops.process(hw, mbx);
1721 timeout -= FM10K_MBX_POLL_DELAY;
1722 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1724 /* in case we didn't close just force the mailbox into shutdown */
1725 mbx->state = FM10K_STATE_CLOSED;
1726 mbx->remote = 0;
1727 fm10k_mbx_reset_work(mbx);
1728 fm10k_mbx_update_max_size(mbx, 0);
1730 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1734 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1735 * @mbx: pointer to mailbox
1737 * This function will parse up the fields in the mailbox header and return
1738 * an error if the header contains any of a number of invalid configurations
1739 * including unrecognized offsets or version numbers.
1741 static s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1743 const u32 *hdr = &mbx->mbx_hdr;
1744 u16 tail, head, ver;
1746 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1747 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1748 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1750 switch (ver) {
1751 case 0:
1752 break;
1753 case FM10K_SM_MBX_VERSION:
1754 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1755 return FM10K_MBX_ERR_HEAD;
1756 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1757 return FM10K_MBX_ERR_TAIL;
1758 if (mbx->tail < head)
1759 head += mbx->mbmem_len - 1;
1760 if (tail < mbx->head)
1761 tail += mbx->mbmem_len - 1;
1762 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1763 return FM10K_MBX_ERR_HEAD;
1764 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1765 break;
1766 return FM10K_MBX_ERR_TAIL;
1767 default:
1768 return FM10K_MBX_ERR_SRC;
1771 return 0;
1775 * fm10k_sm_mbx_process_error - Process header with error flag set
1776 * @mbx: pointer to mailbox
1778 * This function is meant to respond to a request where the error flag
1779 * is set. As a result we will terminate a connection if one is present
1780 * and fall back into the reset state with a connection header of version
1781 * 0 (RESET).
1783 static void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1785 const enum fm10k_mbx_state state = mbx->state;
1787 switch (state) {
1788 case FM10K_STATE_DISCONNECT:
1789 /* if there is an error just disconnect */
1790 mbx->remote = 0;
1791 break;
1792 case FM10K_STATE_OPEN:
1793 /* flush any uncompleted work */
1794 fm10k_sm_mbx_connect_reset(mbx);
1795 break;
1796 case FM10K_STATE_CONNECT:
1797 /* try connnecting at lower version */
1798 if (mbx->remote) {
1799 while (mbx->local > 1)
1800 mbx->local--;
1801 mbx->remote = 0;
1803 break;
1804 default:
1805 break;
1808 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1812 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1813 * @mbx: pointer to mailbox
1814 * @err: local error encountered
1816 * This function will interpret the error provided by err, and based on
1817 * that it may set the error bit in the local message header
1819 static void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1821 /* only generate an error message for these types */
1822 switch (err) {
1823 case FM10K_MBX_ERR_TAIL:
1824 case FM10K_MBX_ERR_HEAD:
1825 case FM10K_MBX_ERR_SRC:
1826 case FM10K_MBX_ERR_SIZE:
1827 case FM10K_MBX_ERR_RSVD0:
1828 break;
1829 default:
1830 return;
1833 /* process it as though we received an error, and send error reply */
1834 fm10k_sm_mbx_process_error(mbx);
1835 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1839 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1840 * @hw: pointer to hardware structure
1841 * @mbx: pointer to mailbox
1843 * This function will dequeue one message from the Rx switch manager mailbox
1844 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1846 static s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1847 struct fm10k_mbx_info *mbx,
1848 u16 tail)
1850 /* reduce length by 1 to convert to a mask */
1851 u16 mbmem_len = mbx->mbmem_len - 1;
1852 s32 err;
1854 /* push tail in front of head */
1855 if (tail < mbx->head)
1856 tail += mbmem_len;
1858 /* copy data to the Rx FIFO */
1859 err = fm10k_mbx_push_tail(hw, mbx, tail);
1860 if (err < 0)
1861 return err;
1863 /* process messages if we have received any */
1864 fm10k_mbx_dequeue_rx(hw, mbx);
1866 /* guarantee head aligns with the end of the last message */
1867 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1868 mbx->pushed = 0;
1870 /* clear any extra bits left over since index adds 1 extra bit */
1871 if (mbx->head > mbmem_len)
1872 mbx->head -= mbmem_len;
1874 return err;
1878 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1879 * @hw: pointer to hardware structure
1880 * @mbx: pointer to mailbox
1882 * This function will dequeue one message from the Tx mailbox FIFO and place
1883 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1885 static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1886 struct fm10k_mbx_info *mbx, u16 head)
1888 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1889 /* reduce length by 1 to convert to a mask */
1890 u16 mbmem_len = mbx->mbmem_len - 1;
1891 u16 tail_len, len = 0;
1892 u32 *msg;
1894 /* push head behind tail */
1895 if (mbx->tail < head)
1896 head += mbmem_len;
1898 fm10k_mbx_pull_head(hw, mbx, head);
1900 /* determine msg aligned offset for end of buffer */
1901 do {
1902 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1903 tail_len = len;
1904 len += FM10K_TLV_DWORD_LEN(*msg);
1905 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1907 /* guarantee we stop on a message boundary */
1908 if (mbx->tail_len > tail_len) {
1909 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1910 mbx->tail_len = tail_len;
1913 /* clear any extra bits left over since index adds 1 extra bit */
1914 if (mbx->tail > mbmem_len)
1915 mbx->tail -= mbmem_len;
1919 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1920 * @mbx: pointer to mailbox
1921 * @head: acknowledgement number
1923 * This function will generate an outgoing message based on the current
1924 * mailbox state and the remote fifo head. It will return the length
1925 * of the outgoing message excluding header on success, and a negative value
1926 * on error.
1928 static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1929 struct fm10k_mbx_info *mbx, u16 head)
1931 switch (mbx->state) {
1932 case FM10K_STATE_OPEN:
1933 case FM10K_STATE_DISCONNECT:
1934 /* flush out Tx data */
1935 fm10k_sm_mbx_transmit(hw, mbx, head);
1937 /* generate new header based on data */
1938 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1939 fm10k_sm_mbx_create_data_hdr(mbx);
1940 } else {
1941 mbx->remote = 0;
1942 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1944 break;
1945 case FM10K_STATE_CONNECT:
1946 case FM10K_STATE_CLOSED:
1947 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1948 break;
1949 default:
1950 break;
1955 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
1956 * @hw: pointer to hardware structure
1957 * @mbx: pointer to mailbox
1959 * This function is meant to respond to a request where the version data
1960 * is set to 0. As such we will either terminate the connection or go
1961 * into the connect state in order to re-establish the connection. This
1962 * function can also be used to respond to an error as the connection
1963 * resetting would also be a means of dealing with errors.
1965 static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
1966 struct fm10k_mbx_info *mbx)
1968 const enum fm10k_mbx_state state = mbx->state;
1970 switch (state) {
1971 case FM10K_STATE_DISCONNECT:
1972 /* drop remote connections and disconnect */
1973 mbx->state = FM10K_STATE_CLOSED;
1974 mbx->remote = 0;
1975 mbx->local = 0;
1976 break;
1977 case FM10K_STATE_OPEN:
1978 /* flush any incomplete work */
1979 fm10k_sm_mbx_connect_reset(mbx);
1980 break;
1981 case FM10K_STATE_CONNECT:
1982 /* Update remote value to match local value */
1983 mbx->remote = mbx->local;
1984 default:
1985 break;
1988 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
1992 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
1993 * @hw: pointer to hardware structure
1994 * @mbx: pointer to mailbox
1996 * This function is meant to process messages received when the remote
1997 * mailbox is active.
1999 static s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2000 struct fm10k_mbx_info *mbx)
2002 const u32 *hdr = &mbx->mbx_hdr;
2003 u16 head, tail;
2004 s32 len;
2006 /* pull all fields needed for verification */
2007 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2008 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2010 /* if we are in connect and wanting version 1 then start up and go */
2011 if (mbx->state == FM10K_STATE_CONNECT) {
2012 if (!mbx->remote)
2013 goto send_reply;
2014 if (mbx->remote != 1)
2015 return FM10K_MBX_ERR_SRC;
2017 mbx->state = FM10K_STATE_OPEN;
2020 do {
2021 /* abort on message size errors */
2022 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2023 if (len < 0)
2024 return len;
2026 /* continue until we have flushed the Rx FIFO */
2027 } while (len);
2029 send_reply:
2030 fm10k_sm_mbx_create_reply(hw, mbx, head);
2032 return 0;
2036 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2037 * @hw: pointer to hardware structure
2038 * @mbx: pointer to mailbox
2040 * This function will process incoming mailbox events and generate mailbox
2041 * replies. It will return a value indicating the number of DWORDs
2042 * transmitted excluding header on success or a negative value on error.
2044 static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2045 struct fm10k_mbx_info *mbx)
2047 s32 err;
2049 /* we do not read mailbox if closed */
2050 if (mbx->state == FM10K_STATE_CLOSED)
2051 return 0;
2053 /* retrieve data from switch manager */
2054 err = fm10k_mbx_read(hw, mbx);
2055 if (err)
2056 return err;
2058 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2059 if (err < 0)
2060 goto fifo_err;
2062 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2063 fm10k_sm_mbx_process_error(mbx);
2064 goto fifo_err;
2067 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2068 case 0:
2069 fm10k_sm_mbx_process_reset(hw, mbx);
2070 break;
2071 case FM10K_SM_MBX_VERSION:
2072 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2073 break;
2076 fifo_err:
2077 if (err < 0)
2078 fm10k_sm_mbx_create_error_msg(mbx, err);
2080 /* report data to switch manager */
2081 fm10k_mbx_write(hw, mbx);
2083 return err;
2087 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2088 * @hw: pointer to hardware structure
2089 * @mbx: pointer to mailbox
2090 * @msg_data: handlers for mailbox events
2092 * This function for now is used to stub out the PF/SM mailbox
2094 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2095 const struct fm10k_msg_data *msg_data)
2097 mbx->mbx_reg = FM10K_GMBX;
2098 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2099 /* start out in closed state */
2100 mbx->state = FM10K_STATE_CLOSED;
2102 /* validate layout of handlers before assigning them */
2103 if (fm10k_mbx_validate_handlers(msg_data))
2104 return FM10K_ERR_PARAM;
2106 /* initialize the message handlers */
2107 mbx->msg_data = msg_data;
2109 /* start mailbox as timed out and let the reset_hw call
2110 * set the timeout value to begin communications
2112 mbx->timeout = 0;
2113 mbx->udelay = FM10K_MBX_INIT_DELAY;
2115 /* Split buffer for use by Tx/Rx FIFOs */
2116 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2117 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2119 /* initialize the FIFOs, sizes are in 4 byte increments */
2120 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2121 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2122 FM10K_MBX_RX_BUFFER_SIZE);
2124 /* initialize function pointers */
2125 mbx->ops.connect = fm10k_sm_mbx_connect;
2126 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2127 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2128 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2129 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2130 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2131 mbx->ops.process = fm10k_sm_mbx_process;
2132 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2134 return 0;