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