fm10k/base: fix mailbox connect
[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_fake_disconnect_hdr - Generate a false disconnect mailbox header
930  *  @mbx: pointer to mailbox
931  *
932  *  This function creates a fake disconnect header for loading into remote
933  *  mailbox header. The primary purpose is to prevent errors on immediate
934  *  start up after mbx->connect.
935  **/
936 STATIC void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
937 {
938         u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
939                   FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
940                   FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
941         u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
942
943         mbx->mbx_lock |= FM10K_MBX_ACK;
944
945         /* load header to memory to be written */
946         mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
947 }
948
949 /**
950  *  fm10k_mbx_create_error_msg - Generate a error message
951  *  @mbx: pointer to mailbox
952  *  @err: local error encountered
953  *
954  *  This function will interpret the error provided by err, and based on
955  *  that it may shift the message by 1 DWORD and then place an error header
956  *  at the start of the message.
957  **/
958 STATIC void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
959 {
960         /* only generate an error message for these types */
961         switch (err) {
962         case FM10K_MBX_ERR_TAIL:
963         case FM10K_MBX_ERR_HEAD:
964         case FM10K_MBX_ERR_TYPE:
965         case FM10K_MBX_ERR_SIZE:
966         case FM10K_MBX_ERR_RSVD0:
967         case FM10K_MBX_ERR_CRC:
968                 break;
969         default:
970                 return;
971         }
972
973         mbx->mbx_lock |= FM10K_MBX_REQ;
974
975         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
976                        FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
977                        FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
978 }
979
980 /**
981  *  fm10k_mbx_validate_msg_hdr - Validate common fields in the message header
982  *  @mbx: pointer to mailbox
983  *  @msg: message array to read
984  *
985  *  This function will parse up the fields in the mailbox header and return
986  *  an error if the header contains any of a number of invalid configurations
987  *  including unrecognized type, invalid route, or a malformed message.
988  **/
989 STATIC s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
990 {
991         u16 type, rsvd0, head, tail, size;
992         const u32 *hdr = &mbx->mbx_hdr;
993
994         DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
995
996         type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
997         rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
998         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
999         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1000         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1001
1002         if (rsvd0)
1003                 return FM10K_MBX_ERR_RSVD0;
1004
1005         switch (type) {
1006         case FM10K_MSG_DISCONNECT:
1007                 /* validate that all data has been received */
1008                 if (tail != mbx->head)
1009                         return FM10K_MBX_ERR_TAIL;
1010
1011                 /* fall through */
1012         case FM10K_MSG_DATA:
1013                 /* validate that head is moving correctly */
1014                 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1015                         return FM10K_MBX_ERR_HEAD;
1016                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1017                         return FM10K_MBX_ERR_HEAD;
1018
1019                 /* validate that tail is moving correctly */
1020                 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
1021                         return FM10K_MBX_ERR_TAIL;
1022                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1023                         break;
1024
1025                 return FM10K_MBX_ERR_TAIL;
1026         case FM10K_MSG_CONNECT:
1027                 /* validate size is in range and is power of 2 mask */
1028                 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
1029                         return FM10K_MBX_ERR_SIZE;
1030
1031                 /* fall through */
1032         case FM10K_MSG_ERROR:
1033                 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
1034                         return FM10K_MBX_ERR_HEAD;
1035                 /* neither create nor error include a tail offset */
1036                 if (tail)
1037                         return FM10K_MBX_ERR_TAIL;
1038
1039                 break;
1040         default:
1041                 return FM10K_MBX_ERR_TYPE;
1042         }
1043
1044         return FM10K_SUCCESS;
1045 }
1046
1047 /**
1048  *  fm10k_mbx_create_reply - Generate reply based on state and remote head
1049  *  @mbx: pointer to mailbox
1050  *  @head: acknowledgement number
1051  *
1052  *  This function will generate an outgoing message based on the current
1053  *  mailbox state and the remote fifo head.  It will return the length
1054  *  of the outgoing message excluding header on success, and a negative value
1055  *  on error.
1056  **/
1057 STATIC s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1058                                   struct fm10k_mbx_info *mbx, u16 head)
1059 {
1060         switch (mbx->state) {
1061         case FM10K_STATE_OPEN:
1062         case FM10K_STATE_DISCONNECT:
1063                 /* update our checksum for the outgoing data */
1064                 fm10k_mbx_update_local_crc(mbx, head);
1065
1066                 /* as long as other end recognizes us keep sending data */
1067                 fm10k_mbx_pull_head(hw, mbx, head);
1068
1069                 /* generate new header based on data */
1070                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1071                         fm10k_mbx_create_data_hdr(mbx);
1072                 else
1073                         fm10k_mbx_create_disconnect_hdr(mbx);
1074                 break;
1075         case FM10K_STATE_CONNECT:
1076                 /* send disconnect even if we aren't connected */
1077                 fm10k_mbx_create_connect_hdr(mbx);
1078                 break;
1079         case FM10K_STATE_CLOSED:
1080                 /* generate new header based on data */
1081                 fm10k_mbx_create_disconnect_hdr(mbx);
1082         default:
1083                 break;
1084         }
1085
1086         return FM10K_SUCCESS;
1087 }
1088
1089 /**
1090  *  fm10k_mbx_reset_work- Reset internal pointers for any pending work
1091  *  @mbx: pointer to mailbox
1092  *
1093  *  This function will reset all internal pointers so any work in progress
1094  *  is dropped.  This call should occur every time we transition from the
1095  *  open state to the connect state.
1096  **/
1097 STATIC void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1098 {
1099         u16 len, head, ack;
1100
1101         /* reset our outgoing max size back to Rx limits */
1102         mbx->max_size = mbx->rx.size - 1;
1103
1104         /* update mbx->pulled to account for tail_len and ack */
1105         head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1106         ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1107         mbx->pulled += mbx->tail_len - ack;
1108
1109         /* now drop any messages which have started or finished transmitting */
1110         while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1111                 len = fm10k_fifo_head_drop(&mbx->tx);
1112                 mbx->tx_dropped++;
1113                 if (mbx->pulled >= len)
1114                         mbx->pulled -= len;
1115                 else
1116                         mbx->pulled = 0;
1117         }
1118
1119         /* just do a quick resysnc to start of message */
1120         mbx->pushed = 0;
1121         mbx->pulled = 0;
1122         mbx->tail_len = 0;
1123         mbx->head_len = 0;
1124         mbx->rx.tail = 0;
1125         mbx->rx.head = 0;
1126 }
1127
1128 /**
1129  *  fm10k_mbx_update_max_size - Update the max_size and drop large messages
1130  *  @mbx: pointer to mailbox
1131  *  @size: new value for max_size
1132  *
1133  *  This function updates the max_size value and drops any outgoing messages
1134  *  at the head of the Tx FIFO if they are larger than max_size. It does not
1135  *  drop all messages, as this is too difficult to parse and remove them from
1136  *  the FIFO. Instead, rely on the checking to ensure that messages larger
1137  *  than max_size aren't pushed into the memory buffer.
1138  **/
1139 STATIC void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1140 {
1141         u16 len;
1142
1143         DEBUGFUNC("fm10k_mbx_update_max_size_hdr");
1144
1145         mbx->max_size = size;
1146
1147         /* flush any oversized messages from the queue */
1148         for (len = fm10k_fifo_head_len(&mbx->tx);
1149              len > size;
1150              len = fm10k_fifo_head_len(&mbx->tx)) {
1151                 fm10k_fifo_head_drop(&mbx->tx);
1152                 mbx->tx_dropped++;
1153         }
1154 }
1155
1156 /**
1157  *  fm10k_mbx_connect_reset - Reset following request for reset
1158  *  @mbx: pointer to mailbox
1159  *
1160  *  This function resets the mailbox to either a disconnected state
1161  *  or a connect state depending on the current mailbox state
1162  **/
1163 STATIC void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1164 {
1165         /* just do a quick resysnc to start of frame */
1166         fm10k_mbx_reset_work(mbx);
1167
1168         /* reset CRC seeds */
1169         mbx->local = FM10K_MBX_CRC_SEED;
1170         mbx->remote = FM10K_MBX_CRC_SEED;
1171
1172         /* we cannot exit connect until the size is good */
1173         if (mbx->state == FM10K_STATE_OPEN)
1174                 mbx->state = FM10K_STATE_CONNECT;
1175         else
1176                 mbx->state = FM10K_STATE_CLOSED;
1177 }
1178
1179 /**
1180  *  fm10k_mbx_process_connect - Process connect header
1181  *  @mbx: pointer to mailbox
1182  *  @msg: message array to process
1183  *
1184  *  This function will read an incoming connect header and reply with the
1185  *  appropriate message.  It will return a value indicating the number of
1186  *  data DWORDs on success, or will return a negative value on failure.
1187  **/
1188 STATIC s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1189                                      struct fm10k_mbx_info *mbx)
1190 {
1191         const enum fm10k_mbx_state state = mbx->state;
1192         const u32 *hdr = &mbx->mbx_hdr;
1193         u16 size, head;
1194
1195         /* we will need to pull all of the fields for verification */
1196         size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1197         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1198
1199         switch (state) {
1200         case FM10K_STATE_DISCONNECT:
1201         case FM10K_STATE_OPEN:
1202                 /* reset any in-progress work */
1203                 fm10k_mbx_connect_reset(mbx);
1204                 break;
1205         case FM10K_STATE_CONNECT:
1206                 /* we cannot exit connect until the size is good */
1207                 if (size > mbx->rx.size) {
1208                         mbx->max_size = mbx->rx.size - 1;
1209                 } else {
1210                         /* record the remote system requesting connection */
1211                         mbx->state = FM10K_STATE_OPEN;
1212
1213                         fm10k_mbx_update_max_size(mbx, size);
1214                 }
1215                 break;
1216         default:
1217                 break;
1218         }
1219
1220         /* align our tail index to remote head index */
1221         mbx->tail = head;
1222
1223         return fm10k_mbx_create_reply(hw, mbx, head);
1224 }
1225
1226 /**
1227  *  fm10k_mbx_process_data - Process data header
1228  *  @mbx: pointer to mailbox
1229  *
1230  *  This function will read an incoming data header and reply with the
1231  *  appropriate message.  It will return a value indicating the number of
1232  *  data DWORDs on success, or will return a negative value on failure.
1233  **/
1234 STATIC s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1235                                   struct fm10k_mbx_info *mbx)
1236 {
1237         const u32 *hdr = &mbx->mbx_hdr;
1238         u16 head, tail;
1239         s32 err;
1240
1241         DEBUGFUNC("fm10k_mbx_process_data");
1242
1243         /* we will need to pull all of the fields for verification */
1244         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1245         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1246
1247         /* if we are in connect just update our data and go */
1248         if (mbx->state == FM10K_STATE_CONNECT) {
1249                 mbx->tail = head;
1250                 mbx->state = FM10K_STATE_OPEN;
1251         }
1252
1253         /* abort on message size errors */
1254         err = fm10k_mbx_push_tail(hw, mbx, tail);
1255         if (err < 0)
1256                 return err;
1257
1258         /* verify the checksum on the incoming data */
1259         err = fm10k_mbx_verify_remote_crc(mbx);
1260         if (err)
1261                 return err;
1262
1263         /* process messages if we have received any */
1264         fm10k_mbx_dequeue_rx(hw, mbx);
1265
1266         return fm10k_mbx_create_reply(hw, mbx, head);
1267 }
1268
1269 /**
1270  *  fm10k_mbx_process_disconnect - Process disconnect header
1271  *  @mbx: pointer to mailbox
1272  *
1273  *  This function will read an incoming disconnect header and reply with the
1274  *  appropriate message.  It will return a value indicating the number of
1275  *  data DWORDs on success, or will return a negative value on failure.
1276  **/
1277 STATIC s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1278                                         struct fm10k_mbx_info *mbx)
1279 {
1280         const enum fm10k_mbx_state state = mbx->state;
1281         const u32 *hdr = &mbx->mbx_hdr;
1282         u16 head;
1283         s32 err;
1284
1285         /* we will need to pull the header field for verification */
1286         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1287
1288         /* We should not be receiving disconnect if Rx is incomplete */
1289         if (mbx->pushed)
1290                 return FM10K_MBX_ERR_TAIL;
1291
1292         /* we have already verified mbx->head == tail so we know this is 0 */
1293         mbx->head_len = 0;
1294
1295         /* verify the checksum on the incoming header is correct */
1296         err = fm10k_mbx_verify_remote_crc(mbx);
1297         if (err)
1298                 return err;
1299
1300         switch (state) {
1301         case FM10K_STATE_DISCONNECT:
1302         case FM10K_STATE_OPEN:
1303                 /* state doesn't change if we still have work to do */
1304                 if (!fm10k_mbx_tx_complete(mbx))
1305                         break;
1306
1307                 /* verify the head indicates we completed all transmits */
1308                 if (head != mbx->tail)
1309                         return FM10K_MBX_ERR_HEAD;
1310
1311                 /* reset any in-progress work */
1312                 fm10k_mbx_connect_reset(mbx);
1313                 break;
1314         default:
1315                 break;
1316         }
1317
1318         return fm10k_mbx_create_reply(hw, mbx, head);
1319 }
1320
1321 /**
1322  *  fm10k_mbx_process_error - Process error header
1323  *  @mbx: pointer to mailbox
1324  *
1325  *  This function will read an incoming error header and reply with the
1326  *  appropriate message.  It will return a value indicating the number of
1327  *  data DWORDs on success, or will return a negative value on failure.
1328  **/
1329 STATIC s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1330                                    struct fm10k_mbx_info *mbx)
1331 {
1332         const u32 *hdr = &mbx->mbx_hdr;
1333         u16 head;
1334
1335         /* we will need to pull all of the fields for verification */
1336         head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1337
1338         switch (mbx->state) {
1339         case FM10K_STATE_OPEN:
1340         case FM10K_STATE_DISCONNECT:
1341                 /* flush any uncompleted work */
1342                 fm10k_mbx_reset_work(mbx);
1343
1344                 /* reset CRC seeds */
1345                 mbx->local = FM10K_MBX_CRC_SEED;
1346                 mbx->remote = FM10K_MBX_CRC_SEED;
1347
1348                 /* reset tail index and size to prepare for reconnect */
1349                 mbx->tail = head;
1350
1351                 /* if open then reset max_size and go back to connect */
1352                 if (mbx->state == FM10K_STATE_OPEN) {
1353                         mbx->state = FM10K_STATE_CONNECT;
1354                         break;
1355                 }
1356
1357                 /* send a connect message to get data flowing again */
1358                 fm10k_mbx_create_connect_hdr(mbx);
1359                 return FM10K_SUCCESS;
1360         default:
1361                 break;
1362         }
1363
1364         return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1365 }
1366
1367 /**
1368  *  fm10k_mbx_process - Process mailbox interrupt
1369  *  @hw: pointer to hardware structure
1370  *  @mbx: pointer to mailbox
1371  *
1372  *  This function will process incoming mailbox events and generate mailbox
1373  *  replies.  It will return a value indicating the number of DWORDs
1374  *  transmitted excluding header on success or a negative value on error.
1375  **/
1376 STATIC s32 fm10k_mbx_process(struct fm10k_hw *hw,
1377                              struct fm10k_mbx_info *mbx)
1378 {
1379         s32 err;
1380
1381         DEBUGFUNC("fm10k_mbx_process");
1382
1383         /* we do not read mailbox if closed */
1384         if (mbx->state == FM10K_STATE_CLOSED)
1385                 return FM10K_SUCCESS;
1386
1387         /* copy data from mailbox */
1388         err = fm10k_mbx_read(hw, mbx);
1389         if (err)
1390                 return err;
1391
1392         /* validate type, source, and destination */
1393         err = fm10k_mbx_validate_msg_hdr(mbx);
1394         if (err < 0)
1395                 goto msg_err;
1396
1397         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1398         case FM10K_MSG_CONNECT:
1399                 err = fm10k_mbx_process_connect(hw, mbx);
1400                 break;
1401         case FM10K_MSG_DATA:
1402                 err = fm10k_mbx_process_data(hw, mbx);
1403                 break;
1404         case FM10K_MSG_DISCONNECT:
1405                 err = fm10k_mbx_process_disconnect(hw, mbx);
1406                 break;
1407         case FM10K_MSG_ERROR:
1408                 err = fm10k_mbx_process_error(hw, mbx);
1409                 break;
1410         default:
1411                 err = FM10K_MBX_ERR_TYPE;
1412                 break;
1413         }
1414
1415 msg_err:
1416         /* notify partner of errors on our end */
1417         if (err < 0)
1418                 fm10k_mbx_create_error_msg(mbx, err);
1419
1420         /* copy data from mailbox */
1421         fm10k_mbx_write(hw, mbx);
1422
1423         return err;
1424 }
1425
1426 /**
1427  *  fm10k_mbx_disconnect - Shutdown mailbox connection
1428  *  @hw: pointer to hardware structure
1429  *  @mbx: pointer to mailbox
1430  *
1431  *  This function will shut down the mailbox.  It places the mailbox first
1432  *  in the disconnect state, it then allows up to a predefined timeout for
1433  *  the mailbox to transition to close on its own.  If this does not occur
1434  *  then the mailbox will be forced into the closed state.
1435  *
1436  *  Any mailbox transactions not completed before calling this function
1437  *  are not guaranteed to complete and may be dropped.
1438  **/
1439 STATIC void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1440                                  struct fm10k_mbx_info *mbx)
1441 {
1442         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1443
1444         DEBUGFUNC("fm10k_mbx_disconnect");
1445
1446         /* Place mbx in ready to disconnect state */
1447         mbx->state = FM10K_STATE_DISCONNECT;
1448
1449         /* trigger interrupt to start shutdown process */
1450         FM10K_WRITE_MBX(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1451                                           FM10K_MBX_INTERRUPT_DISABLE);
1452         do {
1453                 usec_delay(FM10K_MBX_POLL_DELAY);
1454                 mbx->ops.process(hw, mbx);
1455                 timeout -= FM10K_MBX_POLL_DELAY;
1456         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1457
1458         /* in case we didn't close, just force the mailbox into shutdown and
1459          * drop all left over messages in the FIFO.
1460          */
1461         fm10k_mbx_connect_reset(mbx);
1462         fm10k_fifo_drop_all(&mbx->tx);
1463
1464         FM10K_WRITE_MBX(hw, mbx->mbmem_reg, 0);
1465 }
1466
1467 /**
1468  *  fm10k_mbx_connect - Start mailbox connection
1469  *  @hw: pointer to hardware structure
1470  *  @mbx: pointer to mailbox
1471  *
1472  *  This function will initiate a mailbox connection.  It will populate the
1473  *  mailbox with a broadcast connect message and then initialize the lock.
1474  *  This is safe since the connect message is a single DWORD so the mailbox
1475  *  transaction is guaranteed to be atomic.
1476  *
1477  *  This function will return an error if the mailbox has not been initiated
1478  *  or is currently in use.
1479  **/
1480 STATIC s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1481 {
1482         DEBUGFUNC("fm10k_mbx_connect");
1483
1484         /* we cannot connect an uninitialized mailbox */
1485         if (!mbx->rx.buffer)
1486                 return FM10K_MBX_ERR_NO_SPACE;
1487
1488         /* we cannot connect an already connected mailbox */
1489         if (mbx->state != FM10K_STATE_CLOSED)
1490                 return FM10K_MBX_ERR_BUSY;
1491
1492         /* mailbox timeout can now become active */
1493         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1494
1495         /* Place mbx in ready to connect state */
1496         mbx->state = FM10K_STATE_CONNECT;
1497
1498         fm10k_mbx_reset_work(mbx);
1499
1500         fm10k_mbx_create_fake_disconnect_hdr(mbx);
1501         FM10K_WRITE_MBX(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1502
1503         /* enable interrupt and notify other party of new message */
1504         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1505                         FM10K_MBX_INTERRUPT_ENABLE;
1506
1507         /* generate and load connect header into mailbox */
1508         fm10k_mbx_create_connect_hdr(mbx);
1509         fm10k_mbx_write(hw, mbx);
1510
1511         return FM10K_SUCCESS;
1512 }
1513
1514 /**
1515  *  fm10k_mbx_validate_handlers - Validate layout of message parsing data
1516  *  @msg_data: handlers for mailbox events
1517  *
1518  *  This function validates the layout of the message parsing data.  This
1519  *  should be mostly static, but it is important to catch any errors that
1520  *  are made when constructing the parsers.
1521  **/
1522 STATIC s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1523 {
1524         const struct fm10k_tlv_attr *attr;
1525         unsigned int id;
1526
1527         DEBUGFUNC("fm10k_mbx_validate_handlers");
1528
1529         /* Allow NULL mailboxes that transmit but don't receive */
1530         if (!msg_data)
1531                 return FM10K_SUCCESS;
1532
1533         while (msg_data->id != FM10K_TLV_ERROR) {
1534                 /* all messages should have a function handler */
1535                 if (!msg_data->func)
1536                         return FM10K_ERR_PARAM;
1537
1538                 /* parser is optional */
1539                 attr = msg_data->attr;
1540                 if (attr) {
1541                         while (attr->id != FM10K_TLV_ERROR) {
1542                                 id = attr->id;
1543                                 attr++;
1544                                 /* ID should always be increasing */
1545                                 if (id >= attr->id)
1546                                         return FM10K_ERR_PARAM;
1547                                 /* ID should fit in results array */
1548                                 if (id >= FM10K_TLV_RESULTS_MAX)
1549                                         return FM10K_ERR_PARAM;
1550                         }
1551
1552                         /* verify terminator is in the list */
1553                         if (attr->id != FM10K_TLV_ERROR)
1554                                 return FM10K_ERR_PARAM;
1555                 }
1556
1557                 id = msg_data->id;
1558                 msg_data++;
1559                 /* ID should always be increasing */
1560                 if (id >= msg_data->id)
1561                         return FM10K_ERR_PARAM;
1562         }
1563
1564         /* verify terminator is in the list */
1565         if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1566                 return FM10K_ERR_PARAM;
1567
1568         return FM10K_SUCCESS;
1569 }
1570
1571 /**
1572  *  fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
1573  *  @mbx: pointer to mailbox
1574  *  @msg_data: handlers for mailbox events
1575  *
1576  *  This function associates a set of message handling ops with a mailbox.
1577  **/
1578 STATIC s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1579                                        const struct fm10k_msg_data *msg_data)
1580 {
1581         DEBUGFUNC("fm10k_mbx_register_handlers");
1582
1583         /* validate layout of handlers before assigning them */
1584         if (fm10k_mbx_validate_handlers(msg_data))
1585                 return FM10K_ERR_PARAM;
1586
1587         /* initialize the message handlers */
1588         mbx->msg_data = msg_data;
1589
1590         return FM10K_SUCCESS;
1591 }
1592
1593 /**
1594  *  fm10k_pfvf_mbx_init - Initialize mailbox memory for PF/VF mailbox
1595  *  @hw: pointer to hardware structure
1596  *  @mbx: pointer to mailbox
1597  *  @msg_data: handlers for mailbox events
1598  *  @id: ID reference for PF as it supports up to 64 PF/VF mailboxes
1599  *
1600  *  This function initializes the mailbox for use.  It will split the
1601  *  buffer provided an use that th populate both the Tx and Rx FIFO by
1602  *  evenly splitting it.  In order to allow for easy masking of head/tail
1603  *  the value reported in size must be a power of 2 and is reported in
1604  *  DWORDs, not bytes.  Any invalid values will cause the mailbox to return
1605  *  error.
1606  **/
1607 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1608                         const struct fm10k_msg_data *msg_data, u8 id)
1609 {
1610         DEBUGFUNC("fm10k_pfvf_mbx_init");
1611
1612         /* initialize registers */
1613         switch (hw->mac.type) {
1614         case fm10k_mac_vf:
1615                 mbx->mbx_reg = FM10K_VFMBX;
1616                 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1617                 break;
1618         case fm10k_mac_pf:
1619                 /* there are only 64 VF <-> PF mailboxes */
1620                 if (id < 64) {
1621                         mbx->mbx_reg = FM10K_MBX(id);
1622                         mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1623                         break;
1624                 }
1625                 /* fallthough */
1626         default:
1627                 return FM10K_MBX_ERR_NO_MBX;
1628         }
1629
1630         /* start out in closed state */
1631         mbx->state = FM10K_STATE_CLOSED;
1632
1633         /* validate layout of handlers before assigning them */
1634         if (fm10k_mbx_validate_handlers(msg_data))
1635                 return FM10K_ERR_PARAM;
1636
1637         /* initialize the message handlers */
1638         mbx->msg_data = msg_data;
1639
1640         /* start mailbox as timed out and let the reset_hw call
1641          * set the timeout value to begin communications
1642          */
1643         mbx->timeout = 0;
1644         mbx->usec_delay = FM10K_MBX_INIT_DELAY;
1645
1646         /* initialize tail and head */
1647         mbx->tail = 1;
1648         mbx->head = 1;
1649
1650         /* initialize CRC seeds */
1651         mbx->local = FM10K_MBX_CRC_SEED;
1652         mbx->remote = FM10K_MBX_CRC_SEED;
1653
1654         /* Split buffer for use by Tx/Rx FIFOs */
1655         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1656         mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1657
1658         /* initialize the FIFOs, sizes are in 4 byte increments */
1659         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1660         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1661                         FM10K_MBX_RX_BUFFER_SIZE);
1662
1663         /* initialize function pointers */
1664         mbx->ops.connect = fm10k_mbx_connect;
1665         mbx->ops.disconnect = fm10k_mbx_disconnect;
1666         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1667         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1668         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1669         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1670         mbx->ops.process = fm10k_mbx_process;
1671         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1672
1673         return FM10K_SUCCESS;
1674 }
1675
1676 /**
1677  *  fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
1678  *  @mbx: pointer to mailbox
1679  *
1680  *  This function returns a connection mailbox header
1681  **/
1682 STATIC void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1683 {
1684         if (mbx->tail_len)
1685                 mbx->mbx_lock |= FM10K_MBX_REQ;
1686
1687         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1688                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1689                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1690 }
1691
1692 /**
1693  *  fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
1694  *  @mbx: pointer to mailbox
1695  *  @err: error flags to report if any
1696  *
1697  *  This function returns a connection mailbox header
1698  **/
1699 STATIC void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1700 {
1701         if (mbx->local)
1702                 mbx->mbx_lock |= FM10K_MBX_REQ;
1703
1704         mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1705                        FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1706                        FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1707                        FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1708 }
1709
1710 /**
1711  *  fm10k_sm_mbx_connect_reset - Reset following request for reset
1712  *  @mbx: pointer to mailbox
1713  *
1714  *  This function resets the mailbox to a just connected state
1715  **/
1716 STATIC void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1717 {
1718         /* flush any uncompleted work */
1719         fm10k_mbx_reset_work(mbx);
1720
1721         /* set local version to max and remote version to 0 */
1722         mbx->local = FM10K_SM_MBX_VERSION;
1723         mbx->remote = 0;
1724
1725         /* initialize tail and head */
1726         mbx->tail = 1;
1727         mbx->head = 1;
1728
1729         /* reset state back to connect */
1730         mbx->state = FM10K_STATE_CONNECT;
1731 }
1732
1733 /**
1734  *  fm10k_sm_mbx_connect - Start switch manager mailbox connection
1735  *  @hw: pointer to hardware structure
1736  *  @mbx: pointer to mailbox
1737  *
1738  *  This function will initiate a mailbox connection with the switch
1739  *  manager.  To do this it will first disconnect the mailbox, and then
1740  *  reconnect it in order to complete a reset of the mailbox.
1741  *
1742  *  This function will return an error if the mailbox has not been initiated
1743  *  or is currently in use.
1744  **/
1745 STATIC s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1746 {
1747         DEBUGFUNC("fm10k_mbx_connect");
1748
1749         /* we cannot connect an uninitialized mailbox */
1750         if (!mbx->rx.buffer)
1751                 return FM10K_MBX_ERR_NO_SPACE;
1752
1753         /* we cannot connect an already connected mailbox */
1754         if (mbx->state != FM10K_STATE_CLOSED)
1755                 return FM10K_MBX_ERR_BUSY;
1756
1757         /* mailbox timeout can now become active */
1758         mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1759
1760         /* Place mbx in ready to connect state */
1761         mbx->state = FM10K_STATE_CONNECT;
1762         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1763
1764         /* reset interface back to connect */
1765         fm10k_sm_mbx_connect_reset(mbx);
1766
1767         /* enable interrupt and notify other party of new message */
1768         mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1769                         FM10K_MBX_INTERRUPT_ENABLE;
1770
1771         /* generate and load connect header into mailbox */
1772         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1773         fm10k_mbx_write(hw, mbx);
1774
1775         /* enable interrupt and notify other party of new message */
1776
1777         return FM10K_SUCCESS;
1778 }
1779
1780 /**
1781  *  fm10k_sm_mbx_disconnect - Shutdown mailbox connection
1782  *  @hw: pointer to hardware structure
1783  *  @mbx: pointer to mailbox
1784  *
1785  *  This function will shut down the mailbox.  It places the mailbox first
1786  *  in the disconnect state, it then allows up to a predefined timeout for
1787  *  the mailbox to transition to close on its own.  If this does not occur
1788  *  then the mailbox will be forced into the closed state.
1789  *
1790  *  Any mailbox transactions not completed before calling this function
1791  *  are not guaranteed to complete and may be dropped.
1792  **/
1793 STATIC void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1794                                     struct fm10k_mbx_info *mbx)
1795 {
1796         int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1797
1798         DEBUGFUNC("fm10k_sm_mbx_disconnect");
1799
1800         /* Place mbx in ready to disconnect state */
1801         mbx->state = FM10K_STATE_DISCONNECT;
1802
1803         /* trigger interrupt to start shutdown process */
1804         FM10K_WRITE_REG(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1805                                           FM10K_MBX_INTERRUPT_DISABLE);
1806         do {
1807                 usec_delay(FM10K_MBX_POLL_DELAY);
1808                 mbx->ops.process(hw, mbx);
1809                 timeout -= FM10K_MBX_POLL_DELAY;
1810         } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1811
1812         /* in case we didn't close just force the mailbox into shutdown */
1813         mbx->state = FM10K_STATE_CLOSED;
1814         mbx->remote = 0;
1815         fm10k_mbx_reset_work(mbx);
1816         fm10k_fifo_drop_all(&mbx->tx);
1817
1818         FM10K_WRITE_REG(hw, mbx->mbmem_reg, 0);
1819 }
1820
1821 /**
1822  *  fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
1823  *  @mbx: pointer to mailbox
1824  *
1825  *  This function will parse up the fields in the mailbox header and return
1826  *  an error if the header contains any of a number of invalid configurations
1827  *  including unrecognized offsets or version numbers.
1828  **/
1829 STATIC s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1830 {
1831         const u32 *hdr = &mbx->mbx_hdr;
1832         u16 tail, head, ver;
1833
1834         DEBUGFUNC("fm10k_mbx_validate_msg_hdr");
1835
1836         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1837         ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1838         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1839
1840         switch (ver) {
1841         case 0:
1842                 break;
1843         case FM10K_SM_MBX_VERSION:
1844                 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1845                         return FM10K_MBX_ERR_HEAD;
1846                 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1847                         return FM10K_MBX_ERR_TAIL;
1848                 if (mbx->tail < head)
1849                         head += mbx->mbmem_len - 1;
1850                 if (tail < mbx->head)
1851                         tail += mbx->mbmem_len - 1;
1852                 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1853                         return FM10K_MBX_ERR_HEAD;
1854                 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1855                         break;
1856                 return FM10K_MBX_ERR_TAIL;
1857         default:
1858                 return FM10K_MBX_ERR_SRC;
1859         }
1860
1861         return FM10K_SUCCESS;
1862 }
1863
1864 /**
1865  *  fm10k_sm_mbx_process_error - Process header with error flag set
1866  *  @mbx: pointer to mailbox
1867  *
1868  *  This function is meant to respond to a request where the error flag
1869  *  is set.  As a result we will terminate a connection if one is present
1870  *  and fall back into the reset state with a connection header of version
1871  *  0 (RESET).
1872  **/
1873 STATIC void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1874 {
1875         const enum fm10k_mbx_state state = mbx->state;
1876
1877         switch (state) {
1878         case FM10K_STATE_DISCONNECT:
1879                 /* if there is an error just disconnect */
1880                 mbx->remote = 0;
1881                 break;
1882         case FM10K_STATE_OPEN:
1883                 /* flush any uncompleted work */
1884                 fm10k_sm_mbx_connect_reset(mbx);
1885                 break;
1886         case FM10K_STATE_CONNECT:
1887                 /* try connnecting at lower version */
1888                 if (mbx->remote) {
1889                         while (mbx->local > 1)
1890                                 mbx->local--;
1891                         mbx->remote = 0;
1892                 }
1893                 break;
1894         default:
1895                 break;
1896         }
1897
1898         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1899 }
1900
1901 /**
1902  *  fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1903  *  @mbx: pointer to mailbox
1904  *  @err: local error encountered
1905  *
1906  *  This function will interpret the error provided by err, and based on
1907  *  that it may set the error bit in the local message header
1908  **/
1909 STATIC void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1910 {
1911         /* only generate an error message for these types */
1912         switch (err) {
1913         case FM10K_MBX_ERR_TAIL:
1914         case FM10K_MBX_ERR_HEAD:
1915         case FM10K_MBX_ERR_SRC:
1916         case FM10K_MBX_ERR_SIZE:
1917         case FM10K_MBX_ERR_RSVD0:
1918                 break;
1919         default:
1920                 return;
1921         }
1922
1923         /* process it as though we received an error, and send error reply */
1924         fm10k_sm_mbx_process_error(mbx);
1925         fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1926 }
1927
1928 /**
1929  *  fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1930  *  @hw: pointer to hardware structure
1931  *  @mbx: pointer to mailbox
1932  *
1933  *  This function will dequeue one message from the Rx switch manager mailbox
1934  *  FIFO and place it in the Rx mailbox FIFO for processing by software.
1935  **/
1936 STATIC s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1937                                 struct fm10k_mbx_info *mbx,
1938                                 u16 tail)
1939 {
1940         /* reduce length by 1 to convert to a mask */
1941         u16 mbmem_len = mbx->mbmem_len - 1;
1942         s32 err;
1943
1944         DEBUGFUNC("fm10k_sm_mbx_receive");
1945
1946         /* push tail in front of head */
1947         if (tail < mbx->head)
1948                 tail += mbmem_len;
1949
1950         /* copy data to the Rx FIFO */
1951         err = fm10k_mbx_push_tail(hw, mbx, tail);
1952         if (err < 0)
1953                 return err;
1954
1955         /* process messages if we have received any */
1956         fm10k_mbx_dequeue_rx(hw, mbx);
1957
1958         /* guarantee head aligns with the end of the last message */
1959         mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1960         mbx->pushed = 0;
1961
1962         /* clear any extra bits left over since index adds 1 extra bit */
1963         if (mbx->head > mbmem_len)
1964                 mbx->head -= mbmem_len;
1965
1966         return err;
1967 }
1968
1969 /**
1970  *  fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1971  *  @hw: pointer to hardware structure
1972  *  @mbx: pointer to mailbox
1973  *
1974  *  This function will dequeue one message from the Tx mailbox FIFO and place
1975  *  it in the Tx switch manager mailbox FIFO for processing by hardware.
1976  **/
1977 STATIC void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1978                                   struct fm10k_mbx_info *mbx, u16 head)
1979 {
1980         struct fm10k_mbx_fifo *fifo = &mbx->tx;
1981         /* reduce length by 1 to convert to a mask */
1982         u16 mbmem_len = mbx->mbmem_len - 1;
1983         u16 tail_len, len = 0;
1984         u32 *msg;
1985
1986         DEBUGFUNC("fm10k_sm_mbx_transmit");
1987
1988         /* push head behind tail */
1989         if (mbx->tail < head)
1990                 head += mbmem_len;
1991
1992         fm10k_mbx_pull_head(hw, mbx, head);
1993
1994         /* determine msg aligned offset for end of buffer */
1995         do {
1996                 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1997                 tail_len = len;
1998                 len += FM10K_TLV_DWORD_LEN(*msg);
1999         } while ((len <= mbx->tail_len) && (len < mbmem_len));
2000
2001         /* guarantee we stop on a message boundary */
2002         if (mbx->tail_len > tail_len) {
2003                 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
2004                 mbx->tail_len = tail_len;
2005         }
2006
2007         /* clear any extra bits left over since index adds 1 extra bit */
2008         if (mbx->tail > mbmem_len)
2009                 mbx->tail -= mbmem_len;
2010 }
2011
2012 /**
2013  *  fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
2014  *  @mbx: pointer to mailbox
2015  *  @head: acknowledgement number
2016  *
2017  *  This function will generate an outgoing message based on the current
2018  *  mailbox state and the remote fifo head.  It will return the length
2019  *  of the outgoing message excluding header on success, and a negative value
2020  *  on error.
2021  **/
2022 STATIC void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
2023                                       struct fm10k_mbx_info *mbx, u16 head)
2024 {
2025         switch (mbx->state) {
2026         case FM10K_STATE_OPEN:
2027         case FM10K_STATE_DISCONNECT:
2028                 /* flush out Tx data */
2029                 fm10k_sm_mbx_transmit(hw, mbx, head);
2030
2031                 /* generate new header based on data */
2032                 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
2033                         fm10k_sm_mbx_create_data_hdr(mbx);
2034                 } else {
2035                         mbx->remote = 0;
2036                         fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2037                 }
2038                 break;
2039         case FM10K_STATE_CONNECT:
2040         case FM10K_STATE_CLOSED:
2041                 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
2042                 break;
2043         default:
2044                 break;
2045         }
2046 }
2047
2048 /**
2049  *  fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
2050  *  @hw: pointer to hardware structure
2051  *  @mbx: pointer to mailbox
2052  *
2053  *  This function is meant to respond to a request where the version data
2054  *  is set to 0.  As such we will either terminate the connection or go
2055  *  into the connect state in order to re-establish the connection.  This
2056  *  function can also be used to respond to an error as the connection
2057  *  resetting would also be a means of dealing with errors.
2058  **/
2059 STATIC void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2060                                        struct fm10k_mbx_info *mbx)
2061 {
2062         const enum fm10k_mbx_state state = mbx->state;
2063
2064         switch (state) {
2065         case FM10K_STATE_DISCONNECT:
2066                 /* drop remote connections and disconnect */
2067                 mbx->state = FM10K_STATE_CLOSED;
2068                 mbx->remote = 0;
2069                 mbx->local = 0;
2070                 break;
2071         case FM10K_STATE_OPEN:
2072                 /* flush any incomplete work */
2073                 fm10k_sm_mbx_connect_reset(mbx);
2074                 break;
2075         case FM10K_STATE_CONNECT:
2076                 /* Update remote value to match local value */
2077                 mbx->remote = mbx->local;
2078         default:
2079                 break;
2080         }
2081
2082         fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2083 }
2084
2085 /**
2086  *  fm10k_sm_mbx_process_version_1 - Process header with version == 1
2087  *  @hw: pointer to hardware structure
2088  *  @mbx: pointer to mailbox
2089  *
2090  *  This function is meant to process messages received when the remote
2091  *  mailbox is active.
2092  **/
2093 STATIC s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2094                                           struct fm10k_mbx_info *mbx)
2095 {
2096         const u32 *hdr = &mbx->mbx_hdr;
2097         u16 head, tail;
2098         s32 len;
2099
2100         /* pull all fields needed for verification */
2101         tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2102         head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2103
2104         /* if we are in connect and wanting version 1 then start up and go */
2105         if (mbx->state == FM10K_STATE_CONNECT) {
2106                 if (!mbx->remote)
2107                         goto send_reply;
2108                 if (mbx->remote != 1)
2109                         return FM10K_MBX_ERR_SRC;
2110
2111                 mbx->state = FM10K_STATE_OPEN;
2112         }
2113
2114         do {
2115                 /* abort on message size errors */
2116                 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2117                 if (len < 0)
2118                         return len;
2119
2120                 /* continue until we have flushed the Rx FIFO */
2121         } while (len);
2122
2123 send_reply:
2124         fm10k_sm_mbx_create_reply(hw, mbx, head);
2125
2126         return FM10K_SUCCESS;
2127 }
2128
2129 /**
2130  *  fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
2131  *  @hw: pointer to hardware structure
2132  *  @mbx: pointer to mailbox
2133  *
2134  *  This function will process incoming mailbox events and generate mailbox
2135  *  replies.  It will return a value indicating the number of DWORDs
2136  *  transmitted excluding header on success or a negative value on error.
2137  **/
2138 STATIC s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2139                                 struct fm10k_mbx_info *mbx)
2140 {
2141         s32 err;
2142
2143         DEBUGFUNC("fm10k_sm_mbx_process");
2144
2145         /* we do not read mailbox if closed */
2146         if (mbx->state == FM10K_STATE_CLOSED)
2147                 return FM10K_SUCCESS;
2148
2149         /* retrieve data from switch manager */
2150         err = fm10k_mbx_read(hw, mbx);
2151         if (err)
2152                 return err;
2153
2154         err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2155         if (err < 0)
2156                 goto fifo_err;
2157
2158         if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2159                 fm10k_sm_mbx_process_error(mbx);
2160                 goto fifo_err;
2161         }
2162
2163         switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2164         case 0:
2165                 fm10k_sm_mbx_process_reset(hw, mbx);
2166                 break;
2167         case FM10K_SM_MBX_VERSION:
2168                 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2169                 break;
2170         }
2171
2172 fifo_err:
2173         if (err < 0)
2174                 fm10k_sm_mbx_create_error_msg(mbx, err);
2175
2176         /* report data to switch manager */
2177         fm10k_mbx_write(hw, mbx);
2178
2179         return err;
2180 }
2181
2182 /**
2183  *  fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
2184  *  @hw: pointer to hardware structure
2185  *  @mbx: pointer to mailbox
2186  *  @msg_data: handlers for mailbox events
2187  *
2188  *  This function for now is used to stub out the PF/SM mailbox
2189  **/
2190 s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
2191                       const struct fm10k_msg_data *msg_data)
2192 {
2193         DEBUGFUNC("fm10k_sm_mbx_init");
2194         UNREFERENCED_1PARAMETER(hw);
2195
2196         mbx->mbx_reg = FM10K_GMBX;
2197         mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2198
2199         /* start out in closed state */
2200         mbx->state = FM10K_STATE_CLOSED;
2201
2202         /* validate layout of handlers before assigning them */
2203         if (fm10k_mbx_validate_handlers(msg_data))
2204                 return FM10K_ERR_PARAM;
2205
2206         /* initialize the message handlers */
2207         mbx->msg_data = msg_data;
2208
2209         /* start mailbox as timed out and let the reset_hw call
2210          * set the timeout value to begin communications
2211          */
2212         mbx->timeout = 0;
2213         mbx->usec_delay = FM10K_MBX_INIT_DELAY;
2214
2215         /* Split buffer for use by Tx/Rx FIFOs */
2216         mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2217         mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2218
2219         /* initialize the FIFOs, sizes are in 4 byte increments */
2220         fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2221         fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2222                         FM10K_MBX_RX_BUFFER_SIZE);
2223
2224         /* initialize function pointers */
2225         mbx->ops.connect = fm10k_sm_mbx_connect;
2226         mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2227         mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2228         mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2229         mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2230         mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2231         mbx->ops.process = fm10k_sm_mbx_process;
2232         mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2233
2234         return FM10K_SUCCESS;
2235 }