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