fm10k/base: avoid Tx drop increment during mailbox negotiation
[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->rx.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 any large messages
1092  *  @mbx: pointer to mailbox
1093  *  @size: new value for max_size
1094  *
1095  *  This function will update the max_size value and drop any outgoing messages
1096  *  from the head of the Tx FIFO that are larger than max_size.
1097  **/
1098 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1099 {
1100         u16 len;
1101
1102         DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1103
1104         mbx->max_size = size;
1105
1106         /* flush any oversized messages from the queue */
1107         for (len = fm10k_fifo_head_len(&mbx->tx);
1108              len > size;
1109              len = fm10k_fifo_head_len(&mbx->tx)) {
1110                 fm10k_fifo_head_drop(&mbx->tx);
1111                 mbx->tx_dropped++;
1112         }
1113 }
1114
1115 /**
1116  *  fm10k_mbx_connect_reset - Reset following request for reset
1117  *  @mbx: pointer to mailbox
1118  *
1119  *  This function resets the mailbox to either a disconnected state
1120  *  or a connect state depending on the current mailbox state
1121  **/
1122 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1123 {
1124         /* just do a quick resysnc to start of frame */
1125         fm10k_mbx_reset_work(mbx);
1126
1127         /* reset CRC seeds */
1128         mbx->local = FM10K_MBX_CRC_SEED;
1129         mbx->remote = FM10K_MBX_CRC_SEED;
1130
1131         /* we cannot exit connect until the size is good */
1132         if (mbx->state == FM10K_STATE_OPEN)
1133                 mbx->state = FM10K_STATE_CONNECT;
1134         else
1135                 mbx->state = FM10K_STATE_CLOSED;
1136 }
1137
1138 /**
1139  *  fm10k_mbx_process_connect - Process connect header
1140  *  @mbx: pointer to mailbox
1141  *  @msg: message array to process
1142  *
1143  *  This function will read an incoming connect header and reply with the
1144  *  appropriate message.  It will return a value indicating the number of
1145  *  data DWORDs on success, or will return a negative value on failure.
1146  **/
1147 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1148                                      struct fm10k_mbx_info *mbx)
1149 {
1150         const enum fm10k_mbx_state state = mbx->state;
1151         const u32 *hdr = &mbx->mbx_hdr;
1152         u16 size, head;
1153
1154         /* we will need to pull all of the fields for verification */
1155         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1156         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1157
1158         switch (state) {
1159         case FM10K_STATE_DISCONNECT:
1160         case FM10K_STATE_OPEN:
1161                 /* reset any in-progress work */
1162                 fm10k_mbx_connect_reset(mbx);
1163                 break;
1164         case FM10K_STATE_CONNECT:
1165                 /* we cannot exit connect until the size is good */
1166                 if (size > mbx->rx.size) {
1167                         mbx->max_size = mbx->rx.size - 1;
1168                 } else {
1169                         /* record the remote system requesting connection */
1170                         mbx->state = FM10K_STATE_OPEN;
1171
1172                         fm10k_mbx_update_max_size(mbx, size);
1173                 }
1174                 break;
1175         default:
1176                 break;
1177         }
1178
1179         /* align our tail index to remote head index */
1180         mbx->tail = head;
1181
1182         return fm10k_mbx_create_reply(hw, mbx, head);
1183 }
1184
1185 /**
1186  *  fm10k_mbx_process_data - Process data header
1187  *  @mbx: pointer to mailbox
1188  *
1189  *  This function will read an incoming data header and reply with the
1190  *  appropriate message.  It will return a value indicating the number of
1191  *  data DWORDs on success, or will return a negative value on failure.
1192  **/
1193 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1194                                   struct fm10k_mbx_info *mbx)
1195 {
1196         const u32 *hdr = &mbx->mbx_hdr;
1197         u16 head, tail;
1198         s32 err;
1199
1200         DEBUGFUNC("fm10k_mbx_process_data");
1201
1202         /* we will need to pull all of the fields for verification */
1203         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1204         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1205
1206         /* if we are in connect just update our data and go */
1207         if (mbx->state == FM10K_STATE_CONNECT) {
1208                 mbx->tail = head;
1209                 mbx->state = FM10K_STATE_OPEN;
1210         }
1211
1212         /* abort on message size errors */
1213         err = fm10k_mbx_push_tail(hw, mbx, tail);
1214         if (err < 0)
1215                 return err;
1216
1217         /* verify the checksum on the incoming data */
1218         err = fm10k_mbx_verify_remote_crc(mbx);
1219         if (err)
1220                 return err;
1221
1222         /* process messages if we have received any */
1223         fm10k_mbx_dequeue_rx(hw, mbx);
1224
1225         return fm10k_mbx_create_reply(hw, mbx, head);
1226 }
1227
1228 /**
1229  *  fm10k_mbx_process_disconnect - Process disconnect header
1230  *  @mbx: pointer to mailbox
1231  *
1232  *  This function will read an incoming disconnect header and reply with the
1233  *  appropriate message.  It will return a value indicating the number of
1234  *  data DWORDs on success, or will return a negative value on failure.
1235  **/
1236 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1237                                         struct fm10k_mbx_info *mbx)
1238 {
1239         const enum fm10k_mbx_state state = mbx->state;
1240         const u32 *hdr = &mbx->mbx_hdr;
1241         u16 head;
1242         s32 err;
1243
1244         /* we will need to pull the header field for verification */
1245         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1246
1247         /* We should not be receiving disconnect if Rx is incomplete */
1248         if (mbx->pushed)
1249                 return FM10K_MBX_ERR_TAIL;
1250
1251         /* we have already verified mbx->head == tail so we know this is 0 */
1252         mbx->head_len = 0;
1253
1254         /* verify the checksum on the incoming header is correct */
1255         err = fm10k_mbx_verify_remote_crc(mbx);
1256         if (err)
1257                 return err;
1258
1259         switch (state) {
1260         case FM10K_STATE_DISCONNECT:
1261         case FM10K_STATE_OPEN:
1262                 /* state doesn't change if we still have work to do */
1263                 if (!fm10k_mbx_tx_complete(mbx))
1264                         break;
1265
1266                 /* verify the head indicates we completed all transmits */
1267                 if (head != mbx->tail)
1268                         return FM10K_MBX_ERR_HEAD;
1269
1270                 /* reset any in-progress work */
1271                 fm10k_mbx_connect_reset(mbx);
1272                 break;
1273         default:
1274                 break;
1275         }
1276
1277         return fm10k_mbx_create_reply(hw, mbx, head);
1278 }
1279
1280 /**
1281  *  fm10k_mbx_process_error - Process error header
1282  *  @mbx: pointer to mailbox
1283  *
1284  *  This function will read an incoming error header and reply with the
1285  *  appropriate message.  It will return a value indicating the number of
1286  *  data DWORDs on success, or will return a negative value on failure.
1287  **/
1288 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1289                                    struct fm10k_mbx_info *mbx)
1290 {
1291         const u32 *hdr = &mbx->mbx_hdr;
1292         u16 head;
1293
1294         /* we will need to pull all of the fields for verification */
1295         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1296
1297         switch (mbx->state) {
1298         case FM10K_STATE_OPEN:
1299         case FM10K_STATE_DISCONNECT:
1300                 /* flush any uncompleted work */
1301                 fm10k_mbx_reset_work(mbx);
1302
1303                 /* reset CRC seeds */
1304                 mbx->local = FM10K_MBX_CRC_SEED;
1305                 mbx->remote = FM10K_MBX_CRC_SEED;
1306
1307                 /* reset tail index and size to prepare for reconnect */
1308                 mbx->tail = head;
1309
1310                 /* if open then reset max_size and go back to connect */
1311                 if (mbx->state == FM10K_STATE_OPEN) {
1312                         mbx->state = FM10K_STATE_CONNECT;
1313                         break;
1314                 }
1315
1316                 /* send a connect message to get data flowing again */
1317                 fm10k_mbx_create_connect_hdr(mbx);
1318                 return FM10K_SUCCESS;
1319         default:
1320                 break;
1321         }
1322
1323         return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1324 }
1325
1326 /**
1327  *  fm10k_mbx_process - Process mailbox interrupt
1328  *  @hw: pointer to hardware structure
1329  *  @mbx: pointer to mailbox
1330  *
1331  *  This function will process incoming mailbox events and generate mailbox
1332  *  replies.  It will return a value indicating the number of DWORDs
1333  *  transmitted excluding header on success or a negative value on error.
1334  **/
1335 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1336                              struct fm10k_mbx_info *mbx)
1337 {
1338         s32 err;
1339
1340         DEBUGFUNC("fm10k_mbx_process");
1341
1342         /* we do not read mailbox if closed */
1343         if (mbx->state == FM10K_STATE_CLOSED)
1344                 return FM10K_SUCCESS;
1345
1346         /* copy data from mailbox */
1347         err = fm10k_mbx_read(hw, mbx);
1348         if (err)
1349                 return err;
1350
1351         /* validate type, source, and destination */
1352         err = fm10k_mbx_validate_msg_hdr(mbx);
1353         if (err < 0)
1354                 goto msg_err;
1355
1356         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1357         case FM10K_MSG_CONNECT:
1358                 err = fm10k_mbx_process_connect(hw, mbx);
1359                 break;
1360         case FM10K_MSG_DATA:
1361                 err = fm10k_mbx_process_data(hw, mbx);
1362                 break;
1363         case FM10K_MSG_DISCONNECT:
1364                 err = fm10k_mbx_process_disconnect(hw, mbx);
1365                 break;
1366         case FM10K_MSG_ERROR:
1367                 err = fm10k_mbx_process_error(hw, mbx);
1368                 break;
1369         default:
1370                 err = FM10K_MBX_ERR_TYPE;
1371                 break;
1372         }
1373
1374 msg_err:
1375         /* notify partner of errors on our end */
1376         if (err < 0)
1377                 fm10k_mbx_create_error_msg(mbx, err);
1378
1379         /* copy data from mailbox */
1380         fm10k_mbx_write(hw, mbx);
1381
1382         return err;
1383 }
1384
1385 /**
1386  *  fm10k_mbx_disconnect - Shutdown mailbox connection
1387  *  @hw: pointer to hardware structure
1388  *  @mbx: pointer to mailbox
1389  *
1390  *  This function will shut down the mailbox.  It places the mailbox first
1391  *  in the disconnect state, it then allows up to a predefined timeout for
1392  *  the mailbox to transition to close on its own.  If this does not occur
1393  *  then the mailbox will be forced into the closed state.
1394  *
1395  *  Any mailbox transactions not completed before calling this function
1396  *  are not guaranteed to complete and may be dropped.
1397  **/
1398 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1399                                  struct fm10k_mbx_info *mbx)
1400 {
1401         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1402
1403         DEBUGFUNC("fm10k_mbx_disconnect");
1404
1405         /* Place mbx in ready to disconnect state */
1406         mbx->state = FM10K_STATE_DISCONNECT;
1407
1408         /* trigger interrupt to start shutdown process */
1409         FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1410                                           FM10K_MBX_INTERRUPT_DISABLE);
1411         do {
1412                 usec_delay(FM10K_MBX_POLL_DELAY);
1413                 mbx->ops.process(hw, mbx);
1414                 timeout -= FM10K_MBX_POLL_DELAY;
1415         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1416
1417         /* in case we didn't close, just force the mailbox into shutdown and
1418          * drop all left over messages in the FIFO.
1419          */
1420         fm10k_mbx_connect_reset(mbx);
1421         fm10k_fifo_drop_all(&mbx->tx);
1422
1423         FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1424 }
1425
1426 /**
1427  *  fm10k_mbx_connect - Start mailbox connection
1428  *  @hw: pointer to hardware structure
1429  *  @mbx: pointer to mailbox
1430  *
1431  *  This function will initiate a mailbox connection.  It will populate the
1432  *  mailbox with a broadcast connect message and then initialize the lock.
1433  *  This is safe since the connect message is a single DWORD so the mailbox
1434  *  transaction is guaranteed to be atomic.
1435  *
1436  *  This function will return an error if the mailbox has not been initiated
1437  *  or is currently in use.
1438  **/
1439 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1440 {
1441         DEBUGFUNC("fm10k_mbx_connect");
1442
1443         /* we cannot connect an uninitialized mailbox */
1444         if (!mbx->rx.buffer)
1445                 return FM10K_MBX_ERR_NO_SPACE;
1446
1447         /* we cannot connect an already connected mailbox */
1448         if (mbx->state != FM10K_STATE_CLOSED)
1449                 return FM10K_MBX_ERR_BUSY;
1450
1451         /* mailbox timeout can now become active */
1452         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1453
1454         /* Place mbx in ready to connect state */
1455         mbx->state = FM10K_STATE_CONNECT;
1456
1457         /* initialize header of remote mailbox */
1458         fm10k_mbx_create_disconnect_hdr(mbx);
1459         FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1460
1461         /* enable interrupt and notify other party of new message */
1462         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1463                         FM10K_MBX_INTERRUPT_ENABLE;
1464
1465         /* generate and load connect header into mailbox */
1466         fm10k_mbx_create_connect_hdr(mbx);
1467         fm10k_mbx_write(hw, mbx);
1468
1469         return FM10K_SUCCESS;
1470 }
1471
1472 /**
1473  *  fm10k_mbx_validate_handlers - Validate layout of message parsing data
1474  *  @msg_data: handlers for mailbox events
1475  *
1476  *  This function validates the layout of the message parsing data.  This
1477  *  should be mostly static, but it is important to catch any errors that
1478  *  are made when constructing the parsers.
1479  **/
1480 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1481 {
1482         const struct fm10k_tlv_attr *attr;
1483         unsigned int id;
1484
1485         DEBUGFUNC("fm10k_mbx_validate_handlers");
1486
1487         /* Allow NULL mailboxes that transmit but don't receive */
1488         if (!msg_data)
1489                 return FM10K_SUCCESS;
1490
1491         while (msg_data->id != FM10K_TLV_ERROR) {
1492                 /* all messages should have a function handler */
1493                 if (!msg_data->func)
1494                         return FM10K_ERR_PARAM;
1495
1496                 /* parser is optional */
1497                 attr = msg_data->attr;
1498                 if (attr) {
1499                         while (attr->id != FM10K_TLV_ERROR) {
1500                                 id = attr->id;
1501                                 attr++;
1502                                 /* ID should always be increasing */
1503                                 if (id >= attr->id)
1504                                         return FM10K_ERR_PARAM;
1505                                 /* ID should fit in results array */
1506                                 if (id >= FM10K_TLV_RESULTS_MAX)
1507                                         return FM10K_ERR_PARAM;
1508                         }
1509
1510                         /* verify terminator is in the list */
1511                         if (attr->id != FM10K_TLV_ERROR)
1512                                 return FM10K_ERR_PARAM;
1513                 }
1514
1515                 id = msg_data->id;
1516                 msg_data++;
1517                 /* ID should always be increasing */
1518                 if (id >= msg_data->id)
1519                         return FM10K_ERR_PARAM;
1520         }
1521
1522         /* verify terminator is in the list */
1523         if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1524                 return FM10K_ERR_PARAM;
1525
1526         return FM10K_SUCCESS;
1527 }
1528
1529 /**
1530  *  fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1531  *  @mbx: pointer to mailbox
1532  *  @msg_data: handlers for mailbox events
1533  *
1534  *  This function associates a set of message handling ops with a mailbox.
1535  **/
1536 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1537                                        const struct fm10k_msg_data *msg_data)
1538 {
1539         DEBUGFUNC("fm10k_mbx_register_handlers");
1540
1541         /* validate layout of handlers before assigning them */
1542         if (fm10k_mbx_validate_handlers(msg_data))
1543                 return FM10K_ERR_PARAM;
1544
1545         /* initialize the message handlers */
1546         mbx->msg_data = msg_data;
1547
1548         return FM10K_SUCCESS;
1549 }
1550
1551 /**
1552  *  fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1553  *  @hw: pointer to hardware structure
1554  *  @mbx: pointer to mailbox
1555  *  @msg_data: handlers for mailbox events
1556  *  @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1557  *
1558  *  This function initializes the mailbox for use.  It will split the
1559  *  buffer provided an use that th populate both the Tx and Rx FIFO by
1560  *  evenly splitting it.  In order to allow for easy masking of head/tail
1561  *  the value reported in size must be a power of 2 and is reported in
1562  *  DWORDs, not bytes.  Any invalid values will cause the mailbox to return
1563  *  error.
1564  **/
1565 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1566                         const struct fm10k_msg_data *msg_data, u8 id)
1567 {
1568         DEBUGFUNC("fm10k_pfvf_mbx_init");
1569
1570         /* initialize registers */
1571         switch (hw->mac.type) {
1572         case fm10k_mac_vf:
1573                 mbx->mbx_reg = FM10K_VFMBX;
1574                 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1575                 break;
1576         case fm10k_mac_pf:
1577                 /* there are only 64 VF <-> PF mailboxes */
1578                 if (id < 64) {
1579                         mbx->mbx_reg = FM10K_MBX(id);
1580                         mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1581                         break;
1582                 }
1583                 /* fallthough */
1584         default:
1585                 return FM10K_MBX_ERR_NO_MBX;
1586         }
1587
1588         /* start out in closed state */
1589         mbx->state = FM10K_STATE_CLOSED;
1590
1591         /* validate layout of handlers before assigning them */
1592         if (fm10k_mbx_validate_handlers(msg_data))
1593                 return FM10K_ERR_PARAM;
1594
1595         /* initialize the message handlers */
1596         mbx->msg_data = msg_data;
1597
1598         /* start mailbox as timed out and let the reset_hw call
1599          * set the timeout value to begin communications
1600          */
1601         mbx->timeout = 0;
1602         mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1603
1604         /* initialize tail and head */
1605         mbx->tail = 1;
1606         mbx->head = 1;
1607
1608         /* initialize CRC seeds */
1609         mbx->local = FM10K_MBX_CRC_SEED;
1610         mbx->remote = FM10K_MBX_CRC_SEED;
1611
1612         /* Split buffer for use by Tx/Rx FIFOs */
1613         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1614         mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1615
1616         /* initialize the FIFOs, sizes are in 4 byte increments */
1617         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1618         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1619                         FM10K_MBX_RX_BUFFER_SIZE);
1620
1621         /* initialize function pointers */
1622         mbx->ops.connect = fm10k_mbx_connect;
1623         mbx->ops.disconnect = fm10k_mbx_disconnect;
1624         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1625         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1626         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1627         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1628         mbx->ops.process = fm10k_mbx_process;
1629         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1630
1631         return FM10K_SUCCESS;
1632 }
1633
1634 /**
1635  *  fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1636  *  @mbx: pointer to mailbox
1637  *
1638  *  This function returns a connection mailbox header
1639  **/
1640 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1641 {
1642         if (mbx->tail_len)
1643                 mbx->mbx_lock |= FM10K_MBX_REQ;
1644
1645         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1646                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1647                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1648 }
1649
1650 /**
1651  *  fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1652  *  @mbx: pointer to mailbox
1653  *  @err: error flags to report if any
1654  *
1655  *  This function returns a connection mailbox header
1656  **/
1657 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1658 {
1659         if (mbx->local)
1660                 mbx->mbx_lock |= FM10K_MBX_REQ;
1661
1662         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1663                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1664                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1665                        FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1666 }
1667
1668 /**
1669  *  fm10k_sm_mbx_connect_reset - Reset following request for reset
1670  *  @mbx: pointer to mailbox
1671  *
1672  *  This function resets the mailbox to a just connected state
1673  **/
1674 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1675 {
1676         /* flush any uncompleted work */
1677         fm10k_mbx_reset_work(mbx);
1678
1679         /* set local version to max and remote version to 0 */
1680         mbx->local = FM10K_SM_MBX_VERSION;
1681         mbx->remote = 0;
1682
1683         /* initialize tail and head */
1684         mbx->tail = 1;
1685         mbx->head = 1;
1686
1687         /* reset state back to connect */
1688         mbx->state = FM10K_STATE_CONNECT;
1689 }
1690
1691 /**
1692  *  fm10k_sm_mbx_connect - Start switch manager mailbox connection
1693  *  @hw: pointer to hardware structure
1694  *  @mbx: pointer to mailbox
1695  *
1696  *  This function will initiate a mailbox connection with the switch
1697  *  manager.  To do this it will first disconnect the mailbox, and then
1698  *  reconnect it in order to complete a reset of the mailbox.
1699  *
1700  *  This function will return an error if the mailbox has not been initiated
1701  *  or is currently in use.
1702  **/
1703 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1704 {
1705         DEBUGFUNC("fm10k_mbx_connect");
1706
1707         /* we cannot connect an uninitialized mailbox */
1708         if (!mbx->rx.buffer)
1709                 return FM10K_MBX_ERR_NO_SPACE;
1710
1711         /* we cannot connect an already connected mailbox */
1712         if (mbx->state != FM10K_STATE_CLOSED)
1713                 return FM10K_MBX_ERR_BUSY;
1714
1715         /* mailbox timeout can now become active */
1716         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1717
1718         /* Place mbx in ready to connect state */
1719         mbx->state = FM10K_STATE_CONNECT;
1720         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1721
1722         /* reset interface back to connect */
1723         fm10k_sm_mbx_connect_reset(mbx);
1724
1725         /* enable interrupt and notify other party of new message */
1726         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1727                         FM10K_MBX_INTERRUPT_ENABLE;
1728
1729         /* generate and load connect header into mailbox */
1730         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1731         fm10k_mbx_write(hw, mbx);
1732
1733         /* enable interrupt and notify other party of new message */
1734
1735         return FM10K_SUCCESS;
1736 }
1737
1738 /**
1739  *  fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1740  *  @hw: pointer to hardware structure
1741  *  @mbx: pointer to mailbox
1742  *
1743  *  This function will shut down the mailbox.  It places the mailbox first
1744  *  in the disconnect state, it then allows up to a predefined timeout for
1745  *  the mailbox to transition to close on its own.  If this does not occur
1746  *  then the mailbox will be forced into the closed state.
1747  *
1748  *  Any mailbox transactions not completed before calling this function
1749  *  are not guaranteed to complete and may be dropped.
1750  **/
1751 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1752                                     struct fm10k_mbx_info *mbx)
1753 {
1754         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1755
1756         DEBUGFUNC("fm10k_sm_mbx_disconnect");
1757
1758         /* Place mbx in ready to disconnect state */
1759         mbx->state = FM10K_STATE_DISCONNECT;
1760
1761         /* trigger interrupt to start shutdown process */
1762         FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1763                                           FM10K_MBX_INTERRUPT_DISABLE);
1764         do {
1765                 usec_delay(FM10K_MBX_POLL_DELAY);
1766                 mbx->ops.process(hw, mbx);
1767                 timeout -= FM10K_MBX_POLL_DELAY;
1768         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1769
1770         /* in case we didn't close just force the mailbox into shutdown */
1771         mbx->state = FM10K_STATE_CLOSED;
1772         mbx->remote = 0;
1773         fm10k_mbx_reset_work(mbx);
1774         fm10k_mbx_update_max_size(mbx, 0);
1775
1776         FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1777 }
1778
1779 /**
1780  *  fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1781  *  @mbx: pointer to mailbox
1782  *
1783  *  This function will parse up the fields in the mailbox header and return
1784  *  an error if the header contains any of a number of invalid configurations
1785  *  including unrecognized offsets or version numbers.
1786  **/
1787 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1788 {
1789         const u32 *hdr = &mbx->mbx_hdr;
1790         u16 tail, head, ver;
1791
1792         DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1793
1794         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1795         ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1796         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1797
1798         switch (ver) {
1799         case 0:
1800                 break;
1801         case FM10K_SM_MBX_VERSION:
1802                 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1803                         return FM10K_MBX_ERR_HEAD;
1804                 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1805                         return FM10K_MBX_ERR_TAIL;
1806                 if (mbx->tail < head)
1807                         head += mbx->mbmem_len - 1;
1808                 if (tail < mbx->head)
1809                         tail += mbx->mbmem_len - 1;
1810                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1811                         return FM10K_MBX_ERR_HEAD;
1812                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1813                         break;
1814                 return FM10K_MBX_ERR_TAIL;
1815         default:
1816                 return FM10K_MBX_ERR_SRC;
1817         }
1818
1819         return FM10K_SUCCESS;
1820 }
1821
1822 /**
1823  *  fm10k_sm_mbx_process_error - Process header with error flag set
1824  *  @mbx: pointer to mailbox
1825  *
1826  *  This function is meant to respond to a request where the error flag
1827  *  is set.  As a result we will terminate a connection if one is present
1828  *  and fall back into the reset state with a connection header of version
1829  *  0 (RESET).
1830  **/
1831 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1832 {
1833         const enum fm10k_mbx_state state = mbx->state;
1834
1835         switch (state) {
1836         case FM10K_STATE_DISCONNECT:
1837                 /* if there is an error just disconnect */
1838                 mbx->remote = 0;
1839                 break;
1840         case FM10K_STATE_OPEN:
1841                 /* flush any uncompleted work */
1842                 fm10k_sm_mbx_connect_reset(mbx);
1843                 break;
1844         case FM10K_STATE_CONNECT:
1845                 /* try connnecting at lower version */
1846                 if (mbx->remote) {
1847                         while (mbx->local > 1)
1848                                 mbx->local--;
1849                         mbx->remote = 0;
1850                 }
1851                 break;
1852         default:
1853                 break;
1854         }
1855
1856         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1857 }
1858
1859 /**
1860  *  fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1861  *  @mbx: pointer to mailbox
1862  *  @err: local error encountered
1863  *
1864  *  This function will interpret the error provided by err, and based on
1865  *  that it may set the error bit in the local message header
1866  **/
1867 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1868 {
1869         /* only generate an error message for these types */
1870         switch (err) {
1871         case FM10K_MBX_ERR_TAIL:
1872         case FM10K_MBX_ERR_HEAD:
1873         case FM10K_MBX_ERR_SRC:
1874         case FM10K_MBX_ERR_SIZE:
1875         case FM10K_MBX_ERR_RSVD0:
1876                 break;
1877         default:
1878                 return;
1879         }
1880
1881         /* process it as though we received an error, and send error reply */
1882         fm10k_sm_mbx_process_error(mbx);
1883         fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1884 }
1885
1886 /**
1887  *  fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1888  *  @hw: pointer to hardware structure
1889  *  @mbx: pointer to mailbox
1890  *
1891  *  This function will dequeue one message from the Rx switch manager mailbox
1892  *  FIFO and place it in the Rx mailbox FIFO for processing by software.
1893  **/
1894 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1895                                 struct fm10k_mbx_info *mbx,
1896                                 u16 tail)
1897 {
1898         /* reduce length by 1 to convert to a mask */
1899         u16 mbmem_len = mbx->mbmem_len - 1;
1900         s32 err;
1901
1902         DEBUGFUNC("fm10k_sm_mbx_receive");
1903
1904         /* push tail in front of head */
1905         if (tail < mbx->head)
1906                 tail += mbmem_len;
1907
1908         /* copy data to the Rx FIFO */
1909         err = fm10k_mbx_push_tail(hw, mbx, tail);
1910         if (err < 0)
1911                 return err;
1912
1913         /* process messages if we have received any */
1914         fm10k_mbx_dequeue_rx(hw, mbx);
1915
1916         /* guarantee head aligns with the end of the last message */
1917         mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1918         mbx->pushed = 0;
1919
1920         /* clear any extra bits left over since index adds 1 extra bit */
1921         if (mbx->head > mbmem_len)
1922                 mbx->head -= mbmem_len;
1923
1924         return err;
1925 }
1926
1927 /**
1928  *  fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1929  *  @hw: pointer to hardware structure
1930  *  @mbx: pointer to mailbox
1931  *
1932  *  This function will dequeue one message from the Tx mailbox FIFO and place
1933  *  it in the Tx switch manager mailbox FIFO for processing by hardware.
1934  **/
1935 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1936                                   struct fm10k_mbx_info *mbx, u16 head)
1937 {
1938         struct fm10k_mbx_fifo *fifo = &mbx->tx;
1939         /* reduce length by 1 to convert to a mask */
1940         u16 mbmem_len = mbx->mbmem_len - 1;
1941         u16 tail_len, len = 0;
1942         u32 *msg;
1943
1944         DEBUGFUNC("fm10k_sm_mbx_transmit");
1945
1946         /* push head behind tail */
1947         if (mbx->tail < head)
1948                 head += mbmem_len;
1949
1950         fm10k_mbx_pull_head(hw, mbx, head);
1951
1952         /* determine msg aligned offset for end of buffer */
1953         do {
1954                 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1955                 tail_len = len;
1956                 len += FM10K_TLV_DWORD_LEN(*msg);
1957         } while ((len <= mbx->tail_len) && (len < mbmem_len));
1958
1959         /* guarantee we stop on a message boundary */
1960         if (mbx->tail_len > tail_len) {
1961                 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1962                 mbx->tail_len = tail_len;
1963         }
1964
1965         /* clear any extra bits left over since index adds 1 extra bit */
1966         if (mbx->tail > mbmem_len)
1967                 mbx->tail -= mbmem_len;
1968 }
1969
1970 /**
1971  *  fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1972  *  @mbx: pointer to mailbox
1973  *  @head: acknowledgement number
1974  *
1975  *  This function will generate an outgoing message based on the current
1976  *  mailbox state and the remote fifo head.  It will return the length
1977  *  of the outgoing message excluding header on success, and a negative value
1978  *  on error.
1979  **/
1980 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1981                                       struct fm10k_mbx_info *mbx, u16 head)
1982 {
1983         switch (mbx->state) {
1984         case FM10K_STATE_OPEN:
1985         case FM10K_STATE_DISCONNECT:
1986                 /* flush out Tx data */
1987                 fm10k_sm_mbx_transmit(hw, mbx, head);
1988
1989                 /* generate new header based on data */
1990                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1991                         fm10k_sm_mbx_create_data_hdr(mbx);
1992                 } else {
1993                         mbx->remote = 0;
1994                         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1995                 }
1996                 break;
1997         case FM10K_STATE_CONNECT:
1998         case FM10K_STATE_CLOSED:
1999                 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2000                 break;
2001         default:
2002                 break;
2003         }
2004 }
2005
2006 /**
2007  *  fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2008  *  @hw: pointer to hardware structure
2009  *  @mbx: pointer to mailbox
2010  *
2011  *  This function is meant to respond to a request where the version data
2012  *  is set to 0.  As such we will either terminate the connection or go
2013  *  into the connect state in order to re-establish the connection.  This
2014  *  function can also be used to respond to an error as the connection
2015  *  resetting would also be a means of dealing with errors.
2016  **/
2017 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2018                                        struct fm10k_mbx_info *mbx)
2019 {
2020         const enum fm10k_mbx_state state = mbx->state;
2021
2022         switch (state) {
2023         case FM10K_STATE_DISCONNECT:
2024                 /* drop remote connections and disconnect */
2025                 mbx->state = FM10K_STATE_CLOSED;
2026                 mbx->remote = 0;
2027                 mbx->local = 0;
2028                 break;
2029         case FM10K_STATE_OPEN:
2030                 /* flush any incomplete work */
2031                 fm10k_sm_mbx_connect_reset(mbx);
2032                 break;
2033         case FM10K_STATE_CONNECT:
2034                 /* Update remote value to match local value */
2035                 mbx->remote = mbx->local;
2036         default:
2037                 break;
2038         }
2039
2040         fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2041 }
2042
2043 /**
2044  *  fm10k_sm_mbx_process_version_1 - Process header with version == 1
2045  *  @hw: pointer to hardware structure
2046  *  @mbx: pointer to mailbox
2047  *
2048  *  This function is meant to process messages received when the remote
2049  *  mailbox is active.
2050  **/
2051 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2052                                           struct fm10k_mbx_info *mbx)
2053 {
2054         const u32 *hdr = &mbx->mbx_hdr;
2055         u16 head, tail;
2056         s32 len;
2057
2058         /* pull all fields needed for verification */
2059         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2060         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2061
2062         /* if we are in connect and wanting version 1 then start up and go */
2063         if (mbx->state == FM10K_STATE_CONNECT) {
2064                 if (!mbx->remote)
2065                         goto send_reply;
2066                 if (mbx->remote != 1)
2067                         return FM10K_MBX_ERR_SRC;
2068
2069                 mbx->state = FM10K_STATE_OPEN;
2070         }
2071
2072         do {
2073                 /* abort on message size errors */
2074                 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2075                 if (len < 0)
2076                         return len;
2077
2078                 /* continue until we have flushed the Rx FIFO */
2079         } while (len);
2080
2081 send_reply:
2082         fm10k_sm_mbx_create_reply(hw, mbx, head);
2083
2084         return FM10K_SUCCESS;
2085 }
2086
2087 /**
2088  *  fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2089  *  @hw: pointer to hardware structure
2090  *  @mbx: pointer to mailbox
2091  *
2092  *  This function will process incoming mailbox events and generate mailbox
2093  *  replies.  It will return a value indicating the number of DWORDs
2094  *  transmitted excluding header on success or a negative value on error.
2095  **/
2096 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2097                                 struct fm10k_mbx_info *mbx)
2098 {
2099         s32 err;
2100
2101         DEBUGFUNC("fm10k_sm_mbx_process");
2102
2103         /* we do not read mailbox if closed */
2104         if (mbx->state == FM10K_STATE_CLOSED)
2105                 return FM10K_SUCCESS;
2106
2107         /* retrieve data from switch manager */
2108         err = fm10k_mbx_read(hw, mbx);
2109         if (err)
2110                 return err;
2111
2112         err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2113         if (err < 0)
2114                 goto fifo_err;
2115
2116         if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2117                 fm10k_sm_mbx_process_error(mbx);
2118                 goto fifo_err;
2119         }
2120
2121         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2122         case 0:
2123                 fm10k_sm_mbx_process_reset(hw, mbx);
2124                 break;
2125         case FM10K_SM_MBX_VERSION:
2126                 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2127                 break;
2128         }
2129
2130 fifo_err:
2131         if (err < 0)
2132                 fm10k_sm_mbx_create_error_msg(mbx, err);
2133
2134         /* report data to switch manager */
2135         fm10k_mbx_write(hw, mbx);
2136
2137         return err;
2138 }
2139
2140 /**
2141  *  fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2142  *  @hw: pointer to hardware structure
2143  *  @mbx: pointer to mailbox
2144  *  @msg_data: handlers for mailbox events
2145  *
2146  *  This function for now is used to stub out the PF/SM mailbox
2147  **/
2148 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2149                       const struct fm10k_msg_data *msg_data)
2150 {
2151         DEBUGFUNC("fm10k_sm_mbx_init");
2152         UNREFERENCED_1PARAMETER(hw);
2153
2154         mbx->mbx_reg = FM10K_GMBX;
2155         mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2156
2157         /* start out in closed state */
2158         mbx->state = FM10K_STATE_CLOSED;
2159
2160         /* validate layout of handlers before assigning them */
2161         if (fm10k_mbx_validate_handlers(msg_data))
2162                 return FM10K_ERR_PARAM;
2163
2164         /* initialize the message handlers */
2165         mbx->msg_data = msg_data;
2166
2167         /* start mailbox as timed out and let the reset_hw call
2168          * set the timeout value to begin communications
2169          */
2170         mbx->timeout = 0;
2171         mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2172
2173         /* Split buffer for use by Tx/Rx FIFOs */
2174         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2175         mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2176
2177         /* initialize the FIFOs, sizes are in 4 byte increments */
2178         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2179         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2180                         FM10K_MBX_RX_BUFFER_SIZE);
2181
2182         /* initialize function pointers */
2183         mbx->ops.connect = fm10k_sm_mbx_connect;
2184         mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2185         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2186         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2187         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2188         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2189         mbx->ops.process = fm10k_sm_mbx_process;
2190         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2191
2192         return FM10K_SUCCESS;
2193 }