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