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