This source file includes following definitions.
- fm10k_fifo_init
- fm10k_fifo_used
- fm10k_fifo_unused
- fm10k_fifo_empty
- fm10k_fifo_head_offset
- fm10k_fifo_tail_offset
- fm10k_fifo_head_len
- fm10k_fifo_head_drop
- fm10k_fifo_drop_all
- fm10k_mbx_index_len
- fm10k_mbx_tail_add
- fm10k_mbx_tail_sub
- fm10k_mbx_head_add
- fm10k_mbx_head_sub
- fm10k_mbx_pushed_tail_len
- fm10k_fifo_write_copy
- fm10k_fifo_enqueue
- fm10k_mbx_validate_msg_size
- fm10k_mbx_write_copy
- fm10k_mbx_pull_head
- fm10k_mbx_read_copy
- fm10k_mbx_push_tail
- fm10k_crc_16b
- fm10k_fifo_crc
- fm10k_mbx_update_local_crc
- fm10k_mbx_verify_remote_crc
- fm10k_mbx_rx_ready
- fm10k_mbx_tx_ready
- fm10k_mbx_tx_complete
- fm10k_mbx_dequeue_rx
- fm10k_mbx_enqueue_tx
- fm10k_mbx_read
- fm10k_mbx_write
- fm10k_mbx_create_connect_hdr
- fm10k_mbx_create_data_hdr
- fm10k_mbx_create_disconnect_hdr
- fm10k_mbx_create_fake_disconnect_hdr
- fm10k_mbx_create_error_msg
- fm10k_mbx_validate_msg_hdr
- fm10k_mbx_create_reply
- fm10k_mbx_reset_work
- fm10k_mbx_update_max_size
- fm10k_mbx_connect_reset
- fm10k_mbx_process_connect
- fm10k_mbx_process_data
- fm10k_mbx_process_disconnect
- fm10k_mbx_process_error
- fm10k_mbx_process
- fm10k_mbx_disconnect
- fm10k_mbx_connect
- fm10k_mbx_validate_handlers
- fm10k_mbx_register_handlers
- fm10k_pfvf_mbx_init
- fm10k_sm_mbx_create_data_hdr
- fm10k_sm_mbx_create_connect_hdr
- fm10k_sm_mbx_connect_reset
- fm10k_sm_mbx_connect
- fm10k_sm_mbx_disconnect
- fm10k_sm_mbx_validate_fifo_hdr
- fm10k_sm_mbx_process_error
- fm10k_sm_mbx_create_error_msg
- fm10k_sm_mbx_receive
- fm10k_sm_mbx_transmit
- fm10k_sm_mbx_create_reply
- fm10k_sm_mbx_process_reset
- fm10k_sm_mbx_process_version_1
- fm10k_sm_mbx_process
- fm10k_sm_mbx_init
1
2
3
4 #include "fm10k_common.h"
5
6
7
8
9
10
11
12 static void fm10k_fifo_init(struct fm10k_mbx_fifo *fifo, u32 *buffer, u16 size)
13 {
14 fifo->buffer = buffer;
15 fifo->size = size;
16 fifo->head = 0;
17 fifo->tail = 0;
18 }
19
20
21
22
23
24
25
26 static u16 fm10k_fifo_used(struct fm10k_mbx_fifo *fifo)
27 {
28 return fifo->tail - fifo->head;
29 }
30
31
32
33
34
35
36
37 static u16 fm10k_fifo_unused(struct fm10k_mbx_fifo *fifo)
38 {
39 return fifo->size + fifo->head - fifo->tail;
40 }
41
42
43
44
45
46
47
48 static bool fm10k_fifo_empty(struct fm10k_mbx_fifo *fifo)
49 {
50 return fifo->head == fifo->tail;
51 }
52
53
54
55
56
57
58
59
60 static u16 fm10k_fifo_head_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
61 {
62 return (fifo->head + offset) & (fifo->size - 1);
63 }
64
65
66
67
68
69
70
71
72 static u16 fm10k_fifo_tail_offset(struct fm10k_mbx_fifo *fifo, u16 offset)
73 {
74 return (fifo->tail + offset) & (fifo->size - 1);
75 }
76
77
78
79
80
81
82
83 static u16 fm10k_fifo_head_len(struct fm10k_mbx_fifo *fifo)
84 {
85 u32 *head = fifo->buffer + fm10k_fifo_head_offset(fifo, 0);
86
87
88 if (fm10k_fifo_empty(fifo))
89 return 0;
90
91
92 return FM10K_TLV_DWORD_LEN(*head);
93 }
94
95
96
97
98
99
100
101 static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo)
102 {
103 u16 len = fm10k_fifo_head_len(fifo);
104
105
106 fifo->head += len;
107
108 return len;
109 }
110
111
112
113
114
115
116
117
118 static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo)
119 {
120 fifo->head = fifo->tail;
121 }
122
123
124
125
126
127
128
129
130
131
132 static u16 fm10k_mbx_index_len(struct fm10k_mbx_info *mbx, u16 head, u16 tail)
133 {
134 u16 len = tail - head;
135
136
137 if (len > tail)
138 len -= 2;
139
140 return len & ((mbx->mbmem_len << 1) - 1);
141 }
142
143
144
145
146
147
148
149
150
151 static u16 fm10k_mbx_tail_add(struct fm10k_mbx_info *mbx, u16 offset)
152 {
153 u16 tail = (mbx->tail + offset + 1) & ((mbx->mbmem_len << 1) - 1);
154
155
156 return (tail > mbx->tail) ? --tail : ++tail;
157 }
158
159
160
161
162
163
164
165
166
167 static u16 fm10k_mbx_tail_sub(struct fm10k_mbx_info *mbx, u16 offset)
168 {
169 u16 tail = (mbx->tail - offset - 1) & ((mbx->mbmem_len << 1) - 1);
170
171
172 return (tail < mbx->tail) ? ++tail : --tail;
173 }
174
175
176
177
178
179
180
181
182
183 static u16 fm10k_mbx_head_add(struct fm10k_mbx_info *mbx, u16 offset)
184 {
185 u16 head = (mbx->head + offset + 1) & ((mbx->mbmem_len << 1) - 1);
186
187
188 return (head > mbx->head) ? --head : ++head;
189 }
190
191
192
193
194
195
196
197
198
199 static u16 fm10k_mbx_head_sub(struct fm10k_mbx_info *mbx, u16 offset)
200 {
201 u16 head = (mbx->head - offset - 1) & ((mbx->mbmem_len << 1) - 1);
202
203
204 return (head < mbx->head) ? ++head : --head;
205 }
206
207
208
209
210
211
212
213
214 static u16 fm10k_mbx_pushed_tail_len(struct fm10k_mbx_info *mbx)
215 {
216 u32 *tail = mbx->rx.buffer + fm10k_fifo_tail_offset(&mbx->rx, 0);
217
218
219 if (!mbx->pushed)
220 return 0;
221
222 return FM10K_TLV_DWORD_LEN(*tail);
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236 static void fm10k_fifo_write_copy(struct fm10k_mbx_fifo *fifo,
237 const u32 *msg, u16 tail_offset, u16 len)
238 {
239 u16 end = fm10k_fifo_tail_offset(fifo, tail_offset);
240 u32 *tail = fifo->buffer + end;
241
242
243 end = fifo->size - end;
244
245
246 if (end < len)
247 memcpy(fifo->buffer, msg + end, (len - end) << 2);
248 else
249 end = len;
250
251
252 memcpy(tail, msg, end << 2);
253 }
254
255
256
257
258
259
260
261
262
263
264 static s32 fm10k_fifo_enqueue(struct fm10k_mbx_fifo *fifo, const u32 *msg)
265 {
266 u16 len = FM10K_TLV_DWORD_LEN(*msg);
267
268
269 if (len > fifo->size)
270 return FM10K_MBX_ERR_SIZE;
271
272
273 if (len > fm10k_fifo_unused(fifo))
274 return FM10K_MBX_ERR_NO_SPACE;
275
276
277 fm10k_fifo_write_copy(fifo, msg, 0, len);
278
279
280 wmb();
281
282
283 fifo->tail += len;
284
285 return 0;
286 }
287
288
289
290
291
292
293
294
295
296 static u16 fm10k_mbx_validate_msg_size(struct fm10k_mbx_info *mbx, u16 len)
297 {
298 struct fm10k_mbx_fifo *fifo = &mbx->rx;
299 u16 total_len = 0, msg_len;
300
301
302 len += mbx->pushed;
303
304
305 do {
306 u32 *msg;
307
308 msg = fifo->buffer + fm10k_fifo_tail_offset(fifo, total_len);
309 msg_len = FM10K_TLV_DWORD_LEN(*msg);
310 total_len += msg_len;
311 } while (total_len < len);
312
313
314 if ((len < total_len) && (msg_len <= mbx->max_size))
315 return 0;
316
317
318 return (len < total_len) ? len : (len - total_len);
319 }
320
321
322
323
324
325
326
327
328
329
330 static void fm10k_mbx_write_copy(struct fm10k_hw *hw,
331 struct fm10k_mbx_info *mbx)
332 {
333 struct fm10k_mbx_fifo *fifo = &mbx->tx;
334 u32 mbmem = mbx->mbmem_reg;
335 u32 *head = fifo->buffer;
336 u16 end, len, tail, mask;
337
338 if (!mbx->tail_len)
339 return;
340
341
342 mask = mbx->mbmem_len - 1;
343 len = mbx->tail_len;
344 tail = fm10k_mbx_tail_sub(mbx, len);
345 if (tail > mask)
346 tail++;
347
348
349 end = fm10k_fifo_head_offset(fifo, mbx->pulled);
350 head += end;
351
352
353 rmb();
354
355
356 for (end = fifo->size - end; len; head = fifo->buffer) {
357 do {
358
359 tail &= mask;
360 if (!tail)
361 tail++;
362
363 mbx->tx_mbmem_pulled++;
364
365
366 fm10k_write_reg(hw, mbmem + tail++, *(head++));
367 } while (--len && --end);
368 }
369 }
370
371
372
373
374
375
376
377
378
379
380
381
382 static void fm10k_mbx_pull_head(struct fm10k_hw *hw,
383 struct fm10k_mbx_info *mbx, u16 head)
384 {
385 u16 mbmem_len, len, ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
386 struct fm10k_mbx_fifo *fifo = &mbx->tx;
387
388
389 mbx->pulled += mbx->tail_len - ack;
390
391
392 mbmem_len = mbx->mbmem_len - 1;
393 len = fm10k_fifo_used(fifo) - mbx->pulled;
394 if (len > mbmem_len)
395 len = mbmem_len;
396
397
398 mbx->tail = fm10k_mbx_tail_add(mbx, len - ack);
399 mbx->tail_len = len;
400
401
402 for (len = fm10k_fifo_head_len(fifo);
403 len && (mbx->pulled >= len);
404 len = fm10k_fifo_head_len(fifo)) {
405 mbx->pulled -= fm10k_fifo_head_drop(fifo);
406 mbx->tx_messages++;
407 mbx->tx_dwords += len;
408 }
409
410
411 fm10k_mbx_write_copy(hw, mbx);
412 }
413
414
415
416
417
418
419
420
421
422
423 static void fm10k_mbx_read_copy(struct fm10k_hw *hw,
424 struct fm10k_mbx_info *mbx)
425 {
426 struct fm10k_mbx_fifo *fifo = &mbx->rx;
427 u32 mbmem = mbx->mbmem_reg ^ mbx->mbmem_len;
428 u32 *tail = fifo->buffer;
429 u16 end, len, head;
430
431
432 len = mbx->head_len;
433 head = fm10k_mbx_head_sub(mbx, len);
434 if (head >= mbx->mbmem_len)
435 head++;
436
437
438 end = fm10k_fifo_tail_offset(fifo, mbx->pushed);
439 tail += end;
440
441
442 for (end = fifo->size - end; len; tail = fifo->buffer) {
443 do {
444
445 head &= mbx->mbmem_len - 1;
446 if (!head)
447 head++;
448
449 mbx->rx_mbmem_pushed++;
450
451
452 *(tail++) = fm10k_read_reg(hw, mbmem + head++);
453 } while (--len && --end);
454 }
455
456
457 wmb();
458 }
459
460
461
462
463
464
465
466
467
468
469
470
471 static 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
479 len = fm10k_fifo_unused(fifo) - mbx->pushed;
480 if (len > seq)
481 len = seq;
482
483
484 mbx->head = fm10k_mbx_head_add(mbx, len);
485 mbx->head_len = len;
486
487
488 if (!len)
489 return 0;
490
491
492 fm10k_mbx_read_copy(hw, mbx);
493
494
495 if (fm10k_mbx_validate_msg_size(mbx, len))
496 return FM10K_MBX_ERR_SIZE;
497
498
499 mbx->pushed += len;
500
501
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 static 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
551
552
553
554
555
556
557
558
559
560 static 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
581
582
583
584
585
586
587
588 static 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
594 offset = fifo->size - offset;
595
596
597 if (offset < len) {
598 seed = fm10k_crc_16b(data, seed, offset * 2);
599 data = fifo->buffer;
600 len -= offset;
601 }
602
603
604 return fm10k_crc_16b(data, seed, len * 2);
605 }
606
607
608
609
610
611
612
613
614
615
616
617 static 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
622 head = fm10k_fifo_head_offset(&mbx->tx, mbx->pulled);
623
624
625 mbx->local = fm10k_fifo_crc(&mbx->tx, head, len, mbx->local);
626 }
627
628
629
630
631
632
633
634
635
636
637
638 static 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
646 if (len)
647 mbx->remote = fm10k_fifo_crc(fifo, offset, len, mbx->remote);
648
649
650 crc = fm10k_crc_16b(&mbx->mbx_hdr, mbx->remote, 1);
651
652
653 return crc ? FM10K_MBX_ERR_CRC : 0;
654 }
655
656
657
658
659
660
661
662 static 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
671
672
673
674
675
676 static 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
685
686
687
688
689 static bool fm10k_mbx_tx_complete(struct fm10k_mbx_info *mbx)
690 {
691 return fm10k_fifo_empty(&mbx->tx);
692 }
693
694
695
696
697
698
699
700
701
702 static 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
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
720 memmove(fifo->buffer, fifo->buffer + fifo->tail, mbx->pushed << 2);
721
722
723 fifo->tail -= fifo->head;
724 fifo->head = 0;
725
726 return cnt;
727 }
728
729
730
731
732
733
734
735
736
737
738
739 static 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
754 err = fm10k_fifo_enqueue(&mbx->tx, msg);
755
756
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
765 if (err) {
766 mbx->timeout = 0;
767 mbx->tx_busy++;
768 }
769
770
771
772
773
774 if (!mbx->tail_len)
775 mbx->ops.process(hw, mbx);
776
777 return 0;
778 }
779
780
781
782
783
784
785
786
787 static s32 fm10k_mbx_read(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
788 {
789
790 if (mbx->mbx_hdr)
791 return FM10K_MBX_ERR_BUSY;
792
793
794 if (fm10k_read_reg(hw, mbx->mbx_reg) & FM10K_MBX_REQ_INTERRUPT)
795 mbx->mbx_lock = FM10K_MBX_ACK;
796
797
798 fm10k_write_reg(hw, mbx->mbx_reg,
799 FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT);
800
801
802 mbx->mbx_hdr = fm10k_read_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len);
803
804 return 0;
805 }
806
807
808
809
810
811
812
813
814 static void fm10k_mbx_write(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
815 {
816 u32 mbmem = mbx->mbmem_reg;
817
818
819 fm10k_write_reg(hw, mbmem, mbx->mbx_hdr);
820
821
822 if (mbx->mbx_lock)
823 fm10k_write_reg(hw, mbx->mbx_reg, mbx->mbx_lock);
824
825
826 mbx->mbx_hdr = 0;
827 mbx->mbx_lock = 0;
828 }
829
830
831
832
833
834
835
836 static 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
847
848
849
850
851 static 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
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
868 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
869 }
870
871
872
873
874
875
876
877 static 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
887 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
888 }
889
890
891
892
893
894
895
896
897
898 static void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx)
899 {
900 u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) |
901 FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) |
902 FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD);
903 u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1);
904
905 mbx->mbx_lock |= FM10K_MBX_ACK;
906
907
908 mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC);
909 }
910
911
912
913
914
915
916
917
918
919
920 static void fm10k_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
921 {
922
923 switch (err) {
924 case FM10K_MBX_ERR_TAIL:
925 case FM10K_MBX_ERR_HEAD:
926 case FM10K_MBX_ERR_TYPE:
927 case FM10K_MBX_ERR_SIZE:
928 case FM10K_MBX_ERR_RSVD0:
929 case FM10K_MBX_ERR_CRC:
930 break;
931 default:
932 return;
933 }
934
935 mbx->mbx_lock |= FM10K_MBX_REQ;
936
937 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_ERROR, TYPE) |
938 FM10K_MSG_HDR_FIELD_SET(err, ERR_NO) |
939 FM10K_MSG_HDR_FIELD_SET(mbx->head, HEAD);
940 }
941
942
943
944
945
946
947
948
949
950 static s32 fm10k_mbx_validate_msg_hdr(struct fm10k_mbx_info *mbx)
951 {
952 u16 type, rsvd0, head, tail, size;
953 const u32 *hdr = &mbx->mbx_hdr;
954
955 type = FM10K_MSG_HDR_FIELD_GET(*hdr, TYPE);
956 rsvd0 = FM10K_MSG_HDR_FIELD_GET(*hdr, RSVD0);
957 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
958 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
959 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
960
961 if (rsvd0)
962 return FM10K_MBX_ERR_RSVD0;
963
964 switch (type) {
965 case FM10K_MSG_DISCONNECT:
966
967 if (tail != mbx->head)
968 return FM10K_MBX_ERR_TAIL;
969
970
971 case FM10K_MSG_DATA:
972
973 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
974 return FM10K_MBX_ERR_HEAD;
975 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
976 return FM10K_MBX_ERR_HEAD;
977
978
979 if (!tail || (tail == FM10K_MSG_HDR_MASK(TAIL)))
980 return FM10K_MBX_ERR_TAIL;
981 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
982 break;
983
984 return FM10K_MBX_ERR_TAIL;
985 case FM10K_MSG_CONNECT:
986
987 if ((size < FM10K_VFMBX_MSG_MTU) || (size & (size + 1)))
988 return FM10K_MBX_ERR_SIZE;
989
990
991 case FM10K_MSG_ERROR:
992 if (!head || (head == FM10K_MSG_HDR_MASK(HEAD)))
993 return FM10K_MBX_ERR_HEAD;
994
995 if (tail)
996 return FM10K_MBX_ERR_TAIL;
997
998 break;
999 default:
1000 return FM10K_MBX_ERR_TYPE;
1001 }
1002
1003 return 0;
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw,
1018 struct fm10k_mbx_info *mbx, u16 head)
1019 {
1020 switch (mbx->state) {
1021 case FM10K_STATE_OPEN:
1022 case FM10K_STATE_DISCONNECT:
1023
1024 fm10k_mbx_update_local_crc(mbx, head);
1025
1026
1027 fm10k_mbx_pull_head(hw, mbx, head);
1028
1029
1030 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN))
1031 fm10k_mbx_create_data_hdr(mbx);
1032 else
1033 fm10k_mbx_create_disconnect_hdr(mbx);
1034 break;
1035 case FM10K_STATE_CONNECT:
1036
1037 fm10k_mbx_create_connect_hdr(mbx);
1038 break;
1039 case FM10K_STATE_CLOSED:
1040
1041 fm10k_mbx_create_disconnect_hdr(mbx);
1042 default:
1043 break;
1044 }
1045
1046 return 0;
1047 }
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx)
1058 {
1059 u16 len, head, ack;
1060
1061
1062 mbx->max_size = mbx->rx.size - 1;
1063
1064
1065 head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD);
1066 ack = fm10k_mbx_index_len(mbx, head, mbx->tail);
1067 mbx->pulled += mbx->tail_len - ack;
1068
1069
1070 while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) {
1071 len = fm10k_fifo_head_drop(&mbx->tx);
1072 mbx->tx_dropped++;
1073 if (mbx->pulled >= len)
1074 mbx->pulled -= len;
1075 else
1076 mbx->pulled = 0;
1077 }
1078
1079
1080 mbx->pushed = 0;
1081 mbx->pulled = 0;
1082 mbx->tail_len = 0;
1083 mbx->head_len = 0;
1084 mbx->rx.tail = 0;
1085 mbx->rx.head = 0;
1086 }
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099 static void fm10k_mbx_update_max_size(struct fm10k_mbx_info *mbx, u16 size)
1100 {
1101 u16 len;
1102
1103 mbx->max_size = size;
1104
1105
1106 for (len = fm10k_fifo_head_len(&mbx->tx);
1107 len > size;
1108 len = fm10k_fifo_head_len(&mbx->tx)) {
1109 fm10k_fifo_head_drop(&mbx->tx);
1110 mbx->tx_dropped++;
1111 }
1112 }
1113
1114
1115
1116
1117
1118
1119
1120
1121 static void fm10k_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1122 {
1123
1124 fm10k_mbx_reset_work(mbx);
1125
1126
1127 mbx->local = FM10K_MBX_CRC_SEED;
1128 mbx->remote = FM10K_MBX_CRC_SEED;
1129
1130
1131 if (mbx->state == FM10K_STATE_OPEN)
1132 mbx->state = FM10K_STATE_CONNECT;
1133 else
1134 mbx->state = FM10K_STATE_CLOSED;
1135 }
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146 static s32 fm10k_mbx_process_connect(struct fm10k_hw *hw,
1147 struct fm10k_mbx_info *mbx)
1148 {
1149 const enum fm10k_mbx_state state = mbx->state;
1150 const u32 *hdr = &mbx->mbx_hdr;
1151 u16 size, head;
1152
1153
1154 size = FM10K_MSG_HDR_FIELD_GET(*hdr, CONNECT_SIZE);
1155 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1156
1157 switch (state) {
1158 case FM10K_STATE_DISCONNECT:
1159 case FM10K_STATE_OPEN:
1160
1161 fm10k_mbx_connect_reset(mbx);
1162 break;
1163 case FM10K_STATE_CONNECT:
1164
1165 if (size > mbx->rx.size) {
1166 mbx->max_size = mbx->rx.size - 1;
1167 } else {
1168
1169 mbx->state = FM10K_STATE_OPEN;
1170
1171 fm10k_mbx_update_max_size(mbx, size);
1172 }
1173 break;
1174 default:
1175 break;
1176 }
1177
1178
1179 mbx->tail = head;
1180
1181 return fm10k_mbx_create_reply(hw, mbx, head);
1182 }
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 static s32 fm10k_mbx_process_data(struct fm10k_hw *hw,
1194 struct fm10k_mbx_info *mbx)
1195 {
1196 const u32 *hdr = &mbx->mbx_hdr;
1197 u16 head, tail;
1198 s32 err;
1199
1200
1201 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1202 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, TAIL);
1203
1204
1205 if (mbx->state == FM10K_STATE_CONNECT) {
1206 mbx->tail = head;
1207 mbx->state = FM10K_STATE_OPEN;
1208 }
1209
1210
1211 err = fm10k_mbx_push_tail(hw, mbx, tail);
1212 if (err < 0)
1213 return err;
1214
1215
1216 err = fm10k_mbx_verify_remote_crc(mbx);
1217 if (err)
1218 return err;
1219
1220
1221 fm10k_mbx_dequeue_rx(hw, mbx);
1222
1223 return fm10k_mbx_create_reply(hw, mbx, head);
1224 }
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235 static s32 fm10k_mbx_process_disconnect(struct fm10k_hw *hw,
1236 struct fm10k_mbx_info *mbx)
1237 {
1238 const enum fm10k_mbx_state state = mbx->state;
1239 const u32 *hdr = &mbx->mbx_hdr;
1240 u16 head;
1241 s32 err;
1242
1243
1244 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1245
1246
1247 if (mbx->pushed)
1248 return FM10K_MBX_ERR_TAIL;
1249
1250
1251 mbx->head_len = 0;
1252
1253
1254 err = fm10k_mbx_verify_remote_crc(mbx);
1255 if (err)
1256 return err;
1257
1258 switch (state) {
1259 case FM10K_STATE_DISCONNECT:
1260 case FM10K_STATE_OPEN:
1261
1262 if (!fm10k_mbx_tx_complete(mbx))
1263 break;
1264
1265
1266 if (head != mbx->tail)
1267 return FM10K_MBX_ERR_HEAD;
1268
1269
1270 fm10k_mbx_connect_reset(mbx);
1271 break;
1272 default:
1273 break;
1274 }
1275
1276 return fm10k_mbx_create_reply(hw, mbx, head);
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288 static s32 fm10k_mbx_process_error(struct fm10k_hw *hw,
1289 struct fm10k_mbx_info *mbx)
1290 {
1291 const u32 *hdr = &mbx->mbx_hdr;
1292 u16 head;
1293
1294
1295 head = FM10K_MSG_HDR_FIELD_GET(*hdr, HEAD);
1296
1297 switch (mbx->state) {
1298 case FM10K_STATE_OPEN:
1299 case FM10K_STATE_DISCONNECT:
1300
1301 fm10k_mbx_reset_work(mbx);
1302
1303
1304 mbx->local = FM10K_MBX_CRC_SEED;
1305 mbx->remote = FM10K_MBX_CRC_SEED;
1306
1307
1308 mbx->tail = head;
1309
1310
1311 if (mbx->state == FM10K_STATE_OPEN) {
1312 mbx->state = FM10K_STATE_CONNECT;
1313 break;
1314 }
1315
1316
1317 fm10k_mbx_create_connect_hdr(mbx);
1318 return 0;
1319 default:
1320 break;
1321 }
1322
1323 return fm10k_mbx_create_reply(hw, mbx, mbx->tail);
1324 }
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335 static s32 fm10k_mbx_process(struct fm10k_hw *hw,
1336 struct fm10k_mbx_info *mbx)
1337 {
1338 s32 err;
1339
1340
1341 if (mbx->state == FM10K_STATE_CLOSED)
1342 return 0;
1343
1344
1345 err = fm10k_mbx_read(hw, mbx);
1346 if (err)
1347 return err;
1348
1349
1350 err = fm10k_mbx_validate_msg_hdr(mbx);
1351 if (err < 0)
1352 goto msg_err;
1353
1354 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, TYPE)) {
1355 case FM10K_MSG_CONNECT:
1356 err = fm10k_mbx_process_connect(hw, mbx);
1357 break;
1358 case FM10K_MSG_DATA:
1359 err = fm10k_mbx_process_data(hw, mbx);
1360 break;
1361 case FM10K_MSG_DISCONNECT:
1362 err = fm10k_mbx_process_disconnect(hw, mbx);
1363 break;
1364 case FM10K_MSG_ERROR:
1365 err = fm10k_mbx_process_error(hw, mbx);
1366 break;
1367 default:
1368 err = FM10K_MBX_ERR_TYPE;
1369 break;
1370 }
1371
1372 msg_err:
1373
1374 if (err < 0)
1375 fm10k_mbx_create_error_msg(mbx, err);
1376
1377
1378 fm10k_mbx_write(hw, mbx);
1379
1380 return err;
1381 }
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396 static void fm10k_mbx_disconnect(struct fm10k_hw *hw,
1397 struct fm10k_mbx_info *mbx)
1398 {
1399 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1400
1401
1402 mbx->state = FM10K_STATE_DISCONNECT;
1403
1404
1405 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1406 FM10K_MBX_INTERRUPT_DISABLE);
1407 do {
1408 udelay(FM10K_MBX_POLL_DELAY);
1409 mbx->ops.process(hw, mbx);
1410 timeout -= FM10K_MBX_POLL_DELAY;
1411 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1412
1413
1414
1415
1416 fm10k_mbx_connect_reset(mbx);
1417 fm10k_fifo_drop_all(&mbx->tx);
1418
1419 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1420 }
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435 static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1436 {
1437
1438 if (!mbx->rx.buffer)
1439 return FM10K_MBX_ERR_NO_SPACE;
1440
1441
1442 if (mbx->state != FM10K_STATE_CLOSED)
1443 return FM10K_MBX_ERR_BUSY;
1444
1445
1446 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1447
1448
1449 mbx->state = FM10K_STATE_CONNECT;
1450
1451 fm10k_mbx_reset_work(mbx);
1452
1453
1454 fm10k_mbx_create_fake_disconnect_hdr(mbx);
1455 fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr);
1456
1457
1458 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1459 FM10K_MBX_INTERRUPT_ENABLE;
1460
1461
1462 fm10k_mbx_create_connect_hdr(mbx);
1463 fm10k_mbx_write(hw, mbx);
1464
1465 return 0;
1466 }
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476 static s32 fm10k_mbx_validate_handlers(const struct fm10k_msg_data *msg_data)
1477 {
1478 const struct fm10k_tlv_attr *attr;
1479 unsigned int id;
1480
1481
1482 if (!msg_data)
1483 return 0;
1484
1485 while (msg_data->id != FM10K_TLV_ERROR) {
1486
1487 if (!msg_data->func)
1488 return FM10K_ERR_PARAM;
1489
1490
1491 attr = msg_data->attr;
1492 if (attr) {
1493 while (attr->id != FM10K_TLV_ERROR) {
1494 id = attr->id;
1495 attr++;
1496
1497 if (id >= attr->id)
1498 return FM10K_ERR_PARAM;
1499
1500 if (id >= FM10K_TLV_RESULTS_MAX)
1501 return FM10K_ERR_PARAM;
1502 }
1503
1504
1505 if (attr->id != FM10K_TLV_ERROR)
1506 return FM10K_ERR_PARAM;
1507 }
1508
1509 id = msg_data->id;
1510 msg_data++;
1511
1512 if (id >= msg_data->id)
1513 return FM10K_ERR_PARAM;
1514 }
1515
1516
1517 if ((msg_data->id != FM10K_TLV_ERROR) || !msg_data->func)
1518 return FM10K_ERR_PARAM;
1519
1520 return 0;
1521 }
1522
1523
1524
1525
1526
1527
1528
1529
1530 static s32 fm10k_mbx_register_handlers(struct fm10k_mbx_info *mbx,
1531 const struct fm10k_msg_data *msg_data)
1532 {
1533
1534 if (fm10k_mbx_validate_handlers(msg_data))
1535 return FM10K_ERR_PARAM;
1536
1537
1538 mbx->msg_data = msg_data;
1539
1540 return 0;
1541 }
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557 s32 fm10k_pfvf_mbx_init(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx,
1558 const struct fm10k_msg_data *msg_data, u8 id)
1559 {
1560
1561 switch (hw->mac.type) {
1562 case fm10k_mac_vf:
1563 mbx->mbx_reg = FM10K_VFMBX;
1564 mbx->mbmem_reg = FM10K_VFMBMEM(FM10K_VFMBMEM_VF_XOR);
1565 break;
1566 case fm10k_mac_pf:
1567
1568 if (id < 64) {
1569 mbx->mbx_reg = FM10K_MBX(id);
1570 mbx->mbmem_reg = FM10K_MBMEM_VF(id, 0);
1571 break;
1572 }
1573
1574 default:
1575 return FM10K_MBX_ERR_NO_MBX;
1576 }
1577
1578
1579 mbx->state = FM10K_STATE_CLOSED;
1580
1581
1582 if (fm10k_mbx_validate_handlers(msg_data))
1583 return FM10K_ERR_PARAM;
1584
1585
1586 mbx->msg_data = msg_data;
1587
1588
1589
1590
1591 mbx->timeout = 0;
1592 mbx->udelay = FM10K_MBX_INIT_DELAY;
1593
1594
1595 mbx->tail = 1;
1596 mbx->head = 1;
1597
1598
1599 mbx->local = FM10K_MBX_CRC_SEED;
1600 mbx->remote = FM10K_MBX_CRC_SEED;
1601
1602
1603 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1604 mbx->mbmem_len = FM10K_VFMBMEM_VF_XOR;
1605
1606
1607 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
1608 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
1609 FM10K_MBX_RX_BUFFER_SIZE);
1610
1611
1612 mbx->ops.connect = fm10k_mbx_connect;
1613 mbx->ops.disconnect = fm10k_mbx_disconnect;
1614 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
1615 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
1616 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
1617 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
1618 mbx->ops.process = fm10k_mbx_process;
1619 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
1620
1621 return 0;
1622 }
1623
1624
1625
1626
1627
1628
1629
1630 static void fm10k_sm_mbx_create_data_hdr(struct fm10k_mbx_info *mbx)
1631 {
1632 if (mbx->tail_len)
1633 mbx->mbx_lock |= FM10K_MBX_REQ;
1634
1635 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1636 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1637 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD);
1638 }
1639
1640
1641
1642
1643
1644
1645
1646
1647 static void fm10k_sm_mbx_create_connect_hdr(struct fm10k_mbx_info *mbx, u8 err)
1648 {
1649 if (mbx->local)
1650 mbx->mbx_lock |= FM10K_MBX_REQ;
1651
1652 mbx->mbx_hdr = FM10K_MSG_HDR_FIELD_SET(mbx->tail, SM_TAIL) |
1653 FM10K_MSG_HDR_FIELD_SET(mbx->remote, SM_VER) |
1654 FM10K_MSG_HDR_FIELD_SET(mbx->head, SM_HEAD) |
1655 FM10K_MSG_HDR_FIELD_SET(err, SM_ERR);
1656 }
1657
1658
1659
1660
1661
1662
1663
1664 static void fm10k_sm_mbx_connect_reset(struct fm10k_mbx_info *mbx)
1665 {
1666
1667 fm10k_mbx_reset_work(mbx);
1668
1669
1670 mbx->local = FM10K_SM_MBX_VERSION;
1671 mbx->remote = 0;
1672
1673
1674 mbx->tail = 1;
1675 mbx->head = 1;
1676
1677
1678 mbx->state = FM10K_STATE_CONNECT;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693 static s32 fm10k_sm_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx)
1694 {
1695
1696 if (!mbx->rx.buffer)
1697 return FM10K_MBX_ERR_NO_SPACE;
1698
1699
1700 if (mbx->state != FM10K_STATE_CLOSED)
1701 return FM10K_MBX_ERR_BUSY;
1702
1703
1704 mbx->timeout = FM10K_MBX_INIT_TIMEOUT;
1705
1706
1707 mbx->state = FM10K_STATE_CONNECT;
1708 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
1709
1710
1711 fm10k_sm_mbx_connect_reset(mbx);
1712
1713
1714 mbx->mbx_lock = FM10K_MBX_REQ_INTERRUPT | FM10K_MBX_ACK_INTERRUPT |
1715 FM10K_MBX_INTERRUPT_ENABLE;
1716
1717
1718 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1719 fm10k_mbx_write(hw, mbx);
1720
1721 return 0;
1722 }
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737 static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw,
1738 struct fm10k_mbx_info *mbx)
1739 {
1740 int timeout = mbx->timeout ? FM10K_MBX_DISCONNECT_TIMEOUT : 0;
1741
1742
1743 mbx->state = FM10K_STATE_DISCONNECT;
1744
1745
1746 fm10k_write_reg(hw, mbx->mbx_reg, FM10K_MBX_REQ |
1747 FM10K_MBX_INTERRUPT_DISABLE);
1748 do {
1749 udelay(FM10K_MBX_POLL_DELAY);
1750 mbx->ops.process(hw, mbx);
1751 timeout -= FM10K_MBX_POLL_DELAY;
1752 } while ((timeout > 0) && (mbx->state != FM10K_STATE_CLOSED));
1753
1754
1755 mbx->state = FM10K_STATE_CLOSED;
1756 mbx->remote = 0;
1757 fm10k_mbx_reset_work(mbx);
1758 fm10k_fifo_drop_all(&mbx->tx);
1759
1760 fm10k_write_reg(hw, mbx->mbmem_reg, 0);
1761 }
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771 static s32 fm10k_sm_mbx_validate_fifo_hdr(struct fm10k_mbx_info *mbx)
1772 {
1773 const u32 *hdr = &mbx->mbx_hdr;
1774 u16 tail, head, ver;
1775
1776 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
1777 ver = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_VER);
1778 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
1779
1780 switch (ver) {
1781 case 0:
1782 break;
1783 case FM10K_SM_MBX_VERSION:
1784 if (!head || head > FM10K_SM_MBX_FIFO_LEN)
1785 return FM10K_MBX_ERR_HEAD;
1786 if (!tail || tail > FM10K_SM_MBX_FIFO_LEN)
1787 return FM10K_MBX_ERR_TAIL;
1788 if (mbx->tail < head)
1789 head += mbx->mbmem_len - 1;
1790 if (tail < mbx->head)
1791 tail += mbx->mbmem_len - 1;
1792 if (fm10k_mbx_index_len(mbx, head, mbx->tail) > mbx->tail_len)
1793 return FM10K_MBX_ERR_HEAD;
1794 if (fm10k_mbx_index_len(mbx, mbx->head, tail) < mbx->mbmem_len)
1795 break;
1796 return FM10K_MBX_ERR_TAIL;
1797 default:
1798 return FM10K_MBX_ERR_SRC;
1799 }
1800
1801 return 0;
1802 }
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813 static void fm10k_sm_mbx_process_error(struct fm10k_mbx_info *mbx)
1814 {
1815 const enum fm10k_mbx_state state = mbx->state;
1816
1817 switch (state) {
1818 case FM10K_STATE_DISCONNECT:
1819
1820 mbx->remote = 0;
1821 break;
1822 case FM10K_STATE_OPEN:
1823
1824 fm10k_sm_mbx_connect_reset(mbx);
1825 break;
1826 case FM10K_STATE_CONNECT:
1827
1828 if (mbx->remote) {
1829 while (mbx->local > 1)
1830 mbx->local--;
1831 mbx->remote = 0;
1832 }
1833 break;
1834 default:
1835 break;
1836 }
1837
1838 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1839 }
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849 static void fm10k_sm_mbx_create_error_msg(struct fm10k_mbx_info *mbx, s32 err)
1850 {
1851
1852 switch (err) {
1853 case FM10K_MBX_ERR_TAIL:
1854 case FM10K_MBX_ERR_HEAD:
1855 case FM10K_MBX_ERR_SRC:
1856 case FM10K_MBX_ERR_SIZE:
1857 case FM10K_MBX_ERR_RSVD0:
1858 break;
1859 default:
1860 return;
1861 }
1862
1863
1864 fm10k_sm_mbx_process_error(mbx);
1865 fm10k_sm_mbx_create_connect_hdr(mbx, 1);
1866 }
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 static s32 fm10k_sm_mbx_receive(struct fm10k_hw *hw,
1878 struct fm10k_mbx_info *mbx,
1879 u16 tail)
1880 {
1881
1882 u16 mbmem_len = mbx->mbmem_len - 1;
1883 s32 err;
1884
1885
1886 if (tail < mbx->head)
1887 tail += mbmem_len;
1888
1889
1890 err = fm10k_mbx_push_tail(hw, mbx, tail);
1891 if (err < 0)
1892 return err;
1893
1894
1895 fm10k_mbx_dequeue_rx(hw, mbx);
1896
1897
1898 mbx->head = fm10k_mbx_head_sub(mbx, mbx->pushed);
1899 mbx->pushed = 0;
1900
1901
1902 if (mbx->head > mbmem_len)
1903 mbx->head -= mbmem_len;
1904
1905 return err;
1906 }
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917 static void fm10k_sm_mbx_transmit(struct fm10k_hw *hw,
1918 struct fm10k_mbx_info *mbx, u16 head)
1919 {
1920 struct fm10k_mbx_fifo *fifo = &mbx->tx;
1921
1922 u16 mbmem_len = mbx->mbmem_len - 1;
1923 u16 tail_len, len = 0;
1924
1925
1926 if (mbx->tail < head)
1927 head += mbmem_len;
1928
1929 fm10k_mbx_pull_head(hw, mbx, head);
1930
1931
1932 do {
1933 u32 *msg;
1934
1935 msg = fifo->buffer + fm10k_fifo_head_offset(fifo, len);
1936 tail_len = len;
1937 len += FM10K_TLV_DWORD_LEN(*msg);
1938 } while ((len <= mbx->tail_len) && (len < mbmem_len));
1939
1940
1941 if (mbx->tail_len > tail_len) {
1942 mbx->tail = fm10k_mbx_tail_sub(mbx, mbx->tail_len - tail_len);
1943 mbx->tail_len = tail_len;
1944 }
1945
1946
1947 if (mbx->tail > mbmem_len)
1948 mbx->tail -= mbmem_len;
1949 }
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962 static void fm10k_sm_mbx_create_reply(struct fm10k_hw *hw,
1963 struct fm10k_mbx_info *mbx, u16 head)
1964 {
1965 switch (mbx->state) {
1966 case FM10K_STATE_OPEN:
1967 case FM10K_STATE_DISCONNECT:
1968
1969 fm10k_sm_mbx_transmit(hw, mbx, head);
1970
1971
1972 if (mbx->tail_len || (mbx->state == FM10K_STATE_OPEN)) {
1973 fm10k_sm_mbx_create_data_hdr(mbx);
1974 } else {
1975 mbx->remote = 0;
1976 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1977 }
1978 break;
1979 case FM10K_STATE_CONNECT:
1980 case FM10K_STATE_CLOSED:
1981 fm10k_sm_mbx_create_connect_hdr(mbx, 0);
1982 break;
1983 default:
1984 break;
1985 }
1986 }
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999 static s32 fm10k_sm_mbx_process_reset(struct fm10k_hw *hw,
2000 struct fm10k_mbx_info *mbx)
2001 {
2002 s32 err = 0;
2003 const enum fm10k_mbx_state state = mbx->state;
2004
2005 switch (state) {
2006 case FM10K_STATE_DISCONNECT:
2007
2008 mbx->state = FM10K_STATE_CLOSED;
2009 mbx->remote = 0;
2010 mbx->local = 0;
2011 break;
2012 case FM10K_STATE_OPEN:
2013
2014 fm10k_sm_mbx_connect_reset(mbx);
2015 err = FM10K_ERR_RESET_REQUESTED;
2016 break;
2017 case FM10K_STATE_CONNECT:
2018
2019 mbx->remote = mbx->local;
2020 default:
2021 break;
2022 }
2023
2024 fm10k_sm_mbx_create_reply(hw, mbx, mbx->tail);
2025
2026 return err;
2027 }
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037 static s32 fm10k_sm_mbx_process_version_1(struct fm10k_hw *hw,
2038 struct fm10k_mbx_info *mbx)
2039 {
2040 const u32 *hdr = &mbx->mbx_hdr;
2041 u16 head, tail;
2042 s32 len;
2043
2044
2045 tail = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_TAIL);
2046 head = FM10K_MSG_HDR_FIELD_GET(*hdr, SM_HEAD);
2047
2048
2049 if (mbx->state == FM10K_STATE_CONNECT) {
2050 if (!mbx->remote)
2051 goto send_reply;
2052 if (mbx->remote != 1)
2053 return FM10K_MBX_ERR_SRC;
2054
2055 mbx->state = FM10K_STATE_OPEN;
2056 }
2057
2058 do {
2059
2060 len = fm10k_sm_mbx_receive(hw, mbx, tail);
2061 if (len < 0)
2062 return len;
2063
2064
2065 } while (len);
2066
2067 send_reply:
2068 fm10k_sm_mbx_create_reply(hw, mbx, head);
2069
2070 return 0;
2071 }
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082 static s32 fm10k_sm_mbx_process(struct fm10k_hw *hw,
2083 struct fm10k_mbx_info *mbx)
2084 {
2085 s32 err;
2086
2087
2088 if (mbx->state == FM10K_STATE_CLOSED)
2089 return 0;
2090
2091
2092 err = fm10k_mbx_read(hw, mbx);
2093 if (err)
2094 return err;
2095
2096 err = fm10k_sm_mbx_validate_fifo_hdr(mbx);
2097 if (err < 0)
2098 goto fifo_err;
2099
2100 if (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_ERR)) {
2101 fm10k_sm_mbx_process_error(mbx);
2102 goto fifo_err;
2103 }
2104
2105 switch (FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, SM_VER)) {
2106 case 0:
2107 err = fm10k_sm_mbx_process_reset(hw, mbx);
2108 break;
2109 case FM10K_SM_MBX_VERSION:
2110 err = fm10k_sm_mbx_process_version_1(hw, mbx);
2111 break;
2112 }
2113
2114 fifo_err:
2115 if (err < 0)
2116 fm10k_sm_mbx_create_error_msg(mbx, err);
2117
2118
2119 fm10k_mbx_write(hw, mbx);
2120
2121 return err;
2122 }
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137 s32 fm10k_sm_mbx_init(struct fm10k_hw __always_unused *hw,
2138 struct fm10k_mbx_info *mbx,
2139 const struct fm10k_msg_data *msg_data)
2140 {
2141 mbx->mbx_reg = FM10K_GMBX;
2142 mbx->mbmem_reg = FM10K_MBMEM_PF(0);
2143
2144
2145 mbx->state = FM10K_STATE_CLOSED;
2146
2147
2148 if (fm10k_mbx_validate_handlers(msg_data))
2149 return FM10K_ERR_PARAM;
2150
2151
2152 mbx->msg_data = msg_data;
2153
2154
2155
2156
2157 mbx->timeout = 0;
2158 mbx->udelay = FM10K_MBX_INIT_DELAY;
2159
2160
2161 mbx->max_size = FM10K_MBX_MSG_MAX_SIZE;
2162 mbx->mbmem_len = FM10K_MBMEM_PF_XOR;
2163
2164
2165 fm10k_fifo_init(&mbx->tx, mbx->buffer, FM10K_MBX_TX_BUFFER_SIZE);
2166 fm10k_fifo_init(&mbx->rx, &mbx->buffer[FM10K_MBX_TX_BUFFER_SIZE],
2167 FM10K_MBX_RX_BUFFER_SIZE);
2168
2169
2170 mbx->ops.connect = fm10k_sm_mbx_connect;
2171 mbx->ops.disconnect = fm10k_sm_mbx_disconnect;
2172 mbx->ops.rx_ready = fm10k_mbx_rx_ready;
2173 mbx->ops.tx_ready = fm10k_mbx_tx_ready;
2174 mbx->ops.tx_complete = fm10k_mbx_tx_complete;
2175 mbx->ops.enqueue_tx = fm10k_mbx_enqueue_tx;
2176 mbx->ops.process = fm10k_sm_mbx_process;
2177 mbx->ops.register_handlers = fm10k_mbx_register_handlers;
2178
2179 return 0;
2180 }