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