Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[linux-2.6/next.git] / drivers / scsi / bfa / bfa_fcs_lport.c
blob43fa986bb5860b5d932365036dbf8098867b20a5
1 /*
2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
18 #include "bfad_drv.h"
19 #include "bfa_fcs.h"
20 #include "bfa_fcbuild.h"
21 #include "bfa_fc.h"
23 BFA_TRC_FILE(FCS, PORT);
25 static 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);
28 static void bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
29 struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
30 static void bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
31 static void bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
32 static void bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
33 static void bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
34 static void bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
35 static void bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
36 static 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);
39 static 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);
42 static 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);
45 static void bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
46 static void bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
47 static void bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
49 static void bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
50 static void bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
51 static void bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
53 static 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[] = {
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},
68 * fcs_port_sm FCS logical port state machine
71 enum 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,
79 static void bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
80 enum bfa_fcs_lport_event event);
81 static void bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
82 enum bfa_fcs_lport_event event);
83 static void bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
84 enum bfa_fcs_lport_event event);
85 static void bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
86 enum bfa_fcs_lport_event event);
87 static void bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
88 enum bfa_fcs_lport_event event);
90 static void
91 bfa_fcs_lport_sm_uninit(
92 struct bfa_fcs_lport_s *port,
93 enum bfa_fcs_lport_event event)
95 bfa_trc(port->fcs, port->port_cfg.pwwn);
96 bfa_trc(port->fcs, event);
98 switch (event) {
99 case BFA_FCS_PORT_SM_CREATE:
100 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
101 break;
103 default:
104 bfa_sm_fault(port->fcs, event);
108 static void
109 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
110 enum bfa_fcs_lport_event event)
112 bfa_trc(port->fcs, port->port_cfg.pwwn);
113 bfa_trc(port->fcs, event);
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;
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;
126 case BFA_FCS_PORT_SM_OFFLINE:
127 break;
129 default:
130 bfa_sm_fault(port->fcs, event);
134 static void
135 bfa_fcs_lport_sm_online(
136 struct bfa_fcs_lport_s *port,
137 enum bfa_fcs_lport_event event)
139 struct bfa_fcs_rport_s *rport;
140 struct list_head *qe, *qen;
142 bfa_trc(port->fcs, port->port_cfg.pwwn);
143 bfa_trc(port->fcs, event);
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;
151 case BFA_FCS_PORT_SM_DELETE:
153 __port_action[port->fabric->fab_type].offline(port);
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);
165 break;
167 case BFA_FCS_PORT_SM_DELRPORT:
168 break;
170 default:
171 bfa_sm_fault(port->fcs, event);
175 static void
176 bfa_fcs_lport_sm_offline(
177 struct bfa_fcs_lport_s *port,
178 enum bfa_fcs_lport_event event)
180 struct bfa_fcs_rport_s *rport;
181 struct list_head *qe, *qen;
183 bfa_trc(port->fcs, port->port_cfg.pwwn);
184 bfa_trc(port->fcs, event);
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;
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);
203 break;
205 case BFA_FCS_PORT_SM_DELRPORT:
206 case BFA_FCS_PORT_SM_OFFLINE:
207 break;
209 default:
210 bfa_sm_fault(port->fcs, event);
214 static void
215 bfa_fcs_lport_sm_deleting(
216 struct bfa_fcs_lport_s *port,
217 enum bfa_fcs_lport_event event)
219 bfa_trc(port->fcs, port->port_cfg.pwwn);
220 bfa_trc(port->fcs, event);
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);
228 break;
230 default:
231 bfa_sm_fault(port->fcs, event);
236 * fcs_port_pvt
240 * Send a LS reject
242 static void
243 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
244 u8 reason_code, u8 reason_code_expl)
246 struct fchs_s fchs;
247 struct bfa_fcxp_s *fcxp;
248 struct bfa_rport_s *bfa_rport = NULL;
249 int len;
251 bfa_trc(port->fcs, rx_fchs->d_id);
252 bfa_trc(port->fcs, rx_fchs->s_id);
254 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
255 if (!fcxp)
256 return;
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);
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);
268 * Process incoming plogi from a remote port.
270 static void
271 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
272 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
274 struct bfa_fcs_rport_s *rport;
276 bfa_trc(port->fcs, rx_fchs->d_id);
277 bfa_trc(port->fcs, rx_fchs->s_id);
280 * If min cfg mode is enabled, drop any incoming PLOGIs
282 if (__fcs_min_cfg(port->fcs)) {
283 bfa_trc(port->fcs, rx_fchs->s_id);
284 return;
287 if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
288 bfa_trc(port->fcs, rx_fchs->s_id);
290 * send a LS reject
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;
299 * Direct Attach P2P mode : verify address assigned by the r-port.
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 /* Address assigned to us cannot be a WKA */
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;
311 port->pid = rx_fchs->d_id;
312 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
316 * First, check if we know the device by pwwn.
318 rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
319 if (rport) {
321 * Direct Attach P2P mode : handle address assigned by r-port.
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;
330 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
331 return;
335 * Next, lookup rport by PID.
337 rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
338 if (!rport) {
340 * Inbound PLOGI from a new device.
342 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
343 return;
347 * Rport is known only by PID.
349 if (rport->pwwn) {
351 * This is a different device with the same pid. Old device
352 * disappeared. Send implicit LOGO to old device.
354 WARN_ON(rport->pwwn == plogi->port_name);
355 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
358 * Inbound PLOGI from a new device (with old PID).
360 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
361 return;
365 * PLOGI crossing each other.
367 WARN_ON(rport->pwwn != WWN_NULL);
368 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
372 * Process incoming ECHO.
373 * Since it does not require a login, it is processed here.
375 static void
376 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
377 struct fc_echo_s *echo, u16 rx_len)
379 struct fchs_s fchs;
380 struct bfa_fcxp_s *fcxp;
381 struct bfa_rport_s *bfa_rport = NULL;
382 int len, pyld_len;
384 bfa_trc(port->fcs, rx_fchs->s_id);
385 bfa_trc(port->fcs, rx_fchs->d_id);
387 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
388 if (!fcxp)
389 return;
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);
396 * Copy the payload (if any) from the echo frame
398 pyld_len = rx_len - sizeof(struct fchs_s);
399 bfa_trc(port->fcs, rx_len);
400 bfa_trc(port->fcs, pyld_len);
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)));
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);
413 * Process incoming RNID.
414 * Since it does not require a login, it is processed here.
416 static void
417 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
418 struct fc_rnid_cmd_s *rnid, u16 rx_len)
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;
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);
432 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
433 if (!fcxp)
434 return;
437 * Check Node Indentification Data Format
438 * We only support General Topology Discovery Format.
439 * For any other requested Data Formats, we return Common Node Id Data
440 * only, as per FC-LS.
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;
446 * Get General topology data for this port
448 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
449 } else {
450 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
454 * Copy the Node Id Info
456 common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
457 common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
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);
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);
470 * Fill out General Topolpgy Discovery Data for RNID ELS.
472 static void
473 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
474 struct fc_rnid_general_topology_data_s *gen_topo_data)
476 memset(gen_topo_data, 0,
477 sizeof(struct fc_rnid_general_topology_data_s));
479 gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
480 gen_topo_data->phy_port_num = 0; /* @todo */
481 gen_topo_data->num_attached_nodes = cpu_to_be32(1);
484 static void
485 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
487 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
488 char lpwwn_buf[BFA_STRING_32];
490 bfa_trc(port->fcs, port->fabric->oper_type);
492 __port_action[port->fabric->fab_type].init(port);
493 __port_action[port->fabric->fab_type].online(port);
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");
500 bfad->bfad_flags |= BFAD_PORT_ONLINE;
503 static void
504 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
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];
511 bfa_trc(port->fcs, port->fabric->oper_type);
513 __port_action[port->fabric->fab_type].offline(port);
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");
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);
532 static void
533 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
535 WARN_ON(1);
538 static void
539 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
541 WARN_ON(1);
544 static void
545 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
547 WARN_ON(1);
550 static void
551 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
553 struct fchs_s fchs;
554 struct bfa_fcxp_s *fcxp;
555 int len;
557 bfa_trc(port->fcs, rx_fchs->d_id);
558 bfa_trc(port->fcs, rx_fchs->s_id);
560 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
561 if (!fcxp)
562 return;
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);
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);
572 static void
573 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
575 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
576 char lpwwn_buf[BFA_STRING_32];
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");
583 /* Base port will be deleted by the OS driver */
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);
596 * Unsolicited frame receive handling.
598 void
599 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
600 struct fchs_s *fchs, u16 len)
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);
606 bfa_stats(lport, uf_recvs);
607 bfa_trc(lport->fcs, fchs->type);
609 if (!bfa_fcs_lport_is_online(lport)) {
610 bfa_stats(lport, uf_recv_drops);
611 return;
615 * First, handle ELSs that donot require a login.
618 * Handle PLOGI first
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;
627 * Handle ECHO separately.
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;
636 * Handle RNID separately.
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;
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;
651 * look for a matching remote port ID
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);
659 bfa_fcs_rport_uf_recv(rport, fchs, len);
660 return;
664 * Only handles ELS frames for now.
666 if (fchs->type != FC_TYPE_ELS) {
667 bfa_trc(lport->fcs, fchs->s_id);
668 bfa_trc(lport->fcs, fchs->d_id);
669 /* ignore type FC_TYPE_FC_FSS */
670 if (fchs->type != FC_TYPE_FC_FSS)
671 bfa_sm_fault(lport->fcs, fchs->type);
672 return;
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;
681 if (els_cmd->els_code == FC_ELS_LOGO) {
683 * @todo Handle LOGO frames received.
685 return;
688 if (els_cmd->els_code == FC_ELS_PRLI) {
690 * @todo Handle PRLI frames received.
692 return;
696 * Unhandled ELS frames. Send a LS_RJT.
698 bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
699 FC_LS_RJT_EXP_NO_ADDL_INFO);
704 * PID based Lookup for a R-Port in the Port R-Port Queue
706 struct bfa_fcs_rport_s *
707 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
709 struct bfa_fcs_rport_s *rport;
710 struct list_head *qe;
712 list_for_each(qe, &port->rport_q) {
713 rport = (struct bfa_fcs_rport_s *) qe;
714 if (rport->pid == pid)
715 return rport;
718 bfa_trc(port->fcs, pid);
719 return NULL;
723 * PWWN based Lookup for a R-Port in the Port R-Port Queue
725 struct bfa_fcs_rport_s *
726 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
728 struct bfa_fcs_rport_s *rport;
729 struct list_head *qe;
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;
737 bfa_trc(port->fcs, pwwn);
738 return NULL;
742 * NWWN based Lookup for a R-Port in the Port R-Port Queue
744 struct bfa_fcs_rport_s *
745 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
747 struct bfa_fcs_rport_s *rport;
748 struct list_head *qe;
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;
756 bfa_trc(port->fcs, nwwn);
757 return NULL;
761 * Called by rport module when new rports are discovered.
763 void
764 bfa_fcs_lport_add_rport(
765 struct bfa_fcs_lport_s *port,
766 struct bfa_fcs_rport_s *rport)
768 list_add_tail(&rport->qe, &port->rport_q);
769 port->num_rports++;
773 * Called by rport module to when rports are deleted.
775 void
776 bfa_fcs_lport_del_rport(
777 struct bfa_fcs_lport_s *port,
778 struct bfa_fcs_rport_s *rport)
780 WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
781 list_del(&rport->qe);
782 port->num_rports--;
784 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
788 * Called by fabric for base port when fabric login is complete.
789 * Called by vport for virtual ports when FDISC is complete.
791 void
792 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
794 bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
798 * Called by fabric for base port when fabric goes offline.
799 * Called by vport for virtual ports when virtual port becomes offline.
801 void
802 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
804 bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
808 * Called by fabric to delete base lport and associated resources.
810 * Called by vport to delete lport and associated resources. Should call
811 * bfa_fcs_vport_delete_comp() for vports on completion.
813 void
814 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
816 bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
820 * Return TRUE if port is online, else return FALSE
822 bfa_boolean_t
823 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
825 return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
829 * Attach time initialization of logical ports.
831 void
832 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
833 u16 vf_id, struct bfa_fcs_vport_s *vport)
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;
841 INIT_LIST_HEAD(&lport->rport_q);
842 lport->num_rports = 0;
846 * Logical port initialization of base or virtual port.
847 * Called by fabric for base port or by vport for virtual ports.
850 void
851 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
852 struct bfa_lport_cfg_s *port_cfg)
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];
858 lport->port_cfg = *port_cfg;
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);
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");
870 bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
871 bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
875 * fcs_lport_api
878 void
879 bfa_fcs_lport_get_attr(
880 struct bfa_fcs_lport_s *port,
881 struct bfa_lport_attr_s *port_attr)
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;
888 port_attr->port_cfg = port->port_cfg;
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);
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;
910 } else {
911 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
912 port_attr->state = BFA_LPORT_UNINIT;
917 * bfa_fcs_lport_fab port fab functions
921 * Called by port to initialize fabric services of the base port.
923 static void
924 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
926 bfa_fcs_lport_ns_init(port);
927 bfa_fcs_lport_scn_init(port);
928 bfa_fcs_lport_ms_init(port);
932 * Called by port to notify transition to online state.
934 static void
935 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
937 bfa_fcs_lport_ns_online(port);
938 bfa_fcs_lport_scn_online(port);
942 * Called by port to notify transition to offline state.
944 static void
945 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
947 bfa_fcs_lport_ns_offline(port);
948 bfa_fcs_lport_scn_offline(port);
949 bfa_fcs_lport_ms_offline(port);
953 * bfa_fcs_lport_n2n functions
957 * Called by fcs/port to initialize N2N topology.
959 static void
960 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
965 * Called by fcs/port to notify transition to online state.
967 static void
968 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
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;
974 bfa_trc(port->fcs, pcfg->pwwn);
977 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
978 * and assign an Address. if not, we need to wait for its PLOGI.
980 * If our PWWN is < than that of the remote port, it will send a PLOGI
981 * with the PIDs assigned. The rport state machine take care of this
982 * incoming PLOGI.
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);
990 * First, check if we know the device by pwwn.
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;
1003 * In n2n there can be only one rport. Delete the old one
1004 * whose pid should be zero, because it is offline.
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);
1014 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1019 * Called by fcs/port to notify transition to offline state.
1021 static void
1022 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1024 struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1026 bfa_trc(port->fcs, port->pid);
1027 port->pid = 0;
1028 n2n_port->rem_port_wwn = 0;
1029 n2n_port->reply_oxid = 0;
1032 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1035 * forward declarations
1037 static void bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1038 struct bfa_fcxp_s *fcxp_alloced);
1039 static void bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1040 struct bfa_fcxp_s *fcxp_alloced);
1041 static void bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1042 struct bfa_fcxp_s *fcxp_alloced);
1043 static 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);
1050 static 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);
1057 static 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);
1064 static void bfa_fcs_lport_fdmi_timeout(void *arg);
1065 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1066 u8 *pyld);
1067 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1068 u8 *pyld);
1069 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1070 u8 *pyld);
1071 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1072 fdmi, u8 *pyld);
1073 static void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1074 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1075 static void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1076 struct bfa_fcs_fdmi_port_attr_s *port_attr);
1078 * fcs_fdmi_sm FCS FDMI state machine
1082 * FDMI State Machine events
1084 enum 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,
1095 static void bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1096 enum port_fdmi_event event);
1097 static void bfa_fcs_lport_fdmi_sm_sending_rhba(
1098 struct bfa_fcs_lport_fdmi_s *fdmi,
1099 enum port_fdmi_event event);
1100 static void bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1101 enum port_fdmi_event event);
1102 static void bfa_fcs_lport_fdmi_sm_rhba_retry(
1103 struct bfa_fcs_lport_fdmi_s *fdmi,
1104 enum port_fdmi_event event);
1105 static void bfa_fcs_lport_fdmi_sm_sending_rprt(
1106 struct bfa_fcs_lport_fdmi_s *fdmi,
1107 enum port_fdmi_event event);
1108 static void bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1109 enum port_fdmi_event event);
1110 static void bfa_fcs_lport_fdmi_sm_rprt_retry(
1111 struct bfa_fcs_lport_fdmi_s *fdmi,
1112 enum port_fdmi_event event);
1113 static void bfa_fcs_lport_fdmi_sm_sending_rpa(
1114 struct bfa_fcs_lport_fdmi_s *fdmi,
1115 enum port_fdmi_event event);
1116 static void bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1117 enum port_fdmi_event event);
1118 static void bfa_fcs_lport_fdmi_sm_rpa_retry(
1119 struct bfa_fcs_lport_fdmi_s *fdmi,
1120 enum port_fdmi_event event);
1121 static void bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1122 enum port_fdmi_event event);
1123 static void bfa_fcs_lport_fdmi_sm_disabled(
1124 struct bfa_fcs_lport_fdmi_s *fdmi,
1125 enum port_fdmi_event event);
1127 * Start in offline state - awaiting MS to send start.
1129 static void
1130 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1131 enum port_fdmi_event event)
1133 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1135 bfa_trc(port->fcs, port->port_cfg.pwwn);
1136 bfa_trc(port->fcs, event);
1138 fdmi->retry_cnt = 0;
1140 switch (event) {
1141 case FDMISM_EVENT_PORT_ONLINE:
1142 if (port->vport) {
1144 * For Vports, register a new port.
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 {
1151 * For a base port, we should first register the HBA
1152 * atribute. The HBA attribute also contains the base
1153 * port registration.
1155 bfa_sm_set_state(fdmi,
1156 bfa_fcs_lport_fdmi_sm_sending_rhba);
1157 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1159 break;
1161 case FDMISM_EVENT_PORT_OFFLINE:
1162 break;
1164 default:
1165 bfa_sm_fault(port->fcs, event);
1169 static void
1170 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1171 enum port_fdmi_event event)
1173 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1175 bfa_trc(port->fcs, port->port_cfg.pwwn);
1176 bfa_trc(port->fcs, event);
1178 switch (event) {
1179 case FDMISM_EVENT_RHBA_SENT:
1180 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1181 break;
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;
1189 default:
1190 bfa_sm_fault(port->fcs, event);
1194 static void
1195 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1196 enum port_fdmi_event event)
1198 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1200 bfa_trc(port->fcs, port->port_cfg.pwwn);
1201 bfa_trc(port->fcs, event);
1203 switch (event) {
1204 case FDMISM_EVENT_RSP_ERROR:
1206 * if max retries have not been reached, start timer for a
1207 * delayed retry
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 {
1218 * set state to offline
1220 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1222 break;
1224 case FDMISM_EVENT_RSP_OK:
1226 * Initiate Register Port Attributes
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;
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;
1238 default:
1239 bfa_sm_fault(port->fcs, event);
1243 static void
1244 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1245 enum port_fdmi_event event)
1247 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1249 bfa_trc(port->fcs, port->port_cfg.pwwn);
1250 bfa_trc(port->fcs, event);
1252 switch (event) {
1253 case FDMISM_EVENT_TIMEOUT:
1255 * Retry Timer Expired. Re-send
1257 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1258 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1259 break;
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;
1266 default:
1267 bfa_sm_fault(port->fcs, event);
1272 * RPRT : Register Port
1274 static void
1275 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1276 enum port_fdmi_event event)
1278 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1280 bfa_trc(port->fcs, port->port_cfg.pwwn);
1281 bfa_trc(port->fcs, event);
1283 switch (event) {
1284 case FDMISM_EVENT_RPRT_SENT:
1285 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1286 break;
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;
1294 default:
1295 bfa_sm_fault(port->fcs, event);
1299 static void
1300 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1301 enum port_fdmi_event event)
1303 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1305 bfa_trc(port->fcs, port->port_cfg.pwwn);
1306 bfa_trc(port->fcs, event);
1308 switch (event) {
1309 case FDMISM_EVENT_RSP_ERROR:
1311 * if max retries have not been reached, start timer for a
1312 * delayed retry
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);
1322 } else {
1324 * set state to offline
1326 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1327 fdmi->retry_cnt = 0;
1329 break;
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;
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;
1341 default:
1342 bfa_sm_fault(port->fcs, event);
1346 static void
1347 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1348 enum port_fdmi_event event)
1350 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1352 bfa_trc(port->fcs, port->port_cfg.pwwn);
1353 bfa_trc(port->fcs, event);
1355 switch (event) {
1356 case FDMISM_EVENT_TIMEOUT:
1358 * Retry Timer Expired. Re-send
1360 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1361 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1362 break;
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;
1369 default:
1370 bfa_sm_fault(port->fcs, event);
1375 * Register Port Attributes
1377 static void
1378 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1379 enum port_fdmi_event event)
1381 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1383 bfa_trc(port->fcs, port->port_cfg.pwwn);
1384 bfa_trc(port->fcs, event);
1386 switch (event) {
1387 case FDMISM_EVENT_RPA_SENT:
1388 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1389 break;
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;
1397 default:
1398 bfa_sm_fault(port->fcs, event);
1402 static void
1403 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1404 enum port_fdmi_event event)
1406 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1408 bfa_trc(port->fcs, port->port_cfg.pwwn);
1409 bfa_trc(port->fcs, event);
1411 switch (event) {
1412 case FDMISM_EVENT_RSP_ERROR:
1414 * if max retries have not been reached, start timer for a
1415 * delayed retry
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 {
1425 * set state to offline
1427 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1428 fdmi->retry_cnt = 0;
1430 break;
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;
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;
1442 default:
1443 bfa_sm_fault(port->fcs, event);
1447 static void
1448 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1449 enum port_fdmi_event event)
1451 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1453 bfa_trc(port->fcs, port->port_cfg.pwwn);
1454 bfa_trc(port->fcs, event);
1456 switch (event) {
1457 case FDMISM_EVENT_TIMEOUT:
1459 * Retry Timer Expired. Re-send
1461 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1462 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1463 break;
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;
1470 default:
1471 bfa_sm_fault(port->fcs, event);
1475 static void
1476 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1477 enum port_fdmi_event event)
1479 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1481 bfa_trc(port->fcs, port->port_cfg.pwwn);
1482 bfa_trc(port->fcs, event);
1484 switch (event) {
1485 case FDMISM_EVENT_PORT_OFFLINE:
1486 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487 break;
1489 default:
1490 bfa_sm_fault(port->fcs, event);
1494 * FDMI is disabled state.
1496 static void
1497 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1498 enum port_fdmi_event event)
1500 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1502 bfa_trc(port->fcs, port->port_cfg.pwwn);
1503 bfa_trc(port->fcs, event);
1505 /* No op State. It can only be enabled at Driver Init. */
1509 * RHBA : Register HBA Attributes.
1511 static void
1512 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
1521 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
1529 fdmi->fcxp = fcxp;
1531 pyld = bfa_fcxp_get_reqbuf(fcxp);
1532 memset(pyld, 0, FC_MAX_PDUSZ);
1534 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1535 FDMI_RHBA);
1537 attr_len =
1538 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1539 (u8 *) ((struct ct_hdr_s *) pyld
1540 + 1));
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);
1547 bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1550 static u16
1551 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
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;
1563 * get hba attributes
1565 bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
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);
1571 len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1573 count = 0;
1574 len += sizeof(rhba->hba_attr_blk.attr_count);
1577 * fill out the invididual entries of the HBA attrib Block
1579 curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1582 * Node Name
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));
1595 * Manufacturer
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));
1609 * Serial Number
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));
1623 * Model
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));
1637 * Model Desc
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));
1651 * H/W Version
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));
1667 * Driver Version
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));
1681 * Option Rom Version
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));
1697 * f/w Version = driver version
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));
1711 * OS Name
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));
1727 * MAX_CT_PAYLOAD
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));
1739 * Update size of payload
1741 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1743 rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1744 return len;
1747 static void
1748 bfa_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)
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;
1758 bfa_trc(port->fcs, port->port_cfg.pwwn);
1761 * Sanity Checks
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;
1769 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1770 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1772 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1773 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1774 return;
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);
1783 * RPRT : Register Port
1785 static void
1786 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
1795 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
1803 fdmi->fcxp = fcxp;
1805 pyld = bfa_fcxp_get_reqbuf(fcxp);
1806 memset(pyld, 0, FC_MAX_PDUSZ);
1808 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1809 FDMI_RPRT);
1811 attr_len =
1812 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1813 (u8 *) ((struct ct_hdr_s *) pyld
1814 + 1));
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);
1821 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1825 * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1827 static u16
1828 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1829 u8 *pyld)
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;
1840 * get port attributes
1842 bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1844 len = sizeof(port_attrib->attr_count);
1847 * fill out the invididual entries
1849 curr_ptr = (u8 *) &port_attrib->port_attr;
1852 * FC4 Types
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));
1866 * Supported Speed
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));
1880 * current Port Speed
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));
1893 * max frame size
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));
1906 * OS Device Name
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));
1921 * Host Name
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));
1937 * Update size of payload
1939 port_attrib->attr_count = cpu_to_be32(count);
1940 len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1941 return len;
1944 static u16
1945 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1947 struct bfa_fcs_lport_s *port = fdmi->ms->port;
1948 struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
1949 u16 len;
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);
1954 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
1955 (u8 *) &rprt->port_attr_blk);
1957 len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
1959 return len;
1962 static void
1963 bfa_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)
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;
1973 bfa_trc(port->fcs, port->port_cfg.pwwn);
1976 * Sanity Checks
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;
1984 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1985 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1987 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1988 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1989 return;
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);
1998 * RPA : Register Port Attributes.
2000 static void
2001 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
2010 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
2018 fdmi->fcxp = fcxp;
2020 pyld = bfa_fcxp_get_reqbuf(fcxp);
2021 memset(pyld, 0, FC_MAX_PDUSZ);
2023 len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2024 FDMI_RPA);
2026 attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2027 (u8 *) ((struct ct_hdr_s *) pyld + 1));
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);
2034 bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2037 static u16
2038 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2040 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2041 struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2042 u16 len;
2044 rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2046 len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2047 (u8 *) &rpa->port_attr_blk);
2049 len += sizeof(rpa->port_name);
2051 return len;
2054 static void
2055 bfa_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)
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;
2064 bfa_trc(port->fcs, port->port_cfg.pwwn);
2067 * Sanity Checks
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;
2075 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2076 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2078 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2079 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2080 return;
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);
2088 static void
2089 bfa_fcs_lport_fdmi_timeout(void *arg)
2091 struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2093 bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2096 static void
2097 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2098 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2100 struct bfa_fcs_lport_s *port = fdmi->ms->port;
2101 struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info;
2103 memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
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);
2120 strncpy(hba_attr->driver_version, (char *)driver_info->version,
2121 sizeof(hba_attr->driver_version));
2123 strncpy(hba_attr->os_name, driver_info->host_os_name,
2124 sizeof(hba_attr->os_name));
2127 * If there is a patch level, append it
2128 * to the os name along with a separator
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));
2137 hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2140 static void
2141 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2142 struct bfa_fcs_fdmi_port_attr_s *port_attr)
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;
2148 memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2151 * get pport attributes from hal
2153 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2156 * get FC4 type Bitmask
2158 fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2161 * Supported Speeds
2163 port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
2166 * Current Speed
2168 port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
2171 * Max PDU Size.
2173 port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2176 * OS device Name
2178 strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2179 sizeof(port_attr->os_device_name));
2182 * Host name
2184 strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2185 sizeof(port_attr->host_name));
2190 void
2191 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2193 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
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);
2202 void
2203 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2205 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2207 fdmi->ms = ms;
2208 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2211 void
2212 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2214 struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2216 fdmi->ms = ms;
2217 bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2220 #define BFA_FCS_MS_CMD_MAX_RETRIES 2
2223 * forward declarations
2225 static void bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2226 struct bfa_fcxp_s *fcxp_alloced);
2227 static void bfa_fcs_lport_ms_timeout(void *arg);
2228 static 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);
2236 static void bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2237 struct bfa_fcxp_s *fcxp_alloced);
2238 static 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);
2245 static void bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2246 struct bfa_fcxp_s *fcxp_alloced);
2247 static 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);
2255 * fcs_ms_sm FCS MS state machine
2259 * MS State Machine events
2261 enum 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
2271 static void bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2272 enum port_ms_event event);
2273 static void bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2274 enum port_ms_event event);
2275 static void bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2276 enum port_ms_event event);
2277 static void bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2278 enum port_ms_event event);
2279 static void bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2280 enum port_ms_event event);
2281 static void bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2282 enum port_ms_event event);
2283 static void bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2284 enum port_ms_event event);
2285 static void bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2286 enum port_ms_event event);
2287 static void bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2288 enum port_ms_event event);
2289 static void bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2290 enum port_ms_event event);
2291 static void bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2292 enum port_ms_event event);
2294 * Start in offline state - awaiting NS to send start.
2296 static void
2297 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2298 enum port_ms_event event)
2300 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2301 bfa_trc(ms->port->fcs, event);
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;
2309 case MSSM_EVENT_PORT_OFFLINE:
2310 break;
2312 default:
2313 bfa_sm_fault(ms->port->fcs, event);
2317 static void
2318 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2319 enum port_ms_event event)
2321 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2322 bfa_trc(ms->port->fcs, event);
2324 switch (event) {
2325 case MSSM_EVENT_FCXP_SENT:
2326 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2327 break;
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;
2335 default:
2336 bfa_sm_fault(ms->port->fcs, event);
2340 static void
2341 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2342 enum port_ms_event event)
2344 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2345 bfa_trc(ms->port->fcs, event);
2347 switch (event) {
2348 case MSSM_EVENT_RSP_ERROR:
2350 * Start timer for a delayed retry
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;
2359 case MSSM_EVENT_RSP_OK:
2361 * since plogi is done, now invoke MS related sub-modules
2363 bfa_fcs_lport_fdmi_online(ms);
2366 * if this is a Vport, go to online state.
2368 if (ms->port->vport) {
2369 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2370 break;
2374 * For a base port we need to get the
2375 * switch's IP address.
2377 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2378 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2379 break;
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;
2386 default:
2387 bfa_sm_fault(ms->port->fcs, event);
2391 static void
2392 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2393 enum port_ms_event event)
2395 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2396 bfa_trc(ms->port->fcs, event);
2398 switch (event) {
2399 case MSSM_EVENT_TIMEOUT:
2401 * Retry Timer Expired. Re-send
2403 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2404 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2405 break;
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;
2412 default:
2413 bfa_sm_fault(ms->port->fcs, event);
2417 static void
2418 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2419 enum port_ms_event event)
2421 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2422 bfa_trc(ms->port->fcs, event);
2424 switch (event) {
2425 case MSSM_EVENT_PORT_OFFLINE:
2426 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2427 break;
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;
2435 default:
2436 bfa_sm_fault(ms->port->fcs, event);
2440 static void
2441 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2442 enum port_ms_event event)
2444 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2445 bfa_trc(ms->port->fcs, event);
2447 switch (event) {
2448 case MSSM_EVENT_FCXP_SENT:
2449 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2450 break;
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;
2458 default:
2459 bfa_sm_fault(ms->port->fcs, event);
2463 static void
2464 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2465 enum port_ms_event event)
2467 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2468 bfa_trc(ms->port->fcs, event);
2470 switch (event) {
2471 case MSSM_EVENT_RSP_ERROR:
2473 * Start timer for a delayed retry
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;
2486 break;
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;
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;
2498 default:
2499 bfa_sm_fault(ms->port->fcs, event);
2503 static void
2504 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2505 enum port_ms_event event)
2507 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2508 bfa_trc(ms->port->fcs, event);
2510 switch (event) {
2511 case MSSM_EVENT_TIMEOUT:
2513 * Retry Timer Expired. Re-send
2515 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2516 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2517 break;
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;
2524 default:
2525 bfa_sm_fault(ms->port->fcs, event);
2529 * ms_pvt MS local functions
2532 static void
2533 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
2541 bfa_trc(port->fcs, port->pid);
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;
2549 ms->fcxp = fcxp;
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);
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);
2560 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2563 static void
2564 bfa_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)
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;
2577 bfa_trc(port->fcs, req_status);
2578 bfa_trc(port->fcs, port->port_cfg.pwwn);
2581 * Sanity Checks
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;
2589 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2590 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2592 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2593 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
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;
2601 * The response could contain multiple Entries.
2602 * Entries for SNMP interface, etc.
2603 * We look for the entry with a telnet prefix.
2604 * First "http://" entry refers to IP addr
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) {
2614 * if the IP address is terminating with a '/',
2615 * remove it.
2616 * Byte 0 consists of the length of the string.
2618 rsp_str = &(gmal_entry->prefix[0]);
2619 if (rsp_str[gmal_entry->len-1] == '/')
2620 rsp_str[gmal_entry->len-1] = 0;
2622 /* copy IP Address to fabric */
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;
2633 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2634 return;
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);
2642 static void
2643 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2644 enum port_ms_event event)
2646 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2647 bfa_trc(ms->port->fcs, event);
2649 switch (event) {
2650 case MSSM_EVENT_FCXP_SENT:
2651 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2652 break;
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;
2660 default:
2661 bfa_sm_fault(ms->port->fcs, event);
2665 static void
2666 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2667 enum port_ms_event event)
2669 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2670 bfa_trc(ms->port->fcs, event);
2672 switch (event) {
2673 case MSSM_EVENT_RSP_ERROR:
2675 * Start timer for a delayed retry
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;
2687 break;
2689 case MSSM_EVENT_RSP_OK:
2690 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2691 break;
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;
2698 default:
2699 bfa_sm_fault(ms->port->fcs, event);
2703 static void
2704 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2705 enum port_ms_event event)
2707 bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2708 bfa_trc(ms->port->fcs, event);
2710 switch (event) {
2711 case MSSM_EVENT_TIMEOUT:
2713 * Retry Timer Expired. Re-send
2715 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2716 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2717 break;
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;
2724 default:
2725 bfa_sm_fault(ms->port->fcs, event);
2729 * ms_pvt MS local functions
2732 static void
2733 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
2741 bfa_trc(port->fcs, port->pid);
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;
2749 ms->fcxp = fcxp;
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);
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);
2760 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2763 static void
2764 bfa_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)
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;
2773 bfa_trc(port->fcs, req_status);
2774 bfa_trc(port->fcs, port->port_cfg.pwwn);
2777 * Sanity Checks
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;
2785 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2786 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2788 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2789 gfn_resp = (wwn_t *)(cthdr + 1);
2790 /* check if it has actually changed */
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);
2795 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2796 return;
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);
2805 * ms_pvt MS local functions
2808 static void
2809 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
2817 bfa_trc(port->fcs, port->pid);
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;
2826 ms->fcxp = fcxp;
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));
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);
2839 port->stats.ms_plogi_sent++;
2840 bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2843 static void
2844 bfa_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)
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;
2853 bfa_trc(port->fcs, req_status);
2854 bfa_trc(port->fcs, port->port_cfg.pwwn);
2857 * Sanity Checks
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;
2866 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2868 switch (els_cmd->els_code) {
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;
2877 port->stats.ms_plogi_accepts++;
2878 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2879 break;
2881 case FC_ELS_LS_RJT:
2882 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2884 bfa_trc(port->fcs, ls_rjt->reason_code);
2885 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2887 port->stats.ms_rejects++;
2888 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2889 break;
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);
2898 static void
2899 bfa_fcs_lport_ms_timeout(void *arg)
2901 struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2903 ms->port->stats.ms_timeouts++;
2904 bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2908 void
2909 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2911 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2913 ms->port = port;
2914 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2917 * Invoke init routines of sub modules.
2919 bfa_fcs_lport_fdmi_init(ms);
2922 void
2923 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2925 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2927 ms->port = port;
2928 bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2929 bfa_fcs_lport_fdmi_offline(ms);
2932 void
2933 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2935 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2937 ms->port = port;
2938 bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
2940 void
2941 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
2943 struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2945 /* todo. Handle this only when in Online state */
2946 if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
2947 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
2951 * @page ns_sm_info VPORT NS State Machine
2953 * @section ns_sm_interactions VPORT NS State Machine Interactions
2955 * @section ns_sm VPORT NS State Machine
2956 * img ns_sm.jpg
2960 * forward declarations
2962 static void bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
2963 struct bfa_fcxp_s *fcxp_alloced);
2964 static void bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
2965 struct bfa_fcxp_s *fcxp_alloced);
2966 static void bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
2967 struct bfa_fcxp_s *fcxp_alloced);
2968 static void bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
2969 struct bfa_fcxp_s *fcxp_alloced);
2970 static void bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
2971 struct bfa_fcxp_s *fcxp_alloced);
2972 static void bfa_fcs_lport_ns_timeout(void *arg);
2973 static 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);
2980 static 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);
2987 static 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);
2994 static 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);
3001 static 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);
3008 static void bfa_fcs_lport_ns_process_gidft_pids(
3009 struct bfa_fcs_lport_s *port,
3010 u32 *pid_buf, u32 n_pids);
3012 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3014 * fcs_ns_sm FCS nameserver interface state machine
3018 * VPort NS State Machine events
3020 enum 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,
3034 static void bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3035 enum vport_ns_event event);
3036 static void bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3037 enum vport_ns_event event);
3038 static void bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3039 enum vport_ns_event event);
3040 static void bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3041 enum vport_ns_event event);
3042 static void bfa_fcs_lport_ns_sm_sending_rspn_id(
3043 struct bfa_fcs_lport_ns_s *ns,
3044 enum vport_ns_event event);
3045 static void bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3046 enum vport_ns_event event);
3047 static void bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3048 enum vport_ns_event event);
3049 static void bfa_fcs_lport_ns_sm_sending_rft_id(
3050 struct bfa_fcs_lport_ns_s *ns,
3051 enum vport_ns_event event);
3052 static void bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3053 enum vport_ns_event event);
3054 static void bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3055 enum vport_ns_event event);
3056 static void bfa_fcs_lport_ns_sm_sending_rff_id(
3057 struct bfa_fcs_lport_ns_s *ns,
3058 enum vport_ns_event event);
3059 static void bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3060 enum vport_ns_event event);
3061 static void bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3062 enum vport_ns_event event);
3063 static void bfa_fcs_lport_ns_sm_sending_gid_ft(
3064 struct bfa_fcs_lport_ns_s *ns,
3065 enum vport_ns_event event);
3066 static void bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3067 enum vport_ns_event event);
3068 static void bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3069 enum vport_ns_event event);
3070 static void bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3071 enum vport_ns_event event);
3073 * Start in offline state - awaiting linkup
3075 static void
3076 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3077 enum vport_ns_event event)
3079 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3080 bfa_trc(ns->port->fcs, event);
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;
3088 case NSSM_EVENT_PORT_OFFLINE:
3089 break;
3091 default:
3092 bfa_sm_fault(ns->port->fcs, event);
3096 static void
3097 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3098 enum vport_ns_event event)
3100 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3101 bfa_trc(ns->port->fcs, event);
3103 switch (event) {
3104 case NSSM_EVENT_PLOGI_SENT:
3105 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3106 break;
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;
3114 default:
3115 bfa_sm_fault(ns->port->fcs, event);
3119 static void
3120 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3121 enum vport_ns_event event)
3123 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3124 bfa_trc(ns->port->fcs, event);
3126 switch (event) {
3127 case NSSM_EVENT_RSP_ERROR:
3129 * Start timer for a delayed retry
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;
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;
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;
3148 default:
3149 bfa_sm_fault(ns->port->fcs, event);
3153 static void
3154 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3155 enum vport_ns_event event)
3157 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3158 bfa_trc(ns->port->fcs, event);
3160 switch (event) {
3161 case NSSM_EVENT_TIMEOUT:
3163 * Retry Timer Expired. Re-send
3165 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3166 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3167 break;
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;
3174 default:
3175 bfa_sm_fault(ns->port->fcs, event);
3179 static void
3180 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3181 enum vport_ns_event event)
3183 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3184 bfa_trc(ns->port->fcs, event);
3186 switch (event) {
3187 case NSSM_EVENT_RSPNID_SENT:
3188 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3189 break;
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;
3197 default:
3198 bfa_sm_fault(ns->port->fcs, event);
3202 static void
3203 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3204 enum vport_ns_event event)
3206 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3207 bfa_trc(ns->port->fcs, event);
3209 switch (event) {
3210 case NSSM_EVENT_RSP_ERROR:
3212 * Start timer for a delayed retry
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;
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;
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;
3231 default:
3232 bfa_sm_fault(ns->port->fcs, event);
3236 static void
3237 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3238 enum vport_ns_event event)
3240 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3241 bfa_trc(ns->port->fcs, event);
3243 switch (event) {
3244 case NSSM_EVENT_TIMEOUT:
3246 * Retry Timer Expired. Re-send
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;
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;
3257 default:
3258 bfa_sm_fault(ns->port->fcs, event);
3262 static void
3263 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3264 enum vport_ns_event event)
3266 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3267 bfa_trc(ns->port->fcs, event);
3269 switch (event) {
3270 case NSSM_EVENT_RFTID_SENT:
3271 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3272 break;
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;
3280 default:
3281 bfa_sm_fault(ns->port->fcs, event);
3285 static void
3286 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3287 enum vport_ns_event event)
3289 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3290 bfa_trc(ns->port->fcs, event);
3292 switch (event) {
3293 case NSSM_EVENT_RSP_OK:
3294 /* Now move to register FC4 Features */
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;
3299 case NSSM_EVENT_RSP_ERROR:
3301 * Start timer for a delayed retry
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;
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;
3315 default:
3316 bfa_sm_fault(ns->port->fcs, event);
3320 static void
3321 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3322 enum vport_ns_event event)
3324 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3325 bfa_trc(ns->port->fcs, event);
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;
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;
3338 default:
3339 bfa_sm_fault(ns->port->fcs, event);
3343 static void
3344 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3345 enum vport_ns_event event)
3347 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3348 bfa_trc(ns->port->fcs, event);
3350 switch (event) {
3351 case NSSM_EVENT_RFFID_SENT:
3352 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3353 break;
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;
3361 default:
3362 bfa_sm_fault(ns->port->fcs, event);
3366 static void
3367 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3368 enum vport_ns_event event)
3370 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3371 bfa_trc(ns->port->fcs, event);
3373 switch (event) {
3374 case NSSM_EVENT_RSP_OK:
3377 * If min cfg mode is enabled, we donot initiate rport
3378 * discovery with the fabric. Instead, we will retrieve the
3379 * boot targets from HAL/FW.
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;
3388 * If the port role is Initiator Mode issue NS query.
3389 * If it is Target Mode, skip this and go to online.
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);
3397 * kick off mgmt srvr state machine
3399 bfa_fcs_lport_ms_online(ns->port);
3400 break;
3402 case NSSM_EVENT_RSP_ERROR:
3404 * Start timer for a delayed retry
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;
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;
3418 default:
3419 bfa_sm_fault(ns->port->fcs, event);
3423 static void
3424 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3425 enum vport_ns_event event)
3427 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3428 bfa_trc(ns->port->fcs, event);
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;
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;
3441 default:
3442 bfa_sm_fault(ns->port->fcs, event);
3445 static void
3446 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3447 enum vport_ns_event event)
3449 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3450 bfa_trc(ns->port->fcs, event);
3452 switch (event) {
3453 case NSSM_EVENT_GIDFT_SENT:
3454 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3455 break;
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;
3463 default:
3464 bfa_sm_fault(ns->port->fcs, event);
3468 static void
3469 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3470 enum vport_ns_event event)
3472 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3473 bfa_trc(ns->port->fcs, event);
3475 switch (event) {
3476 case NSSM_EVENT_RSP_OK:
3477 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3478 break;
3480 case NSSM_EVENT_RSP_ERROR:
3482 * TBD: for certain reject codes, we don't need to retry
3485 * Start timer for a delayed retry
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;
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;
3499 case NSSM_EVENT_NS_QUERY:
3500 break;
3502 default:
3503 bfa_sm_fault(ns->port->fcs, event);
3507 static void
3508 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3509 enum vport_ns_event event)
3511 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3512 bfa_trc(ns->port->fcs, event);
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;
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;
3525 default:
3526 bfa_sm_fault(ns->port->fcs, event);
3530 static void
3531 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3532 enum vport_ns_event event)
3534 bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3535 bfa_trc(ns->port->fcs, event);
3537 switch (event) {
3538 case NSSM_EVENT_PORT_OFFLINE:
3539 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3540 break;
3542 case NSSM_EVENT_NS_QUERY:
3544 * If the port role is Initiator Mode issue NS query.
3545 * If it is Target Mode, skip this and go to online.
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);
3552 break;
3554 default:
3555 bfa_sm_fault(ns->port->fcs, event);
3562 * ns_pvt Nameserver local functions
3565 static void
3566 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
3574 bfa_trc(port->fcs, port->pid);
3576 fcxp = 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;
3583 ns->fcxp = fcxp;
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));
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++;
3597 bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3600 static void
3601 bfa_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)
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 /* struct fc_logi_s *plogi_resp; */
3608 struct fc_els_cmd_s *els_cmd;
3609 struct fc_ls_rjt_s *ls_rjt;
3611 bfa_trc(port->fcs, req_status);
3612 bfa_trc(port->fcs, port->port_cfg.pwwn);
3615 * Sanity Checks
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;
3624 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3626 switch (els_cmd->els_code) {
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;
3635 port->stats.ns_plogi_accepts++;
3636 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3637 break;
3639 case FC_ELS_LS_RJT:
3640 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3642 bfa_trc(port->fcs, ls_rjt->reason_code);
3643 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3645 port->stats.ns_rejects++;
3647 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3648 break;
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);
3658 * Register the symbolic port name.
3660 static void
3661 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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];
3671 memset(symbl, 0, sizeof(symbl));
3673 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
3682 ns->fcxp = fcxp;
3685 * for V-Port, form a Port Symbolic Name
3687 if (port->vport) {
3689 * For Vports, we append the vport's port symbolic name
3690 * to that of the base port.
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))));
3701 /* Ensure we have a null terminating string. */
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));
3712 len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3713 bfa_fcs_lport_get_fcid(port), 0, psymbl);
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);
3720 port->stats.ns_rspnid_sent++;
3722 bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3725 static void
3726 bfa_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)
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;
3735 bfa_trc(port->fcs, port->port_cfg.pwwn);
3738 * Sanity Checks
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;
3747 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3748 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
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;
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);
3763 * Register FC4-Types
3765 static void
3766 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
3774 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
3783 ns->fcxp = fcxp;
3785 len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3786 bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
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);
3793 port->stats.ns_rftid_sent++;
3794 bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3797 static void
3798 bfa_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)
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;
3807 bfa_trc(port->fcs, port->port_cfg.pwwn);
3810 * Sanity Checks
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;
3819 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3820 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
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;
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);
3835 * Register FC4-Features : Should be done after RFT_ID
3837 static void
3838 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
3847 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
3856 ns->fcxp = fcxp;
3858 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3859 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
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);
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);
3870 port->stats.ns_rffid_sent++;
3871 bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3874 static void
3875 bfa_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)
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;
3884 bfa_trc(port->fcs, port->port_cfg.pwwn);
3887 * Sanity Checks
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;
3896 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3897 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
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;
3905 port->stats.ns_rffid_rejects++;
3906 bfa_trc(port->fcs, cthdr->reason_code);
3907 bfa_trc(port->fcs, cthdr->exp_code);
3909 if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3910 /* if this command is not supported, we don't retry */
3911 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3912 } else
3913 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3916 * Query Fabric for FC4-Types Devices.
3918 * TBD : Need to use a local (FCS private) response buffer, since the response
3919 * can be larger than 2K.
3921 static void
3922 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
3930 bfa_trc(port->fcs, port->pid);
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;
3939 ns->fcxp = fcxp;
3942 * This query is only initiated for FCP initiator mode.
3944 len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3945 ns->port->pid, FC_TYPE_FCP);
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);
3952 port->stats.ns_gidft_sent++;
3954 bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
3957 static void
3958 bfa_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)
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;
3968 bfa_trc(port->fcs, port->port_cfg.pwwn);
3971 * Sanity Checks
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;
3980 if (resid_len != 0) {
3982 * TBD : we will need to allocate a larger buffer & retry the
3983 * command
3985 bfa_trc(port->fcs, rsp_len);
3986 bfa_trc(port->fcs, resid_len);
3987 return;
3990 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3991 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3993 switch (cthdr->cmd_rsp_code) {
3995 case CT_RSP_ACCEPT:
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;
4006 case CT_RSP_REJECT:
4009 * Check the reason code & explanation.
4010 * There may not have been any FC4 devices in the fabric
4012 port->stats.ns_gidft_rejects++;
4013 bfa_trc(port->fcs, cthdr->reason_code);
4014 bfa_trc(port->fcs, cthdr->exp_code);
4016 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4017 && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4019 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4020 } else {
4022 * for all other errors, retry
4024 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4026 break;
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);
4036 * This routine will be called by bfa_timer on timer timeouts.
4038 * param[in] port - pointer to bfa_fcs_lport_t.
4040 * return
4041 * void
4043 * Special Considerations:
4045 * note
4047 static void
4048 bfa_fcs_lport_ns_timeout(void *arg)
4050 struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4052 ns->port->stats.ns_timeouts++;
4053 bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4057 * Process the PID list in GID_FT response
4059 static void
4060 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4061 u32 n_pids)
4063 struct fcgs_gidft_resp_s *gidft_entry;
4064 struct bfa_fcs_rport_s *rport;
4065 u32 ii;
4067 for (ii = 0; ii < n_pids; ii++) {
4068 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4070 if (gidft_entry->pid == port->pid)
4071 continue;
4074 * Check if this rport already exists
4076 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4077 if (rport == NULL) {
4079 * this is a new device. create rport
4081 rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4082 } else {
4084 * this rport already exists
4086 bfa_fcs_rport_scn(rport);
4089 bfa_trc(port->fcs, gidft_entry->pid);
4092 * if the last entry bit is set, bail out.
4094 if (gidft_entry->last)
4095 return;
4100 * fcs_ns_public FCS nameserver public interfaces
4104 * Functions called by port/fab.
4105 * These will send relevant Events to the ns state machine.
4107 void
4108 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4110 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4112 ns->port = port;
4113 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4116 void
4117 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4119 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4121 ns->port = port;
4122 bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4125 void
4126 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4128 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4130 ns->port = port;
4131 bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4134 void
4135 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4137 struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4139 bfa_trc(port->fcs, port->pid);
4140 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4143 static void
4144 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4147 struct bfa_fcs_rport_s *rport;
4148 u8 nwwns;
4149 wwn_t wwns[BFA_PREBOOT_BOOTLUN_MAX];
4150 int ii;
4152 bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4154 for (ii = 0 ; ii < nwwns; ++ii) {
4155 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4156 WARN_ON(!rport);
4161 * FCS SCN
4164 #define FC_QOS_RSCN_EVENT 0x0c
4165 #define FC_FABRIC_NAME_RSCN_EVENT 0x0d
4168 * forward declarations
4170 static void bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4171 struct bfa_fcxp_s *fcxp_alloced);
4172 static 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);
4179 static void bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4180 struct fchs_s *rx_fchs);
4181 static void bfa_fcs_lport_scn_timeout(void *arg);
4184 * fcs_scm_sm FCS SCN state machine
4188 * VPort SCN State Machine events
4190 enum 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,
4199 static void bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4200 enum port_scn_event event);
4201 static void bfa_fcs_lport_scn_sm_sending_scr(
4202 struct bfa_fcs_lport_scn_s *scn,
4203 enum port_scn_event event);
4204 static void bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4205 enum port_scn_event event);
4206 static void bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4207 enum port_scn_event event);
4208 static void bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4209 enum port_scn_event event);
4212 * Starting state - awaiting link up.
4214 static void
4215 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4216 enum port_scn_event event)
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;
4224 case SCNSM_EVENT_PORT_OFFLINE:
4225 break;
4227 default:
4228 bfa_sm_fault(scn->port->fcs, event);
4232 static void
4233 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4234 enum port_scn_event event)
4236 switch (event) {
4237 case SCNSM_EVENT_SCR_SENT:
4238 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4239 break;
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;
4246 default:
4247 bfa_sm_fault(scn->port->fcs, event);
4251 static void
4252 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4253 enum port_scn_event event)
4255 struct bfa_fcs_lport_s *port = scn->port;
4257 switch (event) {
4258 case SCNSM_EVENT_RSP_OK:
4259 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4260 break;
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;
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;
4274 default:
4275 bfa_sm_fault(port->fcs, event);
4279 static void
4280 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4281 enum port_scn_event event)
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;
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;
4294 default:
4295 bfa_sm_fault(scn->port->fcs, event);
4299 static void
4300 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4301 enum port_scn_event event)
4303 switch (event) {
4304 case SCNSM_EVENT_PORT_OFFLINE:
4305 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4306 break;
4308 default:
4309 bfa_sm_fault(scn->port->fcs, event);
4316 * fcs_scn_private FCS SCN private functions
4320 * This routine will be called to send a SCR command.
4322 static void
4323 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
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;
4331 bfa_trc(port->fcs, port->pid);
4332 bfa_trc(port->fcs, port->port_cfg.pwwn);
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;
4340 scn->fcxp = fcxp;
4342 /* Handle VU registrations for Base port only */
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);
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);
4358 bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4361 static void
4362 bfa_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)
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;
4371 bfa_trc(port->fcs, port->port_cfg.pwwn);
4374 * Sanity Checks
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;
4382 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4384 switch (els_cmd->els_code) {
4386 case FC_ELS_ACC:
4387 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4388 break;
4390 case FC_ELS_LS_RJT:
4392 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4394 bfa_trc(port->fcs, ls_rjt->reason_code);
4395 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4397 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4398 break;
4400 default:
4401 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4406 * Send a LS Accept
4408 static void
4409 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4410 struct fchs_s *rx_fchs)
4412 struct fchs_s fchs;
4413 struct bfa_fcxp_s *fcxp;
4414 struct bfa_rport_s *bfa_rport = NULL;
4415 int len;
4417 bfa_trc(port->fcs, rx_fchs->s_id);
4419 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4420 if (!fcxp)
4421 return;
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);
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);
4433 * This routine will be called by bfa_timer on timer timeouts.
4435 * param[in] vport - pointer to bfa_fcs_lport_t.
4436 * param[out] vport_status - pointer to return vport status in
4438 * return
4439 * void
4441 * Special Considerations:
4443 * note
4445 static void
4446 bfa_fcs_lport_scn_timeout(void *arg)
4448 struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4450 bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4456 * fcs_scn_public FCS state change notification public interfaces
4460 * Functions called by port/fab
4462 void
4463 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4465 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4467 scn->port = port;
4468 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4471 void
4472 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4474 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4476 scn->port = port;
4477 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4480 void
4481 bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4483 struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4485 scn->port = port;
4486 bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4489 static void
4490 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4492 struct bfa_fcs_rport_s *rport;
4494 bfa_trc(port->fcs, rpid);
4497 * If this is an unknown device, then it just came online.
4498 * Otherwise let rport handle the RSCN event.
4500 rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4501 if (rport == NULL) {
4503 * If min cfg mode is enabled, we donot need to
4504 * discover any new rports.
4506 if (!__fcs_min_cfg(port->fcs))
4507 rport = bfa_fcs_rport_create(port, rpid);
4508 } else
4509 bfa_fcs_rport_scn(rport);
4513 * rscn format based PID comparison
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])))
4523 static void
4524 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4525 enum fc_rscn_format format,
4526 u32 rscn_pid)
4528 struct bfa_fcs_rport_s *rport;
4529 struct list_head *qe, *qe_next;
4530 u8 *c0, *c1;
4532 bfa_trc(port->fcs, format);
4533 bfa_trc(port->fcs, rscn_pid);
4535 c0 = (u8 *) &rscn_pid;
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);
4546 void
4547 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4548 struct fchs_s *fchs, u32 len)
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;
4556 num_entries =
4557 (be16_to_cpu(rscn->payldlen) -
4558 sizeof(u32)) / sizeof(rscn->event[0]);
4560 bfa_trc(port->fcs, num_entries);
4562 port->stats.num_rscn++;
4564 bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4566 for (i = 0; i < num_entries; i++) {
4567 rscn_pid = rscn->event[i].portid;
4569 bfa_trc(port->fcs, rscn->event[i].format);
4570 bfa_trc(port->fcs, rscn_pid);
4572 /* check for duplicate entries in the list */
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;
4581 /* if found in down the list, pid has been already processed */
4582 if (found) {
4583 bfa_trc(port->fcs, rscn_pid);
4584 continue;
4587 switch (rscn->event[i].format) {
4588 case FC_RSCN_FORMAT_PORTID:
4589 if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4591 * Ignore this event.
4592 * f/w would have processed it
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);
4599 break;
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;
4607 /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
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;
4618 default:
4619 WARN_ON(1);
4620 nsquery = BFA_TRUE;
4625 * If any of area, domain or fabric RSCN is received, do a fresh
4626 * discovery to find new devices.
4628 if (nsquery)
4629 bfa_fcs_lport_ns_query(port);
4633 * BFA FCS port
4636 * fcs_port_api BFA FCS port API
4638 struct bfa_fcs_lport_s *
4639 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4641 return &fcs->fabric.bport;
4644 wwn_t
4645 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4646 int nrports, bfa_boolean_t bwwn)
4648 struct list_head *qh, *qe;
4649 struct bfa_fcs_rport_s *rport = NULL;
4650 int i;
4651 struct bfa_fcs_s *fcs;
4653 if (port == NULL || nrports == 0)
4654 return (wwn_t) 0;
4656 fcs = port->fcs;
4657 bfa_trc(fcs, (u32) nrports);
4659 i = 0;
4660 qh = &port->rport_q;
4661 qe = bfa_q_first(qh);
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;
4673 if (bwwn) {
4674 if (!memcmp(&wwn, &rport->pwwn, 8))
4675 break;
4676 } else {
4677 if (i == index)
4678 break;
4681 i++;
4682 qe = bfa_q_next(qe);
4685 bfa_trc(fcs, i);
4686 if (rport)
4687 return rport->pwwn;
4688 else
4689 return (wwn_t) 0;
4692 void
4693 bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4694 wwn_t rport_wwns[], int *nrports)
4696 struct list_head *qh, *qe;
4697 struct bfa_fcs_rport_s *rport = NULL;
4698 int i;
4699 struct bfa_fcs_s *fcs;
4701 if (port == NULL || rport_wwns == NULL || *nrports == 0)
4702 return;
4704 fcs = port->fcs;
4705 bfa_trc(fcs, (u32) *nrports);
4707 i = 0;
4708 qh = &port->rport_q;
4709 qe = bfa_q_first(qh);
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;
4721 rport_wwns[i] = rport->pwwn;
4723 i++;
4724 qe = bfa_q_next(qe);
4727 bfa_trc(fcs, i);
4728 *nrports = i;
4732 * Iterate's through all the rport's in the given port to
4733 * determine the maximum operating speed.
4735 * !!!! To be used in TRL Functionality only !!!!
4737 bfa_port_speed_t
4738 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
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);
4749 if (port == NULL)
4750 return 0;
4752 fcs = port->fcs;
4754 /* Get Physical port's current speed */
4755 bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4756 port_speed = port_attr.speed;
4757 bfa_trc(fcs, port_speed);
4759 qh = &port->rport_q;
4760 qe = bfa_q_first(qh);
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;
4771 rport_speed = rport->rpf.rpsc_speed;
4772 if ((trl_enabled) && (rport_speed ==
4773 BFA_PORT_SPEED_UNKNOWN)) {
4774 /* Use default ratelim speed setting */
4775 rport_speed =
4776 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
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;
4787 qe = bfa_q_next(qe);
4790 bfa_trc(fcs, max_speed);
4791 return max_speed;
4794 struct bfa_fcs_lport_s *
4795 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4797 struct bfa_fcs_vport_s *vport;
4798 bfa_fcs_vf_t *vf;
4800 WARN_ON(fcs == NULL);
4802 vf = bfa_fcs_vf_lookup(fcs, vf_id);
4803 if (vf == NULL) {
4804 bfa_trc(fcs, vf_id);
4805 return NULL;
4808 if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4809 return &vf->bport;
4811 vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4812 if (vport)
4813 return &vport->lport;
4815 return NULL;
4819 * API corresponding to NPIV_VPORT_GETINFO.
4821 void
4822 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4823 struct bfa_lport_info_s *port_info)
4826 bfa_trc(port->fcs, port->fabric->fabric_name);
4828 if (port->vport == NULL) {
4830 * This is a Physical port
4832 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4835 * @todo : need to fix the state & reason
4837 port_info->port_state = 0;
4838 port_info->offline_reason = 0;
4840 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4841 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
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 {
4851 * This is a virtual port
4853 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4856 * @todo : need to fix the state & reason
4858 port_info->port_state = 0;
4859 port_info->offline_reason = 0;
4861 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4862 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4866 void
4867 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4868 struct bfa_lport_stats_s *port_stats)
4870 *port_stats = fcs_port->stats;
4873 void
4874 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4876 memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
4880 * FCS virtual port state machine
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)
4891 #define BFA_FCS_VPORT_MAX_RETRIES 5
4893 * Forward declarations
4895 static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4896 static void bfa_fcs_vport_timeout(void *vport_arg);
4897 static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4898 static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4901 * fcs_vport_sm FCS virtual port state machine
4905 * VPort State Machine events
4907 enum bfa_fcs_vport_event {
4908 BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */
4909 BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */
4910 BFA_FCS_VPORT_SM_START = 3, /* vport start request */
4911 BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */
4912 BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */
4913 BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */
4914 BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */
4915 BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */
4916 BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */
4917 BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */
4918 BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */
4919 BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error*/
4920 BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */
4923 static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4924 enum bfa_fcs_vport_event event);
4925 static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4926 enum bfa_fcs_vport_event event);
4927 static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4928 enum bfa_fcs_vport_event event);
4929 static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4930 enum bfa_fcs_vport_event event);
4931 static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4932 enum bfa_fcs_vport_event event);
4933 static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
4934 enum bfa_fcs_vport_event event);
4935 static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
4936 enum bfa_fcs_vport_event event);
4937 static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
4938 enum bfa_fcs_vport_event event);
4939 static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
4940 enum bfa_fcs_vport_event event);
4941 static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
4942 enum bfa_fcs_vport_event event);
4944 static 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}
4958 * Beginning state.
4960 static void
4961 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4962 enum bfa_fcs_vport_event event)
4964 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4965 bfa_trc(__vport_fcs(vport), event);
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;
4973 default:
4974 bfa_sm_fault(__vport_fcs(vport), event);
4979 * Created state - a start event is required to start up the state machine.
4981 static void
4982 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4983 enum bfa_fcs_vport_event event)
4985 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4986 bfa_trc(__vport_fcs(vport), event);
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 {
4997 * Fabric is offline or not NPIV capable, stay in
4998 * offline state.
5000 vport->vport_stats.fab_no_npiv++;
5001 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5003 break;
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;
5010 case BFA_FCS_VPORT_SM_ONLINE:
5011 case BFA_FCS_VPORT_SM_OFFLINE:
5013 * Ignore ONLINE/OFFLINE events from fabric
5014 * till vport is started.
5016 break;
5018 default:
5019 bfa_sm_fault(__vport_fcs(vport), event);
5024 * Offline state - awaiting ONLINE event from fabric SM.
5026 static void
5027 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5028 enum bfa_fcs_vport_event event)
5030 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5031 bfa_trc(__vport_fcs(vport), event);
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;
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;
5045 case BFA_FCS_VPORT_SM_OFFLINE:
5047 * This can happen if the vport couldn't be initialzied
5048 * due the fact that the npiv was not enabled on the switch.
5049 * In that case we will put the vport in offline state.
5050 * However, the link can go down and cause the this event to
5051 * be sent when we are already offline. Ignore it.
5053 break;
5055 default:
5056 bfa_sm_fault(__vport_fcs(vport), event);
5062 * FDISC is sent and awaiting reply from fabric.
5064 static void
5065 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5066 enum bfa_fcs_vport_event event)
5068 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5069 bfa_trc(__vport_fcs(vport), event);
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;
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;
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;
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;
5095 case BFA_FCS_VPORT_SM_RSP_FAILED:
5096 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5097 break;
5099 case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5100 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5101 break;
5103 default:
5104 bfa_sm_fault(__vport_fcs(vport), event);
5109 * FDISC attempt failed - a timer is active to retry FDISC.
5111 static void
5112 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5113 enum bfa_fcs_vport_event event)
5115 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5116 bfa_trc(__vport_fcs(vport), event);
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;
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;
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;
5137 default:
5138 bfa_sm_fault(__vport_fcs(vport), event);
5143 * Vport is online (FDISC is complete).
5145 static void
5146 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5147 enum bfa_fcs_vport_event event)
5149 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5150 bfa_trc(__vport_fcs(vport), event);
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;
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;
5164 default:
5165 bfa_sm_fault(__vport_fcs(vport), event);
5170 * Vport is being deleted - awaiting lport delete completion to send
5171 * LOGO to fabric.
5173 static void
5174 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5175 enum bfa_fcs_vport_event event)
5177 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5178 bfa_trc(__vport_fcs(vport), event);
5180 switch (event) {
5181 case BFA_FCS_VPORT_SM_DELETE:
5182 break;
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;
5189 case BFA_FCS_VPORT_SM_OFFLINE:
5190 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5191 break;
5193 default:
5194 bfa_sm_fault(__vport_fcs(vport), event);
5199 * Error State.
5200 * This state will be set when the Vport Creation fails due
5201 * to errors like Dup WWN. In this state only operation allowed
5202 * is a Vport Delete.
5204 static void
5205 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5206 enum bfa_fcs_vport_event event)
5208 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5209 bfa_trc(__vport_fcs(vport), event);
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;
5217 default:
5218 bfa_trc(__vport_fcs(vport), event);
5223 * Lport cleanup is in progress since vport is being deleted. Fabric is
5224 * offline, so no LOGO is needed to complete vport deletion.
5226 static void
5227 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5228 enum bfa_fcs_vport_event event)
5230 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5231 bfa_trc(__vport_fcs(vport), event);
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;
5239 case BFA_FCS_VPORT_SM_DELETE:
5240 break;
5242 default:
5243 bfa_sm_fault(__vport_fcs(vport), event);
5248 * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5249 * is done.
5251 static void
5252 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5253 enum bfa_fcs_vport_event event)
5255 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5256 bfa_trc(__vport_fcs(vport), event);
5258 switch (event) {
5259 case BFA_FCS_VPORT_SM_OFFLINE:
5260 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5262 * !!! fall through !!!
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;
5271 case BFA_FCS_VPORT_SM_DELETE:
5272 break;
5274 default:
5275 bfa_sm_fault(__vport_fcs(vport), event);
5282 * fcs_vport_private FCS virtual port private functions
5285 * This routine will be called to send a FDISC command.
5287 static void
5288 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
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++;
5296 static void
5297 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5299 u8 lsrjt_rsn = vport->lps->lsrjt_rsn;
5300 u8 lsrjt_expl = vport->lps->lsrjt_expl;
5302 bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5303 bfa_trc(__vport_fcs(vport), lsrjt_expl);
5305 /* For certain reason codes, we don't want to retry. */
5306 switch (vport->lps->lsrjt_expl) {
5307 case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5308 case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
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;
5315 case FC_LS_RJT_EXP_INSUFF_RES:
5317 * This means max logins per port/switch setting on the
5318 * switch was exceeded.
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;
5326 default:
5327 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5332 * Called to send a logout to the fabric. Used when a V-Port is
5333 * deleted/stopped.
5335 static void
5336 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5338 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5340 vport->vport_stats.logo_sent++;
5341 bfa_lps_fdisclogo(vport->lps);
5346 * This routine will be called by bfa_timer on timer timeouts.
5348 * param[in] vport - pointer to bfa_fcs_vport_t.
5349 * param[out] vport_status - pointer to return vport status in
5351 * return
5352 * void
5354 * Special Considerations:
5356 * note
5358 static void
5359 bfa_fcs_vport_timeout(void *vport_arg)
5361 struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5363 vport->vport_stats.fdisc_timeouts++;
5364 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5367 static void
5368 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5370 struct bfad_vport_s *vport_drv =
5371 (struct bfad_vport_s *)vport->vport_drv;
5373 bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5375 if (vport_drv->comp_del)
5376 complete(vport_drv->comp_del);
5378 bfa_lps_delete(vport->lps);
5384 * fcs_vport_public FCS virtual port public interfaces
5388 * Online notification from fabric SM.
5390 void
5391 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5393 vport->vport_stats.fab_online++;
5394 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5398 * Offline notification from fabric SM.
5400 void
5401 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5403 vport->vport_stats.fab_offline++;
5404 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5408 * Cleanup notification from fabric SM on link timer expiry.
5410 void
5411 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5413 vport->vport_stats.fab_cleanup++;
5416 * delete notification from fabric SM. To be invoked from within FCS.
5418 void
5419 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5421 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5425 * Delete completion callback from associated lport
5427 void
5428 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5430 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5436 * fcs_vport_api Virtual port API
5440 * Use this function to instantiate a new FCS vport object. This
5441 * function will not trigger any HW initialization process (which will be
5442 * done in vport_start() call)
5444 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5445 * needs to be allocated by the driver.
5446 * param[in] fcs - FCS instance
5447 * param[in] vport_cfg - vport configuration
5448 * param[in] vf_id - VF_ID if vport is created within a VF.
5449 * FC_VF_ID_NULL to specify base fabric.
5450 * param[in] vport_drv - Opaque handle back to the driver's vport
5451 * structure
5453 * retval BFA_STATUS_OK - on success.
5454 * retval BFA_STATUS_FAILED - on failure.
5456 bfa_status_t
5457 bfa_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)
5461 if (vport_cfg->pwwn == 0)
5462 return BFA_STATUS_INVALID_WWN;
5464 if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5465 return BFA_STATUS_VPORT_WWN_BP;
5467 if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5468 return BFA_STATUS_VPORT_EXISTS;
5470 if (fcs->fabric.num_vports ==
5471 bfa_lps_get_max_vport(fcs->bfa))
5472 return BFA_STATUS_VPORT_MAX;
5474 vport->lps = bfa_lps_alloc(fcs->bfa);
5475 if (!vport->lps)
5476 return BFA_STATUS_VPORT_MAX;
5478 vport->vport_drv = vport_drv;
5479 vport_cfg->preboot_vp = BFA_FALSE;
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);
5486 return BFA_STATUS_OK;
5490 * Use this function to instantiate a new FCS PBC vport object. This
5491 * function will not trigger any HW initialization process (which will be
5492 * done in vport_start() call)
5494 * param[in] vport - pointer to bfa_fcs_vport_t. This space
5495 * needs to be allocated by the driver.
5496 * param[in] fcs - FCS instance
5497 * param[in] vport_cfg - vport configuration
5498 * param[in] vf_id - VF_ID if vport is created within a VF.
5499 * FC_VF_ID_NULL to specify base fabric.
5500 * param[in] vport_drv - Opaque handle back to the driver's vport
5501 * structure
5503 * retval BFA_STATUS_OK - on success.
5504 * retval BFA_STATUS_FAILED - on failure.
5506 bfa_status_t
5507 bfa_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)
5511 bfa_status_t rc;
5513 rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5514 vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5516 return rc;
5520 * Use this function to findout if this is a pbc vport or not.
5522 * @param[in] vport - pointer to bfa_fcs_vport_t.
5524 * @returns None
5526 bfa_boolean_t
5527 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5530 if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5531 return BFA_TRUE;
5532 else
5533 return BFA_FALSE;
5538 * Use this function initialize the vport.
5540 * @param[in] vport - pointer to bfa_fcs_vport_t.
5542 * @returns None
5544 bfa_status_t
5545 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5547 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5549 return BFA_STATUS_OK;
5553 * Use this function quiese the vport object. This function will return
5554 * immediately, when the vport is actually stopped, the
5555 * bfa_drv_vport_stop_cb() will be called.
5557 * param[in] vport - pointer to bfa_fcs_vport_t.
5559 * return None
5561 bfa_status_t
5562 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5564 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5566 return BFA_STATUS_OK;
5570 * Use this function to delete a vport object. Fabric object should
5571 * be stopped before this function call.
5573 * !!!!!!! Donot invoke this from within FCS !!!!!!!
5575 * param[in] vport - pointer to bfa_fcs_vport_t.
5577 * return None
5579 bfa_status_t
5580 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5583 if (vport->lport.port_cfg.preboot_vp)
5584 return BFA_STATUS_PBC;
5586 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5588 return BFA_STATUS_OK;
5592 * Use this function to get vport's current status info.
5594 * param[in] vport pointer to bfa_fcs_vport_t.
5595 * param[out] attr pointer to return vport attributes
5597 * return None
5599 void
5600 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5601 struct bfa_vport_attr_s *attr)
5603 if (vport == NULL || attr == NULL)
5604 return;
5606 memset(attr, 0, sizeof(struct bfa_vport_attr_s));
5608 bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5609 attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5614 * Lookup a virtual port. Excludes base port from lookup.
5616 struct bfa_fcs_vport_s *
5617 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5619 struct bfa_fcs_vport_s *vport;
5620 struct bfa_fcs_fabric_s *fabric;
5622 bfa_trc(fcs, vf_id);
5623 bfa_trc(fcs, vpwwn);
5625 fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5626 if (!fabric) {
5627 bfa_trc(fcs, vf_id);
5628 return NULL;
5631 vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5632 return vport;
5636 * FDISC Response
5638 void
5639 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5641 struct bfa_fcs_vport_s *vport = uarg;
5643 bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5644 bfa_trc(__vport_fcs(vport), status);
5646 switch (status) {
5647 case BFA_STATUS_OK:
5649 * Initialize the V-Port fields
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;
5656 case BFA_STATUS_INVALID_MAC:
5657 /* Only for CNA */
5658 vport->vport_stats.fdisc_acc_bad++;
5659 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5661 break;
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;
5669 case BFA_EPROTO_UNKNOWN_RSP:
5670 vport->vport_stats.fdisc_unknown_rsp++;
5671 break;
5673 default:
5674 break;
5677 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5678 break;
5680 case BFA_STATUS_FABRIC_RJT:
5681 vport->vport_stats.fdisc_rejects++;
5682 bfa_fcs_vport_fdisc_rejected(vport);
5683 break;
5685 default:
5686 vport->vport_stats.fdisc_rsp_err++;
5687 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5692 * LOGO response
5694 void
5695 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5697 struct bfa_fcs_vport_s *vport = uarg;
5698 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5702 * Received clear virtual link
5704 void
5705 bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5707 struct bfa_fcs_vport_s *vport = uarg;
5709 /* Send an Offline followed by an ONLINE */
5710 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5711 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);