1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "bfad_drv.h"
19#include "bfa_fcs.h"
20#include "bfa_fcbuild.h"
21#include "bfa_fc.h"
22
23BFA_TRC_FILE(FCS, PORT);
24
25static void bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
26 struct fchs_s *rx_fchs, u8 reason_code,
27 u8 reason_code_expl);
28static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
29 struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
30static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
31static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
32static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
33static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
34static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
35static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
36static void bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
37 struct fchs_s *rx_fchs,
38 struct fc_echo_s *echo, u16 len);
39static void bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
40 struct fchs_s *rx_fchs,
41 struct fc_rnid_cmd_s *rnid, u16 len);
42static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
43 struct fc_rnid_general_topology_data_s *gen_topo_data);
44
45static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
46static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
47static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
48
49static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
50static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
51static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
52
53static struct {
54 void (*init) (struct bfa_fcs_lport_s *port);
55 void (*online) (struct bfa_fcs_lport_s *port);
56 void (*offline) (struct bfa_fcs_lport_s *port);
57} __port_action[] = {
58 {
59 bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
60 bfa_fcs_lport_unknown_offline}, {
61 bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
62 bfa_fcs_lport_fab_offline}, {
63 bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
64 bfa_fcs_lport_n2n_offline},
65 };
66
67
68
69
70
71enum bfa_fcs_lport_event {
72 BFA_FCS_PORT_SM_CREATE = 1,
73 BFA_FCS_PORT_SM_ONLINE = 2,
74 BFA_FCS_PORT_SM_OFFLINE = 3,
75 BFA_FCS_PORT_SM_DELETE = 4,
76 BFA_FCS_PORT_SM_DELRPORT = 5,
77};
78
79static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
80 enum bfa_fcs_lport_event event);
81static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
82 enum bfa_fcs_lport_event event);
83static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
84 enum bfa_fcs_lport_event event);
85static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
86 enum bfa_fcs_lport_event event);
87static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
88 enum bfa_fcs_lport_event event);
89
90static void
91bfa_fcs_lport_sm_uninit(
92 struct bfa_fcs_lport_s *port,
93 enum bfa_fcs_lport_event event)
94{
95 bfa_trc(port->fcs, port->port_cfg.pwwn);
96 bfa_trc(port->fcs, event);
97
98 switch (event) {
99 case BFA_FCS_PORT_SM_CREATE:
100 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
101 break;
102
103 default:
104 bfa_sm_fault(port->fcs, event);
105 }
106}
107
108static void
109bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
110 enum bfa_fcs_lport_event event)
111{
112 bfa_trc(port->fcs, port->port_cfg.pwwn);
113 bfa_trc(port->fcs, event);
114
115 switch (event) {
116 case BFA_FCS_PORT_SM_ONLINE:
117 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
118 bfa_fcs_lport_online_actions(port);
119 break;
120
121 case BFA_FCS_PORT_SM_DELETE:
122 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
123 bfa_fcs_lport_deleted(port);
124 break;
125
126 case BFA_FCS_PORT_SM_OFFLINE:
127 break;
128
129 default:
130 bfa_sm_fault(port->fcs, event);
131 }
132}
133
134static void
135bfa_fcs_lport_sm_online(
136 struct bfa_fcs_lport_s *port,
137 enum bfa_fcs_lport_event event)
138{
139 struct bfa_fcs_rport_s *rport;
140 struct list_head *qe, *qen;
141
142 bfa_trc(port->fcs, port->port_cfg.pwwn);
143 bfa_trc(port->fcs, event);
144
145 switch (event) {
146 case BFA_FCS_PORT_SM_OFFLINE:
147 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
148 bfa_fcs_lport_offline_actions(port);
149 break;
150
151 case BFA_FCS_PORT_SM_DELETE:
152
153 __port_action[port->fabric->fab_type].offline(port);
154
155 if (port->num_rports == 0) {
156 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
157 bfa_fcs_lport_deleted(port);
158 } else {
159 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
160 list_for_each_safe(qe, qen, &port->rport_q) {
161 rport = (struct bfa_fcs_rport_s *) qe;
162 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
163 }
164 }
165 break;
166
167 case BFA_FCS_PORT_SM_DELRPORT:
168 break;
169
170 default:
171 bfa_sm_fault(port->fcs, event);
172 }
173}
174
175static void
176bfa_fcs_lport_sm_offline(
177 struct bfa_fcs_lport_s *port,
178 enum bfa_fcs_lport_event event)
179{
180 struct bfa_fcs_rport_s *rport;
181 struct list_head *qe, *qen;
182
183 bfa_trc(port->fcs, port->port_cfg.pwwn);
184 bfa_trc(port->fcs, event);
185
186 switch (event) {
187 case BFA_FCS_PORT_SM_ONLINE:
188 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
189 bfa_fcs_lport_online_actions(port);
190 break;
191
192 case BFA_FCS_PORT_SM_DELETE:
193 if (port->num_rports == 0) {
194 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
195 bfa_fcs_lport_deleted(port);
196 } else {
197 bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
198 list_for_each_safe(qe, qen, &port->rport_q) {
199 rport = (struct bfa_fcs_rport_s *) qe;
200 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
201 }
202 }
203 break;
204
205 case BFA_FCS_PORT_SM_DELRPORT:
206 case BFA_FCS_PORT_SM_OFFLINE:
207 break;
208
209 default:
210 bfa_sm_fault(port->fcs, event);
211 }
212}
213
214static void
215bfa_fcs_lport_sm_deleting(
216 struct bfa_fcs_lport_s *port,
217 enum bfa_fcs_lport_event event)
218{
219 bfa_trc(port->fcs, port->port_cfg.pwwn);
220 bfa_trc(port->fcs, event);
221
222 switch (event) {
223 case BFA_FCS_PORT_SM_DELRPORT:
224 if (port->num_rports == 0) {
225 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
226 bfa_fcs_lport_deleted(port);
227 }
228 break;
229
230 default:
231 bfa_sm_fault(port->fcs, event);
232 }
233}
234
235
236
237
238
239
240
241
242static void
243bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
244 u8 reason_code, u8 reason_code_expl)
245{
246 struct fchs_s fchs;
247 struct bfa_fcxp_s *fcxp;
248 struct bfa_rport_s *bfa_rport = NULL;
249 int len;
250
251 bfa_trc(port->fcs, rx_fchs->d_id);
252 bfa_trc(port->fcs, rx_fchs->s_id);
253
254 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
255 if (!fcxp)
256 return;
257
258 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
259 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
260 rx_fchs->ox_id, reason_code, reason_code_expl);
261
262 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
263 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
264 FC_MAX_PDUSZ, 0);
265}
266
267
268
269
270static void
271bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
272 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
273{
274 struct bfa_fcs_rport_s *rport;
275
276 bfa_trc(port->fcs, rx_fchs->d_id);
277 bfa_trc(port->fcs, rx_fchs->s_id);
278
279
280
281
282 if (__fcs_min_cfg(port->fcs)) {
283 bfa_trc(port->fcs, rx_fchs->s_id);
284 return;
285 }
286
287 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
288 bfa_trc(port->fcs, rx_fchs->s_id);
289
290
291
292 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
293 FC_LS_RJT_RSN_PROTOCOL_ERROR,
294 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
295 return;
296 }
297
298
299
300
301 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
302 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
303 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
304 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
305
306 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
307 FC_LS_RJT_RSN_PROTOCOL_ERROR,
308 FC_LS_RJT_EXP_INVALID_NPORT_ID);
309 return;
310 }
311 port->pid = rx_fchs->d_id;
312 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
313 }
314
315
316
317
318 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
319 if (rport) {
320
321
322
323 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
324 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
325 (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
326 port->pid = rx_fchs->d_id;
327 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
328 rport->pid = rx_fchs->s_id;
329 }
330 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
331 return;
332 }
333
334
335
336
337 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
338 if (!rport) {
339
340
341
342 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
343 return;
344 }
345
346
347
348
349 if (rport->pwwn) {
350
351
352
353
354 WARN_ON(rport->pwwn == plogi->port_name);
355 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
356
357
358
359
360 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
361 return;
362 }
363
364
365
366
367 WARN_ON(rport->pwwn != WWN_NULL);
368 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
369}
370
371
372
373
374
375static void
376bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
377 struct fc_echo_s *echo, u16 rx_len)
378{
379 struct fchs_s fchs;
380 struct bfa_fcxp_s *fcxp;
381 struct bfa_rport_s *bfa_rport = NULL;
382 int len, pyld_len;
383
384 bfa_trc(port->fcs, rx_fchs->s_id);
385 bfa_trc(port->fcs, rx_fchs->d_id);
386
387 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
388 if (!fcxp)
389 return;
390
391 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
392 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
393 rx_fchs->ox_id);
394
395
396
397
398 pyld_len = rx_len - sizeof(struct fchs_s);
399 bfa_trc(port->fcs, rx_len);
400 bfa_trc(port->fcs, pyld_len);
401
402 if (pyld_len > len)
403 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
404 sizeof(struct fc_echo_s), (echo + 1),
405 (pyld_len - sizeof(struct fc_echo_s)));
406
407 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
408 BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
409 FC_MAX_PDUSZ, 0);
410}
411
412
413
414
415
416static void
417bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
418 struct fc_rnid_cmd_s *rnid, u16 rx_len)
419{
420 struct fc_rnid_common_id_data_s common_id_data;
421 struct fc_rnid_general_topology_data_s gen_topo_data;
422 struct fchs_s fchs;
423 struct bfa_fcxp_s *fcxp;
424 struct bfa_rport_s *bfa_rport = NULL;
425 u16 len;
426 u32 data_format;
427
428 bfa_trc(port->fcs, rx_fchs->s_id);
429 bfa_trc(port->fcs, rx_fchs->d_id);
430 bfa_trc(port->fcs, rx_len);
431
432 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
433 if (!fcxp)
434 return;
435
436
437
438
439
440
441
442 bfa_trc(port->fcs, rnid->node_id_data_format);
443 if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
444 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
445
446
447
448 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
449 } else {
450 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
451 }
452
453
454
455
456 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
457 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
458
459 len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
460 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
461 rx_fchs->ox_id, data_format, &common_id_data,
462 &gen_topo_data);
463
464 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
465 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
466 FC_MAX_PDUSZ, 0);
467}
468
469
470
471
472static void
473bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
474 struct fc_rnid_general_topology_data_s *gen_topo_data)
475{
476 memset(gen_topo_data, 0,
477 sizeof(struct fc_rnid_general_topology_data_s));
478
479 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
480 gen_topo_data->phy_port_num = 0;
481 gen_topo_data->num_attached_nodes = cpu_to_be32(1);
482}
483
484static void
485bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
486{
487 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
488 char lpwwn_buf[BFA_STRING_32];
489
490 bfa_trc(port->fcs, port->fabric->oper_type);
491
492 __port_action[port->fabric->fab_type].init(port);
493 __port_action[port->fabric->fab_type].online(port);
494
495 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
496 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
497 "Logical port online: WWN = %s Role = %s\n",
498 lpwwn_buf, "Initiator");
499
500 bfad->bfad_flags |= BFAD_PORT_ONLINE;
501}
502
503static void
504bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
505{
506 struct list_head *qe, *qen;
507 struct bfa_fcs_rport_s *rport;
508 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
509 char lpwwn_buf[BFA_STRING_32];
510
511 bfa_trc(port->fcs, port->fabric->oper_type);
512
513 __port_action[port->fabric->fab_type].offline(port);
514
515 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
516 if (bfa_sm_cmp_state(port->fabric,
517 bfa_fcs_fabric_sm_online) == BFA_TRUE)
518 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
519 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
520 lpwwn_buf, "Initiator");
521 else
522 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
523 "Logical port taken offline: WWN = %s Role = %s\n",
524 lpwwn_buf, "Initiator");
525
526 list_for_each_safe(qe, qen, &port->rport_q) {
527 rport = (struct bfa_fcs_rport_s *) qe;
528 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
529 }
530}
531
532static void
533bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
534{
535 WARN_ON(1);
536}
537
538static void
539bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
540{
541 WARN_ON(1);
542}
543
544static void
545bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
546{
547 WARN_ON(1);
548}
549
550static void
551bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
552{
553 struct fchs_s fchs;
554 struct bfa_fcxp_s *fcxp;
555 int len;
556
557 bfa_trc(port->fcs, rx_fchs->d_id);
558 bfa_trc(port->fcs, rx_fchs->s_id);
559
560 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
561 if (!fcxp)
562 return;
563
564 len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
565 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
566 rx_fchs->ox_id, 0);
567
568 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
569 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
570 FC_MAX_PDUSZ, 0);
571}
572static void
573bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
574{
575 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
576 char lpwwn_buf[BFA_STRING_32];
577
578 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
579 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
580 "Logical port deleted: WWN = %s Role = %s\n",
581 lpwwn_buf, "Initiator");
582
583
584 if (port->vport) {
585 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
586 port->fabric->vf_drv,
587 port->vport ? port->vport->vport_drv : NULL);
588 bfa_fcs_vport_delete_comp(port->vport);
589 } else {
590 bfa_wc_down(&port->fabric->wc);
591 }
592}
593
594
595
596
597
598void
599bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
600 struct fchs_s *fchs, u16 len)
601{
602 u32 pid = fchs->s_id;
603 struct bfa_fcs_rport_s *rport = NULL;
604 struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
605
606 bfa_stats(lport, uf_recvs);
607 bfa_trc(lport->fcs, fchs->type);
608
609 if (!bfa_fcs_lport_is_online(lport)) {
610 bfa_stats(lport, uf_recv_drops);
611 return;
612 }
613
614
615
616
617
618
619
620 if ((fchs->type == FC_TYPE_ELS) &&
621 (els_cmd->els_code == FC_ELS_PLOGI)) {
622 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
623 return;
624 }
625
626
627
628
629 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
630 bfa_fcs_lport_echo(lport, fchs,
631 (struct fc_echo_s *)els_cmd, len);
632 return;
633 }
634
635
636
637
638 if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
639 bfa_fcs_lport_rnid(lport, fchs,
640 (struct fc_rnid_cmd_s *) els_cmd, len);
641 return;
642 }
643
644 if (fchs->type == FC_TYPE_BLS) {
645 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
646 (fchs->cat_info == FC_CAT_ABTS))
647 bfa_fcs_lport_abts_acc(lport, fchs);
648 return;
649 }
650
651
652
653 rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
654 if (rport) {
655 bfa_trc(rport->fcs, fchs->s_id);
656 bfa_trc(rport->fcs, fchs->d_id);
657 bfa_trc(rport->fcs, fchs->type);
658
659 bfa_fcs_rport_uf_recv(rport, fchs, len);
660 return;
661 }
662
663
664
665
666 if (fchs->type != FC_TYPE_ELS) {
667 bfa_trc(lport->fcs, fchs->s_id);
668 bfa_trc(lport->fcs, fchs->d_id);
669
670 if (fchs->type != FC_TYPE_FC_FSS)
671 bfa_sm_fault(lport->fcs, fchs->type);
672 return;
673 }
674
675 bfa_trc(lport->fcs, els_cmd->els_code);
676 if (els_cmd->els_code == FC_ELS_RSCN) {
677 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
678 return;
679 }
680
681 if (els_cmd->els_code == FC_ELS_LOGO) {
682
683
684
685 return;
686 }
687
688 if (els_cmd->els_code == FC_ELS_PRLI) {
689
690
691
692 return;
693 }
694
695
696
697
698 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
699 FC_LS_RJT_EXP_NO_ADDL_INFO);
700
701}
702
703
704
705
706struct bfa_fcs_rport_s *
707bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
708{
709 struct bfa_fcs_rport_s *rport;
710 struct list_head *qe;
711
712 list_for_each(qe, &port->rport_q) {
713 rport = (struct bfa_fcs_rport_s *) qe;
714 if (rport->pid == pid)
715 return rport;
716 }
717
718 bfa_trc(port->fcs, pid);
719 return NULL;
720}
721
722
723
724
725struct bfa_fcs_rport_s *
726bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
727{
728 struct bfa_fcs_rport_s *rport;
729 struct list_head *qe;
730
731 list_for_each(qe, &port->rport_q) {
732 rport = (struct bfa_fcs_rport_s *) qe;
733 if (wwn_is_equal(rport->pwwn, pwwn))
734 return rport;
735 }
736
737 bfa_trc(port->fcs, pwwn);
738 return NULL;
739}
740
741
742
743
744struct bfa_fcs_rport_s *
745bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
746{
747 struct bfa_fcs_rport_s *rport;
748 struct list_head *qe;
749
750 list_for_each(qe, &port->rport_q) {
751 rport = (struct bfa_fcs_rport_s *) qe;
752 if (wwn_is_equal(rport->nwwn, nwwn))
753 return rport;
754 }
755
756 bfa_trc(port->fcs, nwwn);
757 return NULL;
758}
759
760
761
762
763void
764bfa_fcs_lport_add_rport(
765 struct bfa_fcs_lport_s *port,
766 struct bfa_fcs_rport_s *rport)
767{
768 list_add_tail(&rport->qe, &port->rport_q);
769 port->num_rports++;
770}
771
772
773
774
775void
776bfa_fcs_lport_del_rport(
777 struct bfa_fcs_lport_s *port,
778 struct bfa_fcs_rport_s *rport)
779{
780 WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
781 list_del(&rport->qe);
782 port->num_rports--;
783
784 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
785}
786
787
788
789
790
791void
792bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
793{
794 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
795}
796
797
798
799
800
801void
802bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
803{
804 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
805}
806
807
808
809
810
811
812
813void
814bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
815{
816 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
817}
818
819
820
821
822bfa_boolean_t
823bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
824{
825 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
826}
827
828
829
830
831void
832bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
833 u16 vf_id, struct bfa_fcs_vport_s *vport)
834{
835 lport->fcs = fcs;
836 lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
837 lport->vport = vport;
838 lport->lp_tag = (vport) ? vport->lps->lp_tag :
839 lport->fabric->lps->lp_tag;
840
841 INIT_LIST_HEAD(&lport->rport_q);
842 lport->num_rports = 0;
843}
844
845
846
847
848
849
850void
851bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
852 struct bfa_lport_cfg_s *port_cfg)
853{
854 struct bfa_fcs_vport_s *vport = lport->vport;
855 struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
856 char lpwwn_buf[BFA_STRING_32];
857
858 lport->port_cfg = *port_cfg;
859
860 lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
861 lport->port_cfg.roles,
862 lport->fabric->vf_drv,
863 vport ? vport->vport_drv : NULL);
864
865 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
866 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
867 "New logical port created: WWN = %s Role = %s\n",
868 lpwwn_buf, "Initiator");
869
870 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
871 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
872}
873
874
875
876
877
878void
879bfa_fcs_lport_get_attr(
880 struct bfa_fcs_lport_s *port,
881 struct bfa_lport_attr_s *port_attr)
882{
883 if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
884 port_attr->pid = port->pid;
885 else
886 port_attr->pid = 0;
887
888 port_attr->port_cfg = port->port_cfg;
889
890 if (port->fabric) {
891 port_attr->port_type = port->fabric->oper_type;
892 port_attr->loopback = bfa_sm_cmp_state(port->fabric,
893 bfa_fcs_fabric_sm_loopback);
894 port_attr->authfail =
895 bfa_sm_cmp_state(port->fabric,
896 bfa_fcs_fabric_sm_auth_failed);
897 port_attr->fabric_name = bfa_fcs_lport_get_fabric_name(port);
898 memcpy(port_attr->fabric_ip_addr,
899 bfa_fcs_lport_get_fabric_ipaddr(port),
900 BFA_FCS_FABRIC_IPADDR_SZ);
901
902 if (port->vport != NULL) {
903 port_attr->port_type = BFA_PORT_TYPE_VPORT;
904 port_attr->fpma_mac =
905 port->vport->lps->lp_mac;
906 } else {
907 port_attr->fpma_mac =
908 port->fabric->lps->lp_mac;
909 }
910 } else {
911 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
912 port_attr->state = BFA_LPORT_UNINIT;
913 }
914}
915
916
917
918
919
920
921
922
923static void
924bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
925{
926 bfa_fcs_lport_ns_init(port);
927 bfa_fcs_lport_scn_init(port);
928 bfa_fcs_lport_ms_init(port);
929}
930
931
932
933
934static void
935bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
936{
937 bfa_fcs_lport_ns_online(port);
938 bfa_fcs_lport_scn_online(port);
939}
940
941
942
943
944static void
945bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
946{
947 bfa_fcs_lport_ns_offline(port);
948 bfa_fcs_lport_scn_offline(port);
949 bfa_fcs_lport_ms_offline(port);
950}
951
952
953
954
955
956
957
958
959static void
960bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
961{
962}
963
964
965
966
967static void
968bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
969{
970 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
971 struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
972 struct bfa_fcs_rport_s *rport;
973
974 bfa_trc(port->fcs, pcfg->pwwn);
975
976
977
978
979
980
981
982
983
984 if (memcmp
985 ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
986 sizeof(wwn_t)) > 0) {
987 port->pid = N2N_LOCAL_PID;
988 bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
989
990
991
992 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
993 n2n_port->rem_port_wwn);
994 if (rport) {
995 bfa_trc(port->fcs, rport->pid);
996 bfa_trc(port->fcs, rport->pwwn);
997 rport->pid = N2N_REMOTE_PID;
998 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
999 return;
1000 }
1001
1002
1003
1004
1005
1006 if (port->num_rports > 0) {
1007 rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1008 WARN_ON(rport == NULL);
1009 if (rport) {
1010 bfa_trc(port->fcs, rport->pwwn);
1011 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1012 }
1013 }
1014 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1015 }
1016}
1017
1018
1019
1020
1021static void
1022bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1023{
1024 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1025
1026 bfa_trc(port->fcs, port->pid);
1027 port->pid = 0;
1028 n2n_port->rem_port_wwn = 0;
1029 n2n_port->reply_oxid = 0;
1030}
1031
1032#define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1033
1034
1035
1036
1037static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1038 struct bfa_fcxp_s *fcxp_alloced);
1039static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1040 struct bfa_fcxp_s *fcxp_alloced);
1041static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1042 struct bfa_fcxp_s *fcxp_alloced);
1043static void bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1044 struct bfa_fcxp_s *fcxp,
1045 void *cbarg,
1046 bfa_status_t req_status,
1047 u32 rsp_len,
1048 u32 resid_len,
1049 struct fchs_s *rsp_fchs);
1050static void bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1051 struct bfa_fcxp_s *fcxp,
1052 void *cbarg,
1053 bfa_status_t req_status,
1054 u32 rsp_len,
1055 u32 resid_len,
1056 struct fchs_s *rsp_fchs);
1057static void bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1058 struct bfa_fcxp_s *fcxp,
1059 void *cbarg,
1060 bfa_status_t req_status,
1061 u32 rsp_len,
1062 u32 resid_len,
1063 struct fchs_s *rsp_fchs);
1064static void bfa_fcs_lport_fdmi_timeout(void *arg);
1065static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1066 u8 *pyld);
1067static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1068 u8 *pyld);
1069static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1070 u8 *pyld);
1071static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1072 fdmi, u8 *pyld);
1073static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1074 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1075static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1076 struct bfa_fcs_fdmi_port_attr_s *port_attr);
1077
1078
1079
1080
1081
1082
1083
1084enum port_fdmi_event {
1085 FDMISM_EVENT_PORT_ONLINE = 1,
1086 FDMISM_EVENT_PORT_OFFLINE = 2,
1087 FDMISM_EVENT_RSP_OK = 4,
1088 FDMISM_EVENT_RSP_ERROR = 5,
1089 FDMISM_EVENT_TIMEOUT = 6,
1090 FDMISM_EVENT_RHBA_SENT = 7,
1091 FDMISM_EVENT_RPRT_SENT = 8,
1092 FDMISM_EVENT_RPA_SENT = 9,
1093};
1094
1095static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1096 enum port_fdmi_event event);
1097static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1098 struct bfa_fcs_lport_fdmi_s *fdmi,
1099 enum port_fdmi_event event);
1100static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1101 enum port_fdmi_event event);
1102static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1103 struct bfa_fcs_lport_fdmi_s *fdmi,
1104 enum port_fdmi_event event);
1105static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1106 struct bfa_fcs_lport_fdmi_s *fdmi,
1107 enum port_fdmi_event event);
1108static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1109 enum port_fdmi_event event);
1110static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1111 struct bfa_fcs_lport_fdmi_s *fdmi,
1112 enum port_fdmi_event event);
1113static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1114 struct bfa_fcs_lport_fdmi_s *fdmi,
1115 enum port_fdmi_event event);
1116static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1117 enum port_fdmi_event event);
1118static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1119 struct bfa_fcs_lport_fdmi_s *fdmi,
1120 enum port_fdmi_event event);
1121static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1122 enum port_fdmi_event event);
1123static void bfa_fcs_lport_fdmi_sm_disabled(
1124 struct bfa_fcs_lport_fdmi_s *fdmi,
1125 enum port_fdmi_event event);
1126
1127
1128
1129static void
1130bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1131 enum port_fdmi_event event)
1132{
1133 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1134
1135 bfa_trc(port->fcs, port->port_cfg.pwwn);
1136 bfa_trc(port->fcs, event);
1137
1138 fdmi->retry_cnt = 0;
1139
1140 switch (event) {
1141 case FDMISM_EVENT_PORT_ONLINE:
1142 if (port->vport) {
1143
1144
1145
1146 bfa_sm_set_state(fdmi,
1147 bfa_fcs_lport_fdmi_sm_sending_rprt);
1148 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1149 } else {
1150
1151
1152
1153
1154
1155 bfa_sm_set_state(fdmi,
1156 bfa_fcs_lport_fdmi_sm_sending_rhba);
1157 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1158 }
1159 break;
1160
1161 case FDMISM_EVENT_PORT_OFFLINE:
1162 break;
1163
1164 default:
1165 bfa_sm_fault(port->fcs, event);
1166 }
1167}
1168
1169static void
1170bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1171 enum port_fdmi_event event)
1172{
1173 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1174
1175 bfa_trc(port->fcs, port->port_cfg.pwwn);
1176 bfa_trc(port->fcs, event);
1177
1178 switch (event) {
1179 case FDMISM_EVENT_RHBA_SENT:
1180 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1181 break;
1182
1183 case FDMISM_EVENT_PORT_OFFLINE:
1184 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1185 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1186 &fdmi->fcxp_wqe);
1187 break;
1188
1189 default:
1190 bfa_sm_fault(port->fcs, event);
1191 }
1192}
1193
1194static void
1195bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1196 enum port_fdmi_event event)
1197{
1198 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1199
1200 bfa_trc(port->fcs, port->port_cfg.pwwn);
1201 bfa_trc(port->fcs, event);
1202
1203 switch (event) {
1204 case FDMISM_EVENT_RSP_ERROR:
1205
1206
1207
1208
1209 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1210 bfa_sm_set_state(fdmi,
1211 bfa_fcs_lport_fdmi_sm_rhba_retry);
1212 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1213 &fdmi->timer,
1214 bfa_fcs_lport_fdmi_timeout, fdmi,
1215 BFA_FCS_RETRY_TIMEOUT);
1216 } else {
1217
1218
1219
1220 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1221 }
1222 break;
1223
1224 case FDMISM_EVENT_RSP_OK:
1225
1226
1227
1228 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1229 fdmi->retry_cnt = 0;
1230 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1231 break;
1232
1233 case FDMISM_EVENT_PORT_OFFLINE:
1234 bfa_fcxp_discard(fdmi->fcxp);
1235 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1236 break;
1237
1238 default:
1239 bfa_sm_fault(port->fcs, event);
1240 }
1241}
1242
1243static void
1244bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1245 enum port_fdmi_event event)
1246{
1247 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1248
1249 bfa_trc(port->fcs, port->port_cfg.pwwn);
1250 bfa_trc(port->fcs, event);
1251
1252 switch (event) {
1253 case FDMISM_EVENT_TIMEOUT:
1254
1255
1256
1257 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1258 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1259 break;
1260
1261 case FDMISM_EVENT_PORT_OFFLINE:
1262 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1263 bfa_timer_stop(&fdmi->timer);
1264 break;
1265
1266 default:
1267 bfa_sm_fault(port->fcs, event);
1268 }
1269}
1270
1271
1272
1273
1274static void
1275bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1276 enum port_fdmi_event event)
1277{
1278 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1279
1280 bfa_trc(port->fcs, port->port_cfg.pwwn);
1281 bfa_trc(port->fcs, event);
1282
1283 switch (event) {
1284 case FDMISM_EVENT_RPRT_SENT:
1285 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1286 break;
1287
1288 case FDMISM_EVENT_PORT_OFFLINE:
1289 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1290 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1291 &fdmi->fcxp_wqe);
1292 break;
1293
1294 default:
1295 bfa_sm_fault(port->fcs, event);
1296 }
1297}
1298
1299static void
1300bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1301 enum port_fdmi_event event)
1302{
1303 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1304
1305 bfa_trc(port->fcs, port->port_cfg.pwwn);
1306 bfa_trc(port->fcs, event);
1307
1308 switch (event) {
1309 case FDMISM_EVENT_RSP_ERROR:
1310
1311
1312
1313
1314 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1315 bfa_sm_set_state(fdmi,
1316 bfa_fcs_lport_fdmi_sm_rprt_retry);
1317 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1318 &fdmi->timer,
1319 bfa_fcs_lport_fdmi_timeout, fdmi,
1320 BFA_FCS_RETRY_TIMEOUT);
1321
1322 } else {
1323
1324
1325
1326 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1327 fdmi->retry_cnt = 0;
1328 }
1329 break;
1330
1331 case FDMISM_EVENT_RSP_OK:
1332 fdmi->retry_cnt = 0;
1333 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1334 break;
1335
1336 case FDMISM_EVENT_PORT_OFFLINE:
1337 bfa_fcxp_discard(fdmi->fcxp);
1338 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1339 break;
1340
1341 default:
1342 bfa_sm_fault(port->fcs, event);
1343 }
1344}
1345
1346static void
1347bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1348 enum port_fdmi_event event)
1349{
1350 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1351
1352 bfa_trc(port->fcs, port->port_cfg.pwwn);
1353 bfa_trc(port->fcs, event);
1354
1355 switch (event) {
1356 case FDMISM_EVENT_TIMEOUT:
1357
1358
1359
1360 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1361 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1362 break;
1363
1364 case FDMISM_EVENT_PORT_OFFLINE:
1365 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1366 bfa_timer_stop(&fdmi->timer);
1367 break;
1368
1369 default:
1370 bfa_sm_fault(port->fcs, event);
1371 }
1372}
1373
1374
1375
1376
1377static void
1378bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1379 enum port_fdmi_event event)
1380{
1381 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1382
1383 bfa_trc(port->fcs, port->port_cfg.pwwn);
1384 bfa_trc(port->fcs, event);
1385
1386 switch (event) {
1387 case FDMISM_EVENT_RPA_SENT:
1388 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1389 break;
1390
1391 case FDMISM_EVENT_PORT_OFFLINE:
1392 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1393 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1394 &fdmi->fcxp_wqe);
1395 break;
1396
1397 default:
1398 bfa_sm_fault(port->fcs, event);
1399 }
1400}
1401
1402static void
1403bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1404 enum port_fdmi_event event)
1405{
1406 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1407
1408 bfa_trc(port->fcs, port->port_cfg.pwwn);
1409 bfa_trc(port->fcs, event);
1410
1411 switch (event) {
1412 case FDMISM_EVENT_RSP_ERROR:
1413
1414
1415
1416
1417 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1418 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1419 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1420 &fdmi->timer,
1421 bfa_fcs_lport_fdmi_timeout, fdmi,
1422 BFA_FCS_RETRY_TIMEOUT);
1423 } else {
1424
1425
1426
1427 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1428 fdmi->retry_cnt = 0;
1429 }
1430 break;
1431
1432 case FDMISM_EVENT_RSP_OK:
1433 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1434 fdmi->retry_cnt = 0;
1435 break;
1436
1437 case FDMISM_EVENT_PORT_OFFLINE:
1438 bfa_fcxp_discard(fdmi->fcxp);
1439 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1440 break;
1441
1442 default:
1443 bfa_sm_fault(port->fcs, event);
1444 }
1445}
1446
1447static void
1448bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1449 enum port_fdmi_event event)
1450{
1451 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1452
1453 bfa_trc(port->fcs, port->port_cfg.pwwn);
1454 bfa_trc(port->fcs, event);
1455
1456 switch (event) {
1457 case FDMISM_EVENT_TIMEOUT:
1458
1459
1460
1461 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1462 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1463 break;
1464
1465 case FDMISM_EVENT_PORT_OFFLINE:
1466 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1467 bfa_timer_stop(&fdmi->timer);
1468 break;
1469
1470 default:
1471 bfa_sm_fault(port->fcs, event);
1472 }
1473}
1474
1475static void
1476bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1477 enum port_fdmi_event event)
1478{
1479 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1480
1481 bfa_trc(port->fcs, port->port_cfg.pwwn);
1482 bfa_trc(port->fcs, event);
1483
1484 switch (event) {
1485 case FDMISM_EVENT_PORT_OFFLINE:
1486 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487 break;
1488
1489 default:
1490 bfa_sm_fault(port->fcs, event);
1491 }
1492}
1493
1494
1495
1496static void
1497bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1498 enum port_fdmi_event event)
1499{
1500 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1501
1502 bfa_trc(port->fcs, port->port_cfg.pwwn);
1503 bfa_trc(port->fcs, event);
1504
1505
1506}
1507
1508
1509
1510
1511static void
1512bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1513{
1514 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1515 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1516 struct fchs_s fchs;
1517 int len, attr_len;
1518 struct bfa_fcxp_s *fcxp;
1519 u8 *pyld;
1520
1521 bfa_trc(port->fcs, port->port_cfg.pwwn);
1522
1523 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1524 if (!fcxp) {
1525 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1526 bfa_fcs_lport_fdmi_send_rhba, fdmi);
1527 return;
1528 }
1529 fdmi->fcxp = fcxp;
1530
1531 pyld = bfa_fcxp_get_reqbuf(fcxp);
1532 memset(pyld, 0, FC_MAX_PDUSZ);
1533
1534 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1535 FDMI_RHBA);
1536
1537 attr_len =
1538 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1539 (u8 *) ((struct ct_hdr_s *) pyld
1540 + 1));
1541
1542 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1543 FC_CLASS_3, (len + attr_len), &fchs,
1544 bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1545 FC_MAX_PDUSZ, FC_FCCT_TOV);
1546
1547 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1548}
1549
1550static u16
1551bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1552{
1553 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1554 struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1555 struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1556 struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1557 struct fdmi_attr_s *attr;
1558 u8 *curr_ptr;
1559 u16 len, count;
1560 u16 templen;
1561
1562
1563
1564
1565 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1566
1567 rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1568 rhba->port_list.num_ports = cpu_to_be32(1);
1569 rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1570
1571 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1572
1573 count = 0;
1574 len += sizeof(rhba->hba_attr_blk.attr_count);
1575
1576
1577
1578
1579 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1580
1581
1582
1583
1584 attr = (struct fdmi_attr_s *) curr_ptr;
1585 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1586 templen = sizeof(wwn_t);
1587 memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1588 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1589 len += templen;
1590 count++;
1591 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1592 sizeof(templen));
1593
1594
1595
1596
1597 attr = (struct fdmi_attr_s *) curr_ptr;
1598 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1599 templen = (u16) strlen(fcs_hba_attr->manufacturer);
1600 memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1601 templen = fc_roundup(templen, sizeof(u32));
1602 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1603 len += templen;
1604 count++;
1605 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1606 sizeof(templen));
1607
1608
1609
1610
1611 attr = (struct fdmi_attr_s *) curr_ptr;
1612 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1613 templen = (u16) strlen(fcs_hba_attr->serial_num);
1614 memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1615 templen = fc_roundup(templen, sizeof(u32));
1616 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1617 len += templen;
1618 count++;
1619 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1620 sizeof(templen));
1621
1622
1623
1624
1625 attr = (struct fdmi_attr_s *) curr_ptr;
1626 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1627 templen = (u16) strlen(fcs_hba_attr->model);
1628 memcpy(attr->value, fcs_hba_attr->model, templen);
1629 templen = fc_roundup(templen, sizeof(u32));
1630 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1631 len += templen;
1632 count++;
1633 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1634 sizeof(templen));
1635
1636
1637
1638
1639 attr = (struct fdmi_attr_s *) curr_ptr;
1640 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1641 templen = (u16) strlen(fcs_hba_attr->model_desc);
1642 memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1643 templen = fc_roundup(templen, sizeof(u32));
1644 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1645 len += templen;
1646 count++;
1647 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1648 sizeof(templen));
1649
1650
1651
1652
1653 if (fcs_hba_attr->hw_version[0] != '\0') {
1654 attr = (struct fdmi_attr_s *) curr_ptr;
1655 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
1656 templen = (u16) strlen(fcs_hba_attr->hw_version);
1657 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1658 templen = fc_roundup(templen, sizeof(u32));
1659 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1660 len += templen;
1661 count++;
1662 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1663 sizeof(templen));
1664 }
1665
1666
1667
1668
1669 attr = (struct fdmi_attr_s *) curr_ptr;
1670 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1671 templen = (u16) strlen(fcs_hba_attr->driver_version);
1672 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1673 templen = fc_roundup(templen, sizeof(u32));
1674 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1675 len += templen;;
1676 count++;
1677 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1678 sizeof(templen));
1679
1680
1681
1682
1683 if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1684 attr = (struct fdmi_attr_s *) curr_ptr;
1685 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
1686 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1687 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1688 templen = fc_roundup(templen, sizeof(u32));
1689 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1690 len += templen;
1691 count++;
1692 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1693 sizeof(templen));
1694 }
1695
1696
1697
1698
1699 attr = (struct fdmi_attr_s *) curr_ptr;
1700 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
1701 templen = (u16) strlen(fcs_hba_attr->driver_version);
1702 memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1703 templen = fc_roundup(templen, sizeof(u32));
1704 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1705 len += templen;
1706 count++;
1707 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1708 sizeof(templen));
1709
1710
1711
1712
1713 if (fcs_hba_attr->os_name[0] != '\0') {
1714 attr = (struct fdmi_attr_s *) curr_ptr;
1715 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
1716 templen = (u16) strlen(fcs_hba_attr->os_name);
1717 memcpy(attr->value, fcs_hba_attr->os_name, templen);
1718 templen = fc_roundup(templen, sizeof(u32));
1719 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1720 len += templen;
1721 count++;
1722 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1723 sizeof(templen));
1724 }
1725
1726
1727
1728
1729 attr = (struct fdmi_attr_s *) curr_ptr;
1730 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
1731 templen = sizeof(fcs_hba_attr->max_ct_pyld);
1732 memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1733 len += templen;
1734 count++;
1735 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1736 sizeof(templen));
1737
1738
1739
1740
1741 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1742
1743 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1744 return len;
1745}
1746
1747static void
1748bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1749 void *cbarg, bfa_status_t req_status,
1750 u32 rsp_len, u32 resid_len,
1751 struct fchs_s *rsp_fchs)
1752{
1753 struct bfa_fcs_lport_fdmi_s *fdmi =
1754 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1755 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1756 struct ct_hdr_s *cthdr = NULL;
1757
1758 bfa_trc(port->fcs, port->port_cfg.pwwn);
1759
1760
1761
1762
1763 if (req_status != BFA_STATUS_OK) {
1764 bfa_trc(port->fcs, req_status);
1765 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1766 return;
1767 }
1768
1769 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1770 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1771
1772 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1773 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1774 return;
1775 }
1776
1777 bfa_trc(port->fcs, cthdr->reason_code);
1778 bfa_trc(port->fcs, cthdr->exp_code);
1779 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1780}
1781
1782
1783
1784
1785static void
1786bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1787{
1788 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1789 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1790 struct fchs_s fchs;
1791 u16 len, attr_len;
1792 struct bfa_fcxp_s *fcxp;
1793 u8 *pyld;
1794
1795 bfa_trc(port->fcs, port->port_cfg.pwwn);
1796
1797 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1798 if (!fcxp) {
1799 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1800 bfa_fcs_lport_fdmi_send_rprt, fdmi);
1801 return;
1802 }
1803 fdmi->fcxp = fcxp;
1804
1805 pyld = bfa_fcxp_get_reqbuf(fcxp);
1806 memset(pyld, 0, FC_MAX_PDUSZ);
1807
1808 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1809 FDMI_RPRT);
1810
1811 attr_len =
1812 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1813 (u8 *) ((struct ct_hdr_s *) pyld
1814 + 1));
1815
1816 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1817 FC_CLASS_3, len + attr_len, &fchs,
1818 bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1819 FC_MAX_PDUSZ, FC_FCCT_TOV);
1820
1821 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1822}
1823
1824
1825
1826
1827static u16
1828bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1829 u8 *pyld)
1830{
1831 struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1832 struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1833 struct fdmi_attr_s *attr;
1834 u8 *curr_ptr;
1835 u16 len;
1836 u8 count = 0;
1837 u16 templen;
1838
1839
1840
1841
1842 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1843
1844 len = sizeof(port_attrib->attr_count);
1845
1846
1847
1848
1849 curr_ptr = (u8 *) &port_attrib->port_attr;
1850
1851
1852
1853
1854 attr = (struct fdmi_attr_s *) curr_ptr;
1855 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
1856 templen = sizeof(fcs_port_attr.supp_fc4_types);
1857 memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1858 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1859 len += templen;
1860 ++count;
1861 attr->len =
1862 cpu_to_be16(templen + sizeof(attr->type) +
1863 sizeof(templen));
1864
1865
1866
1867
1868 attr = (struct fdmi_attr_s *) curr_ptr;
1869 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
1870 templen = sizeof(fcs_port_attr.supp_speed);
1871 memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
1872 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1873 len += templen;
1874 ++count;
1875 attr->len =
1876 cpu_to_be16(templen + sizeof(attr->type) +
1877 sizeof(templen));
1878
1879
1880
1881
1882 attr = (struct fdmi_attr_s *) curr_ptr;
1883 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
1884 templen = sizeof(fcs_port_attr.curr_speed);
1885 memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
1886 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1887 len += templen;
1888 ++count;
1889 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1890 sizeof(templen));
1891
1892
1893
1894
1895 attr = (struct fdmi_attr_s *) curr_ptr;
1896 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
1897 templen = sizeof(fcs_port_attr.max_frm_size);
1898 memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
1899 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1900 len += templen;
1901 ++count;
1902 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1903 sizeof(templen));
1904
1905
1906
1907
1908 if (fcs_port_attr.os_device_name[0] != '\0') {
1909 attr = (struct fdmi_attr_s *) curr_ptr;
1910 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
1911 templen = (u16) strlen(fcs_port_attr.os_device_name);
1912 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
1913 templen = fc_roundup(templen, sizeof(u32));
1914 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1915 len += templen;
1916 ++count;
1917 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1918 sizeof(templen));
1919 }
1920
1921
1922
1923 if (fcs_port_attr.host_name[0] != '\0') {
1924 attr = (struct fdmi_attr_s *) curr_ptr;
1925 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
1926 templen = (u16) strlen(fcs_port_attr.host_name);
1927 memcpy(attr->value, fcs_port_attr.host_name, templen);
1928 templen = fc_roundup(templen, sizeof(u32));
1929 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1930 len += templen;
1931 ++count;
1932 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1933 sizeof(templen));
1934 }
1935
1936
1937
1938
1939 port_attrib->attr_count = cpu_to_be32(count);
1940 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1941 return len;
1942}
1943
1944static u16
1945bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1946{
1947 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1948 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
1949 u16 len;
1950
1951 rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
1952 rprt->port_name = bfa_fcs_lport_get_pwwn(port);
1953
1954 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
1955 (u8 *) &rprt->port_attr_blk);
1956
1957 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
1958
1959 return len;
1960}
1961
1962static void
1963bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1964 void *cbarg, bfa_status_t req_status,
1965 u32 rsp_len, u32 resid_len,
1966 struct fchs_s *rsp_fchs)
1967{
1968 struct bfa_fcs_lport_fdmi_s *fdmi =
1969 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1970 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1971 struct ct_hdr_s *cthdr = NULL;
1972
1973 bfa_trc(port->fcs, port->port_cfg.pwwn);
1974
1975
1976
1977
1978 if (req_status != BFA_STATUS_OK) {
1979 bfa_trc(port->fcs, req_status);
1980 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1981 return;
1982 }
1983
1984 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1985 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1986
1987 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1988 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1989 return;
1990 }
1991
1992 bfa_trc(port->fcs, cthdr->reason_code);
1993 bfa_trc(port->fcs, cthdr->exp_code);
1994 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1995}
1996
1997
1998
1999
2000static void
2001bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2002{
2003 struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2004 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2005 struct fchs_s fchs;
2006 u16 len, attr_len;
2007 struct bfa_fcxp_s *fcxp;
2008 u8 *pyld;
2009
2010 bfa_trc(port->fcs, port->port_cfg.pwwn);
2011
2012 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2013 if (!fcxp) {
2014 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2015 bfa_fcs_lport_fdmi_send_rpa, fdmi);
2016 return;
2017 }
2018 fdmi->fcxp = fcxp;
2019
2020 pyld = bfa_fcxp_get_reqbuf(fcxp);
2021 memset(pyld, 0, FC_MAX_PDUSZ);
2022
2023 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2024 FDMI_RPA);
2025
2026 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2027 (u8 *) ((struct ct_hdr_s *) pyld + 1));
2028
2029 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2030 FC_CLASS_3, len + attr_len, &fchs,
2031 bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2032 FC_MAX_PDUSZ, FC_FCCT_TOV);
2033
2034 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2035}
2036
2037static u16
2038bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2039{
2040 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2041 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2042 u16 len;
2043
2044 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2045
2046 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2047 (u8 *) &rpa->port_attr_blk);
2048
2049 len += sizeof(rpa->port_name);
2050
2051 return len;
2052}
2053
2054static void
2055bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2056 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2057 u32 resid_len, struct fchs_s *rsp_fchs)
2058{
2059 struct bfa_fcs_lport_fdmi_s *fdmi =
2060 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2061 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2062 struct ct_hdr_s *cthdr = NULL;
2063
2064 bfa_trc(port->fcs, port->port_cfg.pwwn);
2065
2066
2067
2068
2069 if (req_status != BFA_STATUS_OK) {
2070 bfa_trc(port->fcs, req_status);
2071 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2072 return;
2073 }
2074
2075 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2076 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2077
2078 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2079 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2080 return;
2081 }
2082
2083 bfa_trc(port->fcs, cthdr->reason_code);
2084 bfa_trc(port->fcs, cthdr->exp_code);
2085 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2086}
2087
2088static void
2089bfa_fcs_lport_fdmi_timeout(void *arg)
2090{
2091 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2092
2093 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2094}
2095
2096static void
2097bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2098 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2099{
2100 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2101 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2102
2103 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2104
2105 bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2106 hba_attr->manufacturer);
2107 bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2108 hba_attr->serial_num);
2109 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2110 hba_attr->model);
2111 bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2112 hba_attr->model_desc);
2113 bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2114 hba_attr->hw_version);
2115 bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2116 hba_attr->option_rom_ver);
2117 bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2118 hba_attr->fw_version);
2119
2120 strncpy(hba_attr->driver_version, (char *)driver_info->version,
2121 sizeof(hba_attr->driver_version));
2122
2123 strncpy(hba_attr->os_name, driver_info->host_os_name,
2124 sizeof(hba_attr->os_name));
2125
2126
2127
2128
2129
2130 if (driver_info->host_os_patch[0] != '\0') {
2131 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2132 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2133 strncat(hba_attr->os_name, driver_info->host_os_patch,
2134 sizeof(driver_info->host_os_patch));
2135 }
2136
2137 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2138}
2139
2140static void
2141bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2142 struct bfa_fcs_fdmi_port_attr_s *port_attr)
2143{
2144 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2145 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2146 struct bfa_port_attr_s pport_attr;
2147
2148 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2149
2150
2151
2152
2153 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2154
2155
2156
2157
2158 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2159
2160
2161
2162
2163 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
2164
2165
2166
2167
2168 port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
2169
2170
2171
2172
2173 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2174
2175
2176
2177
2178 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2179 sizeof(port_attr->os_device_name));
2180
2181
2182
2183
2184 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2185 sizeof(port_attr->host_name));
2186
2187}
2188
2189
2190void
2191bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2192{
2193 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2194
2195 fdmi->ms = ms;
2196 if (ms->port->fcs->fdmi_enabled)
2197 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2198 else
2199 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2200}
2201
2202void
2203bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2204{
2205 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2206
2207 fdmi->ms = ms;
2208 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2209}
2210
2211void
2212bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2213{
2214 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2215
2216 fdmi->ms = ms;
2217 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2218}
2219
2220#define BFA_FCS_MS_CMD_MAX_RETRIES 2
2221
2222
2223
2224
2225static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2226 struct bfa_fcxp_s *fcxp_alloced);
2227static void bfa_fcs_lport_ms_timeout(void *arg);
2228static void bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2229 struct bfa_fcxp_s *fcxp,
2230 void *cbarg,
2231 bfa_status_t req_status,
2232 u32 rsp_len,
2233 u32 resid_len,
2234 struct fchs_s *rsp_fchs);
2235
2236static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2237 struct bfa_fcxp_s *fcxp_alloced);
2238static void bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2239 struct bfa_fcxp_s *fcxp,
2240 void *cbarg,
2241 bfa_status_t req_status,
2242 u32 rsp_len,
2243 u32 resid_len,
2244 struct fchs_s *rsp_fchs);
2245static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2246 struct bfa_fcxp_s *fcxp_alloced);
2247static void bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2248 struct bfa_fcxp_s *fcxp,
2249 void *cbarg,
2250 bfa_status_t req_status,
2251 u32 rsp_len,
2252 u32 resid_len,
2253 struct fchs_s *rsp_fchs);
2254
2255
2256
2257
2258
2259
2260
2261enum port_ms_event {
2262 MSSM_EVENT_PORT_ONLINE = 1,
2263 MSSM_EVENT_PORT_OFFLINE = 2,
2264 MSSM_EVENT_RSP_OK = 3,
2265 MSSM_EVENT_RSP_ERROR = 4,
2266 MSSM_EVENT_TIMEOUT = 5,
2267 MSSM_EVENT_FCXP_SENT = 6,
2268 MSSM_EVENT_PORT_FABRIC_RSCN = 7
2269};
2270
2271static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2272 enum port_ms_event event);
2273static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2274 enum port_ms_event event);
2275static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2276 enum port_ms_event event);
2277static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2278 enum port_ms_event event);
2279static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2280 enum port_ms_event event);
2281static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2282 enum port_ms_event event);
2283static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2284 enum port_ms_event event);
2285static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2286 enum port_ms_event event);
2287static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2288 enum port_ms_event event);
2289static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2290 enum port_ms_event event);
2291static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2292 enum port_ms_event event);
2293
2294
2295
2296static void
2297bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2298 enum port_ms_event event)
2299{
2300 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2301 bfa_trc(ms->port->fcs, event);
2302
2303 switch (event) {
2304 case MSSM_EVENT_PORT_ONLINE:
2305 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2306 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2307 break;
2308
2309 case MSSM_EVENT_PORT_OFFLINE:
2310 break;
2311
2312 default:
2313 bfa_sm_fault(ms->port->fcs, event);
2314 }
2315}
2316
2317static void
2318bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2319 enum port_ms_event event)
2320{
2321 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2322 bfa_trc(ms->port->fcs, event);
2323
2324 switch (event) {
2325 case MSSM_EVENT_FCXP_SENT:
2326 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2327 break;
2328
2329 case MSSM_EVENT_PORT_OFFLINE:
2330 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2331 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2332 &ms->fcxp_wqe);
2333 break;
2334
2335 default:
2336 bfa_sm_fault(ms->port->fcs, event);
2337 }
2338}
2339
2340static void
2341bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2342 enum port_ms_event event)
2343{
2344 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2345 bfa_trc(ms->port->fcs, event);
2346
2347 switch (event) {
2348 case MSSM_EVENT_RSP_ERROR:
2349
2350
2351
2352 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2353 ms->port->stats.ms_retries++;
2354 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2355 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2356 BFA_FCS_RETRY_TIMEOUT);
2357 break;
2358
2359 case MSSM_EVENT_RSP_OK:
2360
2361
2362
2363 bfa_fcs_lport_fdmi_online(ms);
2364
2365
2366
2367
2368 if (ms->port->vport) {
2369 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2370 break;
2371 }
2372
2373
2374
2375
2376
2377 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2378 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2379 break;
2380
2381 case MSSM_EVENT_PORT_OFFLINE:
2382 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2383 bfa_fcxp_discard(ms->fcxp);
2384 break;
2385
2386 default:
2387 bfa_sm_fault(ms->port->fcs, event);
2388 }
2389}
2390
2391static void
2392bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2393 enum port_ms_event event)
2394{
2395 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2396 bfa_trc(ms->port->fcs, event);
2397
2398 switch (event) {
2399 case MSSM_EVENT_TIMEOUT:
2400
2401
2402
2403 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2404 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2405 break;
2406
2407 case MSSM_EVENT_PORT_OFFLINE:
2408 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2409 bfa_timer_stop(&ms->timer);
2410 break;
2411
2412 default:
2413 bfa_sm_fault(ms->port->fcs, event);
2414 }
2415}
2416
2417static void
2418bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2419 enum port_ms_event event)
2420{
2421 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2422 bfa_trc(ms->port->fcs, event);
2423
2424 switch (event) {
2425 case MSSM_EVENT_PORT_OFFLINE:
2426 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2427 break;
2428
2429 case MSSM_EVENT_PORT_FABRIC_RSCN:
2430 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2431 ms->retry_cnt = 0;
2432 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2433 break;
2434
2435 default:
2436 bfa_sm_fault(ms->port->fcs, event);
2437 }
2438}
2439
2440static void
2441bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2442 enum port_ms_event event)
2443{
2444 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2445 bfa_trc(ms->port->fcs, event);
2446
2447 switch (event) {
2448 case MSSM_EVENT_FCXP_SENT:
2449 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2450 break;
2451
2452 case MSSM_EVENT_PORT_OFFLINE:
2453 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2454 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2455 &ms->fcxp_wqe);
2456 break;
2457
2458 default:
2459 bfa_sm_fault(ms->port->fcs, event);
2460 }
2461}
2462
2463static void
2464bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2465 enum port_ms_event event)
2466{
2467 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2468 bfa_trc(ms->port->fcs, event);
2469
2470 switch (event) {
2471 case MSSM_EVENT_RSP_ERROR:
2472
2473
2474
2475 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2476 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2477 ms->port->stats.ms_retries++;
2478 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2479 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2480 BFA_FCS_RETRY_TIMEOUT);
2481 } else {
2482 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2483 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2484 ms->retry_cnt = 0;
2485 }
2486 break;
2487
2488 case MSSM_EVENT_RSP_OK:
2489 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2490 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2491 break;
2492
2493 case MSSM_EVENT_PORT_OFFLINE:
2494 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2495 bfa_fcxp_discard(ms->fcxp);
2496 break;
2497
2498 default:
2499 bfa_sm_fault(ms->port->fcs, event);
2500 }
2501}
2502
2503static void
2504bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2505 enum port_ms_event event)
2506{
2507 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2508 bfa_trc(ms->port->fcs, event);
2509
2510 switch (event) {
2511 case MSSM_EVENT_TIMEOUT:
2512
2513
2514
2515 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2516 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2517 break;
2518
2519 case MSSM_EVENT_PORT_OFFLINE:
2520 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2521 bfa_timer_stop(&ms->timer);
2522 break;
2523
2524 default:
2525 bfa_sm_fault(ms->port->fcs, event);
2526 }
2527}
2528
2529
2530
2531
2532static void
2533bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2534{
2535 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2536 bfa_fcs_lport_t *port = ms->port;
2537 struct fchs_s fchs;
2538 int len;
2539 struct bfa_fcxp_s *fcxp;
2540
2541 bfa_trc(port->fcs, port->pid);
2542
2543 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2544 if (!fcxp) {
2545 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2546 bfa_fcs_lport_ms_send_gmal, ms);
2547 return;
2548 }
2549 ms->fcxp = fcxp;
2550
2551 len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2552 bfa_fcs_lport_get_fcid(port),
2553 port->fabric->lps->pr_nwwn);
2554
2555 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2556 FC_CLASS_3, len, &fchs,
2557 bfa_fcs_lport_ms_gmal_response, (void *)ms,
2558 FC_MAX_PDUSZ, FC_FCCT_TOV);
2559
2560 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2561}
2562
2563static void
2564bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2565 void *cbarg, bfa_status_t req_status,
2566 u32 rsp_len, u32 resid_len,
2567 struct fchs_s *rsp_fchs)
2568{
2569 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2570 bfa_fcs_lport_t *port = ms->port;
2571 struct ct_hdr_s *cthdr = NULL;
2572 struct fcgs_gmal_resp_s *gmal_resp;
2573 struct fcgs_gmal_entry_s *gmal_entry;
2574 u32 num_entries;
2575 u8 *rsp_str;
2576
2577 bfa_trc(port->fcs, req_status);
2578 bfa_trc(port->fcs, port->port_cfg.pwwn);
2579
2580
2581
2582
2583 if (req_status != BFA_STATUS_OK) {
2584 bfa_trc(port->fcs, req_status);
2585 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2586 return;
2587 }
2588
2589 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2590 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2591
2592 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2593 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2594
2595 num_entries = be32_to_cpu(gmal_resp->ms_len);
2596 if (num_entries == 0) {
2597 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2598 return;
2599 }
2600
2601
2602
2603
2604
2605
2606
2607 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2608 while (num_entries > 0) {
2609 if (strncmp(gmal_entry->prefix,
2610 CT_GMAL_RESP_PREFIX_HTTP,
2611 sizeof(gmal_entry->prefix)) == 0) {
2612
2613
2614
2615
2616
2617
2618 rsp_str = &(gmal_entry->prefix[0]);
2619 if (rsp_str[gmal_entry->len-1] == '/')
2620 rsp_str[gmal_entry->len-1] = 0;
2621
2622
2623 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2624 gmal_entry->ip_addr,
2625 BFA_FCS_FABRIC_IPADDR_SZ);
2626 break;
2627 } else {
2628 --num_entries;
2629 ++gmal_entry;
2630 }
2631 }
2632
2633 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2634 return;
2635 }
2636
2637 bfa_trc(port->fcs, cthdr->reason_code);
2638 bfa_trc(port->fcs, cthdr->exp_code);
2639 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2640}
2641
2642static void
2643bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2644 enum port_ms_event event)
2645{
2646 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2647 bfa_trc(ms->port->fcs, event);
2648
2649 switch (event) {
2650 case MSSM_EVENT_FCXP_SENT:
2651 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2652 break;
2653
2654 case MSSM_EVENT_PORT_OFFLINE:
2655 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2656 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2657 &ms->fcxp_wqe);
2658 break;
2659
2660 default:
2661 bfa_sm_fault(ms->port->fcs, event);
2662 }
2663}
2664
2665static void
2666bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2667 enum port_ms_event event)
2668{
2669 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2670 bfa_trc(ms->port->fcs, event);
2671
2672 switch (event) {
2673 case MSSM_EVENT_RSP_ERROR:
2674
2675
2676
2677 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2678 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2679 ms->port->stats.ms_retries++;
2680 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2681 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2682 BFA_FCS_RETRY_TIMEOUT);
2683 } else {
2684 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2685 ms->retry_cnt = 0;
2686 }
2687 break;
2688
2689 case MSSM_EVENT_RSP_OK:
2690 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2691 break;
2692
2693 case MSSM_EVENT_PORT_OFFLINE:
2694 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2695 bfa_fcxp_discard(ms->fcxp);
2696 break;
2697
2698 default:
2699 bfa_sm_fault(ms->port->fcs, event);
2700 }
2701}
2702
2703static void
2704bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2705 enum port_ms_event event)
2706{
2707 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2708 bfa_trc(ms->port->fcs, event);
2709
2710 switch (event) {
2711 case MSSM_EVENT_TIMEOUT:
2712
2713
2714
2715 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2716 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2717 break;
2718
2719 case MSSM_EVENT_PORT_OFFLINE:
2720 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2721 bfa_timer_stop(&ms->timer);
2722 break;
2723
2724 default:
2725 bfa_sm_fault(ms->port->fcs, event);
2726 }
2727}
2728
2729
2730
2731
2732static void
2733bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2734{
2735 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2736 bfa_fcs_lport_t *port = ms->port;
2737 struct fchs_s fchs;
2738 int len;
2739 struct bfa_fcxp_s *fcxp;
2740
2741 bfa_trc(port->fcs, port->pid);
2742
2743 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2744 if (!fcxp) {
2745 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2746 bfa_fcs_lport_ms_send_gfn, ms);
2747 return;
2748 }
2749 ms->fcxp = fcxp;
2750
2751 len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2752 bfa_fcs_lport_get_fcid(port),
2753 port->fabric->lps->pr_nwwn);
2754
2755 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2756 FC_CLASS_3, len, &fchs,
2757 bfa_fcs_lport_ms_gfn_response, (void *)ms,
2758 FC_MAX_PDUSZ, FC_FCCT_TOV);
2759
2760 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2761}
2762
2763static void
2764bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2765 void *cbarg, bfa_status_t req_status, u32 rsp_len,
2766 u32 resid_len, struct fchs_s *rsp_fchs)
2767{
2768 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2769 bfa_fcs_lport_t *port = ms->port;
2770 struct ct_hdr_s *cthdr = NULL;
2771 wwn_t *gfn_resp;
2772
2773 bfa_trc(port->fcs, req_status);
2774 bfa_trc(port->fcs, port->port_cfg.pwwn);
2775
2776
2777
2778
2779 if (req_status != BFA_STATUS_OK) {
2780 bfa_trc(port->fcs, req_status);
2781 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2782 return;
2783 }
2784
2785 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2786 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2787
2788 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2789 gfn_resp = (wwn_t *)(cthdr + 1);
2790
2791 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2792 gfn_resp, sizeof(wwn_t)) != 0)) {
2793 bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2794 }
2795 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2796 return;
2797 }
2798
2799 bfa_trc(port->fcs, cthdr->reason_code);
2800 bfa_trc(port->fcs, cthdr->exp_code);
2801 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2802}
2803
2804
2805
2806
2807
2808static void
2809bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2810{
2811 struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2812 struct bfa_fcs_lport_s *port = ms->port;
2813 struct fchs_s fchs;
2814 int len;
2815 struct bfa_fcxp_s *fcxp;
2816
2817 bfa_trc(port->fcs, port->pid);
2818
2819 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2820 if (!fcxp) {
2821 port->stats.ms_plogi_alloc_wait++;
2822 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2823 bfa_fcs_lport_ms_send_plogi, ms);
2824 return;
2825 }
2826 ms->fcxp = fcxp;
2827
2828 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2829 bfa_hton3b(FC_MGMT_SERVER),
2830 bfa_fcs_lport_get_fcid(port), 0,
2831 port->port_cfg.pwwn, port->port_cfg.nwwn,
2832 bfa_fcport_get_maxfrsize(port->fcs->bfa));
2833
2834 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2835 FC_CLASS_3, len, &fchs,
2836 bfa_fcs_lport_ms_plogi_response, (void *)ms,
2837 FC_MAX_PDUSZ, FC_ELS_TOV);
2838
2839 port->stats.ms_plogi_sent++;
2840 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2841}
2842
2843static void
2844bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2845 void *cbarg, bfa_status_t req_status,
2846 u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2847{
2848 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2849 struct bfa_fcs_lport_s *port = ms->port;
2850 struct fc_els_cmd_s *els_cmd;
2851 struct fc_ls_rjt_s *ls_rjt;
2852
2853 bfa_trc(port->fcs, req_status);
2854 bfa_trc(port->fcs, port->port_cfg.pwwn);
2855
2856
2857
2858
2859 if (req_status != BFA_STATUS_OK) {
2860 port->stats.ms_plogi_rsp_err++;
2861 bfa_trc(port->fcs, req_status);
2862 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2863 return;
2864 }
2865
2866 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2867
2868 switch (els_cmd->els_code) {
2869
2870 case FC_ELS_ACC:
2871 if (rsp_len < sizeof(struct fc_logi_s)) {
2872 bfa_trc(port->fcs, rsp_len);
2873 port->stats.ms_plogi_acc_err++;
2874 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2875 break;
2876 }
2877 port->stats.ms_plogi_accepts++;
2878 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2879 break;
2880
2881 case FC_ELS_LS_RJT:
2882 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2883
2884 bfa_trc(port->fcs, ls_rjt->reason_code);
2885 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2886
2887 port->stats.ms_rejects++;
2888 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2889 break;
2890
2891 default:
2892 port->stats.ms_plogi_unknown_rsp++;
2893 bfa_trc(port->fcs, els_cmd->els_code);
2894 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2895 }
2896}
2897
2898static void
2899bfa_fcs_lport_ms_timeout(void *arg)
2900{
2901 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2902
2903 ms->port->stats.ms_timeouts++;
2904 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2905}
2906
2907
2908void
2909bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2910{
2911 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2912
2913 ms->port = port;
2914 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2915
2916
2917
2918
2919 bfa_fcs_lport_fdmi_init(ms);
2920}
2921
2922void
2923bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2924{
2925 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2926
2927 ms->port = port;
2928 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2929 bfa_fcs_lport_fdmi_offline(ms);
2930}
2931
2932void
2933bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2934{
2935 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2936
2937 ms->port = port;
2938 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
2939}
2940void
2941bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
2942{
2943 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2944
2945
2946 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
2947 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
2948}
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
2963 struct bfa_fcxp_s *fcxp_alloced);
2964static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
2965 struct bfa_fcxp_s *fcxp_alloced);
2966static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
2967 struct bfa_fcxp_s *fcxp_alloced);
2968static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
2969 struct bfa_fcxp_s *fcxp_alloced);
2970static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
2971 struct bfa_fcxp_s *fcxp_alloced);
2972static void bfa_fcs_lport_ns_timeout(void *arg);
2973static void bfa_fcs_lport_ns_plogi_response(void *fcsarg,
2974 struct bfa_fcxp_s *fcxp,
2975 void *cbarg,
2976 bfa_status_t req_status,
2977 u32 rsp_len,
2978 u32 resid_len,
2979 struct fchs_s *rsp_fchs);
2980static void bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
2981 struct bfa_fcxp_s *fcxp,
2982 void *cbarg,
2983 bfa_status_t req_status,
2984 u32 rsp_len,
2985 u32 resid_len,
2986 struct fchs_s *rsp_fchs);
2987static void bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
2988 struct bfa_fcxp_s *fcxp,
2989 void *cbarg,
2990 bfa_status_t req_status,
2991 u32 rsp_len,
2992 u32 resid_len,
2993 struct fchs_s *rsp_fchs);
2994static void bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
2995 struct bfa_fcxp_s *fcxp,
2996 void *cbarg,
2997 bfa_status_t req_status,
2998 u32 rsp_len,
2999 u32 resid_len,
3000 struct fchs_s *rsp_fchs);
3001static void bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3002 struct bfa_fcxp_s *fcxp,
3003 void *cbarg,
3004 bfa_status_t req_status,
3005 u32 rsp_len,
3006 u32 resid_len,
3007 struct fchs_s *rsp_fchs);
3008static void bfa_fcs_lport_ns_process_gidft_pids(
3009 struct bfa_fcs_lport_s *port,
3010 u32 *pid_buf, u32 n_pids);
3011
3012static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3013
3014
3015
3016
3017
3018
3019
3020enum vport_ns_event {
3021 NSSM_EVENT_PORT_ONLINE = 1,
3022 NSSM_EVENT_PORT_OFFLINE = 2,
3023 NSSM_EVENT_PLOGI_SENT = 3,
3024 NSSM_EVENT_RSP_OK = 4,
3025 NSSM_EVENT_RSP_ERROR = 5,
3026 NSSM_EVENT_TIMEOUT = 6,
3027 NSSM_EVENT_NS_QUERY = 7,
3028 NSSM_EVENT_RSPNID_SENT = 8,
3029 NSSM_EVENT_RFTID_SENT = 9,
3030 NSSM_EVENT_RFFID_SENT = 10,
3031 NSSM_EVENT_GIDFT_SENT = 11,
3032};
3033
3034static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3035 enum vport_ns_event event);
3036static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3037 enum vport_ns_event event);
3038static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3039 enum vport_ns_event event);
3040static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3041 enum vport_ns_event event);
3042static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3043 struct bfa_fcs_lport_ns_s *ns,
3044 enum vport_ns_event event);
3045static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3046 enum vport_ns_event event);
3047static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3048 enum vport_ns_event event);
3049static void bfa_fcs_lport_ns_sm_sending_rft_id(
3050 struct bfa_fcs_lport_ns_s *ns,
3051 enum vport_ns_event event);
3052static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3053 enum vport_ns_event event);
3054static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3055 enum vport_ns_event event);
3056static void bfa_fcs_lport_ns_sm_sending_rff_id(
3057 struct bfa_fcs_lport_ns_s *ns,
3058 enum vport_ns_event event);
3059static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3060 enum vport_ns_event event);
3061static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3062 enum vport_ns_event event);
3063static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3064 struct bfa_fcs_lport_ns_s *ns,
3065 enum vport_ns_event event);
3066static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3067 enum vport_ns_event event);
3068static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3069 enum vport_ns_event event);
3070static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3071 enum vport_ns_event event);
3072
3073
3074
3075static void
3076bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3077 enum vport_ns_event event)
3078{
3079 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3080 bfa_trc(ns->port->fcs, event);
3081
3082 switch (event) {
3083 case NSSM_EVENT_PORT_ONLINE:
3084 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3085 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3086 break;
3087
3088 case NSSM_EVENT_PORT_OFFLINE:
3089 break;
3090
3091 default:
3092 bfa_sm_fault(ns->port->fcs, event);
3093 }
3094}
3095
3096static void
3097bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3098 enum vport_ns_event event)
3099{
3100 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3101 bfa_trc(ns->port->fcs, event);
3102
3103 switch (event) {
3104 case NSSM_EVENT_PLOGI_SENT:
3105 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3106 break;
3107
3108 case NSSM_EVENT_PORT_OFFLINE:
3109 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3110 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3111 &ns->fcxp_wqe);
3112 break;
3113
3114 default:
3115 bfa_sm_fault(ns->port->fcs, event);
3116 }
3117}
3118
3119static void
3120bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3121 enum vport_ns_event event)
3122{
3123 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3124 bfa_trc(ns->port->fcs, event);
3125
3126 switch (event) {
3127 case NSSM_EVENT_RSP_ERROR:
3128
3129
3130
3131 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3132 ns->port->stats.ns_retries++;
3133 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3134 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3135 BFA_FCS_RETRY_TIMEOUT);
3136 break;
3137
3138 case NSSM_EVENT_RSP_OK:
3139 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3140 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3141 break;
3142
3143 case NSSM_EVENT_PORT_OFFLINE:
3144 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3145 bfa_fcxp_discard(ns->fcxp);
3146 break;
3147
3148 default:
3149 bfa_sm_fault(ns->port->fcs, event);
3150 }
3151}
3152
3153static void
3154bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3155 enum vport_ns_event event)
3156{
3157 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3158 bfa_trc(ns->port->fcs, event);
3159
3160 switch (event) {
3161 case NSSM_EVENT_TIMEOUT:
3162
3163
3164
3165 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3166 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3167 break;
3168
3169 case NSSM_EVENT_PORT_OFFLINE:
3170 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3171 bfa_timer_stop(&ns->timer);
3172 break;
3173
3174 default:
3175 bfa_sm_fault(ns->port->fcs, event);
3176 }
3177}
3178
3179static void
3180bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3181 enum vport_ns_event event)
3182{
3183 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3184 bfa_trc(ns->port->fcs, event);
3185
3186 switch (event) {
3187 case NSSM_EVENT_RSPNID_SENT:
3188 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3189 break;
3190
3191 case NSSM_EVENT_PORT_OFFLINE:
3192 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3193 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3194 &ns->fcxp_wqe);
3195 break;
3196
3197 default:
3198 bfa_sm_fault(ns->port->fcs, event);
3199 }
3200}
3201
3202static void
3203bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3204 enum vport_ns_event event)
3205{
3206 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3207 bfa_trc(ns->port->fcs, event);
3208
3209 switch (event) {
3210 case NSSM_EVENT_RSP_ERROR:
3211
3212
3213
3214 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3215 ns->port->stats.ns_retries++;
3216 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3217 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3218 BFA_FCS_RETRY_TIMEOUT);
3219 break;
3220
3221 case NSSM_EVENT_RSP_OK:
3222 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3223 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3224 break;
3225
3226 case NSSM_EVENT_PORT_OFFLINE:
3227 bfa_fcxp_discard(ns->fcxp);
3228 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3229 break;
3230
3231 default:
3232 bfa_sm_fault(ns->port->fcs, event);
3233 }
3234}
3235
3236static void
3237bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3238 enum vport_ns_event event)
3239{
3240 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3241 bfa_trc(ns->port->fcs, event);
3242
3243 switch (event) {
3244 case NSSM_EVENT_TIMEOUT:
3245
3246
3247
3248 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3249 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3250 break;
3251
3252 case NSSM_EVENT_PORT_OFFLINE:
3253 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3254 bfa_timer_stop(&ns->timer);
3255 break;
3256
3257 default:
3258 bfa_sm_fault(ns->port->fcs, event);
3259 }
3260}
3261
3262static void
3263bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3264 enum vport_ns_event event)
3265{
3266 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3267 bfa_trc(ns->port->fcs, event);
3268
3269 switch (event) {
3270 case NSSM_EVENT_RFTID_SENT:
3271 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3272 break;
3273
3274 case NSSM_EVENT_PORT_OFFLINE:
3275 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3276 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3277 &ns->fcxp_wqe);
3278 break;
3279
3280 default:
3281 bfa_sm_fault(ns->port->fcs, event);
3282 }
3283}
3284
3285static void
3286bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3287 enum vport_ns_event event)
3288{
3289 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3290 bfa_trc(ns->port->fcs, event);
3291
3292 switch (event) {
3293 case NSSM_EVENT_RSP_OK:
3294
3295 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3296 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3297 break;
3298
3299 case NSSM_EVENT_RSP_ERROR:
3300
3301
3302
3303 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3304 ns->port->stats.ns_retries++;
3305 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3306 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3307 BFA_FCS_RETRY_TIMEOUT);
3308 break;
3309
3310 case NSSM_EVENT_PORT_OFFLINE:
3311 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3312 bfa_fcxp_discard(ns->fcxp);
3313 break;
3314
3315 default:
3316 bfa_sm_fault(ns->port->fcs, event);
3317 }
3318}
3319
3320static void
3321bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3322 enum vport_ns_event event)
3323{
3324 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3325 bfa_trc(ns->port->fcs, event);
3326
3327 switch (event) {
3328 case NSSM_EVENT_TIMEOUT:
3329 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3330 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3331 break;
3332
3333 case NSSM_EVENT_PORT_OFFLINE:
3334 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3335 bfa_timer_stop(&ns->timer);
3336 break;
3337
3338 default:
3339 bfa_sm_fault(ns->port->fcs, event);
3340 }
3341}
3342
3343static void
3344bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3345 enum vport_ns_event event)
3346{
3347 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3348 bfa_trc(ns->port->fcs, event);
3349
3350 switch (event) {
3351 case NSSM_EVENT_RFFID_SENT:
3352 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3353 break;
3354
3355 case NSSM_EVENT_PORT_OFFLINE:
3356 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3357 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3358 &ns->fcxp_wqe);
3359 break;
3360
3361 default:
3362 bfa_sm_fault(ns->port->fcs, event);
3363 }
3364}
3365
3366static void
3367bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3368 enum vport_ns_event event)
3369{
3370 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3371 bfa_trc(ns->port->fcs, event);
3372
3373 switch (event) {
3374 case NSSM_EVENT_RSP_OK:
3375
3376
3377
3378
3379
3380
3381 if (__fcs_min_cfg(ns->port->fcs)) {
3382 bfa_fcs_lport_ns_boot_target_disc(ns->port);
3383 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3384 return;
3385 }
3386
3387
3388
3389
3390
3391 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3392 bfa_sm_set_state(ns,
3393 bfa_fcs_lport_ns_sm_sending_gid_ft);
3394 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3395 }
3396
3397
3398
3399 bfa_fcs_lport_ms_online(ns->port);
3400 break;
3401
3402 case NSSM_EVENT_RSP_ERROR:
3403
3404
3405
3406 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3407 ns->port->stats.ns_retries++;
3408 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3409 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3410 BFA_FCS_RETRY_TIMEOUT);
3411 break;
3412
3413 case NSSM_EVENT_PORT_OFFLINE:
3414 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3415 bfa_fcxp_discard(ns->fcxp);
3416 break;
3417
3418 default:
3419 bfa_sm_fault(ns->port->fcs, event);
3420 }
3421}
3422
3423static void
3424bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3425 enum vport_ns_event event)
3426{
3427 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3428 bfa_trc(ns->port->fcs, event);
3429
3430 switch (event) {
3431 case NSSM_EVENT_TIMEOUT:
3432 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3433 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3434 break;
3435
3436 case NSSM_EVENT_PORT_OFFLINE:
3437 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3438 bfa_timer_stop(&ns->timer);
3439 break;
3440
3441 default:
3442 bfa_sm_fault(ns->port->fcs, event);
3443 }
3444}
3445static void
3446bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3447 enum vport_ns_event event)
3448{
3449 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3450 bfa_trc(ns->port->fcs, event);
3451
3452 switch (event) {
3453 case NSSM_EVENT_GIDFT_SENT:
3454 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3455 break;
3456
3457 case NSSM_EVENT_PORT_OFFLINE:
3458 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3459 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3460 &ns->fcxp_wqe);
3461 break;
3462
3463 default:
3464 bfa_sm_fault(ns->port->fcs, event);
3465 }
3466}
3467
3468static void
3469bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3470 enum vport_ns_event event)
3471{
3472 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3473 bfa_trc(ns->port->fcs, event);
3474
3475 switch (event) {
3476 case NSSM_EVENT_RSP_OK:
3477 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3478 break;
3479
3480 case NSSM_EVENT_RSP_ERROR:
3481
3482
3483
3484
3485
3486
3487 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3488 ns->port->stats.ns_retries++;
3489 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3490 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3491 BFA_FCS_RETRY_TIMEOUT);
3492 break;
3493
3494 case NSSM_EVENT_PORT_OFFLINE:
3495 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3496 bfa_fcxp_discard(ns->fcxp);
3497 break;
3498
3499 case NSSM_EVENT_NS_QUERY:
3500 break;
3501
3502 default:
3503 bfa_sm_fault(ns->port->fcs, event);
3504 }
3505}
3506
3507static void
3508bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3509 enum vport_ns_event event)
3510{
3511 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3512 bfa_trc(ns->port->fcs, event);
3513
3514 switch (event) {
3515 case NSSM_EVENT_TIMEOUT:
3516 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3517 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3518 break;
3519
3520 case NSSM_EVENT_PORT_OFFLINE:
3521 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3522 bfa_timer_stop(&ns->timer);
3523 break;
3524
3525 default:
3526 bfa_sm_fault(ns->port->fcs, event);
3527 }
3528}
3529
3530static void
3531bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3532 enum vport_ns_event event)
3533{
3534 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3535 bfa_trc(ns->port->fcs, event);
3536
3537 switch (event) {
3538 case NSSM_EVENT_PORT_OFFLINE:
3539 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3540 break;
3541
3542 case NSSM_EVENT_NS_QUERY:
3543
3544
3545
3546
3547 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3548 bfa_sm_set_state(ns,
3549 bfa_fcs_lport_ns_sm_sending_gid_ft);
3550 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3551 };
3552 break;
3553
3554 default:
3555 bfa_sm_fault(ns->port->fcs, event);
3556 }
3557}
3558
3559
3560
3561
3562
3563
3564
3565static void
3566bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3567{
3568 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3569 struct bfa_fcs_lport_s *port = ns->port;
3570 struct fchs_s fchs;
3571 int len;
3572 struct bfa_fcxp_s *fcxp;
3573
3574 bfa_trc(port->fcs, port->pid);
3575
3576fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3577 if (!fcxp) {
3578 port->stats.ns_plogi_alloc_wait++;
3579 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3580 bfa_fcs_lport_ns_send_plogi, ns);
3581 return;
3582 }
3583 ns->fcxp = fcxp;
3584
3585 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3586 bfa_hton3b(FC_NAME_SERVER),
3587 bfa_fcs_lport_get_fcid(port), 0,
3588 port->port_cfg.pwwn, port->port_cfg.nwwn,
3589 bfa_fcport_get_maxfrsize(port->fcs->bfa));
3590
3591 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3592 FC_CLASS_3, len, &fchs,
3593 bfa_fcs_lport_ns_plogi_response, (void *)ns,
3594 FC_MAX_PDUSZ, FC_ELS_TOV);
3595 port->stats.ns_plogi_sent++;
3596
3597 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3598}
3599
3600static void
3601bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3602 void *cbarg, bfa_status_t req_status, u32 rsp_len,
3603 u32 resid_len, struct fchs_s *rsp_fchs)
3604{
3605 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3606 struct bfa_fcs_lport_s *port = ns->port;
3607
3608 struct fc_els_cmd_s *els_cmd;
3609 struct fc_ls_rjt_s *ls_rjt;
3610
3611 bfa_trc(port->fcs, req_status);
3612 bfa_trc(port->fcs, port->port_cfg.pwwn);
3613
3614
3615
3616
3617 if (req_status != BFA_STATUS_OK) {
3618 bfa_trc(port->fcs, req_status);
3619 port->stats.ns_plogi_rsp_err++;
3620 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3621 return;
3622 }
3623
3624 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3625
3626 switch (els_cmd->els_code) {
3627
3628 case FC_ELS_ACC:
3629 if (rsp_len < sizeof(struct fc_logi_s)) {
3630 bfa_trc(port->fcs, rsp_len);
3631 port->stats.ns_plogi_acc_err++;
3632 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3633 break;
3634 }
3635 port->stats.ns_plogi_accepts++;
3636 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3637 break;
3638
3639 case FC_ELS_LS_RJT:
3640 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3641
3642 bfa_trc(port->fcs, ls_rjt->reason_code);
3643 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3644
3645 port->stats.ns_rejects++;
3646
3647 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3648 break;
3649
3650 default:
3651 port->stats.ns_plogi_unknown_rsp++;
3652 bfa_trc(port->fcs, els_cmd->els_code);
3653 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3654 }
3655}
3656
3657
3658
3659
3660static void
3661bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3662{
3663 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3664 struct bfa_fcs_lport_s *port = ns->port;
3665 struct fchs_s fchs;
3666 int len;
3667 struct bfa_fcxp_s *fcxp;
3668 u8 symbl[256];
3669 u8 *psymbl = &symbl[0];
3670
3671 memset(symbl, 0, sizeof(symbl));
3672
3673 bfa_trc(port->fcs, port->port_cfg.pwwn);
3674
3675 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3676 if (!fcxp) {
3677 port->stats.ns_rspnid_alloc_wait++;
3678 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3679 bfa_fcs_lport_ns_send_rspn_id, ns);
3680 return;
3681 }
3682 ns->fcxp = fcxp;
3683
3684
3685
3686
3687 if (port->vport) {
3688
3689
3690
3691
3692
3693 strncpy((char *)psymbl,
3694 (char *) &
3695 (bfa_fcs_lport_get_psym_name
3696 (bfa_fcs_get_base_port(port->fcs))),
3697 strlen((char *) &
3698 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3699 (port->fcs))));
3700
3701
3702 ((char *)psymbl)[strlen((char *) &
3703 bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3704 (port->fcs)))] = 0;
3705 strncat((char *)psymbl,
3706 (char *) &(bfa_fcs_lport_get_psym_name(port)),
3707 strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3708 } else {
3709 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3710 }
3711
3712 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3713 bfa_fcs_lport_get_fcid(port), 0, psymbl);
3714
3715 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3716 FC_CLASS_3, len, &fchs,
3717 bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3718 FC_MAX_PDUSZ, FC_FCCT_TOV);
3719
3720 port->stats.ns_rspnid_sent++;
3721
3722 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3723}
3724
3725static void
3726bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3727 void *cbarg, bfa_status_t req_status,
3728 u32 rsp_len, u32 resid_len,
3729 struct fchs_s *rsp_fchs)
3730{
3731 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3732 struct bfa_fcs_lport_s *port = ns->port;
3733 struct ct_hdr_s *cthdr = NULL;
3734
3735 bfa_trc(port->fcs, port->port_cfg.pwwn);
3736
3737
3738
3739
3740 if (req_status != BFA_STATUS_OK) {
3741 bfa_trc(port->fcs, req_status);
3742 port->stats.ns_rspnid_rsp_err++;
3743 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3744 return;
3745 }
3746
3747 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3748 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3749
3750 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3751 port->stats.ns_rspnid_accepts++;
3752 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3753 return;
3754 }
3755
3756 port->stats.ns_rspnid_rejects++;
3757 bfa_trc(port->fcs, cthdr->reason_code);
3758 bfa_trc(port->fcs, cthdr->exp_code);
3759 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3760}
3761
3762
3763
3764
3765static void
3766bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3767{
3768 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3769 struct bfa_fcs_lport_s *port = ns->port;
3770 struct fchs_s fchs;
3771 int len;
3772 struct bfa_fcxp_s *fcxp;
3773
3774 bfa_trc(port->fcs, port->port_cfg.pwwn);
3775
3776 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3777 if (!fcxp) {
3778 port->stats.ns_rftid_alloc_wait++;
3779 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3780 bfa_fcs_lport_ns_send_rft_id, ns);
3781 return;
3782 }
3783 ns->fcxp = fcxp;
3784
3785 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3786 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3787
3788 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3789 FC_CLASS_3, len, &fchs,
3790 bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3791 FC_MAX_PDUSZ, FC_FCCT_TOV);
3792
3793 port->stats.ns_rftid_sent++;
3794 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3795}
3796
3797static void
3798bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3799 void *cbarg, bfa_status_t req_status,
3800 u32 rsp_len, u32 resid_len,
3801 struct fchs_s *rsp_fchs)
3802{
3803 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3804 struct bfa_fcs_lport_s *port = ns->port;
3805 struct ct_hdr_s *cthdr = NULL;
3806
3807 bfa_trc(port->fcs, port->port_cfg.pwwn);
3808
3809
3810
3811
3812 if (req_status != BFA_STATUS_OK) {
3813 bfa_trc(port->fcs, req_status);
3814 port->stats.ns_rftid_rsp_err++;
3815 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3816 return;
3817 }
3818
3819 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3820 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3821
3822 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3823 port->stats.ns_rftid_accepts++;
3824 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3825 return;
3826 }
3827
3828 port->stats.ns_rftid_rejects++;
3829 bfa_trc(port->fcs, cthdr->reason_code);
3830 bfa_trc(port->fcs, cthdr->exp_code);
3831 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3832}
3833
3834
3835
3836
3837static void
3838bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3839{
3840 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3841 struct bfa_fcs_lport_s *port = ns->port;
3842 struct fchs_s fchs;
3843 int len;
3844 struct bfa_fcxp_s *fcxp;
3845 u8 fc4_ftrs = 0;
3846
3847 bfa_trc(port->fcs, port->port_cfg.pwwn);
3848
3849 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3850 if (!fcxp) {
3851 port->stats.ns_rffid_alloc_wait++;
3852 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3853 bfa_fcs_lport_ns_send_rff_id, ns);
3854 return;
3855 }
3856 ns->fcxp = fcxp;
3857
3858 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3859 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3860
3861 len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3862 bfa_fcs_lport_get_fcid(port), 0,
3863 FC_TYPE_FCP, fc4_ftrs);
3864
3865 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3866 FC_CLASS_3, len, &fchs,
3867 bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3868 FC_MAX_PDUSZ, FC_FCCT_TOV);
3869
3870 port->stats.ns_rffid_sent++;
3871 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3872}
3873
3874static void
3875bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3876 void *cbarg, bfa_status_t req_status,
3877 u32 rsp_len, u32 resid_len,
3878 struct fchs_s *rsp_fchs)
3879{
3880 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3881 struct bfa_fcs_lport_s *port = ns->port;
3882 struct ct_hdr_s *cthdr = NULL;
3883
3884 bfa_trc(port->fcs, port->port_cfg.pwwn);
3885
3886
3887
3888
3889 if (req_status != BFA_STATUS_OK) {
3890 bfa_trc(port->fcs, req_status);
3891 port->stats.ns_rffid_rsp_err++;
3892 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3893 return;
3894 }
3895
3896 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3897 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3898
3899 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3900 port->stats.ns_rffid_accepts++;
3901 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3902 return;
3903 }
3904
3905 port->stats.ns_rffid_rejects++;
3906 bfa_trc(port->fcs, cthdr->reason_code);
3907 bfa_trc(port->fcs, cthdr->exp_code);
3908
3909 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3910
3911 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3912 } else
3913 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3914}
3915
3916
3917
3918
3919
3920
3921static void
3922bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3923{
3924 struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3925 struct bfa_fcs_lport_s *port = ns->port;
3926 struct fchs_s fchs;
3927 int len;
3928 struct bfa_fcxp_s *fcxp;
3929
3930 bfa_trc(port->fcs, port->pid);
3931
3932 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3933 if (!fcxp) {
3934 port->stats.ns_gidft_alloc_wait++;
3935 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3936 bfa_fcs_lport_ns_send_gid_ft, ns);
3937 return;
3938 }
3939 ns->fcxp = fcxp;
3940
3941
3942
3943
3944 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3945 ns->port->pid, FC_TYPE_FCP);
3946
3947 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3948 FC_CLASS_3, len, &fchs,
3949 bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
3950 bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
3951
3952 port->stats.ns_gidft_sent++;
3953
3954 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
3955}
3956
3957static void
3958bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3959 void *cbarg, bfa_status_t req_status,
3960 u32 rsp_len, u32 resid_len,
3961 struct fchs_s *rsp_fchs)
3962{
3963 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3964 struct bfa_fcs_lport_s *port = ns->port;
3965 struct ct_hdr_s *cthdr = NULL;
3966 u32 n_pids;
3967
3968 bfa_trc(port->fcs, port->port_cfg.pwwn);
3969
3970
3971
3972
3973 if (req_status != BFA_STATUS_OK) {
3974 bfa_trc(port->fcs, req_status);
3975 port->stats.ns_gidft_rsp_err++;
3976 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3977 return;
3978 }
3979
3980 if (resid_len != 0) {
3981
3982
3983
3984
3985 bfa_trc(port->fcs, rsp_len);
3986 bfa_trc(port->fcs, resid_len);
3987 return;
3988 }
3989
3990 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3991 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3992
3993 switch (cthdr->cmd_rsp_code) {
3994
3995 case CT_RSP_ACCEPT:
3996
3997 port->stats.ns_gidft_accepts++;
3998 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
3999 bfa_trc(port->fcs, n_pids);
4000 bfa_fcs_lport_ns_process_gidft_pids(port,
4001 (u32 *) (cthdr + 1),
4002 n_pids);
4003 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4004 break;
4005
4006 case CT_RSP_REJECT:
4007
4008
4009
4010
4011
4012 port->stats.ns_gidft_rejects++;
4013 bfa_trc(port->fcs, cthdr->reason_code);
4014 bfa_trc(port->fcs, cthdr->exp_code);
4015
4016 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4017 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4018
4019 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4020 } else {
4021
4022
4023
4024 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4025 }
4026 break;
4027
4028 default:
4029 port->stats.ns_gidft_unknown_rsp++;
4030 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4031 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4032 }
4033}
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047static void
4048bfa_fcs_lport_ns_timeout(void *arg)
4049{
4050 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4051
4052 ns->port->stats.ns_timeouts++;
4053 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4054}
4055
4056
4057
4058
4059static void
4060bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4061 u32 n_pids)
4062{
4063 struct fcgs_gidft_resp_s *gidft_entry;
4064 struct bfa_fcs_rport_s *rport;
4065 u32 ii;
4066
4067 for (ii = 0; ii < n_pids; ii++) {
4068 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4069
4070 if (gidft_entry->pid == port->pid)
4071 continue;
4072
4073
4074
4075
4076 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4077 if (rport == NULL) {
4078
4079
4080
4081 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4082 } else {
4083
4084
4085
4086 bfa_fcs_rport_scn(rport);
4087 }
4088
4089 bfa_trc(port->fcs, gidft_entry->pid);
4090
4091
4092
4093
4094 if (gidft_entry->last)
4095 return;
4096 }
4097}
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107void
4108bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4109{
4110 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4111
4112 ns->port = port;
4113 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4114}
4115
4116void
4117bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4118{
4119 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4120
4121 ns->port = port;
4122 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4123}
4124
4125void
4126bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4127{
4128 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4129
4130 ns->port = port;
4131 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4132}
4133
4134void
4135bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4136{
4137 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4138
4139 bfa_trc(port->fcs, port->pid);
4140 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4141}
4142
4143static void
4144bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4145{
4146
4147 struct bfa_fcs_rport_s *rport;
4148 u8 nwwns;
4149 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
4150 int ii;
4151
4152 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4153
4154 for (ii = 0 ; ii < nwwns; ++ii) {
4155 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4156 WARN_ON(!rport);
4157 }
4158}
4159
4160
4161
4162
4163
4164#define FC_QOS_RSCN_EVENT 0x0c
4165#define FC_FABRIC_NAME_RSCN_EVENT 0x0d
4166
4167
4168
4169
4170static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4171 struct bfa_fcxp_s *fcxp_alloced);
4172static void bfa_fcs_lport_scn_scr_response(void *fcsarg,
4173 struct bfa_fcxp_s *fcxp,
4174 void *cbarg,
4175 bfa_status_t req_status,
4176 u32 rsp_len,
4177 u32 resid_len,
4178 struct fchs_s *rsp_fchs);
4179static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4180 struct fchs_s *rx_fchs);
4181static void bfa_fcs_lport_scn_timeout(void *arg);
4182
4183
4184
4185
4186
4187
4188
4189
4190enum port_scn_event {
4191 SCNSM_EVENT_PORT_ONLINE = 1,
4192 SCNSM_EVENT_PORT_OFFLINE = 2,
4193 SCNSM_EVENT_RSP_OK = 3,
4194 SCNSM_EVENT_RSP_ERROR = 4,
4195 SCNSM_EVENT_TIMEOUT = 5,
4196 SCNSM_EVENT_SCR_SENT = 6,
4197};
4198
4199static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4200 enum port_scn_event event);
4201static void bfa_fcs_lport_scn_sm_sending_scr(
4202 struct bfa_fcs_lport_scn_s *scn,
4203 enum port_scn_event event);
4204static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4205 enum port_scn_event event);
4206static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4207 enum port_scn_event event);
4208static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4209 enum port_scn_event event);
4210
4211
4212
4213
4214static void
4215bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4216 enum port_scn_event event)
4217{
4218 switch (event) {
4219 case SCNSM_EVENT_PORT_ONLINE:
4220 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4221 bfa_fcs_lport_scn_send_scr(scn, NULL);
4222 break;
4223
4224 case SCNSM_EVENT_PORT_OFFLINE:
4225 break;
4226
4227 default:
4228 bfa_sm_fault(scn->port->fcs, event);
4229 }
4230}
4231
4232static void
4233bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4234 enum port_scn_event event)
4235{
4236 switch (event) {
4237 case SCNSM_EVENT_SCR_SENT:
4238 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4239 break;
4240
4241 case SCNSM_EVENT_PORT_OFFLINE:
4242 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4243 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4244 break;
4245
4246 default:
4247 bfa_sm_fault(scn->port->fcs, event);
4248 }
4249}
4250
4251static void
4252bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4253 enum port_scn_event event)
4254{
4255 struct bfa_fcs_lport_s *port = scn->port;
4256
4257 switch (event) {
4258 case SCNSM_EVENT_RSP_OK:
4259 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4260 break;
4261
4262 case SCNSM_EVENT_RSP_ERROR:
4263 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4264 bfa_timer_start(port->fcs->bfa, &scn->timer,
4265 bfa_fcs_lport_scn_timeout, scn,
4266 BFA_FCS_RETRY_TIMEOUT);
4267 break;
4268
4269 case SCNSM_EVENT_PORT_OFFLINE:
4270 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4271 bfa_fcxp_discard(scn->fcxp);
4272 break;
4273
4274 default:
4275 bfa_sm_fault(port->fcs, event);
4276 }
4277}
4278
4279static void
4280bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4281 enum port_scn_event event)
4282{
4283 switch (event) {
4284 case SCNSM_EVENT_TIMEOUT:
4285 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4286 bfa_fcs_lport_scn_send_scr(scn, NULL);
4287 break;
4288
4289 case SCNSM_EVENT_PORT_OFFLINE:
4290 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4291 bfa_timer_stop(&scn->timer);
4292 break;
4293
4294 default:
4295 bfa_sm_fault(scn->port->fcs, event);
4296 }
4297}
4298
4299static void
4300bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4301 enum port_scn_event event)
4302{
4303 switch (event) {
4304 case SCNSM_EVENT_PORT_OFFLINE:
4305 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4306 break;
4307
4308 default:
4309 bfa_sm_fault(scn->port->fcs, event);
4310 }
4311}
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322static void
4323bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4324{
4325 struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4326 struct bfa_fcs_lport_s *port = scn->port;
4327 struct fchs_s fchs;
4328 int len;
4329 struct bfa_fcxp_s *fcxp;
4330
4331 bfa_trc(port->fcs, port->pid);
4332 bfa_trc(port->fcs, port->port_cfg.pwwn);
4333
4334 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4335 if (!fcxp) {
4336 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4337 bfa_fcs_lport_scn_send_scr, scn);
4338 return;
4339 }
4340 scn->fcxp = fcxp;
4341
4342
4343 if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4344 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4345 port->fabric->lps->brcd_switch,
4346 port->pid, 0);
4347 } else {
4348 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4349 BFA_FALSE,
4350 port->pid, 0);
4351 }
4352
4353 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4354 FC_CLASS_3, len, &fchs,
4355 bfa_fcs_lport_scn_scr_response,
4356 (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4357
4358 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4359}
4360
4361static void
4362bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4363 void *cbarg, bfa_status_t req_status, u32 rsp_len,
4364 u32 resid_len, struct fchs_s *rsp_fchs)
4365{
4366 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4367 struct bfa_fcs_lport_s *port = scn->port;
4368 struct fc_els_cmd_s *els_cmd;
4369 struct fc_ls_rjt_s *ls_rjt;
4370
4371 bfa_trc(port->fcs, port->port_cfg.pwwn);
4372
4373
4374
4375
4376 if (req_status != BFA_STATUS_OK) {
4377 bfa_trc(port->fcs, req_status);
4378 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4379 return;
4380 }
4381
4382 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4383
4384 switch (els_cmd->els_code) {
4385
4386 case FC_ELS_ACC:
4387 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4388 break;
4389
4390 case FC_ELS_LS_RJT:
4391
4392 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4393
4394 bfa_trc(port->fcs, ls_rjt->reason_code);
4395 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4396
4397 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4398 break;
4399
4400 default:
4401 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4402 }
4403}
4404
4405
4406
4407
4408static void
4409bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4410 struct fchs_s *rx_fchs)
4411{
4412 struct fchs_s fchs;
4413 struct bfa_fcxp_s *fcxp;
4414 struct bfa_rport_s *bfa_rport = NULL;
4415 int len;
4416
4417 bfa_trc(port->fcs, rx_fchs->s_id);
4418
4419 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4420 if (!fcxp)
4421 return;
4422
4423 len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4424 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4425 rx_fchs->ox_id);
4426
4427 bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4428 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4429 FC_MAX_PDUSZ, 0);
4430}
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445static void
4446bfa_fcs_lport_scn_timeout(void *arg)
4447{
4448 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4449
4450 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4451}
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462void
4463bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4464{
4465 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4466
4467 scn->port = port;
4468 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4469}
4470
4471void
4472bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4473{
4474 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4475
4476 scn->port = port;
4477 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4478}
4479
4480void
4481bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4482{
4483 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4484
4485 scn->port = port;
4486 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4487}
4488
4489static void
4490bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4491{
4492 struct bfa_fcs_rport_s *rport;
4493
4494 bfa_trc(port->fcs, rpid);
4495
4496
4497
4498
4499
4500 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4501 if (rport == NULL) {
4502
4503
4504
4505
4506 if (!__fcs_min_cfg(port->fcs))
4507 rport = bfa_fcs_rport_create(port, rpid);
4508 } else
4509 bfa_fcs_rport_scn(rport);
4510}
4511
4512
4513
4514
4515#define __fc_pid_match(__c0, __c1, __fmt) \
4516 (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \
4517 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \
4518 ((__c0)[0] == (__c1)[0])) || \
4519 (((__fmt) == FC_RSCN_FORMAT_AREA) && \
4520 ((__c0)[0] == (__c1)[0]) && \
4521 ((__c0)[1] == (__c1)[1])))
4522
4523static void
4524bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4525 enum fc_rscn_format format,
4526 u32 rscn_pid)
4527{
4528 struct bfa_fcs_rport_s *rport;
4529 struct list_head *qe, *qe_next;
4530 u8 *c0, *c1;
4531
4532 bfa_trc(port->fcs, format);
4533 bfa_trc(port->fcs, rscn_pid);
4534
4535 c0 = (u8 *) &rscn_pid;
4536
4537 list_for_each_safe(qe, qe_next, &port->rport_q) {
4538 rport = (struct bfa_fcs_rport_s *) qe;
4539 c1 = (u8 *) &rport->pid;
4540 if (__fc_pid_match(c0, c1, format))
4541 bfa_fcs_rport_scn(rport);
4542 }
4543}
4544
4545
4546void
4547bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4548 struct fchs_s *fchs, u32 len)
4549{
4550 struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4551 int num_entries;
4552 u32 rscn_pid;
4553 bfa_boolean_t nsquery = BFA_FALSE, found;
4554 int i = 0, j;
4555
4556 num_entries =
4557 (be16_to_cpu(rscn->payldlen) -
4558 sizeof(u32)) / sizeof(rscn->event[0]);
4559
4560 bfa_trc(port->fcs, num_entries);
4561
4562 port->stats.num_rscn++;
4563
4564 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4565
4566 for (i = 0; i < num_entries; i++) {
4567 rscn_pid = rscn->event[i].portid;
4568
4569 bfa_trc(port->fcs, rscn->event[i].format);
4570 bfa_trc(port->fcs, rscn_pid);
4571
4572
4573 found = BFA_FALSE;
4574 for (j = 0; j < i; j++) {
4575 if (rscn->event[j].portid == rscn_pid) {
4576 found = BFA_TRUE;
4577 break;
4578 }
4579 }
4580
4581
4582 if (found) {
4583 bfa_trc(port->fcs, rscn_pid);
4584 continue;
4585 }
4586
4587 switch (rscn->event[i].format) {
4588 case FC_RSCN_FORMAT_PORTID:
4589 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4590
4591
4592
4593
4594 bfa_trc(port->fcs, rscn_pid);
4595 } else {
4596 port->stats.num_portid_rscn++;
4597 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4598 }
4599 break;
4600
4601 case FC_RSCN_FORMAT_FABRIC:
4602 if (rscn->event[i].qualifier ==
4603 FC_FABRIC_NAME_RSCN_EVENT) {
4604 bfa_fcs_lport_ms_fabric_rscn(port);
4605 break;
4606 }
4607
4608
4609 case FC_RSCN_FORMAT_AREA:
4610 case FC_RSCN_FORMAT_DOMAIN:
4611 nsquery = BFA_TRUE;
4612 bfa_fcs_lport_scn_multiport_rscn(port,
4613 rscn->event[i].format,
4614 rscn_pid);
4615 break;
4616
4617
4618 default:
4619 WARN_ON(1);
4620 nsquery = BFA_TRUE;
4621 }
4622 }
4623
4624
4625
4626
4627
4628 if (nsquery)
4629 bfa_fcs_lport_ns_query(port);
4630}
4631
4632
4633
4634
4635
4636
4637
4638struct bfa_fcs_lport_s *
4639bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4640{
4641 return &fcs->fabric.bport;
4642}
4643
4644wwn_t
4645bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4646 int nrports, bfa_boolean_t bwwn)
4647{
4648 struct list_head *qh, *qe;
4649 struct bfa_fcs_rport_s *rport = NULL;
4650 int i;
4651 struct bfa_fcs_s *fcs;
4652
4653 if (port == NULL || nrports == 0)
4654 return (wwn_t) 0;
4655
4656 fcs = port->fcs;
4657 bfa_trc(fcs, (u32) nrports);
4658
4659 i = 0;
4660 qh = &port->rport_q;
4661 qe = bfa_q_first(qh);
4662
4663 while ((qe != qh) && (i < nrports)) {
4664 rport = (struct bfa_fcs_rport_s *) qe;
4665 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4666 qe = bfa_q_next(qe);
4667 bfa_trc(fcs, (u32) rport->pwwn);
4668 bfa_trc(fcs, rport->pid);
4669 bfa_trc(fcs, i);
4670 continue;
4671 }
4672
4673 if (bwwn) {
4674 if (!memcmp(&wwn, &rport->pwwn, 8))
4675 break;
4676 } else {
4677 if (i == index)
4678 break;
4679 }
4680
4681 i++;
4682 qe = bfa_q_next(qe);
4683 }
4684
4685 bfa_trc(fcs, i);
4686 if (rport)
4687 return rport->pwwn;
4688 else
4689 return (wwn_t) 0;
4690}
4691
4692void
4693bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4694 wwn_t rport_wwns[], int *nrports)
4695{
4696 struct list_head *qh, *qe;
4697 struct bfa_fcs_rport_s *rport = NULL;
4698 int i;
4699 struct bfa_fcs_s *fcs;
4700
4701 if (port == NULL || rport_wwns == NULL || *nrports == 0)
4702 return;
4703
4704 fcs = port->fcs;
4705 bfa_trc(fcs, (u32) *nrports);
4706
4707 i = 0;
4708 qh = &port->rport_q;
4709 qe = bfa_q_first(qh);
4710
4711 while ((qe != qh) && (i < *nrports)) {
4712 rport = (struct bfa_fcs_rport_s *) qe;
4713 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4714 qe = bfa_q_next(qe);
4715 bfa_trc(fcs, (u32) rport->pwwn);
4716 bfa_trc(fcs, rport->pid);
4717 bfa_trc(fcs, i);
4718 continue;
4719 }
4720
4721 rport_wwns[i] = rport->pwwn;
4722
4723 i++;
4724 qe = bfa_q_next(qe);
4725 }
4726
4727 bfa_trc(fcs, i);
4728 *nrports = i;
4729}
4730
4731
4732
4733
4734
4735
4736
4737bfa_port_speed_t
4738bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4739{
4740 struct list_head *qh, *qe;
4741 struct bfa_fcs_rport_s *rport = NULL;
4742 struct bfa_fcs_s *fcs;
4743 bfa_port_speed_t max_speed = 0;
4744 struct bfa_port_attr_s port_attr;
4745 bfa_port_speed_t port_speed, rport_speed;
4746 bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4747
4748
4749 if (port == NULL)
4750 return 0;
4751
4752 fcs = port->fcs;
4753
4754
4755 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4756 port_speed = port_attr.speed;
4757 bfa_trc(fcs, port_speed);
4758
4759 qh = &port->rport_q;
4760 qe = bfa_q_first(qh);
4761
4762 while (qe != qh) {
4763 rport = (struct bfa_fcs_rport_s *) qe;
4764 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
4765 (bfa_fcs_rport_get_state(rport) ==
4766 BFA_RPORT_OFFLINE)) {
4767 qe = bfa_q_next(qe);
4768 continue;
4769 }
4770
4771 rport_speed = rport->rpf.rpsc_speed;
4772 if ((trl_enabled) && (rport_speed ==
4773 BFA_PORT_SPEED_UNKNOWN)) {
4774
4775 rport_speed =
4776 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4777 }
4778
4779 if ((rport_speed == BFA_PORT_SPEED_8GBPS) ||
4780 (rport_speed > port_speed)) {
4781 max_speed = rport_speed;
4782 break;
4783 } else if (rport_speed > max_speed) {
4784 max_speed = rport_speed;
4785 }
4786
4787 qe = bfa_q_next(qe);
4788 }
4789
4790 bfa_trc(fcs, max_speed);
4791 return max_speed;
4792}
4793
4794struct bfa_fcs_lport_s *
4795bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4796{
4797 struct bfa_fcs_vport_s *vport;
4798 bfa_fcs_vf_t *vf;
4799
4800 WARN_ON(fcs == NULL);
4801
4802 vf = bfa_fcs_vf_lookup(fcs, vf_id);
4803 if (vf == NULL) {
4804 bfa_trc(fcs, vf_id);
4805 return NULL;
4806 }
4807
4808 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4809 return &vf->bport;
4810
4811 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4812 if (vport)
4813 return &vport->lport;
4814
4815 return NULL;
4816}
4817
4818
4819
4820
4821void
4822bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4823 struct bfa_lport_info_s *port_info)
4824{
4825
4826 bfa_trc(port->fcs, port->fabric->fabric_name);
4827
4828 if (port->vport == NULL) {
4829
4830
4831
4832 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4833
4834
4835
4836
4837 port_info->port_state = 0;
4838 port_info->offline_reason = 0;
4839
4840 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4841 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4842
4843 port_info->max_vports_supp =
4844 bfa_lps_get_max_vport(port->fcs->bfa);
4845 port_info->num_vports_inuse =
4846 port->fabric->num_vports;
4847 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4848 port_info->num_rports_inuse = port->num_rports;
4849 } else {
4850
4851
4852
4853 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4854
4855
4856
4857
4858 port_info->port_state = 0;
4859 port_info->offline_reason = 0;
4860
4861 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4862 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4863 }
4864}
4865
4866void
4867bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4868 struct bfa_lport_stats_s *port_stats)
4869{
4870 *port_stats = fcs_port->stats;
4871}
4872
4873void
4874bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4875{
4876 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
4877}
4878
4879
4880
4881
4882
4883#define __vport_fcs(__vp) ((__vp)->lport.fcs)
4884#define __vport_pwwn(__vp) ((__vp)->lport.port_cfg.pwwn)
4885#define __vport_nwwn(__vp) ((__vp)->lport.port_cfg.nwwn)
4886#define __vport_bfa(__vp) ((__vp)->lport.fcs->bfa)
4887#define __vport_fcid(__vp) ((__vp)->lport.pid)
4888#define __vport_fabric(__vp) ((__vp)->lport.fabric)
4889#define __vport_vfid(__vp) ((__vp)->lport.fabric->vf_id)
4890
4891#define BFA_FCS_VPORT_MAX_RETRIES 5
4892
4893
4894
4895static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4896static void bfa_fcs_vport_timeout(void *vport_arg);
4897static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4898static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4899
4900
4901
4902
4903
4904
4905
4906
4907enum bfa_fcs_vport_event {
4908 BFA_FCS_VPORT_SM_CREATE = 1,
4909 BFA_FCS_VPORT_SM_DELETE = 2,
4910 BFA_FCS_VPORT_SM_START = 3,
4911 BFA_FCS_VPORT_SM_STOP = 4,
4912 BFA_FCS_VPORT_SM_ONLINE = 5,
4913 BFA_FCS_VPORT_SM_OFFLINE = 6,
4914 BFA_FCS_VPORT_SM_FRMSENT = 7,
4915 BFA_FCS_VPORT_SM_RSP_OK = 8,
4916 BFA_FCS_VPORT_SM_RSP_ERROR = 9,
4917 BFA_FCS_VPORT_SM_TIMEOUT = 10,
4918 BFA_FCS_VPORT_SM_DELCOMP = 11,
4919 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,
4920 BFA_FCS_VPORT_SM_RSP_FAILED = 13,
4921};
4922
4923static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4924 enum bfa_fcs_vport_event event);
4925static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4926 enum bfa_fcs_vport_event event);
4927static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4928 enum bfa_fcs_vport_event event);
4929static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4930 enum bfa_fcs_vport_event event);
4931static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4932 enum bfa_fcs_vport_event event);
4933static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
4934 enum bfa_fcs_vport_event event);
4935static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
4936 enum bfa_fcs_vport_event event);
4937static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
4938 enum bfa_fcs_vport_event event);
4939static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
4940 enum bfa_fcs_vport_event event);
4941static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
4942 enum bfa_fcs_vport_event event);
4943
4944static struct bfa_sm_table_s vport_sm_table[] = {
4945 {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
4946 {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
4947 {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
4948 {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
4949 {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
4950 {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
4951 {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
4952 {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
4953 {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
4954 {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
4955};
4956
4957
4958
4959
4960static void
4961bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4962 enum bfa_fcs_vport_event event)
4963{
4964 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4965 bfa_trc(__vport_fcs(vport), event);
4966
4967 switch (event) {
4968 case BFA_FCS_VPORT_SM_CREATE:
4969 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
4970 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
4971 break;
4972
4973 default:
4974 bfa_sm_fault(__vport_fcs(vport), event);
4975 }
4976}
4977
4978
4979
4980
4981static void
4982bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4983 enum bfa_fcs_vport_event event)
4984{
4985 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4986 bfa_trc(__vport_fcs(vport), event);
4987
4988 switch (event) {
4989 case BFA_FCS_VPORT_SM_START:
4990 if (bfa_sm_cmp_state(__vport_fabric(vport),
4991 bfa_fcs_fabric_sm_online)
4992 && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
4993 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
4994 bfa_fcs_vport_do_fdisc(vport);
4995 } else {
4996
4997
4998
4999
5000 vport->vport_stats.fab_no_npiv++;
5001 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5002 }
5003 break;
5004
5005 case BFA_FCS_VPORT_SM_DELETE:
5006 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5007 bfa_fcs_lport_delete(&vport->lport);
5008 break;
5009
5010 case BFA_FCS_VPORT_SM_ONLINE:
5011 case BFA_FCS_VPORT_SM_OFFLINE:
5012
5013
5014
5015
5016 break;
5017
5018 default:
5019 bfa_sm_fault(__vport_fcs(vport), event);
5020 }
5021}
5022
5023
5024
5025
5026static void
5027bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5028 enum bfa_fcs_vport_event event)
5029{
5030 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5031 bfa_trc(__vport_fcs(vport), event);
5032
5033 switch (event) {
5034 case BFA_FCS_VPORT_SM_DELETE:
5035 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5036 bfa_fcs_lport_delete(&vport->lport);
5037 break;
5038
5039 case BFA_FCS_VPORT_SM_ONLINE:
5040 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5041 vport->fdisc_retries = 0;
5042 bfa_fcs_vport_do_fdisc(vport);
5043 break;
5044
5045 case BFA_FCS_VPORT_SM_OFFLINE:
5046
5047
5048
5049
5050
5051
5052
5053 break;
5054
5055 default:
5056 bfa_sm_fault(__vport_fcs(vport), event);
5057 }
5058}
5059
5060
5061
5062
5063
5064static void
5065bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5066 enum bfa_fcs_vport_event event)
5067{
5068 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5069 bfa_trc(__vport_fcs(vport), event);
5070
5071 switch (event) {
5072 case BFA_FCS_VPORT_SM_DELETE:
5073 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5074 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5075 bfa_fcs_lport_delete(&vport->lport);
5076 break;
5077
5078 case BFA_FCS_VPORT_SM_OFFLINE:
5079 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5080 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5081 break;
5082
5083 case BFA_FCS_VPORT_SM_RSP_OK:
5084 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5085 bfa_fcs_lport_online(&vport->lport);
5086 break;
5087
5088 case BFA_FCS_VPORT_SM_RSP_ERROR:
5089 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5090 bfa_timer_start(__vport_bfa(vport), &vport->timer,
5091 bfa_fcs_vport_timeout, vport,
5092 BFA_FCS_RETRY_TIMEOUT);
5093 break;
5094
5095 case BFA_FCS_VPORT_SM_RSP_FAILED:
5096 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5097 break;
5098
5099 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5100 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5101 break;
5102
5103 default:
5104 bfa_sm_fault(__vport_fcs(vport), event);
5105 }
5106}
5107
5108
5109
5110
5111static void
5112bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5113 enum bfa_fcs_vport_event event)
5114{
5115 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5116 bfa_trc(__vport_fcs(vport), event);
5117
5118 switch (event) {
5119 case BFA_FCS_VPORT_SM_DELETE:
5120 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5121 bfa_timer_stop(&vport->timer);
5122 bfa_fcs_lport_delete(&vport->lport);
5123 break;
5124
5125 case BFA_FCS_VPORT_SM_OFFLINE:
5126 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5127 bfa_timer_stop(&vport->timer);
5128 break;
5129
5130 case BFA_FCS_VPORT_SM_TIMEOUT:
5131 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5132 vport->vport_stats.fdisc_retries++;
5133 vport->fdisc_retries++;
5134 bfa_fcs_vport_do_fdisc(vport);
5135 break;
5136
5137 default:
5138 bfa_sm_fault(__vport_fcs(vport), event);
5139 }
5140}
5141
5142
5143
5144
5145static void
5146bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5147 enum bfa_fcs_vport_event event)
5148{
5149 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5150 bfa_trc(__vport_fcs(vport), event);
5151
5152 switch (event) {
5153 case BFA_FCS_VPORT_SM_DELETE:
5154 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5155 bfa_fcs_lport_delete(&vport->lport);
5156 break;
5157
5158 case BFA_FCS_VPORT_SM_OFFLINE:
5159 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5160 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5161 bfa_fcs_lport_offline(&vport->lport);
5162 break;
5163
5164 default:
5165 bfa_sm_fault(__vport_fcs(vport), event);
5166 }
5167}
5168
5169
5170
5171
5172
5173static void
5174bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5175 enum bfa_fcs_vport_event event)
5176{
5177 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5178 bfa_trc(__vport_fcs(vport), event);
5179
5180 switch (event) {
5181 case BFA_FCS_VPORT_SM_DELETE:
5182 break;
5183
5184 case BFA_FCS_VPORT_SM_DELCOMP:
5185 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5186 bfa_fcs_vport_do_logo(vport);
5187 break;
5188
5189 case BFA_FCS_VPORT_SM_OFFLINE:
5190 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5191 break;
5192
5193 default:
5194 bfa_sm_fault(__vport_fcs(vport), event);
5195 }
5196}
5197
5198
5199
5200
5201
5202
5203
5204static void
5205bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5206 enum bfa_fcs_vport_event event)
5207{
5208 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5209 bfa_trc(__vport_fcs(vport), event);
5210
5211 switch (event) {
5212 case BFA_FCS_VPORT_SM_DELETE:
5213 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5214 bfa_fcs_lport_delete(&vport->lport);
5215 break;
5216
5217 default:
5218 bfa_trc(__vport_fcs(vport), event);
5219 }
5220}
5221
5222
5223
5224
5225
5226static void
5227bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5228 enum bfa_fcs_vport_event event)
5229{
5230 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5231 bfa_trc(__vport_fcs(vport), event);
5232
5233 switch (event) {
5234 case BFA_FCS_VPORT_SM_DELCOMP:
5235 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5236 bfa_fcs_vport_free(vport);
5237 break;
5238
5239 case BFA_FCS_VPORT_SM_DELETE:
5240 break;
5241
5242 default:
5243 bfa_sm_fault(__vport_fcs(vport), event);
5244 }
5245}
5246
5247
5248
5249
5250
5251static void
5252bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5253 enum bfa_fcs_vport_event event)
5254{
5255 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5256 bfa_trc(__vport_fcs(vport), event);
5257
5258 switch (event) {
5259 case BFA_FCS_VPORT_SM_OFFLINE:
5260 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5261
5262
5263
5264
5265 case BFA_FCS_VPORT_SM_RSP_OK:
5266 case BFA_FCS_VPORT_SM_RSP_ERROR:
5267 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5268 bfa_fcs_vport_free(vport);
5269 break;
5270
5271 case BFA_FCS_VPORT_SM_DELETE:
5272 break;
5273
5274 default:
5275 bfa_sm_fault(__vport_fcs(vport), event);
5276 }
5277}
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287static void
5288bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5289{
5290 bfa_lps_fdisc(vport->lps, vport,
5291 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5292 __vport_pwwn(vport), __vport_nwwn(vport));
5293 vport->vport_stats.fdisc_sent++;
5294}
5295
5296static void
5297bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5298{
5299 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
5300 u8 lsrjt_expl = vport->lps->lsrjt_expl;
5301
5302 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5303 bfa_trc(__vport_fcs(vport), lsrjt_expl);
5304
5305
5306 switch (vport->lps->lsrjt_expl) {
5307 case FC_LS_RJT_EXP_INV_PORT_NAME:
5308 case FC_LS_RJT_EXP_INVALID_NPORT_ID:
5309 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5310 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5311 else
5312 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5313 break;
5314
5315 case FC_LS_RJT_EXP_INSUFF_RES:
5316
5317
5318
5319
5320 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5321 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5322 else
5323 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5324 break;
5325
5326 default:
5327 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5328 }
5329}
5330
5331
5332
5333
5334
5335static void
5336bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5337{
5338 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5339
5340 vport->vport_stats.logo_sent++;
5341 bfa_lps_fdisclogo(vport->lps);
5342}
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358static void
5359bfa_fcs_vport_timeout(void *vport_arg)
5360{
5361 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5362
5363 vport->vport_stats.fdisc_timeouts++;
5364 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5365}
5366
5367static void
5368bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5369{
5370 struct bfad_vport_s *vport_drv =
5371 (struct bfad_vport_s *)vport->vport_drv;
5372
5373 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5374
5375 if (vport_drv->comp_del)
5376 complete(vport_drv->comp_del);
5377
5378 bfa_lps_delete(vport->lps);
5379}
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390void
5391bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5392{
5393 vport->vport_stats.fab_online++;
5394 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5395}
5396
5397
5398
5399
5400void
5401bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5402{
5403 vport->vport_stats.fab_offline++;
5404 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5405}
5406
5407
5408
5409
5410void
5411bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5412{
5413 vport->vport_stats.fab_cleanup++;
5414}
5415
5416
5417
5418void
5419bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5420{
5421 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5422}
5423
5424
5425
5426
5427void
5428bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5429{
5430 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5431}
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456bfa_status_t
5457bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5458 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5459 struct bfad_vport_s *vport_drv)
5460{
5461 if (vport_cfg->pwwn == 0)
5462 return BFA_STATUS_INVALID_WWN;
5463
5464 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5465 return BFA_STATUS_VPORT_WWN_BP;
5466
5467 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5468 return BFA_STATUS_VPORT_EXISTS;
5469
5470 if (fcs->fabric.num_vports ==
5471 bfa_lps_get_max_vport(fcs->bfa))
5472 return BFA_STATUS_VPORT_MAX;
5473
5474 vport->lps = bfa_lps_alloc(fcs->bfa);
5475 if (!vport->lps)
5476 return BFA_STATUS_VPORT_MAX;
5477
5478 vport->vport_drv = vport_drv;
5479 vport_cfg->preboot_vp = BFA_FALSE;
5480
5481 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5482 bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5483 bfa_fcs_lport_init(&vport->lport, vport_cfg);
5484 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5485
5486 return BFA_STATUS_OK;
5487}
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506bfa_status_t
5507bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5508 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5509 struct bfad_vport_s *vport_drv)
5510{
5511 bfa_status_t rc;
5512
5513 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5514 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5515
5516 return rc;
5517}
5518
5519
5520
5521
5522
5523
5524
5525
5526bfa_boolean_t
5527bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5528{
5529
5530 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5531 return BFA_TRUE;
5532 else
5533 return BFA_FALSE;
5534
5535}
5536
5537
5538
5539
5540
5541
5542
5543
5544bfa_status_t
5545bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5546{
5547 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5548
5549 return BFA_STATUS_OK;
5550}
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561bfa_status_t
5562bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5563{
5564 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5565
5566 return BFA_STATUS_OK;
5567}
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579bfa_status_t
5580bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5581{
5582
5583 if (vport->lport.port_cfg.preboot_vp)
5584 return BFA_STATUS_PBC;
5585
5586 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5587
5588 return BFA_STATUS_OK;
5589}
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599void
5600bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5601 struct bfa_vport_attr_s *attr)
5602{
5603 if (vport == NULL || attr == NULL)
5604 return;
5605
5606 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
5607
5608 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5609 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5610}
5611
5612
5613
5614
5615
5616struct bfa_fcs_vport_s *
5617bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5618{
5619 struct bfa_fcs_vport_s *vport;
5620 struct bfa_fcs_fabric_s *fabric;
5621
5622 bfa_trc(fcs, vf_id);
5623 bfa_trc(fcs, vpwwn);
5624
5625 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5626 if (!fabric) {
5627 bfa_trc(fcs, vf_id);
5628 return NULL;
5629 }
5630
5631 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5632 return vport;
5633}
5634
5635
5636
5637
5638void
5639bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5640{
5641 struct bfa_fcs_vport_s *vport = uarg;
5642
5643 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5644 bfa_trc(__vport_fcs(vport), status);
5645
5646 switch (status) {
5647 case BFA_STATUS_OK:
5648
5649
5650
5651 __vport_fcid(vport) = vport->lps->lp_pid;
5652 vport->vport_stats.fdisc_accepts++;
5653 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5654 break;
5655
5656 case BFA_STATUS_INVALID_MAC:
5657
5658 vport->vport_stats.fdisc_acc_bad++;
5659 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5660
5661 break;
5662
5663 case BFA_STATUS_EPROTOCOL:
5664 switch (vport->lps->ext_status) {
5665 case BFA_EPROTO_BAD_ACCEPT:
5666 vport->vport_stats.fdisc_acc_bad++;
5667 break;
5668
5669 case BFA_EPROTO_UNKNOWN_RSP:
5670 vport->vport_stats.fdisc_unknown_rsp++;
5671 break;
5672
5673 default:
5674 break;
5675 }
5676
5677 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5678 break;
5679
5680 case BFA_STATUS_FABRIC_RJT:
5681 vport->vport_stats.fdisc_rejects++;
5682 bfa_fcs_vport_fdisc_rejected(vport);
5683 break;
5684
5685 default:
5686 vport->vport_stats.fdisc_rsp_err++;
5687 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5688 }
5689}
5690
5691
5692
5693
5694void
5695bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5696{
5697 struct bfa_fcs_vport_s *vport = uarg;
5698 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5699}
5700
5701
5702
5703
5704void
5705bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5706{
5707 struct bfa_fcs_vport_s *vport = uarg;
5708
5709
5710 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5711 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5712}
5713