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