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