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