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