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