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