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