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