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 }
2126