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