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