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