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