1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "efc.h"
22
23static void
24efc_fabric_initiate_shutdown(struct efc_node *node)
25{
26 struct efc *efc = node->efc;
27
28 node->els_io_enabled = false;
29
30 if (node->attached) {
31 int rc;
32
33
34
35
36
37 rc = efc_cmd_node_detach(efc, &node->rnode);
38 if (rc < 0) {
39 node_printf(node, "Failed freeing HW node, rc=%d\n",
40 rc);
41 }
42 }
43
44
45
46
47 efc_node_initiate_cleanup(node);
48}
49
50static void
51__efc_fabric_common(const char *funcname, struct efc_sm_ctx *ctx,
52 enum efc_sm_event evt, void *arg)
53{
54 struct efc_node *node = NULL;
55
56 node = ctx->app;
57
58 switch (evt) {
59 case EFC_EVT_DOMAIN_ATTACH_OK:
60 break;
61 case EFC_EVT_SHUTDOWN:
62 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
63 efc_fabric_initiate_shutdown(node);
64 break;
65
66 default:
67
68 __efc_node_common(funcname, ctx, evt, arg);
69 }
70}
71
72void
73__efc_fabric_init(struct efc_sm_ctx *ctx, enum efc_sm_event evt,
74 void *arg)
75{
76 struct efc_node *node = ctx->app;
77 struct efc *efc = node->efc;
78
79 efc_node_evt_set(ctx, evt, __func__);
80
81 node_sm_trace();
82
83 switch (evt) {
84 case EFC_EVT_REENTER:
85 efc_log_debug(efc, ">>> reenter !!\n");
86 fallthrough;
87
88 case EFC_EVT_ENTER:
89
90 efc_send_flogi(node);
91 efc_node_transition(node, __efc_fabric_flogi_wait_rsp, NULL);
92 break;
93
94 default:
95 __efc_fabric_common(__func__, ctx, evt, arg);
96 }
97}
98
99void
100efc_fabric_set_topology(struct efc_node *node,
101 enum efc_nport_topology topology)
102{
103 node->nport->topology = topology;
104}
105
106void
107efc_fabric_notify_topology(struct efc_node *node)
108{
109 struct efc_node *tmp_node;
110 unsigned long index;
111
112
113
114
115
116 xa_for_each(&node->nport->lookup, index, tmp_node) {
117 if (tmp_node != node) {
118 efc_node_post_event(tmp_node,
119 EFC_EVT_NPORT_TOPOLOGY_NOTIFY,
120 &node->nport->topology);
121 }
122 }
123}
124
125static bool efc_rnode_is_nport(struct fc_els_flogi *rsp)
126{
127 return !(ntohs(rsp->fl_csp.sp_features) & FC_SP_FT_FPORT);
128}
129
130void
131__efc_fabric_flogi_wait_rsp(struct efc_sm_ctx *ctx,
132 enum efc_sm_event evt, void *arg)
133{
134 struct efc_node_cb *cbdata = arg;
135 struct efc_node *node = ctx->app;
136
137 efc_node_evt_set(ctx, evt, __func__);
138
139 node_sm_trace();
140
141 switch (evt) {
142 case EFC_EVT_SRRS_ELS_REQ_OK: {
143 if (efc_node_check_els_req(ctx, evt, arg, ELS_FLOGI,
144 __efc_fabric_common, __func__)) {
145 return;
146 }
147 WARN_ON(!node->els_req_cnt);
148 node->els_req_cnt--;
149
150 memcpy(node->nport->domain->flogi_service_params,
151 cbdata->els_rsp.virt,
152 sizeof(struct fc_els_flogi));
153
154
155 if (!efc_rnode_is_nport(cbdata->els_rsp.virt)) {
156
157
158 efc_fabric_set_topology(node, EFC_NPORT_TOPO_FABRIC);
159 efc_fabric_notify_topology(node);
160 WARN_ON(node->nport->domain->attached);
161 efc_domain_attach(node->nport->domain,
162 cbdata->ext_status);
163 efc_node_transition(node,
164 __efc_fabric_wait_domain_attach,
165 NULL);
166 break;
167 }
168
169
170 efc_fabric_set_topology(node, EFC_NPORT_TOPO_P2P);
171 if (efc_p2p_setup(node->nport)) {
172 node_printf(node,
173 "p2p setup failed, shutting down node\n");
174 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
175 efc_fabric_initiate_shutdown(node);
176 break;
177 }
178
179 if (node->nport->p2p_winner) {
180 efc_node_transition(node,
181 __efc_p2p_wait_domain_attach,
182 NULL);
183 if (node->nport->domain->attached &&
184 !node->nport->domain->domain_notify_pend) {
185
186
187
188
189 node_printf(node,
190 "p2p winner, domain already attached\n");
191 efc_node_post_event(node,
192 EFC_EVT_DOMAIN_ATTACH_OK,
193 NULL);
194 }
195 } else {
196
197
198
199
200
201
202 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
203 efc_fabric_initiate_shutdown(node);
204 }
205
206 break;
207 }
208
209 case EFC_EVT_ELS_REQ_ABORTED:
210 case EFC_EVT_SRRS_ELS_REQ_RJT:
211 case EFC_EVT_SRRS_ELS_REQ_FAIL: {
212 struct efc_nport *nport = node->nport;
213
214
215
216
217
218 if (efc_node_check_els_req(ctx, evt, arg, ELS_FLOGI,
219 __efc_fabric_common, __func__)) {
220 return;
221 }
222 node_printf(node,
223 "FLOGI failed evt=%s, shutting down nport [%s]\n",
224 efc_sm_event_name(evt), nport->display_name);
225 WARN_ON(!node->els_req_cnt);
226 node->els_req_cnt--;
227 efc_sm_post_event(&nport->sm, EFC_EVT_SHUTDOWN, NULL);
228 break;
229 }
230
231 default:
232 __efc_fabric_common(__func__, ctx, evt, arg);
233 }
234}
235
236void
237__efc_vport_fabric_init(struct efc_sm_ctx *ctx,
238 enum efc_sm_event evt, void *arg)
239{
240 struct efc_node *node = ctx->app;
241
242 efc_node_evt_set(ctx, evt, __func__);
243
244 node_sm_trace();
245
246 switch (evt) {
247 case EFC_EVT_ENTER:
248
249 efc_send_fdisc(node);
250 efc_node_transition(node, __efc_fabric_fdisc_wait_rsp, NULL);
251 break;
252
253 default:
254 __efc_fabric_common(__func__, ctx, evt, arg);
255 }
256}
257
258void
259__efc_fabric_fdisc_wait_rsp(struct efc_sm_ctx *ctx,
260 enum efc_sm_event evt, void *arg)
261{
262 struct efc_node_cb *cbdata = arg;
263 struct efc_node *node = ctx->app;
264
265 efc_node_evt_set(ctx, evt, __func__);
266
267 node_sm_trace();
268
269 switch (evt) {
270 case EFC_EVT_SRRS_ELS_REQ_OK: {
271
272 if (efc_node_check_els_req(ctx, evt, arg, ELS_FDISC,
273 __efc_fabric_common, __func__)) {
274 return;
275 }
276
277 WARN_ON(!node->els_req_cnt);
278 node->els_req_cnt--;
279
280 efc_nport_attach(node->nport, cbdata->ext_status);
281 efc_node_transition(node, __efc_fabric_wait_domain_attach,
282 NULL);
283 break;
284 }
285
286 case EFC_EVT_SRRS_ELS_REQ_RJT:
287 case EFC_EVT_SRRS_ELS_REQ_FAIL: {
288 if (efc_node_check_els_req(ctx, evt, arg, ELS_FDISC,
289 __efc_fabric_common, __func__)) {
290 return;
291 }
292 WARN_ON(!node->els_req_cnt);
293 node->els_req_cnt--;
294 efc_log_err(node->efc, "FDISC failed, shutting down nport\n");
295
296 efc_sm_post_event(&node->nport->sm, EFC_EVT_SHUTDOWN, NULL);
297 break;
298 }
299
300 default:
301 __efc_fabric_common(__func__, ctx, evt, arg);
302 }
303}
304
305static int
306efc_start_ns_node(struct efc_nport *nport)
307{
308 struct efc_node *ns;
309
310
311 ns = efc_node_find(nport, FC_FID_DIR_SERV);
312 if (!ns) {
313 ns = efc_node_alloc(nport, FC_FID_DIR_SERV, false, false);
314 if (!ns)
315 return -EIO;
316 }
317
318
319
320
321
322
323 if (ns->efc->nodedb_mask & EFC_NODEDB_PAUSE_NAMESERVER)
324 efc_node_pause(ns, __efc_ns_init);
325 else
326 efc_node_transition(ns, __efc_ns_init, NULL);
327 return 0;
328}
329
330static int
331efc_start_fabctl_node(struct efc_nport *nport)
332{
333 struct efc_node *fabctl;
334
335 fabctl = efc_node_find(nport, FC_FID_FCTRL);
336 if (!fabctl) {
337 fabctl = efc_node_alloc(nport, FC_FID_FCTRL,
338 false, false);
339 if (!fabctl)
340 return -EIO;
341 }
342
343
344
345
346
347
348 efc_node_transition(fabctl, __efc_fabctl_init, NULL);
349 return 0;
350}
351
352void
353__efc_fabric_wait_domain_attach(struct efc_sm_ctx *ctx,
354 enum efc_sm_event evt, void *arg)
355{
356 struct efc_node *node = ctx->app;
357
358 efc_node_evt_set(ctx, evt, __func__);
359
360 node_sm_trace();
361
362 switch (evt) {
363 case EFC_EVT_ENTER:
364 efc_node_hold_frames(node);
365 break;
366
367 case EFC_EVT_EXIT:
368 efc_node_accept_frames(node);
369 break;
370 case EFC_EVT_DOMAIN_ATTACH_OK:
371 case EFC_EVT_NPORT_ATTACH_OK: {
372 int rc;
373
374 rc = efc_start_ns_node(node->nport);
375 if (rc)
376 return;
377
378
379
380 if (node->nport->enable_rscn) {
381 rc = efc_start_fabctl_node(node->nport);
382 if (rc)
383 return;
384 }
385 efc_node_transition(node, __efc_fabric_idle, NULL);
386 break;
387 }
388 default:
389 __efc_fabric_common(__func__, ctx, evt, arg);
390 }
391}
392
393void
394__efc_fabric_idle(struct efc_sm_ctx *ctx, enum efc_sm_event evt,
395 void *arg)
396{
397 struct efc_node *node = ctx->app;
398
399 efc_node_evt_set(ctx, evt, __func__);
400
401 node_sm_trace();
402
403 switch (evt) {
404 case EFC_EVT_DOMAIN_ATTACH_OK:
405 break;
406 default:
407 __efc_fabric_common(__func__, ctx, evt, arg);
408 }
409}
410
411void
412__efc_ns_init(struct efc_sm_ctx *ctx, enum efc_sm_event evt, void *arg)
413{
414 struct efc_node *node = ctx->app;
415
416 efc_node_evt_set(ctx, evt, __func__);
417
418 node_sm_trace();
419
420 switch (evt) {
421 case EFC_EVT_ENTER:
422
423 efc_send_plogi(node);
424 efc_node_transition(node, __efc_ns_plogi_wait_rsp, NULL);
425 break;
426 default:
427 __efc_fabric_common(__func__, ctx, evt, arg);
428 }
429}
430
431void
432__efc_ns_plogi_wait_rsp(struct efc_sm_ctx *ctx,
433 enum efc_sm_event evt, void *arg)
434{
435 struct efc_node_cb *cbdata = arg;
436 struct efc_node *node = ctx->app;
437
438 efc_node_evt_set(ctx, evt, __func__);
439
440 node_sm_trace();
441
442 switch (evt) {
443 case EFC_EVT_SRRS_ELS_REQ_OK: {
444 int rc;
445
446
447 if (efc_node_check_els_req(ctx, evt, arg, ELS_PLOGI,
448 __efc_fabric_common, __func__)) {
449 return;
450 }
451 WARN_ON(!node->els_req_cnt);
452 node->els_req_cnt--;
453
454 efc_node_save_sparms(node, cbdata->els_rsp.virt);
455 rc = efc_node_attach(node);
456 efc_node_transition(node, __efc_ns_wait_node_attach, NULL);
457 if (rc < 0)
458 efc_node_post_event(node, EFC_EVT_NODE_ATTACH_FAIL,
459 NULL);
460 break;
461 }
462 default:
463 __efc_fabric_common(__func__, ctx, evt, arg);
464 }
465}
466
467void
468__efc_ns_wait_node_attach(struct efc_sm_ctx *ctx,
469 enum efc_sm_event evt, void *arg)
470{
471 struct efc_node *node = ctx->app;
472
473 efc_node_evt_set(ctx, evt, __func__);
474
475 node_sm_trace();
476
477 switch (evt) {
478 case EFC_EVT_ENTER:
479 efc_node_hold_frames(node);
480 break;
481
482 case EFC_EVT_EXIT:
483 efc_node_accept_frames(node);
484 break;
485
486 case EFC_EVT_NODE_ATTACH_OK:
487 node->attached = true;
488
489 efc_ns_send_rftid(node);
490 efc_node_transition(node, __efc_ns_rftid_wait_rsp, NULL);
491 break;
492
493 case EFC_EVT_NODE_ATTACH_FAIL:
494
495 node->attached = false;
496 node_printf(node, "Node attach failed\n");
497 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
498 efc_fabric_initiate_shutdown(node);
499 break;
500
501 case EFC_EVT_SHUTDOWN:
502 node_printf(node, "Shutdown event received\n");
503 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
504 efc_node_transition(node,
505 __efc_fabric_wait_attach_evt_shutdown,
506 NULL);
507 break;
508
509
510
511
512
513 case EFC_EVT_RSCN_RCVD:
514 break;
515
516 default:
517 __efc_fabric_common(__func__, ctx, evt, arg);
518 }
519}
520
521void
522__efc_fabric_wait_attach_evt_shutdown(struct efc_sm_ctx *ctx,
523 enum efc_sm_event evt, void *arg)
524{
525 struct efc_node *node = ctx->app;
526
527 efc_node_evt_set(ctx, evt, __func__);
528
529 node_sm_trace();
530
531 switch (evt) {
532 case EFC_EVT_ENTER:
533 efc_node_hold_frames(node);
534 break;
535
536 case EFC_EVT_EXIT:
537 efc_node_accept_frames(node);
538 break;
539
540
541 case EFC_EVT_NODE_ATTACH_OK:
542 node->attached = true;
543 node_printf(node, "Attach evt=%s, proceed to shutdown\n",
544 efc_sm_event_name(evt));
545 efc_fabric_initiate_shutdown(node);
546 break;
547
548 case EFC_EVT_NODE_ATTACH_FAIL:
549 node->attached = false;
550 node_printf(node, "Attach evt=%s, proceed to shutdown\n",
551 efc_sm_event_name(evt));
552 efc_fabric_initiate_shutdown(node);
553 break;
554
555
556 case EFC_EVT_SHUTDOWN:
557 node_printf(node, "Shutdown event received\n");
558 break;
559
560 default:
561 __efc_fabric_common(__func__, ctx, evt, arg);
562 }
563}
564
565void
566__efc_ns_rftid_wait_rsp(struct efc_sm_ctx *ctx,
567 enum efc_sm_event evt, void *arg)
568{
569 struct efc_node *node = ctx->app;
570
571 efc_node_evt_set(ctx, evt, __func__);
572
573 node_sm_trace();
574
575 switch (evt) {
576 case EFC_EVT_SRRS_ELS_REQ_OK:
577 if (efc_node_check_ns_req(ctx, evt, arg, FC_NS_RFT_ID,
578 __efc_fabric_common, __func__)) {
579 return;
580 }
581 WARN_ON(!node->els_req_cnt);
582 node->els_req_cnt--;
583
584 efc_ns_send_rffid(node);
585 efc_node_transition(node, __efc_ns_rffid_wait_rsp, NULL);
586 break;
587
588
589
590
591
592 case EFC_EVT_RSCN_RCVD:
593 break;
594
595 default:
596 __efc_fabric_common(__func__, ctx, evt, arg);
597 }
598}
599
600void
601__efc_ns_rffid_wait_rsp(struct efc_sm_ctx *ctx,
602 enum efc_sm_event evt, void *arg)
603{
604 struct efc_node *node = ctx->app;
605
606 efc_node_evt_set(ctx, evt, __func__);
607
608 node_sm_trace();
609
610
611
612
613
614 switch (evt) {
615 case EFC_EVT_SRRS_ELS_REQ_OK: {
616 if (efc_node_check_ns_req(ctx, evt, arg, FC_NS_RFF_ID,
617 __efc_fabric_common, __func__)) {
618 return;
619 }
620 WARN_ON(!node->els_req_cnt);
621 node->els_req_cnt--;
622 if (node->nport->enable_rscn) {
623
624 efc_ns_send_gidpt(node);
625
626 efc_node_transition(node, __efc_ns_gidpt_wait_rsp,
627 NULL);
628 } else {
629
630 efc_node_transition(node, __efc_ns_idle, NULL);
631 }
632 break;
633 }
634
635
636
637
638 case EFC_EVT_RSCN_RCVD:
639 break;
640
641 default:
642 __efc_fabric_common(__func__, ctx, evt, arg);
643 }
644}
645
646static int
647efc_process_gidpt_payload(struct efc_node *node,
648 void *data, u32 gidpt_len)
649{
650 u32 i, j;
651 struct efc_node *newnode;
652 struct efc_nport *nport = node->nport;
653 struct efc *efc = node->efc;
654 u32 port_id = 0, port_count, plist_count;
655 struct efc_node *n;
656 struct efc_node **active_nodes;
657 int residual;
658 struct {
659 struct fc_ct_hdr hdr;
660 struct fc_gid_pn_resp pn_rsp;
661 } *rsp;
662 struct fc_gid_pn_resp *gidpt;
663 unsigned long index;
664
665 rsp = data;
666 gidpt = &rsp->pn_rsp;
667 residual = be16_to_cpu(rsp->hdr.ct_mr_size);
668
669 if (residual != 0)
670 efc_log_debug(node->efc, "residual is %u words\n", residual);
671
672 if (be16_to_cpu(rsp->hdr.ct_cmd) == FC_FS_RJT) {
673 node_printf(node,
674 "GIDPT request failed: rsn x%x rsn_expl x%x\n",
675 rsp->hdr.ct_reason, rsp->hdr.ct_explan);
676 return -EIO;
677 }
678
679 plist_count = (gidpt_len - sizeof(struct fc_ct_hdr)) / sizeof(*gidpt);
680
681
682 port_count = 0;
683 xa_for_each(&nport->lookup, index, n) {
684 port_count++;
685 }
686
687
688 active_nodes = kzalloc(port_count * sizeof(*active_nodes), GFP_ATOMIC);
689 if (!active_nodes) {
690 node_printf(node, "efc_malloc failed\n");
691 return -EIO;
692 }
693
694
695 i = 0;
696 xa_for_each(&nport->lookup, index, n) {
697 port_id = n->rnode.fc_id;
698 switch (port_id) {
699 case FC_FID_FLOGI:
700 case FC_FID_FCTRL:
701 case FC_FID_DIR_SERV:
702 break;
703 default:
704 if (port_id != FC_FID_DOM_MGR)
705 active_nodes[i++] = n;
706 break;
707 }
708 }
709
710
711 for (i = 0; i < plist_count; i++) {
712 hton24(gidpt[i].fp_fid, port_id);
713
714 for (j = 0; j < port_count; j++) {
715 if (active_nodes[j] &&
716 port_id == active_nodes[j]->rnode.fc_id) {
717 active_nodes[j] = NULL;
718 }
719 }
720
721 if (gidpt[i].fp_resvd & FC_NS_FID_LAST)
722 break;
723 }
724
725
726 for (i = 0; i < port_count; i++) {
727
728
729
730
731
732
733 if (!active_nodes[i])
734 continue;
735
736 if ((node->nport->enable_ini && active_nodes[i]->targ) ||
737 (node->nport->enable_tgt && enable_target_rscn(efc))) {
738 efc_node_post_event(active_nodes[i],
739 EFC_EVT_NODE_MISSING, NULL);
740 } else {
741 node_printf(node,
742 "GID_PT: skipping non-tgt port_id x%06x\n",
743 active_nodes[i]->rnode.fc_id);
744 }
745 }
746 kfree(active_nodes);
747
748 for (i = 0; i < plist_count; i++) {
749 hton24(gidpt[i].fp_fid, port_id);
750
751
752 if (port_id == node->rnode.nport->fc_id) {
753 if (gidpt[i].fp_resvd & FC_NS_FID_LAST)
754 break;
755 continue;
756 }
757
758 newnode = efc_node_find(nport, port_id);
759 if (!newnode) {
760 if (!node->nport->enable_ini)
761 continue;
762
763 newnode = efc_node_alloc(nport, port_id, false, false);
764 if (!newnode) {
765 efc_log_err(efc, "efc_node_alloc() failed\n");
766 return -EIO;
767 }
768
769
770
771
772 efc_node_init_device(newnode, true);
773 }
774
775 if (node->nport->enable_ini && newnode->targ) {
776 efc_node_post_event(newnode, EFC_EVT_NODE_REFOUND,
777 NULL);
778 }
779
780 if (gidpt[i].fp_resvd & FC_NS_FID_LAST)
781 break;
782 }
783 return 0;
784}
785
786void
787__efc_ns_gidpt_wait_rsp(struct efc_sm_ctx *ctx,
788 enum efc_sm_event evt, void *arg)
789{
790 struct efc_node_cb *cbdata = arg;
791 struct efc_node *node = ctx->app;
792
793 efc_node_evt_set(ctx, evt, __func__);
794
795 node_sm_trace();
796
797
798
799
800
801 switch (evt) {
802 case EFC_EVT_SRRS_ELS_REQ_OK: {
803 if (efc_node_check_ns_req(ctx, evt, arg, FC_NS_GID_PT,
804 __efc_fabric_common, __func__)) {
805 return;
806 }
807 WARN_ON(!node->els_req_cnt);
808 node->els_req_cnt--;
809
810 efc_process_gidpt_payload(node, cbdata->els_rsp.virt,
811 cbdata->els_rsp.len);
812 efc_node_transition(node, __efc_ns_idle, NULL);
813 break;
814 }
815
816 case EFC_EVT_SRRS_ELS_REQ_FAIL: {
817
818 node_printf(node, "GID_PT failed to complete\n");
819 WARN_ON(!node->els_req_cnt);
820 node->els_req_cnt--;
821 efc_node_transition(node, __efc_ns_idle, NULL);
822 break;
823 }
824
825
826 case EFC_EVT_RSCN_RCVD: {
827 node_printf(node, "RSCN received during GID_PT processing\n");
828 node->rscn_pending = true;
829 break;
830 }
831
832 default:
833 __efc_fabric_common(__func__, ctx, evt, arg);
834 }
835}
836
837void
838__efc_ns_idle(struct efc_sm_ctx *ctx, enum efc_sm_event evt, void *arg)
839{
840 struct efc_node *node = ctx->app;
841 struct efc *efc = node->efc;
842
843 efc_node_evt_set(ctx, evt, __func__);
844
845 node_sm_trace();
846
847
848
849
850
851
852 switch (evt) {
853 case EFC_EVT_ENTER:
854 if (!node->rscn_pending)
855 break;
856
857 node_printf(node, "RSCN pending, restart discovery\n");
858 node->rscn_pending = false;
859 fallthrough;
860
861 case EFC_EVT_RSCN_RCVD: {
862
863
864
865
866
867
868
869 if (efc->tgt_rscn_delay_msec != 0 &&
870 !node->nport->enable_ini && node->nport->enable_tgt &&
871 enable_target_rscn(efc)) {
872 efc_node_transition(node, __efc_ns_gidpt_delay, NULL);
873 } else {
874 efc_ns_send_gidpt(node);
875 efc_node_transition(node, __efc_ns_gidpt_wait_rsp,
876 NULL);
877 }
878 break;
879 }
880
881 default:
882 __efc_fabric_common(__func__, ctx, evt, arg);
883 }
884}
885
886static void
887gidpt_delay_timer_cb(struct timer_list *t)
888{
889 struct efc_node *node = from_timer(node, t, gidpt_delay_timer);
890
891 del_timer(&node->gidpt_delay_timer);
892
893 efc_node_post_event(node, EFC_EVT_GIDPT_DELAY_EXPIRED, NULL);
894}
895
896void
897__efc_ns_gidpt_delay(struct efc_sm_ctx *ctx,
898 enum efc_sm_event evt, void *arg)
899{
900 struct efc_node *node = ctx->app;
901 struct efc *efc = node->efc;
902
903 efc_node_evt_set(ctx, evt, __func__);
904
905 node_sm_trace();
906
907 switch (evt) {
908 case EFC_EVT_ENTER: {
909 u64 delay_msec, tmp;
910
911
912
913
914
915
916 delay_msec = efc->tgt_rscn_delay_msec;
917 tmp = jiffies_to_msecs(jiffies) - node->time_last_gidpt_msec;
918 if (tmp < efc->tgt_rscn_period_msec)
919 delay_msec = efc->tgt_rscn_period_msec;
920
921 timer_setup(&node->gidpt_delay_timer, &gidpt_delay_timer_cb,
922 0);
923 mod_timer(&node->gidpt_delay_timer,
924 jiffies + msecs_to_jiffies(delay_msec));
925
926 break;
927 }
928
929 case EFC_EVT_GIDPT_DELAY_EXPIRED:
930 node->time_last_gidpt_msec = jiffies_to_msecs(jiffies);
931
932 efc_ns_send_gidpt(node);
933 efc_node_transition(node, __efc_ns_gidpt_wait_rsp, NULL);
934 break;
935
936 case EFC_EVT_RSCN_RCVD: {
937 efc_log_debug(efc,
938 "RSCN received while in GIDPT delay - no action\n");
939 break;
940 }
941
942 default:
943 __efc_fabric_common(__func__, ctx, evt, arg);
944 }
945}
946
947void
948__efc_fabctl_init(struct efc_sm_ctx *ctx,
949 enum efc_sm_event evt, void *arg)
950{
951 struct efc_node *node = ctx->app;
952
953 node_sm_trace();
954
955 switch (evt) {
956 case EFC_EVT_ENTER:
957
958 efc_send_scr(node);
959 efc_node_transition(node, __efc_fabctl_wait_scr_rsp, NULL);
960 break;
961
962 case EFC_EVT_NODE_ATTACH_OK:
963 node->attached = true;
964 break;
965
966 default:
967 __efc_fabric_common(__func__, ctx, evt, arg);
968 }
969}
970
971void
972__efc_fabctl_wait_scr_rsp(struct efc_sm_ctx *ctx,
973 enum efc_sm_event evt, void *arg)
974{
975 struct efc_node *node = ctx->app;
976
977 efc_node_evt_set(ctx, evt, __func__);
978
979 node_sm_trace();
980
981
982
983
984
985 switch (evt) {
986 case EFC_EVT_SRRS_ELS_REQ_OK:
987 if (efc_node_check_els_req(ctx, evt, arg, ELS_SCR,
988 __efc_fabric_common, __func__)) {
989 return;
990 }
991 WARN_ON(!node->els_req_cnt);
992 node->els_req_cnt--;
993 efc_node_transition(node, __efc_fabctl_ready, NULL);
994 break;
995
996 default:
997 __efc_fabric_common(__func__, ctx, evt, arg);
998 }
999}
1000
1001static void
1002efc_process_rscn(struct efc_node *node, struct efc_node_cb *cbdata)
1003{
1004 struct efc *efc = node->efc;
1005 struct efc_nport *nport = node->nport;
1006 struct efc_node *ns;
1007
1008
1009 ns = efc_node_find(nport, FC_FID_DIR_SERV);
1010 if (ns)
1011 efc_node_post_event(ns, EFC_EVT_RSCN_RCVD, cbdata);
1012 else
1013 efc_log_warn(efc, "can't find name server node\n");
1014}
1015
1016void
1017__efc_fabctl_ready(struct efc_sm_ctx *ctx,
1018 enum efc_sm_event evt, void *arg)
1019{
1020 struct efc_node_cb *cbdata = arg;
1021 struct efc_node *node = ctx->app;
1022
1023 efc_node_evt_set(ctx, evt, __func__);
1024
1025 node_sm_trace();
1026
1027
1028
1029
1030
1031
1032
1033 switch (evt) {
1034 case EFC_EVT_RSCN_RCVD: {
1035 struct fc_frame_header *hdr = cbdata->header->dma.virt;
1036
1037
1038
1039
1040
1041 efc_process_rscn(node, cbdata);
1042 efc_send_ls_acc(node, be16_to_cpu(hdr->fh_ox_id));
1043 efc_node_transition(node, __efc_fabctl_wait_ls_acc_cmpl,
1044 NULL);
1045 break;
1046 }
1047
1048 default:
1049 __efc_fabric_common(__func__, ctx, evt, arg);
1050 }
1051}
1052
1053void
1054__efc_fabctl_wait_ls_acc_cmpl(struct efc_sm_ctx *ctx,
1055 enum efc_sm_event evt, void *arg)
1056{
1057 struct efc_node *node = ctx->app;
1058
1059 efc_node_evt_set(ctx, evt, __func__);
1060
1061 node_sm_trace();
1062
1063 switch (evt) {
1064 case EFC_EVT_ENTER:
1065 efc_node_hold_frames(node);
1066 break;
1067
1068 case EFC_EVT_EXIT:
1069 efc_node_accept_frames(node);
1070 break;
1071
1072 case EFC_EVT_SRRS_ELS_CMPL_OK:
1073 WARN_ON(!node->els_cmpl_cnt);
1074 node->els_cmpl_cnt--;
1075 efc_node_transition(node, __efc_fabctl_ready, NULL);
1076 break;
1077
1078 default:
1079 __efc_fabric_common(__func__, ctx, evt, arg);
1080 }
1081}
1082
1083static uint64_t
1084efc_get_wwpn(struct fc_els_flogi *sp)
1085{
1086 return be64_to_cpu(sp->fl_wwnn);
1087}
1088
1089static int
1090efc_rnode_is_winner(struct efc_nport *nport)
1091{
1092 struct fc_els_flogi *remote_sp;
1093 u64 remote_wwpn;
1094 u64 local_wwpn = nport->wwpn;
1095 u64 wwn_bump = 0;
1096
1097 remote_sp = (struct fc_els_flogi *)nport->domain->flogi_service_params;
1098 remote_wwpn = efc_get_wwpn(remote_sp);
1099
1100 local_wwpn ^= wwn_bump;
1101
1102 efc_log_debug(nport->efc, "r: %llx\n",
1103 be64_to_cpu(remote_sp->fl_wwpn));
1104 efc_log_debug(nport->efc, "l: %llx\n", local_wwpn);
1105
1106 if (remote_wwpn == local_wwpn) {
1107 efc_log_warn(nport->efc,
1108 "WWPN of remote node [%08x %08x] matches local WWPN\n",
1109 (u32)(local_wwpn >> 32ll),
1110 (u32)local_wwpn);
1111 return -1;
1112 }
1113
1114 return (remote_wwpn > local_wwpn);
1115}
1116
1117void
1118__efc_p2p_wait_domain_attach(struct efc_sm_ctx *ctx,
1119 enum efc_sm_event evt, void *arg)
1120{
1121 struct efc_node *node = ctx->app;
1122 struct efc *efc = node->efc;
1123
1124 efc_node_evt_set(ctx, evt, __func__);
1125
1126 node_sm_trace();
1127
1128 switch (evt) {
1129 case EFC_EVT_ENTER:
1130 efc_node_hold_frames(node);
1131 break;
1132
1133 case EFC_EVT_EXIT:
1134 efc_node_accept_frames(node);
1135 break;
1136
1137 case EFC_EVT_DOMAIN_ATTACH_OK: {
1138 struct efc_nport *nport = node->nport;
1139 struct efc_node *rnode;
1140
1141
1142
1143
1144
1145
1146
1147 WARN_ON(!node->nport->p2p_winner);
1148
1149 rnode = efc_node_find(nport, node->nport->p2p_remote_port_id);
1150 if (rnode) {
1151
1152
1153
1154
1155
1156 node_printf(node,
1157 "Node with fc_id x%x already exists\n",
1158 rnode->rnode.fc_id);
1159 } else {
1160
1161
1162
1163
1164 rnode = efc_node_alloc(nport,
1165 nport->p2p_remote_port_id,
1166 false, false);
1167 if (!rnode) {
1168 efc_log_err(efc, "node alloc failed\n");
1169 return;
1170 }
1171
1172 efc_fabric_notify_topology(node);
1173
1174 efc_node_transition(rnode, __efc_p2p_rnode_init,
1175 NULL);
1176 }
1177
1178
1179
1180
1181
1182 if (node->rnode.fc_id == 0) {
1183
1184
1185
1186
1187
1188
1189 efc_node_init_device(node, false);
1190 } else {
1191
1192
1193
1194
1195 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
1196 efc_fabric_initiate_shutdown(node);
1197 }
1198 break;
1199 }
1200
1201 default:
1202 __efc_fabric_common(__func__, ctx, evt, arg);
1203 }
1204}
1205
1206void
1207__efc_p2p_rnode_init(struct efc_sm_ctx *ctx,
1208 enum efc_sm_event evt, void *arg)
1209{
1210 struct efc_node_cb *cbdata = arg;
1211 struct efc_node *node = ctx->app;
1212
1213 efc_node_evt_set(ctx, evt, __func__);
1214
1215 node_sm_trace();
1216
1217 switch (evt) {
1218 case EFC_EVT_ENTER:
1219
1220 efc_send_plogi(node);
1221 efc_node_transition(node, __efc_p2p_wait_plogi_rsp, NULL);
1222 break;
1223
1224 case EFC_EVT_ABTS_RCVD:
1225
1226 efc_send_bls_acc(node, cbdata->header->dma.virt);
1227
1228 break;
1229
1230 default:
1231 __efc_fabric_common(__func__, ctx, evt, arg);
1232 }
1233}
1234
1235void
1236__efc_p2p_wait_flogi_acc_cmpl(struct efc_sm_ctx *ctx,
1237 enum efc_sm_event evt, void *arg)
1238{
1239 struct efc_node_cb *cbdata = arg;
1240 struct efc_node *node = ctx->app;
1241
1242 efc_node_evt_set(ctx, evt, __func__);
1243
1244 node_sm_trace();
1245
1246 switch (evt) {
1247 case EFC_EVT_ENTER:
1248 efc_node_hold_frames(node);
1249 break;
1250
1251 case EFC_EVT_EXIT:
1252 efc_node_accept_frames(node);
1253 break;
1254
1255 case EFC_EVT_SRRS_ELS_CMPL_OK:
1256 WARN_ON(!node->els_cmpl_cnt);
1257 node->els_cmpl_cnt--;
1258
1259
1260 if (node->nport->p2p_winner) {
1261 efc_node_transition(node,
1262 __efc_p2p_wait_domain_attach,
1263 NULL);
1264 if (!node->nport->domain->attached) {
1265 node_printf(node, "Domain not attached\n");
1266 efc_domain_attach(node->nport->domain,
1267 node->nport->p2p_port_id);
1268 } else {
1269 node_printf(node, "Domain already attached\n");
1270 efc_node_post_event(node,
1271 EFC_EVT_DOMAIN_ATTACH_OK,
1272 NULL);
1273 }
1274 } else {
1275
1276
1277
1278
1279
1280
1281
1282
1283 efc_node_init_device(node, false);
1284 }
1285 break;
1286
1287 case EFC_EVT_SRRS_ELS_CMPL_FAIL:
1288
1289
1290
1291
1292
1293 node_printf(node, "FLOGI LS_ACC failed, shutting down\n");
1294 WARN_ON(!node->els_cmpl_cnt);
1295 node->els_cmpl_cnt--;
1296 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
1297 efc_fabric_initiate_shutdown(node);
1298 break;
1299
1300 case EFC_EVT_ABTS_RCVD: {
1301
1302 efc_send_bls_acc(node, cbdata->header->dma.virt);
1303 break;
1304 }
1305
1306 default:
1307 __efc_fabric_common(__func__, ctx, evt, arg);
1308 }
1309}
1310
1311void
1312__efc_p2p_wait_plogi_rsp(struct efc_sm_ctx *ctx,
1313 enum efc_sm_event evt, void *arg)
1314{
1315 struct efc_node_cb *cbdata = arg;
1316 struct efc_node *node = ctx->app;
1317
1318 efc_node_evt_set(ctx, evt, __func__);
1319
1320 node_sm_trace();
1321
1322 switch (evt) {
1323 case EFC_EVT_SRRS_ELS_REQ_OK: {
1324 int rc;
1325
1326 if (efc_node_check_els_req(ctx, evt, arg, ELS_PLOGI,
1327 __efc_fabric_common, __func__)) {
1328 return;
1329 }
1330 WARN_ON(!node->els_req_cnt);
1331 node->els_req_cnt--;
1332
1333 efc_node_save_sparms(node, cbdata->els_rsp.virt);
1334 rc = efc_node_attach(node);
1335 efc_node_transition(node, __efc_p2p_wait_node_attach, NULL);
1336 if (rc < 0)
1337 efc_node_post_event(node, EFC_EVT_NODE_ATTACH_FAIL,
1338 NULL);
1339 break;
1340 }
1341 case EFC_EVT_SRRS_ELS_REQ_FAIL: {
1342 if (efc_node_check_els_req(ctx, evt, arg, ELS_PLOGI,
1343 __efc_fabric_common, __func__)) {
1344 return;
1345 }
1346 node_printf(node, "PLOGI failed, shutting down\n");
1347 WARN_ON(!node->els_req_cnt);
1348 node->els_req_cnt--;
1349 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
1350 efc_fabric_initiate_shutdown(node);
1351 break;
1352 }
1353
1354 case EFC_EVT_PLOGI_RCVD: {
1355 struct fc_frame_header *hdr = cbdata->header->dma.virt;
1356
1357 if (node->efc->external_loopback) {
1358 efc_send_plogi_acc(node, be16_to_cpu(hdr->fh_ox_id));
1359 } else {
1360
1361
1362
1363
1364 __efc_fabric_common(__func__, ctx, evt, arg);
1365 }
1366 break;
1367 }
1368 case EFC_EVT_PRLI_RCVD:
1369
1370
1371
1372
1373
1374
1375
1376 efc_process_prli_payload(node, cbdata->payload->dma.virt);
1377 efc_send_ls_acc_after_attach(node,
1378 cbdata->header->dma.virt,
1379 EFC_NODE_SEND_LS_ACC_PRLI);
1380 efc_node_transition(node, __efc_p2p_wait_plogi_rsp_recvd_prli,
1381 NULL);
1382 break;
1383 default:
1384 __efc_fabric_common(__func__, ctx, evt, arg);
1385 }
1386}
1387
1388void
1389__efc_p2p_wait_plogi_rsp_recvd_prli(struct efc_sm_ctx *ctx,
1390 enum efc_sm_event evt, void *arg)
1391{
1392 struct efc_node_cb *cbdata = arg;
1393 struct efc_node *node = ctx->app;
1394
1395 efc_node_evt_set(ctx, evt, __func__);
1396
1397 node_sm_trace();
1398
1399 switch (evt) {
1400 case EFC_EVT_ENTER:
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412 efc_node_hold_frames(node);
1413 break;
1414
1415 case EFC_EVT_EXIT:
1416 efc_node_accept_frames(node);
1417 break;
1418
1419 case EFC_EVT_SRRS_ELS_REQ_OK: {
1420 int rc;
1421
1422
1423 if (efc_node_check_els_req(ctx, evt, arg, ELS_PLOGI,
1424 __efc_fabric_common, __func__)) {
1425 return;
1426 }
1427 WARN_ON(!node->els_req_cnt);
1428 node->els_req_cnt--;
1429
1430 efc_node_save_sparms(node, cbdata->els_rsp.virt);
1431 rc = efc_node_attach(node);
1432 efc_node_transition(node, __efc_p2p_wait_node_attach, NULL);
1433 if (rc < 0)
1434 efc_node_post_event(node, EFC_EVT_NODE_ATTACH_FAIL,
1435 NULL);
1436 break;
1437 }
1438 case EFC_EVT_SRRS_ELS_REQ_FAIL:
1439 case EFC_EVT_SRRS_ELS_REQ_RJT:
1440
1441 if (efc_node_check_els_req(ctx, evt, arg, ELS_PLOGI,
1442 __efc_fabric_common, __func__)) {
1443 return;
1444 }
1445 WARN_ON(!node->els_req_cnt);
1446 node->els_req_cnt--;
1447 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
1448 efc_fabric_initiate_shutdown(node);
1449 break;
1450
1451 default:
1452 __efc_fabric_common(__func__, ctx, evt, arg);
1453 }
1454}
1455
1456void
1457__efc_p2p_wait_node_attach(struct efc_sm_ctx *ctx,
1458 enum efc_sm_event evt, void *arg)
1459{
1460 struct efc_node_cb *cbdata = arg;
1461 struct efc_node *node = ctx->app;
1462
1463 efc_node_evt_set(ctx, evt, __func__);
1464
1465 node_sm_trace();
1466
1467 switch (evt) {
1468 case EFC_EVT_ENTER:
1469 efc_node_hold_frames(node);
1470 break;
1471
1472 case EFC_EVT_EXIT:
1473 efc_node_accept_frames(node);
1474 break;
1475
1476 case EFC_EVT_NODE_ATTACH_OK:
1477 node->attached = true;
1478 switch (node->send_ls_acc) {
1479 case EFC_NODE_SEND_LS_ACC_PRLI: {
1480 efc_d_send_prli_rsp(node->ls_acc_io,
1481 node->ls_acc_oxid);
1482 node->send_ls_acc = EFC_NODE_SEND_LS_ACC_NONE;
1483 node->ls_acc_io = NULL;
1484 break;
1485 }
1486 case EFC_NODE_SEND_LS_ACC_PLOGI:
1487 case EFC_NODE_SEND_LS_ACC_NONE:
1488 default:
1489
1490
1491 efc_node_transition(node, __efc_d_port_logged_in,
1492 NULL);
1493 break;
1494 }
1495 break;
1496
1497 case EFC_EVT_NODE_ATTACH_FAIL:
1498
1499 node->attached = false;
1500 node_printf(node, "Node attach failed\n");
1501 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
1502 efc_fabric_initiate_shutdown(node);
1503 break;
1504
1505 case EFC_EVT_SHUTDOWN:
1506 node_printf(node, "%s received\n", efc_sm_event_name(evt));
1507 node->shutdown_reason = EFC_NODE_SHUTDOWN_DEFAULT;
1508 efc_node_transition(node,
1509 __efc_fabric_wait_attach_evt_shutdown,
1510 NULL);
1511 break;
1512 case EFC_EVT_PRLI_RCVD:
1513 node_printf(node, "%s: PRLI received before node is attached\n",
1514 efc_sm_event_name(evt));
1515 efc_process_prli_payload(node, cbdata->payload->dma.virt);
1516 efc_send_ls_acc_after_attach(node,
1517 cbdata->header->dma.virt,
1518 EFC_NODE_SEND_LS_ACC_PRLI);
1519 break;
1520
1521 default:
1522 __efc_fabric_common(__func__, ctx, evt, arg);
1523 }
1524}
1525
1526int
1527efc_p2p_setup(struct efc_nport *nport)
1528{
1529 struct efc *efc = nport->efc;
1530 int rnode_winner;
1531
1532 rnode_winner = efc_rnode_is_winner(nport);
1533
1534
1535 if (rnode_winner == 1) {
1536 nport->p2p_remote_port_id = 0;
1537 nport->p2p_port_id = 0;
1538 nport->p2p_winner = false;
1539 } else if (rnode_winner == 0) {
1540 nport->p2p_remote_port_id = 2;
1541 nport->p2p_port_id = 1;
1542 nport->p2p_winner = true;
1543 } else {
1544
1545 if (nport->efc->external_loopback) {
1546
1547
1548
1549
1550
1551 efc_log_debug(efc,
1552 "External loopback mode enabled\n");
1553 nport->p2p_remote_port_id = 1;
1554 nport->p2p_port_id = 1;
1555 nport->p2p_winner = true;
1556 } else {
1557 efc_log_warn(efc,
1558 "failed to determine p2p winner\n");
1559 return rnode_winner;
1560 }
1561 }
1562 return 0;
1563}
1564