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