fm10k/base: ignore oversized mailbox messages
[dpdk.git] / drivers / net / fm10k / base / fm10k_mbx.c
1 /*******************************************************************************
2
3 Copyright (c) 2013 - 2015, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11
12  2. Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in the
14     documentation and/or other materials provided with the distribution.
15
16  3. Neither the name of the Intel Corporation nor the names of its
17     contributors may be used to endorse or promote products derived from
18     this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
31
32 ***************************************************************************/
33
34 #include "fm10k_common.h"
35
36 /**
37  *  fm10k_fifo_init - Initialize a message FIFO
38  *  @fifo: pointer to FIFO
39  *  @buffer: pointer to memory to be used to store FIFO
40  *  @size: maximum message size to store in FIFO, must be 2^n - 1
41  **/
42 STATIC void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
43 {
44         fifo->buffer = buffer;
45         fifo->size = size;
46         fifo->head = 0;
47         fifo->tail = 0;
48 }
49
50 /**
51  *  fm10k_fifo_used - Retrieve used space in FIFO
52  *  @fifo: pointer to FIFO
53  *
54  *  This function returns the number of DWORDs used in the FIFO
55  **/
56 STATIC u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
57 {
58         return fifo->tail - fifo->head;
59 }
60
61 /**
62  *  fm10k_fifo_unused - Retrieve unused space in FIFO
63  *  @fifo: pointer to FIFO
64  *
65  *  This function returns the number of unused DWORDs in the FIFO
66  **/
67 STATIC u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
68 {
69         return fifo->size + fifo->head - fifo->tail;
70 }
71
72 /**
73  *  fm10k_fifo_empty - Test to verify if fifo is empty
74  *  @fifo: pointer to FIFO
75  *
76  *  This function returns true if the FIFO is empty, else false
77  **/
78 STATIC bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
79 {
80         return fifo->head == fifo->tail;
81 }
82
83 /**
84  *  fm10k_fifo_head_offset - returns indices of head with given offset
85  *  @fifo: pointer to FIFO
86  *  @offset: offset to add to head
87  *
88  *  This function returns the indices into the fifo based on head + offset
89  **/
90 STATIC u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
91 {
92         return (fifo->head + offset) & (fifo->size - 1);
93 }
94
95 /**
96  *  fm10k_fifo_tail_offset - returns indices of tail with given offset
97  *  @fifo: pointer to FIFO
98  *  @offset: offset to add to tail
99  *
100  *  This function returns the indices into the fifo based on tail + offset
101  **/
102 STATIC u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
103 {
104         return (fifo->tail + offset) & (fifo->size - 1);
105 }
106
107 /**
108  *  fm10k_fifo_head_len - Retrieve length of first message in FIFO
109  *  @fifo: pointer to FIFO
110  *
111  *  This function returns the size of the first message in the FIFO
112  **/
113 STATIC u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
114 {
115         u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
116
117         /* verify there is at least 1 DWORD in the fifo so *head is valid */
118         if (fm10k_fifo_empty(fifo))
119                 return 0;
120
121         /* retieve the message length */
122         return FM10K_TLV_DWORD_LEN(*head);
123 }
124
125 /**
126  *  fm10k_fifo_head_drop - Drop the first message in FIFO
127  *  @fifo: pointer to FIFO
128  *
129  *  This function returns the size of the message dropped from the FIFO
130  **/
131 STATIC u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
132 {
133         u16 len = fm10k_fifo_head_len(fifo);
134
135         /* update head so it is at the start of next frame */
136         fifo->head += len;
137
138         return len;
139 }
140
141 /**
142  *  fm10k_fifo_drop_all - Drop all messages in FIFO
143  *  @fifo: pointer to FIFO
144  *
145  *  This function resets the head pointer to drop all messages in the FIFO,
146  *  and ensure the FIFO is empty.
147  **/
148 STATIC void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
149 {
150         fifo->head = fifo->tail;
151 }
152
153 /**
154  *  fm10k_mbx_index_len - Convert a head/tail index into a length value
155  *  @mbx: pointer to mailbox
156  *  @head: head index
157  *  @tail: head index
158  *
159  *  This function takes the head and tail index and determines the length
160  *  of the data indicated by this pair.
161  **/
162 STATIC u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
163 {
164         u16 len = tail - head;
165
166         /* we wrapped so subtract 2, one for index 0, one for all 1s index */
167         if (len > tail)
168                 len -= 2;
169
170         return len & ((mbx->mbmem_len << 1) - 1);
171 }
172
173 /**
174  *  fm10k_mbx_tail_add - Determine new tail value with added offset
175  *  @mbx: pointer to mailbox
176  *  @offset: length to add to head offset
177  *
178  *  This function takes the local tail index and recomputes it for
179  *  a given length added as an offset.
180  **/
181 STATIC u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
182 {
183         u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
184
185         /* add/sub 1 because we cannot have offset 0 or all 1s */
186         return (tail > mbx->tail) ? --tail : ++tail;
187 }
188
189 /**
190  *  fm10k_mbx_tail_sub - Determine new tail value with subtracted offset
191  *  @mbx: pointer to mailbox
192  *  @offset: length to add to head offset
193  *
194  *  This function takes the local tail index and recomputes it for
195  *  a given length added as an offset.
196  **/
197 STATIC u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
198 {
199         u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
200
201         /* sub/add 1 because we cannot have offset 0 or all 1s */
202         return (tail < mbx->tail) ? ++tail : --tail;
203 }
204
205 /**
206  *  fm10k_mbx_head_add - Determine new head value with added offset
207  *  @mbx: pointer to mailbox
208  *  @offset: length to add to head offset
209  *
210  *  This function takes the local head index and recomputes it for
211  *  a given length added as an offset.
212  **/
213 STATIC u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
214 {
215         u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
216
217         /* add/sub 1 because we cannot have offset 0 or all 1s */
218         return (head > mbx->head) ? --head : ++head;
219 }
220
221 /**
222  *  fm10k_mbx_head_sub - Determine new head value with subtracted offset
223  *  @mbx: pointer to mailbox
224  *  @offset: length to add to head offset
225  *
226  *  This function takes the local head index and recomputes it for
227  *  a given length added as an offset.
228  **/
229 STATIC u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
230 {
231         u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
232
233         /* sub/add 1 because we cannot have offset 0 or all 1s */
234         return (head < mbx->head) ? ++head : --head;
235 }
236
237 /**
238  *  fm10k_mbx_pushed_tail_len - Retrieve the length of message being pushed
239  *  @mbx: pointer to mailbox
240  *
241  *  This function will return the length of the message currently being
242  *  pushed onto the tail of the Rx queue.
243  **/
244 STATIC u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
245 {
246         u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
247
248         /* pushed tail is only valid if pushed is set */
249         if (!mbx->pushed)
250                 return 0;
251
252         return FM10K_TLV_DWORD_LEN(*tail);
253 }
254
255 /**
256  *  fm10k_fifo_write_copy - pulls data off of msg and places it in fifo
257  *  @fifo: pointer to FIFO
258  *  @msg: message array to populate
259  *  @tail_offset: additional offset to add to tail pointer
260  *  @len: length of FIFO to copy into message header
261  *
262  *  This function will take a message and copy it into a section of the
263  *  FIFO.  In order to get something into a location other than just
264  *  the tail you can use tail_offset to adjust the pointer.
265  **/
266 STATIC void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
267                                   const u32 *msg, u16 tail_offset, u16 len)
268 {
269         u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
270         u32 *tail = fifo->buffer + end;
271
272         /* track when we should cross the end of the FIFO */
273         end = fifo->size - end;
274
275         /* copy end of message before start of message */
276         if (end < len)
277                 memcpy(fifo->buffer, msg + end, (len - end) << 2);
278         else
279                 end = len;
280
281         /* Copy remaining message into Tx FIFO */
282         memcpy(tail, msg, end << 2);
283 }
284
285 /**
286  *  fm10k_fifo_enqueue - Enqueues the message to the tail of the FIFO
287  *  @fifo: pointer to FIFO
288  *  @msg: message array to read
289  *
290  *  This function enqueues a message up to the size specified by the length
291  *  contained in the first DWORD of the message and will place at the tail
292  *  of the FIFO.  It will return 0 on success, or a negative value on error.
293  **/
294 STATIC s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
295 {
296         u16 len = FM10K_TLV_DWORD_LEN(*msg);
297
298         DEBUGFUNC("fm10k_fifo_enqueue");
299
300         /* verify parameters */
301         if (len > fifo->size)
302                 return FM10K_MBX_ERR_SIZE;
303
304         /* verify there is room for the message */
305         if (len > fm10k_fifo_unused(fifo))
306                 return FM10K_MBX_ERR_NO_SPACE;
307
308         /* Copy message into FIFO */
309         fm10k_fifo_write_copy(fifo, msg, 0, len);
310
311         /* memory barrier to guarantee FIFO is written before tail update */
312         FM10K_WMB();
313
314         /* Update Tx FIFO tail */
315         fifo->tail += len;
316
317         return FM10K_SUCCESS;
318 }
319
320 /**
321  *  fm10k_mbx_validate_msg_size - Validate incoming message based on size
322  *  @mbx: pointer to mailbox
323  *  @len: length of data pushed onto buffer
324  *
325  *  This function analyzes the frame and will return a non-zero value when
326  *  the start of a message larger than the mailbox is detected.
327  **/
328 STATIC u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
329 {
330         struct fm10k_mbx_fifo *fifo = &mbx->rx;
331         u16 total_len = 0, msg_len;
332         u32 *msg;
333
334         DEBUGFUNC("fm10k_mbx_validate_msg");
335
336         /* length should include previous amounts pushed */
337         len += mbx->pushed;
338
339         /* offset in message is based off of current message size */
340         do {
341                 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
342                 msg_len = FM10K_TLV_DWORD_LEN(*msg);
343                 total_len += msg_len;
344         } while (total_len < len);
345
346         /* message extends out of pushed section, but fits in FIFO */
347         if ((len < total_len) && (msg_len <= mbx->max_size))
348                 return 0;
349
350         /* return length of invalid section */
351         return (len < total_len) ? len : (len - total_len);
352 }
353
354 /**
355  *  fm10k_mbx_write_copy - pulls data off of Tx FIFO and places it in mbmem
356  *  @mbx: pointer to mailbox
357  *
358  *  This function will take a section of the Tx FIFO and copy it into the
359  *  mailbox memory.  The offset in mbmem is based on the lower bits of the
360  *  tail and len determines the length to copy.
361  **/
362 STATIC void fm10k_mbx_write_copy(struct fm10k_hw *hw,
363                                  struct fm10k_mbx_info *mbx)
364 {
365         struct fm10k_mbx_fifo *fifo = &mbx->tx;
366         u32 mbmem = mbx->mbmem_reg;
367         u32 *head = fifo->buffer;
368         u16 end, len, tail, mask;
369
370         DEBUGFUNC("fm10k_mbx_write_copy");
371
372         if (!mbx->tail_len)
373                 return;
374
375         /* determine data length and mbmem tail index */
376         mask = mbx->mbmem_len - 1;
377         len = mbx->tail_len;
378         tail = fm10k_mbx_tail_sub(mbx, len);
379         if (tail > mask)
380                 tail++;
381
382         /* determine offset in the ring */
383         end = fm10k_fifo_head_offset(fifo, mbx->pulled);
384         head += end;
385
386         /* memory barrier to guarantee data is ready to be read */
387         FM10K_RMB();
388
389         /* Copy message from Tx FIFO */
390         for (end = fifo->size - end; len; head = fifo->buffer) {
391                 do {
392                         /* adjust tail to match offset for FIFO */
393                         tail &= mask;
394                         if (!tail)
395                                 tail++;
396
397                         /* write message to hardware FIFO */
398                         FM10K_WRITE_MBX(hw, mbmem + tail++, *(head++));
399                 } while (--len && --end);
400         }
401 }
402
403 /**
404  *  fm10k_mbx_pull_head - Pulls data off of head of Tx FIFO
405  *  @hw: pointer to hardware structure
406  *  @mbx: pointer to mailbox
407  *  @head: acknowledgement number last received
408  *
409  *  This function will push the tail index forward based on the remote
410  *  head index.  It will then pull up to mbmem_len DWORDs off of the
411  *  head of the FIFO and will place it in the MBMEM registers
412  *  associated with the mailbox.
413  **/
414 STATIC void fm10k_mbx_pull_head(struct fm10k_hw *hw,
415                                 struct fm10k_mbx_info *mbx, u16 head)
416 {
417         u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
418         struct fm10k_mbx_fifo *fifo = &mbx->tx;
419
420         /* update number of bytes pulled and update bytes in transit */
421         mbx->pulled += mbx->tail_len - ack;
422
423         /* determine length of data to pull, reserve space for mbmem header */
424         mbmem_len = mbx->mbmem_len - 1;
425         len = fm10k_fifo_used(fifo) - mbx->pulled;
426         if (len > mbmem_len)
427                 len = mbmem_len;
428
429         /* update tail and record number of bytes in transit */
430         mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
431         mbx->tail_len = len;
432
433         /* drop pulled messages from the FIFO */
434         for (len = fm10k_fifo_head_len(fifo);
435              len && (mbx->pulled >= len);
436              len = fm10k_fifo_head_len(fifo)) {
437                 mbx->pulled -= fm10k_fifo_head_drop(fifo);
438                 mbx->tx_messages++;
439                 mbx->tx_dwords += len;
440         }
441
442         /* Copy message out from the Tx FIFO */
443         fm10k_mbx_write_copy(hw, mbx);
444 }
445
446 /**
447  *  fm10k_mbx_read_copy - pulls data off of mbmem and places it in Rx FIFO
448  *  @hw: pointer to hardware structure
449  *  @mbx: pointer to mailbox
450  *
451  *  This function will take a section of the mailbox memory and copy it
452  *  into the Rx FIFO.  The offset is based on the lower bits of the
453  *  head and len determines the length to copy.
454  **/
455 STATIC void fm10k_mbx_read_copy(struct fm10k_hw *hw,
456                                 struct fm10k_mbx_info *mbx)
457 {
458         struct fm10k_mbx_fifo *fifo = &mbx->rx;
459         u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
460         u32 *tail = fifo->buffer;
461         u16 end, len, head;
462
463         DEBUGFUNC("fm10k_mbx_read_copy");
464
465         /* determine data length and mbmem head index */
466         len = mbx->head_len;
467         head = fm10k_mbx_head_sub(mbx, len);
468         if (head >= mbx->mbmem_len)
469                 head++;
470
471         /* determine offset in the ring */
472         end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
473         tail += end;
474
475         /* Copy message into Rx FIFO */
476         for (end = fifo->size - end; len; tail = fifo->buffer) {
477                 do {
478                         /* adjust head to match offset for FIFO */
479                         head &= mbx->mbmem_len - 1;
480                         if (!head)
481                                 head++;
482
483                         /* read message from hardware FIFO */
484                         *(tail++) = FM10K_READ_MBX(hw, mbmem + head++);
485                 } while (--len && --end);
486         }
487
488         /* memory barrier to guarantee FIFO is written before tail update */
489         FM10K_WMB();
490 }
491
492 /**
493  *  fm10k_mbx_push_tail - Pushes up to 15 DWORDs on to tail of FIFO
494  *  @hw: pointer to hardware structure
495  *  @mbx: pointer to mailbox
496  *  @tail: tail index of message
497  *
498  *  This function will first validate the tail index and size for the
499  *  incoming message.  It then updates the acknowledgment number and
500  *  copies the data into the FIFO.  It will return the number of messages
501  *  dequeued on success and a negative value on error.
502  **/
503 STATIC s32 fm10k_mbx_push_tail(struct fm10k_hw *hw,
504                                struct fm10k_mbx_info *mbx,
505                                u16 tail)
506 {
507         struct fm10k_mbx_fifo *fifo = &mbx->rx;
508         u16 len, seq = fm10k_mbx_index_len(mbx, mbx->head, tail);
509
510         DEBUGFUNC("fm10k_mbx_push_tail");
511
512         /* determine length of data to push */
513         len = fm10k_fifo_unused(fifo) - mbx->pushed;
514         if (len > seq)
515                 len = seq;
516
517         /* update head and record bytes received */
518         mbx->head = fm10k_mbx_head_add(mbx, len);
519         mbx->head_len = len;
520
521         /* nothing to do if there is no data */
522         if (!len)
523                 return FM10K_SUCCESS;
524
525         /* Copy msg into Rx FIFO */
526         fm10k_mbx_read_copy(hw, mbx);
527
528         /* determine if there are any invalid lengths in message */
529         if (fm10k_mbx_validate_msg_size(mbx, len))
530                 return FM10K_MBX_ERR_SIZE;
531
532         /* Update pushed */
533         mbx->pushed += len;
534
535         /* flush any completed messages */
536         for (len = fm10k_mbx_pushed_tail_len(mbx);
537              len && (mbx->pushed >= len);
538              len = fm10k_mbx_pushed_tail_len(mbx)) {
539                 fifo->tail += len;
540                 mbx->pushed -= len;
541                 mbx->rx_messages++;
542                 mbx->rx_dwords += len;
543         }
544
545         return FM10K_SUCCESS;
546 }
547
548 /* pre-generated data for generating the CRC based on the poly 0xAC9A. */
549 static const u16 fm10k_crc_16b_table[256] = {
550         0x0000, 0x7956, 0xF2AC, 0x8BFA, 0xBC6D, 0xC53B, 0x4EC1, 0x3797,
551         0x21EF, 0x58B9, 0xD343, 0xAA15, 0x9D82, 0xE4D4, 0x6F2E, 0x1678,
552         0x43DE, 0x3A88, 0xB172, 0xC824, 0xFFB3, 0x86E5, 0x0D1F, 0x7449,
553         0x6231, 0x1B67, 0x909D, 0xE9CB, 0xDE5C, 0xA70A, 0x2CF0, 0x55A6,
554         0x87BC, 0xFEEA, 0x7510, 0x0C46, 0x3BD1, 0x4287, 0xC97D, 0xB02B,
555         0xA653, 0xDF05, 0x54FF, 0x2DA9, 0x1A3E, 0x6368, 0xE892, 0x91C4,
556         0xC462, 0xBD34, 0x36CE, 0x4F98, 0x780F, 0x0159, 0x8AA3, 0xF3F5,
557         0xE58D, 0x9CDB, 0x1721, 0x6E77, 0x59E0, 0x20B6, 0xAB4C, 0xD21A,
558         0x564D, 0x2F1B, 0xA4E1, 0xDDB7, 0xEA20, 0x9376, 0x188C, 0x61DA,
559         0x77A2, 0x0EF4, 0x850E, 0xFC58, 0xCBCF, 0xB299, 0x3963, 0x4035,
560         0x1593, 0x6CC5, 0xE73F, 0x9E69, 0xA9FE, 0xD0A8, 0x5B52, 0x2204,
561         0x347C, 0x4D2A, 0xC6D0, 0xBF86, 0x8811, 0xF147, 0x7ABD, 0x03EB,
562         0xD1F1, 0xA8A7, 0x235D, 0x5A0B, 0x6D9C, 0x14CA, 0x9F30, 0xE666,
563         0xF01E, 0x8948, 0x02B2, 0x7BE4, 0x4C73, 0x3525, 0xBEDF, 0xC789,
564         0x922F, 0xEB79, 0x6083, 0x19D5, 0x2E42, 0x5714, 0xDCEE, 0xA5B8,
565         0xB3C0, 0xCA96, 0x416C, 0x383A, 0x0FAD, 0x76FB, 0xFD01, 0x8457,
566         0xAC9A, 0xD5CC, 0x5E36, 0x2760, 0x10F7, 0x69A1, 0xE25B, 0x9B0D,
567         0x8D75, 0xF423, 0x7FD9, 0x068F, 0x3118, 0x484E, 0xC3B4, 0xBAE2,
568         0xEF44, 0x9612, 0x1DE8, 0x64BE, 0x5329, 0x2A7F, 0xA185, 0xD8D3,
569         0xCEAB, 0xB7FD, 0x3C07, 0x4551, 0x72C6, 0x0B90, 0x806A, 0xF93C,
570         0x2B26, 0x5270, 0xD98A, 0xA0DC, 0x974B, 0xEE1D, 0x65E7, 0x1CB1,
571         0x0AC9, 0x739F, 0xF865, 0x8133, 0xB6A4, 0xCFF2, 0x4408, 0x3D5E,
572         0x68F8, 0x11AE, 0x9A54, 0xE302, 0xD495, 0xADC3, 0x2639, 0x5F6F,
573         0x4917, 0x3041, 0xBBBB, 0xC2ED, 0xF57A, 0x8C2C, 0x07D6, 0x7E80,
574         0xFAD7, 0x8381, 0x087B, 0x712D, 0x46BA, 0x3FEC, 0xB416, 0xCD40,
575         0xDB38, 0xA26E, 0x2994, 0x50C2, 0x6755, 0x1E03, 0x95F9, 0xECAF,
576         0xB909, 0xC05F, 0x4BA5, 0x32F3, 0x0564, 0x7C32, 0xF7C8, 0x8E9E,
577         0x98E6, 0xE1B0, 0x6A4A, 0x131C, 0x248B, 0x5DDD, 0xD627, 0xAF71,
578         0x7D6B, 0x043D, 0x8FC7, 0xF691, 0xC106, 0xB850, 0x33AA, 0x4AFC,
579         0x5C84, 0x25D2, 0xAE28, 0xD77E, 0xE0E9, 0x99BF, 0x1245, 0x6B13,
580         0x3EB5, 0x47E3, 0xCC19, 0xB54F, 0x82D8, 0xFB8E, 0x7074, 0x0922,
581         0x1F5A, 0x660C, 0xEDF6, 0x94A0, 0xA337, 0xDA61, 0x519B, 0x28CD };
582
583 /**
584  *  fm10k_crc_16b - Generate a 16 bit CRC for a region of 16 bit data
585  *  @data: pointer to data to process
586  *  @seed: seed value for CRC
587  *  @len: length measured in 16 bits words
588  *
589  *  This function will generate a CRC based on the polynomial 0xAC9A and
590  *  whatever value is stored in the seed variable.  Note that this
591  *  value inverts the local seed and the result in order to capture all
592  *  leading and trailing zeros.
593  */
594 STATIC u16 fm10k_crc_16b(const u32 *data, u16 seed, u16 len)
595 {
596         u32 result = seed;
597
598         while (len--) {
599                 result ^= *(data++);
600                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
601                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
602
603                 if (!(len--))
604                         break;
605
606                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
607                 result = (result >> 8) ^ fm10k_crc_16b_table[result & 0xFF];
608         }
609
610         return (u16)result;
611 }
612
613 /**
614  *  fm10k_fifo_crc - generate a CRC based off of FIFO data
615  *  @fifo: pointer to FIFO
616  *  @offset: offset point for start of FIFO
617  *  @len: number of DWORDS words to process
618  *  @seed: seed value for CRC
619  *
620  *  This function generates a CRC for some region of the FIFO
621  **/
622 STATIC u16 fm10k_fifo_crc(struct fm10k_mbx_fifo *fifo, u16 offset,
623                           u16 len, u16 seed)
624 {
625         u32 *data = fifo->buffer + offset;
626
627         /* track when we should cross the end of the FIFO */
628         offset = fifo->size - offset;
629
630         /* if we are in 2 blocks process the end of the FIFO first */
631         if (offset < len) {
632                 seed = fm10k_crc_16b(data, seed, offset * 2);
633                 data = fifo->buffer;
634                 len -= offset;
635         }
636
637         /* process any remaining bits */
638         return fm10k_crc_16b(data, seed, len * 2);
639 }
640
641 /**
642  *  fm10k_mbx_update_local_crc - Update the local CRC for outgoing data
643  *  @mbx: pointer to mailbox
644  *  @head: head index provided by remote mailbox
645  *
646  *  This function will generate the CRC for all data from the end of the
647  *  last head update to the current one.  It uses the result of the
648  *  previous CRC as the seed for this update.  The result is stored in
649  *  mbx->local.
650  **/
651 STATIC void fm10k_mbx_update_local_crc(struct fm10k_mbx_info *mbx, u16 head)
652 {
653         u16 len = mbx->tail_len - fm10k_mbx_index_len(mbx, head, mbx->tail);
654
655         /* determine the offset for the start of the region to be pulled */
656         head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
657
658         /* update local CRC to include all of the pulled data */
659         mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
660 }
661
662 /**
663  *  fm10k_mbx_verify_remote_crc - Verify the CRC is correct for current data
664  *  @mbx: pointer to mailbox
665  *
666  *  This function will take all data that has been provided from the remote
667  *  end and generate a CRC for it.  This is stored in mbx->remote.  The
668  *  CRC for the header is then computed and if the result is non-zero this
669  *  is an error and we signal an error dropping all data and resetting the
670  *  connection.
671  */
672 STATIC s32 fm10k_mbx_verify_remote_crc(struct fm10k_mbx_info *mbx)
673 {
674         struct fm10k_mbx_fifo *fifo = &mbx->rx;
675         u16 len = mbx->head_len;
676         u16 offset = fm10k_fifo_tail_offset(fifo, mbx->pushed) - len;
677         u16 crc;
678
679         /* update the remote CRC if new data has been received */
680         if (len)
681                 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
682
683         /* process the full header as we have to validate the CRC */
684         crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
685
686         /* notify other end if we have a problem */
687         return crc ? FM10K_MBX_ERR_CRC : FM10K_SUCCESS;
688 }
689
690 /**
691  *  fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
692  *  @mbx: pointer to mailbox
693  *
694  *  This function returns true if there is a message in the Rx FIFO to dequeue.
695  **/
696 STATIC bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
697 {
698         u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
699
700         return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
701 }
702
703 /**
704  *  fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
705  *  @mbx: pointer to mailbox
706  *  @len: verify free space is >= this value
707  *
708  *  This function returns true if the mailbox is in a state ready to transmit.
709  **/
710 STATIC bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
711 {
712         u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
713
714         return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
715 }
716
717 /**
718  *  fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
719  *  @mbx: pointer to mailbox
720  *
721  *  This function returns true if the Tx FIFO is empty.
722  **/
723 STATIC bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
724 {
725         return fm10k_fifo_empty(&mbx->tx);
726 }
727
728 /**
729  *  fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
730  *  @hw: pointer to hardware structure
731  *  @mbx: pointer to mailbox
732  *
733  *  This function dequeues messages and hands them off to the tlv parser.
734  *  It will return the number of messages processed when called.
735  **/
736 STATIC u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
737                                 struct fm10k_mbx_info *mbx)
738 {
739         struct fm10k_mbx_fifo *fifo = &mbx->rx;
740         s32 err;
741         u16 cnt;
742
743         /* parse Rx messages out of the Rx FIFO to empty it */
744         for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
745                 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
746                                           mbx, mbx->msg_data);
747                 if (err < 0)
748                         mbx->rx_parse_err++;
749
750                 fm10k_fifo_head_drop(fifo);
751         }
752
753         /* shift remaining bytes back to start of FIFO */
754         memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
755
756         /* shift head and tail based on the memory we moved */
757         fifo->tail -= fifo->head;
758         fifo->head = 0;
759
760         return cnt;
761 }
762
763 /**
764  *  fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
765  *  @hw: pointer to hardware structure
766  *  @mbx: pointer to mailbox
767  *  @msg: message array to read
768  *
769  *  This function enqueues a message up to the size specified by the length
770  *  contained in the first DWORD of the message and will place at the tail
771  *  of the FIFO.  It will return 0 on success, or a negative value on error.
772  **/
773 STATIC s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
774                                 struct fm10k_mbx_info *mbx, const u32 *msg)
775 {
776         u32 countdown = mbx->timeout;
777         s32 err;
778
779         switch (mbx->state) {
780         case FM10K_STATE_CLOSED:
781         case FM10K_STATE_DISCONNECT:
782                 return FM10K_MBX_ERR_NO_MBX;
783         default:
784                 break;
785         }
786
787         /* enqueue the message on the Tx FIFO */
788         err = fm10k_fifo_enqueue(&mbx->tx, msg);
789
790         /* if it failed give the FIFO a chance to drain */
791         while (err && countdown) {
792                 countdown--;
793                 usec_delay(mbx->usec_delay);
794                 mbx->ops.process(hw, mbx);
795                 err = fm10k_fifo_enqueue(&mbx->tx, msg);
796         }
797
798         /* if we failed treat the error */
799         if (err) {
800                 mbx->timeout = 0;
801                 mbx->tx_busy++;
802         }
803
804         /* begin processing message, ignore errors as this is just meant
805          * to start the mailbox flow so we are not concerned if there
806          * is a bad error, or the mailbox is already busy with a request
807          */
808         if (!mbx->tail_len)
809                 mbx->ops.process(hw, mbx);
810
811         return FM10K_SUCCESS;
812 }
813
814 /**
815  *  fm10k_mbx_read - Copies the mbmem to local message buffer
816  *  @hw: pointer to hardware structure
817  *  @mbx: pointer to mailbox
818  *
819  *  This function copies the message from the mbmem to the message array
820  **/
821 STATIC s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
822 {
823         DEBUGFUNC("fm10k_mbx_read");
824
825         /* only allow one reader in here at a time */
826         if (mbx->mbx_hdr)
827                 return FM10K_MBX_ERR_BUSY;
828
829         /* read to capture initial interrupt bits */
830         if (FM10K_READ_MBX(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
831                 mbx->mbx_lock = FM10K_MBX_ACK;
832
833         /* write back interrupt bits to clear */
834         FM10K_WRITE_MBX(hw, mbx->mbx_reg,
835                         FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
836
837         /* read remote header */
838         mbx->mbx_hdr = FM10K_READ_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
839
840         return FM10K_SUCCESS;
841 }
842
843 /**
844  *  fm10k_mbx_write - Copies the local message buffer to mbmem
845  *  @hw: pointer to hardware structure
846  *  @mbx: pointer to mailbox
847  *
848  *  This function copies the message from the the message array to mbmem
849  **/
850 STATIC void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
851 {
852         u32 mbmem = mbx->mbmem_reg;
853
854         DEBUGFUNC("fm10k_mbx_write");
855
856         /* write new msg header to notify recipient of change */
857         FM10K_WRITE_MBX(hw, mbmem, mbx->mbx_hdr);
858
859         /* write mailbox to send interrupt */
860         if (mbx->mbx_lock)
861                 FM10K_WRITE_MBX(hw, mbx->mbx_reg, mbx->mbx_lock);
862
863         /* we no longer are using the header so free it */
864         mbx->mbx_hdr = 0;
865         mbx->mbx_lock = 0;
866 }
867
868 /**
869  *  fm10k_mbx_create_connect_hdr - Generate a connect mailbox header
870  *  @mbx: pointer to mailbox
871  *
872  *  This function returns a connection mailbox header
873  **/
874 STATIC void fm10k_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx)
875 {
876         mbx->mbx_lock |= FM10K_MBX_REQ;
877
878         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_CONNECT, TYPE) |
879                        FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD) |
880                        FM10K_MSG_HDR_FIELD_SET(mbx->rx.size - 1, CONNECT_SIZE);
881 }
882
883 /**
884  *  fm10k_mbx_create_data_hdr - Generate a data mailbox header
885  *  @mbx: pointer to mailbox
886  *
887  *  This function returns a data mailbox header
888  **/
889 STATIC void fm10k_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
890 {
891         u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DATA, TYPE) |
892                   FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
893                   FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
894         struct fm10k_mbx_fifo *fifo = &mbx->tx;
895         u16 crc;
896
897         if (mbx->tail_len)
898                 mbx->mbx_lock |= FM10K_MBX_REQ;
899
900         /* generate CRC for data in flight and header */
901         crc = fm10k_fifo_crc(fifo, fm10k_fifo_head_offset(fifo, mbx->pulled),
902                              mbx->tail_len, mbx->local);
903         crc = fm10k_crc_16b(&hdr, crc, 1);
904
905         /* load header to memory to be written */
906         mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
907 }
908
909 /**
910  *  fm10k_mbx_create_disconnect_hdr - Generate a disconnect mailbox header
911  *  @mbx: pointer to mailbox
912  *
913  *  This function returns a disconnect mailbox header
914  **/
915 STATIC void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx)
916 {
917         u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
918                   FM10K_MSG_HDR_FIELD_SET(mbx->tail, TAIL) |
919                   FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
920         u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
921
922         mbx->mbx_lock |= FM10K_MBX_ACK;
923
924         /* load header to memory to be written */
925         mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
926 }
927
928 /**
929  *  fm10k_mbx_create_error_msg - Generate a error message
930  *  @mbx: pointer to mailbox
931  *  @err: local error encountered
932  *
933  *  This function will interpret the error provided by err, and based on
934  *  that it may shift the message by 1 DWORD and then place an error header
935  *  at the start of the message.
936  **/
937 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
938 {
939         /* only generate an error message for these types */
940         switch (err) {
941         case FM10K_MBX_ERR_TAIL:
942         case FM10K_MBX_ERR_HEAD:
943         case FM10K_MBX_ERR_TYPE:
944         case FM10K_MBX_ERR_SIZE:
945         case FM10K_MBX_ERR_RSVD0:
946         case FM10K_MBX_ERR_CRC:
947                 break;
948         default:
949                 return;
950         }
951
952         mbx->mbx_lock |= FM10K_MBX_REQ;
953
954         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
955                        FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
956                        FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
957 }
958
959 /**
960  *  fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
961  *  @mbx: pointer to mailbox
962  *  @msg: message array to read
963  *
964  *  This function will parse up the fields in the mailbox header and return
965  *  an error if the header contains any of a number of invalid configurations
966  *  including unrecognized type, invalid route, or a malformed message.
967  **/
968 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
969 {
970         u16 type, rsvd0, head, tail, size;
971         const u32 *hdr = &mbx->mbx_hdr;
972
973         DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
974
975         type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
976         rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
977         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
978         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
979         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
980
981         if (rsvd0)
982                 return FM10K_MBX_ERR_RSVD0;
983
984         switch (type) {
985         case FM10K_MSG_DISCONNECT:
986                 /* validate that all data has been received */
987                 if (tail != mbx->head)
988                         return FM10K_MBX_ERR_TAIL;
989
990                 /* fall through */
991         case FM10K_MSG_DATA:
992                 /* validate that head is moving correctly */
993                 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
994                         return FM10K_MBX_ERR_HEAD;
995                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
996                         return FM10K_MBX_ERR_HEAD;
997
998                 /* validate that tail is moving correctly */
999                 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
1000                         return FM10K_MBX_ERR_TAIL;
1001                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1002                         break;
1003
1004                 return FM10K_MBX_ERR_TAIL;
1005         case FM10K_MSG_CONNECT:
1006                 /* validate size is in range and is power of 2 mask */
1007                 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
1008                         return FM10K_MBX_ERR_SIZE;
1009
1010                 /* fall through */
1011         case FM10K_MSG_ERROR:
1012                 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1013                         return FM10K_MBX_ERR_HEAD;
1014                 /* neither create nor error include a tail offset */
1015                 if (tail)
1016                         return FM10K_MBX_ERR_TAIL;
1017
1018                 break;
1019         default:
1020                 return FM10K_MBX_ERR_TYPE;
1021         }
1022
1023         return FM10K_SUCCESS;
1024 }
1025
1026 /**
1027  *  fm10k_mbx_create_reply - Generate reply based on state and remote head
1028  *  @mbx: pointer to mailbox
1029  *  @head: acknowledgement number
1030  *
1031  *  This function will generate an outgoing message based on the current
1032  *  mailbox state and the remote fifo head.  It will return the length
1033  *  of the outgoing message excluding header on success, and a negative value
1034  *  on error.
1035  **/
1036 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1037                                   struct fm10k_mbx_info *mbx, u16 head)
1038 {
1039         switch (mbx->state) {
1040         case FM10K_STATE_OPEN:
1041         case FM10K_STATE_DISCONNECT:
1042                 /* update our checksum for the outgoing data */
1043                 fm10k_mbx_update_local_crc(mbx, head);
1044
1045                 /* as long as other end recognizes us keep sending data */
1046                 fm10k_mbx_pull_head(hw, mbx, head);
1047
1048                 /* generate new header based on data */
1049                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1050                         fm10k_mbx_create_data_hdr(mbx);
1051                 else
1052                         fm10k_mbx_create_disconnect_hdr(mbx);
1053                 break;
1054         case FM10K_STATE_CONNECT:
1055                 /* send disconnect even if we aren't connected */
1056                 fm10k_mbx_create_connect_hdr(mbx);
1057                 break;
1058         case FM10K_STATE_CLOSED:
1059                 /* generate new header based on data */
1060                 fm10k_mbx_create_disconnect_hdr(mbx);
1061         default:
1062                 break;
1063         }
1064
1065         return FM10K_SUCCESS;
1066 }
1067
1068 /**
1069  *  fm10k_mbx_reset_work- Reset internal pointers for any pending work
1070  *  @mbx: pointer to mailbox
1071  *
1072  *  This function will reset all internal pointers so any work in progress
1073  *  is dropped.  This call should occur every time we transition from the
1074  *  open state to the connect state.
1075  **/
1076 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1077 {
1078         /* reset our outgoing max size back to Rx limits */
1079         mbx->max_size = mbx->rx.size - 1;
1080
1081         /* just do a quick resysnc to start of message */
1082         mbx->pushed = 0;
1083         mbx->pulled = 0;
1084         mbx->tail_len = 0;
1085         mbx->head_len = 0;
1086         mbx->rx.tail = 0;
1087         mbx->rx.head = 0;
1088 }
1089
1090 /**
1091  *  fm10k_mbx_update_max_size - Update the max_size and drop large messages
1092  *  @mbx: pointer to mailbox
1093  *  @size: new value for max_size
1094  *
1095  *  This function updates the max_size value and drops any outgoing messages
1096  *  at the head of the Tx FIFO if they are larger than max_size. It does not
1097  *  drop all messages, as this is too difficult to parse and remove them from
1098  *  the FIFO. Instead, rely on the checking to ensure that messages larger
1099  *  than max_size aren't pushed into the memory buffer.
1100  **/
1101 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1102 {
1103         u16 len;
1104
1105         DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1106
1107         mbx->max_size = size;
1108
1109         /* flush any oversized messages from the queue */
1110         for (len = fm10k_fifo_head_len(&mbx->tx);
1111              len > size;
1112              len = fm10k_fifo_head_len(&mbx->tx)) {
1113                 fm10k_fifo_head_drop(&mbx->tx);
1114                 mbx->tx_dropped++;
1115         }
1116 }
1117
1118 /**
1119  *  fm10k_mbx_connect_reset - Reset following request for reset
1120  *  @mbx: pointer to mailbox
1121  *
1122  *  This function resets the mailbox to either a disconnected state
1123  *  or a connect state depending on the current mailbox state
1124  **/
1125 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1126 {
1127         /* just do a quick resysnc to start of frame */
1128         fm10k_mbx_reset_work(mbx);
1129
1130         /* reset CRC seeds */
1131         mbx->local = FM10K_MBX_CRC_SEED;
1132         mbx->remote = FM10K_MBX_CRC_SEED;
1133
1134         /* we cannot exit connect until the size is good */
1135         if (mbx->state == FM10K_STATE_OPEN)
1136                 mbx->state = FM10K_STATE_CONNECT;
1137         else
1138                 mbx->state = FM10K_STATE_CLOSED;
1139 }
1140
1141 /**
1142  *  fm10k_mbx_process_connect - Process connect header
1143  *  @mbx: pointer to mailbox
1144  *  @msg: message array to process
1145  *
1146  *  This function will read an incoming connect header and reply with the
1147  *  appropriate message.  It will return a value indicating the number of
1148  *  data DWORDs on success, or will return a negative value on failure.
1149  **/
1150 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1151                                      struct fm10k_mbx_info *mbx)
1152 {
1153         const enum fm10k_mbx_state state = mbx->state;
1154         const u32 *hdr = &mbx->mbx_hdr;
1155         u16 size, head;
1156
1157         /* we will need to pull all of the fields for verification */
1158         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1159         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1160
1161         switch (state) {
1162         case FM10K_STATE_DISCONNECT:
1163         case FM10K_STATE_OPEN:
1164                 /* reset any in-progress work */
1165                 fm10k_mbx_connect_reset(mbx);
1166                 break;
1167         case FM10K_STATE_CONNECT:
1168                 /* we cannot exit connect until the size is good */
1169                 if (size > mbx->rx.size) {
1170                         mbx->max_size = mbx->rx.size - 1;
1171                 } else {
1172                         /* record the remote system requesting connection */
1173                         mbx->state = FM10K_STATE_OPEN;
1174
1175                         fm10k_mbx_update_max_size(mbx, size);
1176                 }
1177                 break;
1178         default:
1179                 break;
1180         }
1181
1182         /* align our tail index to remote head index */
1183         mbx->tail = head;
1184
1185         return fm10k_mbx_create_reply(hw, mbx, head);
1186 }
1187
1188 /**
1189  *  fm10k_mbx_process_data - Process data header
1190  *  @mbx: pointer to mailbox
1191  *
1192  *  This function will read an incoming data header and reply with the
1193  *  appropriate message.  It will return a value indicating the number of
1194  *  data DWORDs on success, or will return a negative value on failure.
1195  **/
1196 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1197                                   struct fm10k_mbx_info *mbx)
1198 {
1199         const u32 *hdr = &mbx->mbx_hdr;
1200         u16 head, tail;
1201         s32 err;
1202
1203         DEBUGFUNC("fm10k_mbx_process_data");
1204
1205         /* we will need to pull all of the fields for verification */
1206         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1207         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1208
1209         /* if we are in connect just update our data and go */
1210         if (mbx->state == FM10K_STATE_CONNECT) {
1211                 mbx->tail = head;
1212                 mbx->state = FM10K_STATE_OPEN;
1213         }
1214
1215         /* abort on message size errors */
1216         err = fm10k_mbx_push_tail(hw, mbx, tail);
1217         if (err < 0)
1218                 return err;
1219
1220         /* verify the checksum on the incoming data */
1221         err = fm10k_mbx_verify_remote_crc(mbx);
1222         if (err)
1223                 return err;
1224
1225         /* process messages if we have received any */
1226         fm10k_mbx_dequeue_rx(hw, mbx);
1227
1228         return fm10k_mbx_create_reply(hw, mbx, head);
1229 }
1230
1231 /**
1232  *  fm10k_mbx_process_disconnect - Process disconnect header
1233  *  @mbx: pointer to mailbox
1234  *
1235  *  This function will read an incoming disconnect header and reply with the
1236  *  appropriate message.  It will return a value indicating the number of
1237  *  data DWORDs on success, or will return a negative value on failure.
1238  **/
1239 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1240                                         struct fm10k_mbx_info *mbx)
1241 {
1242         const enum fm10k_mbx_state state = mbx->state;
1243         const u32 *hdr = &mbx->mbx_hdr;
1244         u16 head;
1245         s32 err;
1246
1247         /* we will need to pull the header field for verification */
1248         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1249
1250         /* We should not be receiving disconnect if Rx is incomplete */
1251         if (mbx->pushed)
1252                 return FM10K_MBX_ERR_TAIL;
1253
1254         /* we have already verified mbx->head == tail so we know this is 0 */
1255         mbx->head_len = 0;
1256
1257         /* verify the checksum on the incoming header is correct */
1258         err = fm10k_mbx_verify_remote_crc(mbx);
1259         if (err)
1260                 return err;
1261
1262         switch (state) {
1263         case FM10K_STATE_DISCONNECT:
1264         case FM10K_STATE_OPEN:
1265                 /* state doesn't change if we still have work to do */
1266                 if (!fm10k_mbx_tx_complete(mbx))
1267                         break;
1268
1269                 /* verify the head indicates we completed all transmits */
1270                 if (head != mbx->tail)
1271                         return FM10K_MBX_ERR_HEAD;
1272
1273                 /* reset any in-progress work */
1274                 fm10k_mbx_connect_reset(mbx);
1275                 break;
1276         default:
1277                 break;
1278         }
1279
1280         return fm10k_mbx_create_reply(hw, mbx, head);
1281 }
1282
1283 /**
1284  *  fm10k_mbx_process_error - Process error header
1285  *  @mbx: pointer to mailbox
1286  *
1287  *  This function will read an incoming error header and reply with the
1288  *  appropriate message.  It will return a value indicating the number of
1289  *  data DWORDs on success, or will return a negative value on failure.
1290  **/
1291 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1292                                    struct fm10k_mbx_info *mbx)
1293 {
1294         const u32 *hdr = &mbx->mbx_hdr;
1295         u16 head;
1296
1297         /* we will need to pull all of the fields for verification */
1298         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1299
1300         switch (mbx->state) {
1301         case FM10K_STATE_OPEN:
1302         case FM10K_STATE_DISCONNECT:
1303                 /* flush any uncompleted work */
1304                 fm10k_mbx_reset_work(mbx);
1305
1306                 /* reset CRC seeds */
1307                 mbx->local = FM10K_MBX_CRC_SEED;
1308                 mbx->remote = FM10K_MBX_CRC_SEED;
1309
1310                 /* reset tail index and size to prepare for reconnect */
1311                 mbx->tail = head;
1312
1313                 /* if open then reset max_size and go back to connect */
1314                 if (mbx->state == FM10K_STATE_OPEN) {
1315                         mbx->state = FM10K_STATE_CONNECT;
1316                         break;
1317                 }
1318
1319                 /* send a connect message to get data flowing again */
1320                 fm10k_mbx_create_connect_hdr(mbx);
1321                 return FM10K_SUCCESS;
1322         default:
1323                 break;
1324         }
1325
1326         return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1327 }
1328
1329 /**
1330  *  fm10k_mbx_process - Process mailbox interrupt
1331  *  @hw: pointer to hardware structure
1332  *  @mbx: pointer to mailbox
1333  *
1334  *  This function will process incoming mailbox events and generate mailbox
1335  *  replies.  It will return a value indicating the number of DWORDs
1336  *  transmitted excluding header on success or a negative value on error.
1337  **/
1338 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1339                              struct fm10k_mbx_info *mbx)
1340 {
1341         s32 err;
1342
1343         DEBUGFUNC("fm10k_mbx_process");
1344
1345         /* we do not read mailbox if closed */
1346         if (mbx->state == FM10K_STATE_CLOSED)
1347                 return FM10K_SUCCESS;
1348
1349         /* copy data from mailbox */
1350         err = fm10k_mbx_read(hw, mbx);
1351         if (err)
1352                 return err;
1353
1354         /* validate type, source, and destination */
1355         err = fm10k_mbx_validate_msg_hdr(mbx);
1356         if (err < 0)
1357                 goto msg_err;
1358
1359         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1360         case FM10K_MSG_CONNECT:
1361                 err = fm10k_mbx_process_connect(hw, mbx);
1362                 break;
1363         case FM10K_MSG_DATA:
1364                 err = fm10k_mbx_process_data(hw, mbx);
1365                 break;
1366         case FM10K_MSG_DISCONNECT:
1367                 err = fm10k_mbx_process_disconnect(hw, mbx);
1368                 break;
1369         case FM10K_MSG_ERROR:
1370                 err = fm10k_mbx_process_error(hw, mbx);
1371                 break;
1372         default:
1373                 err = FM10K_MBX_ERR_TYPE;
1374                 break;
1375         }
1376
1377 msg_err:
1378         /* notify partner of errors on our end */
1379         if (err < 0)
1380                 fm10k_mbx_create_error_msg(mbx, err);
1381
1382         /* copy data from mailbox */
1383         fm10k_mbx_write(hw, mbx);
1384
1385         return err;
1386 }
1387
1388 /**
1389  *  fm10k_mbx_disconnect - Shutdown mailbox connection
1390  *  @hw: pointer to hardware structure
1391  *  @mbx: pointer to mailbox
1392  *
1393  *  This function will shut down the mailbox.  It places the mailbox first
1394  *  in the disconnect state, it then allows up to a predefined timeout for
1395  *  the mailbox to transition to close on its own.  If this does not occur
1396  *  then the mailbox will be forced into the closed state.
1397  *
1398  *  Any mailbox transactions not completed before calling this function
1399  *  are not guaranteed to complete and may be dropped.
1400  **/
1401 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1402                                  struct fm10k_mbx_info *mbx)
1403 {
1404         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1405
1406         DEBUGFUNC("fm10k_mbx_disconnect");
1407
1408         /* Place mbx in ready to disconnect state */
1409         mbx->state = FM10K_STATE_DISCONNECT;
1410
1411         /* trigger interrupt to start shutdown process */
1412         FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1413                                           FM10K_MBX_INTERRUPT_DISABLE);
1414         do {
1415                 usec_delay(FM10K_MBX_POLL_DELAY);
1416                 mbx->ops.process(hw, mbx);
1417                 timeout -= FM10K_MBX_POLL_DELAY;
1418         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1419
1420         /* in case we didn't close, just force the mailbox into shutdown and
1421          * drop all left over messages in the FIFO.
1422          */
1423         fm10k_mbx_connect_reset(mbx);
1424         fm10k_fifo_drop_all(&mbx->tx);
1425
1426         FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1427 }
1428
1429 /**
1430  *  fm10k_mbx_connect - Start mailbox connection
1431  *  @hw: pointer to hardware structure
1432  *  @mbx: pointer to mailbox
1433  *
1434  *  This function will initiate a mailbox connection.  It will populate the
1435  *  mailbox with a broadcast connect message and then initialize the lock.
1436  *  This is safe since the connect message is a single DWORD so the mailbox
1437  *  transaction is guaranteed to be atomic.
1438  *
1439  *  This function will return an error if the mailbox has not been initiated
1440  *  or is currently in use.
1441  **/
1442 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1443 {
1444         DEBUGFUNC("fm10k_mbx_connect");
1445
1446         /* we cannot connect an uninitialized mailbox */
1447         if (!mbx->rx.buffer)
1448                 return FM10K_MBX_ERR_NO_SPACE;
1449
1450         /* we cannot connect an already connected mailbox */
1451         if (mbx->state != FM10K_STATE_CLOSED)
1452                 return FM10K_MBX_ERR_BUSY;
1453
1454         /* mailbox timeout can now become active */
1455         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1456
1457         /* Place mbx in ready to connect state */
1458         mbx->state = FM10K_STATE_CONNECT;
1459
1460         /* initialize header of remote mailbox */
1461         fm10k_mbx_create_disconnect_hdr(mbx);
1462         FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1463
1464         /* enable interrupt and notify other party of new message */
1465         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1466                         FM10K_MBX_INTERRUPT_ENABLE;
1467
1468         /* generate and load connect header into mailbox */
1469         fm10k_mbx_create_connect_hdr(mbx);
1470         fm10k_mbx_write(hw, mbx);
1471
1472         return FM10K_SUCCESS;
1473 }
1474
1475 /**
1476  *  fm10k_mbx_validate_handlers - Validate layout of message parsing data
1477  *  @msg_data: handlers for mailbox events
1478  *
1479  *  This function validates the layout of the message parsing data.  This
1480  *  should be mostly static, but it is important to catch any errors that
1481  *  are made when constructing the parsers.
1482  **/
1483 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1484 {
1485         const struct fm10k_tlv_attr *attr;
1486         unsigned int id;
1487
1488         DEBUGFUNC("fm10k_mbx_validate_handlers");
1489
1490         /* Allow NULL mailboxes that transmit but don't receive */
1491         if (!msg_data)
1492                 return FM10K_SUCCESS;
1493
1494         while (msg_data->id != FM10K_TLV_ERROR) {
1495                 /* all messages should have a function handler */
1496                 if (!msg_data->func)
1497                         return FM10K_ERR_PARAM;
1498
1499                 /* parser is optional */
1500                 attr = msg_data->attr;
1501                 if (attr) {
1502                         while (attr->id != FM10K_TLV_ERROR) {
1503                                 id = attr->id;
1504                                 attr++;
1505                                 /* ID should always be increasing */
1506                                 if (id >= attr->id)
1507                                         return FM10K_ERR_PARAM;
1508                                 /* ID should fit in results array */
1509                                 if (id >= FM10K_TLV_RESULTS_MAX)
1510                                         return FM10K_ERR_PARAM;
1511                         }
1512
1513                         /* verify terminator is in the list */
1514                         if (attr->id != FM10K_TLV_ERROR)
1515                                 return FM10K_ERR_PARAM;
1516                 }
1517
1518                 id = msg_data->id;
1519                 msg_data++;
1520                 /* ID should always be increasing */
1521                 if (id >= msg_data->id)
1522                         return FM10K_ERR_PARAM;
1523         }
1524
1525         /* verify terminator is in the list */
1526         if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1527                 return FM10K_ERR_PARAM;
1528
1529         return FM10K_SUCCESS;
1530 }
1531
1532 /**
1533  *  fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1534  *  @mbx: pointer to mailbox
1535  *  @msg_data: handlers for mailbox events
1536  *
1537  *  This function associates a set of message handling ops with a mailbox.
1538  **/
1539 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1540                                        const struct fm10k_msg_data *msg_data)
1541 {
1542         DEBUGFUNC("fm10k_mbx_register_handlers");
1543
1544         /* validate layout of handlers before assigning them */
1545         if (fm10k_mbx_validate_handlers(msg_data))
1546                 return FM10K_ERR_PARAM;
1547
1548         /* initialize the message handlers */
1549         mbx->msg_data = msg_data;
1550
1551         return FM10K_SUCCESS;
1552 }
1553
1554 /**
1555  *  fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1556  *  @hw: pointer to hardware structure
1557  *  @mbx: pointer to mailbox
1558  *  @msg_data: handlers for mailbox events
1559  *  @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1560  *
1561  *  This function initializes the mailbox for use.  It will split the
1562  *  buffer provided an use that th populate both the Tx and Rx FIFO by
1563  *  evenly splitting it.  In order to allow for easy masking of head/tail
1564  *  the value reported in size must be a power of 2 and is reported in
1565  *  DWORDs, not bytes.  Any invalid values will cause the mailbox to return
1566  *  error.
1567  **/
1568 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1569                         const struct fm10k_msg_data *msg_data, u8 id)
1570 {
1571         DEBUGFUNC("fm10k_pfvf_mbx_init");
1572
1573         /* initialize registers */
1574         switch (hw->mac.type) {
1575         case fm10k_mac_vf:
1576                 mbx->mbx_reg = FM10K_VFMBX;
1577                 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1578                 break;
1579         case fm10k_mac_pf:
1580                 /* there are only 64 VF <-> PF mailboxes */
1581                 if (id < 64) {
1582                         mbx->mbx_reg = FM10K_MBX(id);
1583                         mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1584                         break;
1585                 }
1586                 /* fallthough */
1587         default:
1588                 return FM10K_MBX_ERR_NO_MBX;
1589         }
1590
1591         /* start out in closed state */
1592         mbx->state = FM10K_STATE_CLOSED;
1593
1594         /* validate layout of handlers before assigning them */
1595         if (fm10k_mbx_validate_handlers(msg_data))
1596                 return FM10K_ERR_PARAM;
1597
1598         /* initialize the message handlers */
1599         mbx->msg_data = msg_data;
1600
1601         /* start mailbox as timed out and let the reset_hw call
1602          * set the timeout value to begin communications
1603          */
1604         mbx->timeout = 0;
1605         mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1606
1607         /* initialize tail and head */
1608         mbx->tail = 1;
1609         mbx->head = 1;
1610
1611         /* initialize CRC seeds */
1612         mbx->local = FM10K_MBX_CRC_SEED;
1613         mbx->remote = FM10K_MBX_CRC_SEED;
1614
1615         /* Split buffer for use by Tx/Rx FIFOs */
1616         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1617         mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1618
1619         /* initialize the FIFOs, sizes are in 4 byte increments */
1620         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1621         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1622                         FM10K_MBX_RX_BUFFER_SIZE);
1623
1624         /* initialize function pointers */
1625         mbx->ops.connect = fm10k_mbx_connect;
1626         mbx->ops.disconnect = fm10k_mbx_disconnect;
1627         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1628         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1629         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1630         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1631         mbx->ops.process = fm10k_mbx_process;
1632         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1633
1634         return FM10K_SUCCESS;
1635 }
1636
1637 /**
1638  *  fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1639  *  @mbx: pointer to mailbox
1640  *
1641  *  This function returns a connection mailbox header
1642  **/
1643 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1644 {
1645         if (mbx->tail_len)
1646                 mbx->mbx_lock |= FM10K_MBX_REQ;
1647
1648         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1649                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1650                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1651 }
1652
1653 /**
1654  *  fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1655  *  @mbx: pointer to mailbox
1656  *  @err: error flags to report if any
1657  *
1658  *  This function returns a connection mailbox header
1659  **/
1660 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1661 {
1662         if (mbx->local)
1663                 mbx->mbx_lock |= FM10K_MBX_REQ;
1664
1665         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1666                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1667                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1668                        FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1669 }
1670
1671 /**
1672  *  fm10k_sm_mbx_connect_reset - Reset following request for reset
1673  *  @mbx: pointer to mailbox
1674  *
1675  *  This function resets the mailbox to a just connected state
1676  **/
1677 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1678 {
1679         /* flush any uncompleted work */
1680         fm10k_mbx_reset_work(mbx);
1681
1682         /* set local version to max and remote version to 0 */
1683         mbx->local = FM10K_SM_MBX_VERSION;
1684         mbx->remote = 0;
1685
1686         /* initialize tail and head */
1687         mbx->tail = 1;
1688         mbx->head = 1;
1689
1690         /* reset state back to connect */
1691         mbx->state = FM10K_STATE_CONNECT;
1692 }
1693
1694 /**
1695  *  fm10k_sm_mbx_connect - Start switch manager mailbox connection
1696  *  @hw: pointer to hardware structure
1697  *  @mbx: pointer to mailbox
1698  *
1699  *  This function will initiate a mailbox connection with the switch
1700  *  manager.  To do this it will first disconnect the mailbox, and then
1701  *  reconnect it in order to complete a reset of the mailbox.
1702  *
1703  *  This function will return an error if the mailbox has not been initiated
1704  *  or is currently in use.
1705  **/
1706 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1707 {
1708         DEBUGFUNC("fm10k_mbx_connect");
1709
1710         /* we cannot connect an uninitialized mailbox */
1711         if (!mbx->rx.buffer)
1712                 return FM10K_MBX_ERR_NO_SPACE;
1713
1714         /* we cannot connect an already connected mailbox */
1715         if (mbx->state != FM10K_STATE_CLOSED)
1716                 return FM10K_MBX_ERR_BUSY;
1717
1718         /* mailbox timeout can now become active */
1719         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1720
1721         /* Place mbx in ready to connect state */
1722         mbx->state = FM10K_STATE_CONNECT;
1723         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1724
1725         /* reset interface back to connect */
1726         fm10k_sm_mbx_connect_reset(mbx);
1727
1728         /* enable interrupt and notify other party of new message */
1729         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1730                         FM10K_MBX_INTERRUPT_ENABLE;
1731
1732         /* generate and load connect header into mailbox */
1733         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1734         fm10k_mbx_write(hw, mbx);
1735
1736         /* enable interrupt and notify other party of new message */
1737
1738         return FM10K_SUCCESS;
1739 }
1740
1741 /**
1742  *  fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1743  *  @hw: pointer to hardware structure
1744  *  @mbx: pointer to mailbox
1745  *
1746  *  This function will shut down the mailbox.  It places the mailbox first
1747  *  in the disconnect state, it then allows up to a predefined timeout for
1748  *  the mailbox to transition to close on its own.  If this does not occur
1749  *  then the mailbox will be forced into the closed state.
1750  *
1751  *  Any mailbox transactions not completed before calling this function
1752  *  are not guaranteed to complete and may be dropped.
1753  **/
1754 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1755                                     struct fm10k_mbx_info *mbx)
1756 {
1757         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1758
1759         DEBUGFUNC("fm10k_sm_mbx_disconnect");
1760
1761         /* Place mbx in ready to disconnect state */
1762         mbx->state = FM10K_STATE_DISCONNECT;
1763
1764         /* trigger interrupt to start shutdown process */
1765         FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1766                                           FM10K_MBX_INTERRUPT_DISABLE);
1767         do {
1768                 usec_delay(FM10K_MBX_POLL_DELAY);
1769                 mbx->ops.process(hw, mbx);
1770                 timeout -= FM10K_MBX_POLL_DELAY;
1771         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1772
1773         /* in case we didn't close just force the mailbox into shutdown */
1774         mbx->state = FM10K_STATE_CLOSED;
1775         mbx->remote = 0;
1776         fm10k_mbx_reset_work(mbx);
1777         fm10k_mbx_update_max_size(mbx, 0);
1778
1779         FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1780 }
1781
1782 /**
1783  *  fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1784  *  @mbx: pointer to mailbox
1785  *
1786  *  This function will parse up the fields in the mailbox header and return
1787  *  an error if the header contains any of a number of invalid configurations
1788  *  including unrecognized offsets or version numbers.
1789  **/
1790 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1791 {
1792         const u32 *hdr = &mbx->mbx_hdr;
1793         u16 tail, head, ver;
1794
1795         DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1796
1797         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1798         ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1799         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1800
1801         switch (ver) {
1802         case 0:
1803                 break;
1804         case FM10K_SM_MBX_VERSION:
1805                 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1806                         return FM10K_MBX_ERR_HEAD;
1807                 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1808                         return FM10K_MBX_ERR_TAIL;
1809                 if (mbx->tail < head)
1810                         head += mbx->mbmem_len - 1;
1811                 if (tail < mbx->head)
1812                         tail += mbx->mbmem_len - 1;
1813                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1814                         return FM10K_MBX_ERR_HEAD;
1815                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1816                         break;
1817                 return FM10K_MBX_ERR_TAIL;
1818         default:
1819                 return FM10K_MBX_ERR_SRC;
1820         }
1821
1822         return FM10K_SUCCESS;
1823 }
1824
1825 /**
1826  *  fm10k_sm_mbx_process_error - Process header with error flag set
1827  *  @mbx: pointer to mailbox
1828  *
1829  *  This function is meant to respond to a request where the error flag
1830  *  is set.  As a result we will terminate a connection if one is present
1831  *  and fall back into the reset state with a connection header of version
1832  *  0 (RESET).
1833  **/
1834 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1835 {
1836         const enum fm10k_mbx_state state = mbx->state;
1837
1838         switch (state) {
1839         case FM10K_STATE_DISCONNECT:
1840                 /* if there is an error just disconnect */
1841                 mbx->remote = 0;
1842                 break;
1843         case FM10K_STATE_OPEN:
1844                 /* flush any uncompleted work */
1845                 fm10k_sm_mbx_connect_reset(mbx);
1846                 break;
1847         case FM10K_STATE_CONNECT:
1848                 /* try connnecting at lower version */
1849                 if (mbx->remote) {
1850                         while (mbx->local > 1)
1851                                 mbx->local--;
1852                         mbx->remote = 0;
1853                 }
1854                 break;
1855         default:
1856                 break;
1857         }
1858
1859         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1860 }
1861
1862 /**
1863  *  fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1864  *  @mbx: pointer to mailbox
1865  *  @err: local error encountered
1866  *
1867  *  This function will interpret the error provided by err, and based on
1868  *  that it may set the error bit in the local message header
1869  **/
1870 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1871 {
1872         /* only generate an error message for these types */
1873         switch (err) {
1874         case FM10K_MBX_ERR_TAIL:
1875         case FM10K_MBX_ERR_HEAD:
1876         case FM10K_MBX_ERR_SRC:
1877         case FM10K_MBX_ERR_SIZE:
1878         case FM10K_MBX_ERR_RSVD0:
1879                 break;
1880         default:
1881                 return;
1882         }
1883
1884         /* process it as though we received an error, and send error reply */
1885         fm10k_sm_mbx_process_error(mbx);
1886         fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1887 }
1888
1889 /**
1890  *  fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1891  *  @hw: pointer to hardware structure
1892  *  @mbx: pointer to mailbox
1893  *
1894  *  This function will dequeue one message from the Rx switch manager mailbox
1895  *  FIFO and place it in the Rx mailbox FIFO for processing by software.
1896  **/
1897 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1898                                 struct fm10k_mbx_info *mbx,
1899                                 u16 tail)
1900 {
1901         /* reduce length by 1 to convert to a mask */
1902         u16 mbmem_len = mbx->mbmem_len - 1;
1903         s32 err;
1904
1905         DEBUGFUNC("fm10k_sm_mbx_receive");
1906
1907         /* push tail in front of head */
1908         if (tail < mbx->head)
1909                 tail += mbmem_len;
1910
1911         /* copy data to the Rx FIFO */
1912         err = fm10k_mbx_push_tail(hw, mbx, tail);
1913         if (err < 0)
1914                 return err;
1915
1916         /* process messages if we have received any */
1917         fm10k_mbx_dequeue_rx(hw, mbx);
1918
1919         /* guarantee head aligns with the end of the last message */
1920         mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1921         mbx->pushed = 0;
1922
1923         /* clear any extra bits left over since index adds 1 extra bit */
1924         if (mbx->head > mbmem_len)
1925                 mbx->head -= mbmem_len;
1926
1927         return err;
1928 }
1929
1930 /**
1931  *  fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1932  *  @hw: pointer to hardware structure
1933  *  @mbx: pointer to mailbox
1934  *
1935  *  This function will dequeue one message from the Tx mailbox FIFO and place
1936  *  it in the Tx switch manager mailbox FIFO for processing by hardware.
1937  **/
1938 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1939                                   struct fm10k_mbx_info *mbx, u16 head)
1940 {
1941         struct fm10k_mbx_fifo *fifo = &mbx->tx;
1942         /* reduce length by 1 to convert to a mask */
1943         u16 mbmem_len = mbx->mbmem_len - 1;
1944         u16 tail_len, len = 0;
1945         u32 *msg;
1946
1947         DEBUGFUNC("fm10k_sm_mbx_transmit");
1948
1949         /* push head behind tail */
1950         if (mbx->tail < head)
1951                 head += mbmem_len;
1952
1953         fm10k_mbx_pull_head(hw, mbx, head);
1954
1955         /* determine msg aligned offset for end of buffer */
1956         do {
1957                 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1958                 tail_len = len;
1959                 len += FM10K_TLV_DWORD_LEN(*msg);
1960         } while ((len <= mbx->tail_len) && (len < mbmem_len));
1961
1962         /* guarantee we stop on a message boundary */
1963         if (mbx->tail_len > tail_len) {
1964                 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1965                 mbx->tail_len = tail_len;
1966         }
1967
1968         /* clear any extra bits left over since index adds 1 extra bit */
1969         if (mbx->tail > mbmem_len)
1970                 mbx->tail -= mbmem_len;
1971 }
1972
1973 /**
1974  *  fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1975  *  @mbx: pointer to mailbox
1976  *  @head: acknowledgement number
1977  *
1978  *  This function will generate an outgoing message based on the current
1979  *  mailbox state and the remote fifo head.  It will return the length
1980  *  of the outgoing message excluding header on success, and a negative value
1981  *  on error.
1982  **/
1983 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1984                                       struct fm10k_mbx_info *mbx, u16 head)
1985 {
1986         switch (mbx->state) {
1987         case FM10K_STATE_OPEN:
1988         case FM10K_STATE_DISCONNECT:
1989                 /* flush out Tx data */
1990                 fm10k_sm_mbx_transmit(hw, mbx, head);
1991
1992                 /* generate new header based on data */
1993                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1994                         fm10k_sm_mbx_create_data_hdr(mbx);
1995                 } else {
1996                         mbx->remote = 0;
1997                         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1998                 }
1999                 break;
2000         case FM10K_STATE_CONNECT:
2001         case FM10K_STATE_CLOSED:
2002                 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2003                 break;
2004         default:
2005                 break;
2006         }
2007 }
2008
2009 /**
2010  *  fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2011  *  @hw: pointer to hardware structure
2012  *  @mbx: pointer to mailbox
2013  *
2014  *  This function is meant to respond to a request where the version data
2015  *  is set to 0.  As such we will either terminate the connection or go
2016  *  into the connect state in order to re-establish the connection.  This
2017  *  function can also be used to respond to an error as the connection
2018  *  resetting would also be a means of dealing with errors.
2019  **/
2020 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2021                                        struct fm10k_mbx_info *mbx)
2022 {
2023         const enum fm10k_mbx_state state = mbx->state;
2024
2025         switch (state) {
2026         case FM10K_STATE_DISCONNECT:
2027                 /* drop remote connections and disconnect */
2028                 mbx->state = FM10K_STATE_CLOSED;
2029                 mbx->remote = 0;
2030                 mbx->local = 0;
2031                 break;
2032         case FM10K_STATE_OPEN:
2033                 /* flush any incomplete work */
2034                 fm10k_sm_mbx_connect_reset(mbx);
2035                 break;
2036         case FM10K_STATE_CONNECT:
2037                 /* Update remote value to match local value */
2038                 mbx->remote = mbx->local;
2039         default:
2040                 break;
2041         }
2042
2043         fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2044 }
2045
2046 /**
2047  *  fm10k_sm_mbx_process_version_1 - Process header with version == 1
2048  *  @hw: pointer to hardware structure
2049  *  @mbx: pointer to mailbox
2050  *
2051  *  This function is meant to process messages received when the remote
2052  *  mailbox is active.
2053  **/
2054 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2055                                           struct fm10k_mbx_info *mbx)
2056 {
2057         const u32 *hdr = &mbx->mbx_hdr;
2058         u16 head, tail;
2059         s32 len;
2060
2061         /* pull all fields needed for verification */
2062         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2063         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2064
2065         /* if we are in connect and wanting version 1 then start up and go */
2066         if (mbx->state == FM10K_STATE_CONNECT) {
2067                 if (!mbx->remote)
2068                         goto send_reply;
2069                 if (mbx->remote != 1)
2070                         return FM10K_MBX_ERR_SRC;
2071
2072                 mbx->state = FM10K_STATE_OPEN;
2073         }
2074
2075         do {
2076                 /* abort on message size errors */
2077                 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2078                 if (len < 0)
2079                         return len;
2080
2081                 /* continue until we have flushed the Rx FIFO */
2082         } while (len);
2083
2084 send_reply:
2085         fm10k_sm_mbx_create_reply(hw, mbx, head);
2086
2087         return FM10K_SUCCESS;
2088 }
2089
2090 /**
2091  *  fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2092  *  @hw: pointer to hardware structure
2093  *  @mbx: pointer to mailbox
2094  *
2095  *  This function will process incoming mailbox events and generate mailbox
2096  *  replies.  It will return a value indicating the number of DWORDs
2097  *  transmitted excluding header on success or a negative value on error.
2098  **/
2099 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2100                                 struct fm10k_mbx_info *mbx)
2101 {
2102         s32 err;
2103
2104         DEBUGFUNC("fm10k_sm_mbx_process");
2105
2106         /* we do not read mailbox if closed */
2107         if (mbx->state == FM10K_STATE_CLOSED)
2108                 return FM10K_SUCCESS;
2109
2110         /* retrieve data from switch manager */
2111         err = fm10k_mbx_read(hw, mbx);
2112         if (err)
2113                 return err;
2114
2115         err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2116         if (err < 0)
2117                 goto fifo_err;
2118
2119         if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2120                 fm10k_sm_mbx_process_error(mbx);
2121                 goto fifo_err;
2122         }
2123
2124         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2125         case 0:
2126                 fm10k_sm_mbx_process_reset(hw, mbx);
2127                 break;
2128         case FM10K_SM_MBX_VERSION:
2129                 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2130                 break;
2131         }
2132
2133 fifo_err:
2134         if (err < 0)
2135                 fm10k_sm_mbx_create_error_msg(mbx, err);
2136
2137         /* report data to switch manager */
2138         fm10k_mbx_write(hw, mbx);
2139
2140         return err;
2141 }
2142
2143 /**
2144  *  fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2145  *  @hw: pointer to hardware structure
2146  *  @mbx: pointer to mailbox
2147  *  @msg_data: handlers for mailbox events
2148  *
2149  *  This function for now is used to stub out the PF/SM mailbox
2150  **/
2151 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2152                       const struct fm10k_msg_data *msg_data)
2153 {
2154         DEBUGFUNC("fm10k_sm_mbx_init");
2155         UNREFERENCED_1PARAMETER(hw);
2156
2157         mbx->mbx_reg = FM10K_GMBX;
2158         mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2159
2160         /* start out in closed state */
2161         mbx->state = FM10K_STATE_CLOSED;
2162
2163         /* validate layout of handlers before assigning them */
2164         if (fm10k_mbx_validate_handlers(msg_data))
2165                 return FM10K_ERR_PARAM;
2166
2167         /* initialize the message handlers */
2168         mbx->msg_data = msg_data;
2169
2170         /* start mailbox as timed out and let the reset_hw call
2171          * set the timeout value to begin communications
2172          */
2173         mbx->timeout = 0;
2174         mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2175
2176         /* Split buffer for use by Tx/Rx FIFOs */
2177         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2178         mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2179
2180         /* initialize the FIFOs, sizes are in 4 byte increments */
2181         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2182         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2183                         FM10K_MBX_RX_BUFFER_SIZE);
2184
2185         /* initialize function pointers */
2186         mbx->ops.connect = fm10k_sm_mbx_connect;
2187         mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2188         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2189         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2190         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2191         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2192         mbx->ops.process = fm10k_sm_mbx_process;
2193         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2194
2195         return FM10K_SUCCESS;
2196 }