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