blob: 2609847bbdea8daa0b59ca046f7cad21bc6efddc [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
514/**
515 * fm10k_mbx_rx_ready - Indicates that a message is ready in the Rx FIFO
516 * @mbx: pointer to mailbox
517 *
518 * This function returns true if there is a message in the Rx FIFO to dequeue.
519 **/
520static bool fm10k_mbx_rx_ready(struct fm10k_mbx_info *mbx)
521{
522 u16 msg_size = fm10k_fifo_head_len(&mbx->rx);
523
524 return msg_size && (fm10k_fifo_used(&mbx->rx) >= msg_size);
525}
526
527/**
528 * fm10k_mbx_tx_ready - Indicates that the mailbox is in state ready for Tx
529 * @mbx: pointer to mailbox
530 * @len: verify free space is >= this value
531 *
532 * This function returns true if the mailbox is in a state ready to transmit.
533 **/
534static bool fm10k_mbx_tx_ready(struct fm10k_mbx_info *mbx, u16 len)
535{
536 u16 fifo_unused = fm10k_fifo_unused(&mbx->tx);
537
538 return (mbx->state == FM10K_STATE_OPEN) && (fifo_unused >= len);
539}
540
541/**
542 * fm10k_mbx_tx_complete - Indicates that the Tx FIFO has been emptied
543 * @mbx: pointer to mailbox
544 *
545 * This function returns true if the Tx FIFO is empty.
546 **/
547static bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
548{
549 return fm10k_fifo_empty(&mbx->tx);
550}
551
552/**
553 * fm10k_mbx_deqeueue_rx - Dequeues the message from the head in the Rx FIFO
554 * @hw: pointer to hardware structure
555 * @mbx: pointer to mailbox
556 *
557 * This function dequeues messages and hands them off to the tlv parser.
558 * It will return the number of messages processed when called.
559 **/
560static u16 fm10k_mbx_dequeue_rx(struct fm10k_hw *hw,
561 struct fm10k_mbx_info *mbx)
562{
563 struct fm10k_mbx_fifo *fifo = &mbx->rx;
564 s32 err;
565 u16 cnt;
566
567 /* parse Rx messages out of the Rx FIFO to empty it */
568 for (cnt = 0; !fm10k_fifo_empty(fifo); cnt++) {
569 err = fm10k_tlv_msg_parse(hw, fifo->buffer + fifo->head,
570 mbx, mbx->msg_data);
571 if (err < 0)
572 mbx->rx_parse_err++;
573
574 fm10k_fifo_head_drop(fifo);
575 }
576
577 /* shift remaining bytes back to start of FIFO */
578 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
579
580 /* shift head and tail based on the memory we moved */
581 fifo->tail -= fifo->head;
582 fifo->head = 0;
583
584 return cnt;
585}
586
587/**
588 * fm10k_mbx_enqueue_tx - Enqueues the message to the tail of the Tx FIFO
589 * @hw: pointer to hardware structure
590 * @mbx: pointer to mailbox
591 * @msg: message array to read
592 *
593 * This function enqueues a message up to the size specified by the length
594 * contained in the first DWORD of the message and will place at the tail
595 * of the FIFO. It will return 0 on success, or a negative value on error.
596 **/
597static s32 fm10k_mbx_enqueue_tx(struct fm10k_hw *hw,
598 struct fm10k_mbx_info *mbx, const u32 *msg)
599{
600 u32 countdown = mbx->timeout;
601 s32 err;
602
603 switch (mbx->state) {
604 case FM10K_STATE_CLOSED:
605 case FM10K_STATE_DISCONNECT:
606 return FM10K_MBX_ERR_NO_MBX;
607 default:
608 break;
609 }
610
611 /* enqueue the message on the Tx FIFO */
612 err = fm10k_fifo_enqueue(&mbx->tx, msg);
613
614 /* if it failed give the FIFO a chance to drain */
615 while (err && countdown) {
616 countdown--;
617 udelay(mbx->udelay);
618 mbx->ops.process(hw, mbx);
619 err = fm10k_fifo_enqueue(&mbx->tx, msg);
620 }
621
622 /* if we failed trhead the error */
623 if (err) {
624 mbx->timeout = 0;
625 mbx->tx_busy++;
626 }
627
628 /* begin processing message, ignore errors as this is just meant
629 * to start the mailbox flow so we are not concerned if there
630 * is a bad error, or the mailbox is already busy with a request
631 */
632 if (!mbx->tail_len)
633 mbx->ops.process(hw, mbx);
634
635 return 0;
636}
637
638/**
639 * fm10k_mbx_read - Copies the mbmem to local message buffer
640 * @hw: pointer to hardware structure
641 * @mbx: pointer to mailbox
642 *
643 * This function copies the message from the mbmem to the message array
644 **/
645static s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
646{
647 /* only allow one reader in here at a time */
648 if (mbx->mbx_hdr)
649 return FM10K_MBX_ERR_BUSY;
650
651 /* read to capture initial interrupt bits */
652 if (fm10k_read_reg(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
653 mbx->mbx_lock = FM10K_MBX_ACK;
654
655 /* write back interrupt bits to clear */
656 fm10k_write_reg(hw, mbx->mbx_reg,
657 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
658
659 /* read remote header */
660 mbx->mbx_hdr = fm10k_read_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
661
662 return 0;
663}
664
665/**
666 * fm10k_mbx_write - Copies the local message buffer to mbmem
667 * @hw: pointer to hardware structure
668 * @mbx: pointer to mailbox
669 *
670 * This function copies the message from the the message array to mbmem
671 **/
672static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
673{
674 u32 mbmem = mbx->mbmem_reg;
675
676 /* write new msg header to notify recepient of change */
677 fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
678
679 /* write mailbox to sent interrupt */
680 if (mbx->mbx_lock)
681 fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock);
682
683 /* we no longer are using the header so free it */
684 mbx->mbx_hdr = 0;
685 mbx->mbx_lock = 0;
686}
687
688/**
689 * fm10k_mbx_reset_work- Reset internal pointers for any pending work
690 * @mbx: pointer to mailbox
691 *
692 * This function will reset all internal pointers so any work in progress
693 * is dropped. This call should occur every time we transition from the
694 * open state to the connect state.
695 **/
696static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
697{
698 /* reset our outgoing max size back to Rx limits */
699 mbx->max_size = mbx->rx.size - 1;
700
701 /* just do a quick resysnc to start of message */
702 mbx->pushed = 0;
703 mbx->pulled = 0;
704 mbx->tail_len = 0;
705 mbx->head_len = 0;
706 mbx->rx.tail = 0;
707 mbx->rx.head = 0;
708}
709
710/**
711 * fm10k_mbx_update_max_size - Update the max_size and drop any large messages
712 * @mbx: pointer to mailbox
713 * @size: new value for max_size
714 *
715 * This function will update the max_size value and drop any outgoing messages
716 * from the head of the Tx FIFO that are larger than max_size.
717 **/
718static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
719{
720 u16 len;
721
722 mbx->max_size = size;
723
724 /* flush any oversized messages from the queue */
725 for (len = fm10k_fifo_head_len(&mbx->tx);
726 len > size;
727 len = fm10k_fifo_head_len(&mbx->tx)) {
728 fm10k_fifo_head_drop(&mbx->tx);
729 mbx->tx_dropped++;
730 }
731}
732
733/**
734 * fm10k_mbx_validate_handlers - Validate layout of message parsing data
735 * @msg_data: handlers for mailbox events
736 *
737 * This function validates the layout of the message parsing data. This
738 * should be mostly static, but it is important to catch any errors that
739 * are made when constructing the parsers.
740 **/
741static s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
742{
743 const struct fm10k_tlv_attr *attr;
744 unsigned int id;
745
746 /* Allow NULL mailboxes that transmit but don't receive */
747 if (!msg_data)
748 return 0;
749
750 while (msg_data->id != FM10K_TLV_ERROR) {
751 /* all messages should have a function handler */
752 if (!msg_data->func)
753 return FM10K_ERR_PARAM;
754
755 /* parser is optional */
756 attr = msg_data->attr;
757 if (attr) {
758 while (attr->id != FM10K_TLV_ERROR) {
759 id = attr->id;
760 attr++;
761 /* ID should always be increasing */
762 if (id >= attr->id)
763 return FM10K_ERR_PARAM;
764 /* ID should fit in results array */
765 if (id >= FM10K_TLV_RESULTS_MAX)
766 return FM10K_ERR_PARAM;
767 }
768
769 /* verify terminator is in the list */
770 if (attr->id != FM10K_TLV_ERROR)
771 return FM10K_ERR_PARAM;
772 }
773
774 id = msg_data->id;
775 msg_data++;
776 /* ID should always be increasing */
777 if (id >= msg_data->id)
778 return FM10K_ERR_PARAM;
779 }
780
781 /* verify terminator is in the list */
782 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
783 return FM10K_ERR_PARAM;
784
785 return 0;
786}
787
788/**
789 * fm10k_mbx_register_handlers - Register a set of handler ops for mailbox
790 * @mbx: pointer to mailbox
791 * @msg_data: handlers for mailbox events
792 *
793 * This function associates a set of message handling ops with a mailbox.
794 **/
795static s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
796 const struct fm10k_msg_data *msg_data)
797{
798 /* validate layout of handlers before assigning them */
799 if (fm10k_mbx_validate_handlers(msg_data))
800 return FM10K_ERR_PARAM;
801
802 /* initialize the message handlers */
803 mbx->msg_data = msg_data;
804
805 return 0;
806}
807
808/**
809 * fm10k_sm_mbx_create_data_hdr - Generate a mailbox header for local FIFO
810 * @mbx: pointer to mailbox
811 *
812 * This function returns a connection mailbox header
813 **/
814static void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
815{
816 if (mbx->tail_len)
817 mbx->mbx_lock |= FM10K_MBX_REQ;
818
819 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
820 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
821 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
822}
823
824/**
825 * fm10k_sm_mbx_create_connect_hdr - Generate a mailbox header for local FIFO
826 * @mbx: pointer to mailbox
827 * @err: error flags to report if any
828 *
829 * This function returns a connection mailbox header
830 **/
831static void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
832{
833 if (mbx->local)
834 mbx->mbx_lock |= FM10K_MBX_REQ;
835
836 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
837 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
838 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
839 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
840}
841
842/**
843 * fm10k_sm_mbx_connect_reset - Reset following request for reset
844 * @mbx: pointer to mailbox
845 *
846 * This function resets the mailbox to a just connected state
847 **/
848static void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
849{
850 /* flush any uncompleted work */
851 fm10k_mbx_reset_work(mbx);
852
853 /* set local version to max and remote version to 0 */
854 mbx->local = FM10K_SM_MBX_VERSION;
855 mbx->remote = 0;
856
857 /* initalize tail and head */
858 mbx->tail = 1;
859 mbx->head = 1;
860
861 /* reset state back to connect */
862 mbx->state = FM10K_STATE_CONNECT;
863}
864
865/**
866 * fm10k_sm_mbx_connect - Start switch manager mailbox connection
867 * @hw: pointer to hardware structure
868 * @mbx: pointer to mailbox
869 *
870 * This function will initiate a mailbox connection with the switch
871 * manager. To do this it will first disconnect the mailbox, and then
872 * reconnect it in order to complete a reset of the mailbox.
873 *
874 * This function will return an error if the mailbox has not been initiated
875 * or is currently in use.
876 **/
877static s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
878{
879 /* we cannot connect an uninitialized mailbox */
880 if (!mbx->rx.buffer)
881 return FM10K_MBX_ERR_NO_SPACE;
882
883 /* we cannot connect an already connected mailbox */
884 if (mbx->state != FM10K_STATE_CLOSED)
885 return FM10K_MBX_ERR_BUSY;
886
887 /* mailbox timeout can now become active */
888 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
889
890 /* Place mbx in ready to connect state */
891 mbx->state = FM10K_STATE_CONNECT;
892 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
893
894 /* reset interface back to connect */
895 fm10k_sm_mbx_connect_reset(mbx);
896
897 /* enable interrupt and notify other party of new message */
898 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
899 FM10K_MBX_INTERRUPT_ENABLE;
900
901 /* generate and load connect header into mailbox */
902 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
903 fm10k_mbx_write(hw, mbx);
904
905 /* enable interrupt and notify other party of new message */
906
907 return 0;
908}
909
910/**
911 * fm10k_sm_mbx_disconnect - Shutdown mailbox connection
912 * @hw: pointer to hardware structure
913 * @mbx: pointer to mailbox
914 *
915 * This function will shut down the mailbox. It places the mailbox first
916 * in the disconnect state, it then allows up to a predefined timeout for
917 * the mailbox to transition to close on its own. If this does not occur
918 * then the mailbox will be forced into the closed state.
919 *
920 * Any mailbox transactions not completed before calling this function
921 * are not guaranteed to complete and may be dropped.
922 **/
923static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
924 struct fm10k_mbx_info *mbx)
925{
926 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
927
928 /* Place mbx in ready to disconnect state */
929 mbx->state = FM10K_STATE_DISCONNECT;
930
931 /* trigger interrupt to start shutdown process */
932 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
933 FM10K_MBX_INTERRUPT_DISABLE);
934 do {
935 udelay(FM10K_MBX_POLL_DELAY);
936 mbx->ops.process(hw, mbx);
937 timeout -= FM10K_MBX_POLL_DELAY;
938 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
939
940 /* in case we didn't close just force the mailbox into shutdown */
941 mbx->state = FM10K_STATE_CLOSED;
942 mbx->remote = 0;
943 fm10k_mbx_reset_work(mbx);
944 fm10k_mbx_update_max_size(mbx, 0);
945
946 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
947}
948
949/**
950 * fm10k_mbx_validate_fifo_hdr - Validate fields in the remote FIFO header
951 * @mbx: pointer to mailbox
952 *
953 * This function will parse up the fields in the mailbox header and return
954 * an error if the header contains any of a number of invalid configurations
955 * including unrecognized offsets or version numbers.
956 **/
957static s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
958{
959 const u32 *hdr = &mbx->mbx_hdr;
960 u16 tail, head, ver;
961
962 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
963 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
964 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
965
966 switch (ver) {
967 case 0:
968 break;
969 case FM10K_SM_MBX_VERSION:
970 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
971 return FM10K_MBX_ERR_HEAD;
972 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
973 return FM10K_MBX_ERR_TAIL;
974 if (mbx->tail < head)
975 head += mbx->mbmem_len - 1;
976 if (tail < mbx->head)
977 tail += mbx->mbmem_len - 1;
978 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
979 return FM10K_MBX_ERR_HEAD;
980 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
981 break;
982 return FM10K_MBX_ERR_TAIL;
983 default:
984 return FM10K_MBX_ERR_SRC;
985 }
986
987 return 0;
988}
989
990/**
991 * fm10k_sm_mbx_process_error - Process header with error flag set
992 * @mbx: pointer to mailbox
993 *
994 * This function is meant to respond to a request where the error flag
995 * is set. As a result we will terminate a connection if one is present
996 * and fall back into the reset state with a connection header of version
997 * 0 (RESET).
998 **/
999static void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1000{
1001 const enum fm10k_mbx_state state = mbx->state;
1002
1003 switch (state) {
1004 case FM10K_STATE_DISCONNECT:
1005 /* if there is an error just disconnect */
1006 mbx->remote = 0;
1007 break;
1008 case FM10K_STATE_OPEN:
1009 /* flush any uncompleted work */
1010 fm10k_sm_mbx_connect_reset(mbx);
1011 break;
1012 case FM10K_STATE_CONNECT:
1013 /* try connnecting at lower version */
1014 if (mbx->remote) {
1015 while (mbx->local > 1)
1016 mbx->local--;
1017 mbx->remote = 0;
1018 }
1019 break;
1020 default:
1021 break;
1022 }
1023
1024 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1025}
1026
1027/**
1028 * fm10k_sm_mbx_create_error_message - Process an error in FIFO hdr
1029 * @mbx: pointer to mailbox
1030 * @err: local error encountered
1031 *
1032 * This function will interpret the error provided by err, and based on
1033 * that it may set the error bit in the local message header
1034 **/
1035static void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1036{
1037 /* only generate an error message for these types */
1038 switch (err) {
1039 case FM10K_MBX_ERR_TAIL:
1040 case FM10K_MBX_ERR_HEAD:
1041 case FM10K_MBX_ERR_SRC:
1042 case FM10K_MBX_ERR_SIZE:
1043 case FM10K_MBX_ERR_RSVD0:
1044 break;
1045 default:
1046 return;
1047 }
1048
1049 /* process it as though we received an error, and send error reply */
1050 fm10k_sm_mbx_process_error(mbx);
1051 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1052}
1053
1054/**
1055 * fm10k_sm_mbx_receive - Take message from Rx mailbox FIFO and put it in Rx
1056 * @hw: pointer to hardware structure
1057 * @mbx: pointer to mailbox
1058 *
1059 * This function will dequeue one message from the Rx switch manager mailbox
1060 * FIFO and place it in the Rx mailbox FIFO for processing by software.
1061 **/
1062static s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1063 struct fm10k_mbx_info *mbx,
1064 u16 tail)
1065{
1066 /* reduce length by 1 to convert to a mask */
1067 u16 mbmem_len = mbx->mbmem_len - 1;
1068 s32 err;
1069
1070 /* push tail in front of head */
1071 if (tail < mbx->head)
1072 tail += mbmem_len;
1073
1074 /* copy data to the Rx FIFO */
1075 err = fm10k_mbx_push_tail(hw, mbx, tail);
1076 if (err < 0)
1077 return err;
1078
1079 /* process messages if we have received any */
1080 fm10k_mbx_dequeue_rx(hw, mbx);
1081
1082 /* guarantee head aligns with the end of the last message */
1083 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1084 mbx->pushed = 0;
1085
1086 /* clear any extra bits left over since index adds 1 extra bit */
1087 if (mbx->head > mbmem_len)
1088 mbx->head -= mbmem_len;
1089
1090 return err;
1091}
1092
1093/**
1094 * fm10k_sm_mbx_transmit - Take message from Tx and put it in Tx mailbox FIFO
1095 * @hw: pointer to hardware structure
1096 * @mbx: pointer to mailbox
1097 *
1098 * This function will dequeue one message from the Tx mailbox FIFO and place
1099 * it in the Tx switch manager mailbox FIFO for processing by hardware.
1100 **/
1101static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1102 struct fm10k_mbx_info *mbx, u16 head)
1103{
1104 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1105 /* reduce length by 1 to convert to a mask */
1106 u16 mbmem_len = mbx->mbmem_len - 1;
1107 u16 tail_len, len = 0;
1108 u32 *msg;
1109
1110 /* push head behind tail */
1111 if (mbx->tail < head)
1112 head += mbmem_len;
1113
1114 fm10k_mbx_pull_head(hw, mbx, head);
1115
1116 /* determine msg aligned offset for end of buffer */
1117 do {
1118 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1119 tail_len = len;
1120 len += FM10K_TLV_DWORD_LEN(*msg);
1121 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1122
1123 /* guarantee we stop on a message boundary */
1124 if (mbx->tail_len > tail_len) {
1125 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1126 mbx->tail_len = tail_len;
1127 }
1128
1129 /* clear any extra bits left over since index adds 1 extra bit */
1130 if (mbx->tail > mbmem_len)
1131 mbx->tail -= mbmem_len;
1132}
1133
1134/**
1135 * fm10k_sm_mbx_create_reply - Generate reply based on state and remote head
1136 * @mbx: pointer to mailbox
1137 * @head: acknowledgement number
1138 *
1139 * This function will generate an outgoing message based on the current
1140 * mailbox state and the remote fifo head. It will return the length
1141 * of the outgoing message excluding header on success, and a negative value
1142 * on error.
1143 **/
1144static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1145 struct fm10k_mbx_info *mbx, u16 head)
1146{
1147 switch (mbx->state) {
1148 case FM10K_STATE_OPEN:
1149 case FM10K_STATE_DISCONNECT:
1150 /* flush out Tx data */
1151 fm10k_sm_mbx_transmit(hw, mbx, head);
1152
1153 /* generate new header based on data */
1154 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1155 fm10k_sm_mbx_create_data_hdr(mbx);
1156 } else {
1157 mbx->remote = 0;
1158 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1159 }
1160 break;
1161 case FM10K_STATE_CONNECT:
1162 case FM10K_STATE_CLOSED:
1163 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1164 break;
1165 default:
1166 break;
1167 }
1168}
1169
1170/**
1171 * fm10k_sm_mbx_process_reset - Process header with version == 0 (RESET)
1172 * @hw: pointer to hardware structure
1173 * @mbx: pointer to mailbox
1174 *
1175 * This function is meant to respond to a request where the version data
1176 * is set to 0. As such we will either terminate the connection or go
1177 * into the connect state in order to re-establish the connection. This
1178 * function can also be used to respond to an error as the connection
1179 * resetting would also be a means of dealing with errors.
1180 **/
1181static void fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
1182 struct fm10k_mbx_info *mbx)
1183{
1184 const enum fm10k_mbx_state state = mbx->state;
1185
1186 switch (state) {
1187 case FM10K_STATE_DISCONNECT:
1188 /* drop remote connections and disconnect */
1189 mbx->state = FM10K_STATE_CLOSED;
1190 mbx->remote = 0;
1191 mbx->local = 0;
1192 break;
1193 case FM10K_STATE_OPEN:
1194 /* flush any incomplete work */
1195 fm10k_sm_mbx_connect_reset(mbx);
1196 break;
1197 case FM10K_STATE_CONNECT:
1198 /* Update remote value to match local value */
1199 mbx->remote = mbx->local;
1200 default:
1201 break;
1202 }
1203
1204 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
1205}
1206
1207/**
1208 * fm10k_sm_mbx_process_version_1 - Process header with version == 1
1209 * @hw: pointer to hardware structure
1210 * @mbx: pointer to mailbox
1211 *
1212 * This function is meant to process messages received when the remote
1213 * mailbox is active.
1214 **/
1215static s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
1216 struct fm10k_mbx_info *mbx)
1217{
1218 const u32 *hdr = &mbx->mbx_hdr;
1219 u16 head, tail;
1220 s32 len;
1221
1222 /* pull all fields needed for verification */
1223 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1224 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1225
1226 /* if we are in connect and wanting version 1 then start up and go */
1227 if (mbx->state == FM10K_STATE_CONNECT) {
1228 if (!mbx->remote)
1229 goto send_reply;
1230 if (mbx->remote != 1)
1231 return FM10K_MBX_ERR_SRC;
1232
1233 mbx->state = FM10K_STATE_OPEN;
1234 }
1235
1236 do {
1237 /* abort on message size errors */
1238 len = fm10k_sm_mbx_receive(hw, mbx, tail);
1239 if (len < 0)
1240 return len;
1241
1242 /* continue until we have flushed the Rx FIFO */
1243 } while (len);
1244
1245send_reply:
1246 fm10k_sm_mbx_create_reply(hw, mbx, head);
1247
1248 return 0;
1249}
1250
1251/**
1252 * fm10k_sm_mbx_process - Process mailbox switch mailbox interrupt
1253 * @hw: pointer to hardware structure
1254 * @mbx: pointer to mailbox
1255 *
1256 * This function will process incoming mailbox events and generate mailbox
1257 * replies. It will return a value indicating the number of DWORDs
1258 * transmitted excluding header on success or a negative value on error.
1259 **/
1260static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
1261 struct fm10k_mbx_info *mbx)
1262{
1263 s32 err;
1264
1265 /* we do not read mailbox if closed */
1266 if (mbx->state == FM10K_STATE_CLOSED)
1267 return 0;
1268
1269 /* retrieve data from switch manager */
1270 err = fm10k_mbx_read(hw, mbx);
1271 if (err)
1272 return err;
1273
1274 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
1275 if (err < 0)
1276 goto fifo_err;
1277
1278 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
1279 fm10k_sm_mbx_process_error(mbx);
1280 goto fifo_err;
1281 }
1282
1283 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
1284 case 0:
1285 fm10k_sm_mbx_process_reset(hw, mbx);
1286 break;
1287 case FM10K_SM_MBX_VERSION:
1288 err = fm10k_sm_mbx_process_version_1(hw, mbx);
1289 break;
1290 }
1291
1292fifo_err:
1293 if (err < 0)
1294 fm10k_sm_mbx_create_error_msg(mbx, err);
1295
1296 /* report data to switch manager */
1297 fm10k_mbx_write(hw, mbx);
1298
1299 return err;
1300}
1301
1302/**
1303 * fm10k_sm_mbx_init - Initialize mailbox memory for PF/SM mailbox
1304 * @hw: pointer to hardware structure
1305 * @mbx: pointer to mailbox
1306 * @msg_data: handlers for mailbox events
1307 *
1308 * This function for now is used to stub out the PF/SM mailbox
1309 **/
1310s32 fm10k_sm_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1311 const struct fm10k_msg_data *msg_data)
1312{
1313 mbx->mbx_reg = FM10K_GMBX;
1314 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
1315 /* start out in closed state */
1316 mbx->state = FM10K_STATE_CLOSED;
1317
1318 /* validate layout of handlers before assigning them */
1319 if (fm10k_mbx_validate_handlers(msg_data))
1320 return FM10K_ERR_PARAM;
1321
1322 /* initialize the message handlers */
1323 mbx->msg_data = msg_data;
1324
1325 /* start mailbox as timed out and let the reset_hw call
1326 * set the timeout value to begin communications
1327 */
1328 mbx->timeout = 0;
1329 mbx->udelay = FM10K_MBX_INIT_DELAY;
1330
1331 /* Split buffer for use by Tx/Rx FIFOs */
1332 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1333 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
1334
1335 /* initialize the FIFOs, sizes are in 4 byte increments */
1336 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1337 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1338 FM10K_MBX_RX_BUFFER_SIZE);
1339
1340 /* initialize function pointers */
1341 mbx->ops.connect = fm10k_sm_mbx_connect;
1342 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
1343 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1344 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1345 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1346 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1347 mbx->ops.process = fm10k_sm_mbx_process;
1348 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1349
1350 return 0;
1351}