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