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