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