2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
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.
19 * bfa_fcs_port.c BFA FCS port
22 #include <fcs/bfa_fcs.h>
23 #include <fcs/bfa_fcs_lport.h>
24 #include <fcs/bfa_fcs_rport.h>
25 #include <fcb/bfa_fcb_port.h>
27 #include <log/bfa_log_fcs.h>
29 #include "fcs_lport.h"
30 #include "fcs_vport.h"
31 #include "fcs_rport.h"
33 #include "fcs_trcmod.h"
34 #include "lport_priv.h"
35 #include <aen/bfa_aen_lport.h>
37 BFA_TRC_FILE(FCS
, PORT
);
40 * Forward declarations
43 static void bfa_fcs_port_aen_post(struct bfa_fcs_port_s
*port
,
44 enum bfa_lport_aen_event event
);
45 static void bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s
*port
,
46 struct fchs_s
*rx_fchs
, u8 reason_code
,
48 static void bfa_fcs_port_plogi(struct bfa_fcs_port_s
*port
,
49 struct fchs_s
*rx_fchs
,
50 struct fc_logi_s
*plogi
);
51 static void bfa_fcs_port_online_actions(struct bfa_fcs_port_s
*port
);
52 static void bfa_fcs_port_offline_actions(struct bfa_fcs_port_s
*port
);
53 static void bfa_fcs_port_unknown_init(struct bfa_fcs_port_s
*port
);
54 static void bfa_fcs_port_unknown_online(struct bfa_fcs_port_s
*port
);
55 static void bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s
*port
);
56 static void bfa_fcs_port_deleted(struct bfa_fcs_port_s
*port
);
57 static void bfa_fcs_port_echo(struct bfa_fcs_port_s
*port
,
58 struct fchs_s
*rx_fchs
,
59 struct fc_echo_s
*echo
, u16 len
);
60 static void bfa_fcs_port_rnid(struct bfa_fcs_port_s
*port
,
61 struct fchs_s
*rx_fchs
,
62 struct fc_rnid_cmd_s
*rnid
, u16 len
);
63 static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s
*port
,
64 struct fc_rnid_general_topology_data_s
*gen_topo_data
);
67 void (*init
) (struct bfa_fcs_port_s
*port
);
68 void (*online
) (struct bfa_fcs_port_s
*port
);
69 void (*offline
) (struct bfa_fcs_port_s
*port
);
72 bfa_fcs_port_unknown_init
, bfa_fcs_port_unknown_online
,
73 bfa_fcs_port_unknown_offline
}, {
74 bfa_fcs_port_fab_init
, bfa_fcs_port_fab_online
,
75 bfa_fcs_port_fab_offline
}, {
76 bfa_fcs_port_loop_init
, bfa_fcs_port_loop_online
,
77 bfa_fcs_port_loop_offline
}, {
78 bfa_fcs_port_n2n_init
, bfa_fcs_port_n2n_online
,
79 bfa_fcs_port_n2n_offline
},};
82 * fcs_port_sm FCS logical port state machine
85 enum bfa_fcs_port_event
{
86 BFA_FCS_PORT_SM_CREATE
= 1,
87 BFA_FCS_PORT_SM_ONLINE
= 2,
88 BFA_FCS_PORT_SM_OFFLINE
= 3,
89 BFA_FCS_PORT_SM_DELETE
= 4,
90 BFA_FCS_PORT_SM_DELRPORT
= 5,
93 static void bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s
*port
,
94 enum bfa_fcs_port_event event
);
95 static void bfa_fcs_port_sm_init(struct bfa_fcs_port_s
*port
,
96 enum bfa_fcs_port_event event
);
97 static void bfa_fcs_port_sm_online(struct bfa_fcs_port_s
*port
,
98 enum bfa_fcs_port_event event
);
99 static void bfa_fcs_port_sm_offline(struct bfa_fcs_port_s
*port
,
100 enum bfa_fcs_port_event event
);
101 static void bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s
*port
,
102 enum bfa_fcs_port_event event
);
105 bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s
*port
,
106 enum bfa_fcs_port_event event
)
108 bfa_trc(port
->fcs
, port
->port_cfg
.pwwn
);
109 bfa_trc(port
->fcs
, event
);
112 case BFA_FCS_PORT_SM_CREATE
:
113 bfa_sm_set_state(port
, bfa_fcs_port_sm_init
);
122 bfa_fcs_port_sm_init(struct bfa_fcs_port_s
*port
, enum bfa_fcs_port_event event
)
124 bfa_trc(port
->fcs
, port
->port_cfg
.pwwn
);
125 bfa_trc(port
->fcs
, event
);
128 case BFA_FCS_PORT_SM_ONLINE
:
129 bfa_sm_set_state(port
, bfa_fcs_port_sm_online
);
130 bfa_fcs_port_online_actions(port
);
133 case BFA_FCS_PORT_SM_DELETE
:
134 bfa_sm_set_state(port
, bfa_fcs_port_sm_uninit
);
135 bfa_fcs_port_deleted(port
);
144 bfa_fcs_port_sm_online(struct bfa_fcs_port_s
*port
,
145 enum bfa_fcs_port_event event
)
147 struct bfa_fcs_rport_s
*rport
;
148 struct list_head
*qe
, *qen
;
150 bfa_trc(port
->fcs
, port
->port_cfg
.pwwn
);
151 bfa_trc(port
->fcs
, event
);
154 case BFA_FCS_PORT_SM_OFFLINE
:
155 bfa_sm_set_state(port
, bfa_fcs_port_sm_offline
);
156 bfa_fcs_port_offline_actions(port
);
159 case BFA_FCS_PORT_SM_DELETE
:
161 __port_action
[port
->fabric
->fab_type
].offline(port
);
163 if (port
->num_rports
== 0) {
164 bfa_sm_set_state(port
, bfa_fcs_port_sm_uninit
);
165 bfa_fcs_port_deleted(port
);
167 bfa_sm_set_state(port
, bfa_fcs_port_sm_deleting
);
168 list_for_each_safe(qe
, qen
, &port
->rport_q
) {
169 rport
= (struct bfa_fcs_rport_s
*)qe
;
170 bfa_fcs_rport_delete(rport
);
175 case BFA_FCS_PORT_SM_DELRPORT
:
184 bfa_fcs_port_sm_offline(struct bfa_fcs_port_s
*port
,
185 enum bfa_fcs_port_event event
)
187 struct bfa_fcs_rport_s
*rport
;
188 struct list_head
*qe
, *qen
;
190 bfa_trc(port
->fcs
, port
->port_cfg
.pwwn
);
191 bfa_trc(port
->fcs
, event
);
194 case BFA_FCS_PORT_SM_ONLINE
:
195 bfa_sm_set_state(port
, bfa_fcs_port_sm_online
);
196 bfa_fcs_port_online_actions(port
);
199 case BFA_FCS_PORT_SM_DELETE
:
200 if (port
->num_rports
== 0) {
201 bfa_sm_set_state(port
, bfa_fcs_port_sm_uninit
);
202 bfa_fcs_port_deleted(port
);
204 bfa_sm_set_state(port
, bfa_fcs_port_sm_deleting
);
205 list_for_each_safe(qe
, qen
, &port
->rport_q
) {
206 rport
= (struct bfa_fcs_rport_s
*)qe
;
207 bfa_fcs_rport_delete(rport
);
212 case BFA_FCS_PORT_SM_DELRPORT
:
213 case BFA_FCS_PORT_SM_OFFLINE
:
222 bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s
*port
,
223 enum bfa_fcs_port_event event
)
225 bfa_trc(port
->fcs
, port
->port_cfg
.pwwn
);
226 bfa_trc(port
->fcs
, event
);
229 case BFA_FCS_PORT_SM_DELRPORT
:
230 if (port
->num_rports
== 0) {
231 bfa_sm_set_state(port
, bfa_fcs_port_sm_uninit
);
232 bfa_fcs_port_deleted(port
);
248 * Send AEN notification
251 bfa_fcs_port_aen_post(struct bfa_fcs_port_s
*port
,
252 enum bfa_lport_aen_event event
)
254 union bfa_aen_data_u aen_data
;
255 struct bfa_log_mod_s
*logmod
= port
->fcs
->logm
;
256 enum bfa_port_role role
= port
->port_cfg
.roles
;
257 wwn_t lpwwn
= bfa_fcs_port_get_pwwn(port
);
258 char lpwwn_ptr
[BFA_STRING_32
];
259 char *role_str
[BFA_PORT_ROLE_FCP_MAX
/ 2 + 1] =
260 { "Initiator", "Target", "IPFC" };
262 wwn2str(lpwwn_ptr
, lpwwn
);
264 bfa_assert(role
<= BFA_PORT_ROLE_FCP_MAX
);
267 case BFA_LPORT_AEN_ONLINE
:
268 bfa_log(logmod
, BFA_AEN_LPORT_ONLINE
, lpwwn_ptr
,
271 case BFA_LPORT_AEN_OFFLINE
:
272 bfa_log(logmod
, BFA_AEN_LPORT_OFFLINE
, lpwwn_ptr
,
275 case BFA_LPORT_AEN_NEW
:
276 bfa_log(logmod
, BFA_AEN_LPORT_NEW
, lpwwn_ptr
,
279 case BFA_LPORT_AEN_DELETE
:
280 bfa_log(logmod
, BFA_AEN_LPORT_DELETE
, lpwwn_ptr
,
283 case BFA_LPORT_AEN_DISCONNECT
:
284 bfa_log(logmod
, BFA_AEN_LPORT_DISCONNECT
, lpwwn_ptr
,
291 aen_data
.lport
.vf_id
= port
->fabric
->vf_id
;
292 aen_data
.lport
.roles
= role
;
293 aen_data
.lport
.ppwwn
=
294 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port
->fcs
));
295 aen_data
.lport
.lpwwn
= lpwwn
;
302 bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s
*port
, struct fchs_s
*rx_fchs
,
303 u8 reason_code
, u8 reason_code_expl
)
306 struct bfa_fcxp_s
*fcxp
;
307 struct bfa_rport_s
*bfa_rport
= NULL
;
310 bfa_trc(port
->fcs
, rx_fchs
->s_id
);
312 fcxp
= bfa_fcs_fcxp_alloc(port
->fcs
);
316 len
= fc_ls_rjt_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
), rx_fchs
->s_id
,
317 bfa_fcs_port_get_fcid(port
), rx_fchs
->ox_id
,
318 reason_code
, reason_code_expl
);
320 bfa_fcxp_send(fcxp
, bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
321 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
, NULL
, NULL
,
326 * Process incoming plogi from a remote port.
329 bfa_fcs_port_plogi(struct bfa_fcs_port_s
*port
, struct fchs_s
*rx_fchs
,
330 struct fc_logi_s
*plogi
)
332 struct bfa_fcs_rport_s
*rport
;
334 bfa_trc(port
->fcs
, rx_fchs
->d_id
);
335 bfa_trc(port
->fcs
, rx_fchs
->s_id
);
338 * If min cfg mode is enabled, drop any incoming PLOGIs
340 if (__fcs_min_cfg(port
->fcs
)) {
341 bfa_trc(port
->fcs
, rx_fchs
->s_id
);
345 if (fc_plogi_parse(rx_fchs
) != FC_PARSE_OK
) {
346 bfa_trc(port
->fcs
, rx_fchs
->s_id
);
350 bfa_fcs_port_send_ls_rjt(port
, rx_fchs
,
351 FC_LS_RJT_RSN_PROTOCOL_ERROR
,
352 FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS
);
357 * Direct Attach P2P mode : verify address assigned by the r-port.
359 if ((!bfa_fcs_fabric_is_switched(port
->fabric
))
362 ((void *)&bfa_fcs_port_get_pwwn(port
), (void *)&plogi
->port_name
,
363 sizeof(wwn_t
)) < 0)) {
364 if (BFA_FCS_PID_IS_WKA(rx_fchs
->d_id
)) {
366 * Address assigned to us cannot be a WKA
368 bfa_fcs_port_send_ls_rjt(port
, rx_fchs
,
369 FC_LS_RJT_RSN_PROTOCOL_ERROR
,
370 FC_LS_RJT_EXP_INVALID_NPORT_ID
);
373 port
->pid
= rx_fchs
->d_id
;
377 * First, check if we know the device by pwwn.
379 rport
= bfa_fcs_port_get_rport_by_pwwn(port
, plogi
->port_name
);
382 * Direct Attach P2P mode: handle address assigned by the rport.
384 if ((!bfa_fcs_fabric_is_switched(port
->fabric
))
387 ((void *)&bfa_fcs_port_get_pwwn(port
),
388 (void *)&plogi
->port_name
, sizeof(wwn_t
)) < 0)) {
389 port
->pid
= rx_fchs
->d_id
;
390 rport
->pid
= rx_fchs
->s_id
;
392 bfa_fcs_rport_plogi(rport
, rx_fchs
, plogi
);
397 * Next, lookup rport by PID.
399 rport
= bfa_fcs_port_get_rport_by_pid(port
, rx_fchs
->s_id
);
402 * Inbound PLOGI from a new device.
404 bfa_fcs_rport_plogi_create(port
, rx_fchs
, plogi
);
409 * Rport is known only by PID.
413 * This is a different device with the same pid. Old device
414 * disappeared. Send implicit LOGO to old device.
416 bfa_assert(rport
->pwwn
!= plogi
->port_name
);
417 bfa_fcs_rport_logo_imp(rport
);
420 * Inbound PLOGI from a new device (with old PID).
422 bfa_fcs_rport_plogi_create(port
, rx_fchs
, plogi
);
427 * PLOGI crossing each other.
429 bfa_assert(rport
->pwwn
== WWN_NULL
);
430 bfa_fcs_rport_plogi(rport
, rx_fchs
, plogi
);
434 * Process incoming ECHO.
435 * Since it does not require a login, it is processed here.
438 bfa_fcs_port_echo(struct bfa_fcs_port_s
*port
, struct fchs_s
*rx_fchs
,
439 struct fc_echo_s
*echo
, u16 rx_len
)
442 struct bfa_fcxp_s
*fcxp
;
443 struct bfa_rport_s
*bfa_rport
= NULL
;
446 bfa_trc(port
->fcs
, rx_fchs
->s_id
);
447 bfa_trc(port
->fcs
, rx_fchs
->d_id
);
448 bfa_trc(port
->fcs
, rx_len
);
450 fcxp
= bfa_fcs_fcxp_alloc(port
->fcs
);
454 len
= fc_ls_acc_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
), rx_fchs
->s_id
,
455 bfa_fcs_port_get_fcid(port
), rx_fchs
->ox_id
);
458 * Copy the payload (if any) from the echo frame
460 pyld_len
= rx_len
- sizeof(struct fchs_s
);
461 bfa_trc(port
->fcs
, pyld_len
);
464 memcpy(((u8
*) bfa_fcxp_get_reqbuf(fcxp
)) +
465 sizeof(struct fc_echo_s
), (echo
+ 1),
466 (pyld_len
- sizeof(struct fc_echo_s
)));
468 bfa_fcxp_send(fcxp
, bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
469 BFA_FALSE
, FC_CLASS_3
, pyld_len
, &fchs
, NULL
, NULL
,
474 * Process incoming RNID.
475 * Since it does not require a login, it is processed here.
478 bfa_fcs_port_rnid(struct bfa_fcs_port_s
*port
, struct fchs_s
*rx_fchs
,
479 struct fc_rnid_cmd_s
*rnid
, u16 rx_len
)
481 struct fc_rnid_common_id_data_s common_id_data
;
482 struct fc_rnid_general_topology_data_s gen_topo_data
;
484 struct bfa_fcxp_s
*fcxp
;
485 struct bfa_rport_s
*bfa_rport
= NULL
;
489 bfa_trc(port
->fcs
, rx_fchs
->s_id
);
490 bfa_trc(port
->fcs
, rx_fchs
->d_id
);
491 bfa_trc(port
->fcs
, rx_len
);
493 fcxp
= bfa_fcs_fcxp_alloc(port
->fcs
);
498 * Check Node Indentification Data Format
499 * We only support General Topology Discovery Format.
500 * For any other requested Data Formats, we return Common Node Id Data
501 * only, as per FC-LS.
503 bfa_trc(port
->fcs
, rnid
->node_id_data_format
);
504 if (rnid
->node_id_data_format
== RNID_NODEID_DATA_FORMAT_DISCOVERY
) {
505 data_format
= RNID_NODEID_DATA_FORMAT_DISCOVERY
;
507 * Get General topology data for this port
509 bfa_fs_port_get_gen_topo_data(port
, &gen_topo_data
);
511 data_format
= RNID_NODEID_DATA_FORMAT_COMMON
;
515 * Copy the Node Id Info
517 common_id_data
.port_name
= bfa_fcs_port_get_pwwn(port
);
518 common_id_data
.node_name
= bfa_fcs_port_get_nwwn(port
);
520 len
= fc_rnid_acc_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
), rx_fchs
->s_id
,
521 bfa_fcs_port_get_fcid(port
), rx_fchs
->ox_id
,
522 data_format
, &common_id_data
, &gen_topo_data
);
524 bfa_fcxp_send(fcxp
, bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
525 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
, NULL
, NULL
,
532 * Fill out General Topolpgy Discovery Data for RNID ELS.
535 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s
*port
,
536 struct fc_rnid_general_topology_data_s
*gen_topo_data
)
539 bfa_os_memset(gen_topo_data
, 0,
540 sizeof(struct fc_rnid_general_topology_data_s
));
542 gen_topo_data
->asso_type
= bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST
);
543 gen_topo_data
->phy_port_num
= 0; /* @todo */
544 gen_topo_data
->num_attached_nodes
= bfa_os_htonl(1);
548 bfa_fcs_port_online_actions(struct bfa_fcs_port_s
*port
)
550 bfa_trc(port
->fcs
, port
->fabric
->oper_type
);
552 __port_action
[port
->fabric
->fab_type
].init(port
);
553 __port_action
[port
->fabric
->fab_type
].online(port
);
555 bfa_fcs_port_aen_post(port
, BFA_LPORT_AEN_ONLINE
);
556 bfa_fcb_port_online(port
->fcs
->bfad
, port
->port_cfg
.roles
,
557 port
->fabric
->vf_drv
, (port
->vport
== NULL
) ?
558 NULL
: port
->vport
->vport_drv
);
562 bfa_fcs_port_offline_actions(struct bfa_fcs_port_s
*port
)
564 struct list_head
*qe
, *qen
;
565 struct bfa_fcs_rport_s
*rport
;
567 bfa_trc(port
->fcs
, port
->fabric
->oper_type
);
569 __port_action
[port
->fabric
->fab_type
].offline(port
);
571 if (bfa_fcs_fabric_is_online(port
->fabric
) == BFA_TRUE
) {
572 bfa_fcs_port_aen_post(port
, BFA_LPORT_AEN_DISCONNECT
);
574 bfa_fcs_port_aen_post(port
, BFA_LPORT_AEN_OFFLINE
);
576 bfa_fcb_port_offline(port
->fcs
->bfad
, port
->port_cfg
.roles
,
577 port
->fabric
->vf_drv
,
578 (port
->vport
== NULL
) ? NULL
: port
->vport
->vport_drv
);
580 list_for_each_safe(qe
, qen
, &port
->rport_q
) {
581 rport
= (struct bfa_fcs_rport_s
*)qe
;
582 bfa_fcs_rport_offline(rport
);
587 bfa_fcs_port_unknown_init(struct bfa_fcs_port_s
*port
)
593 bfa_fcs_port_unknown_online(struct bfa_fcs_port_s
*port
)
599 bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s
*port
)
605 bfa_fcs_port_deleted(struct bfa_fcs_port_s
*port
)
607 bfa_fcs_port_aen_post(port
, BFA_LPORT_AEN_DELETE
);
610 * Base port will be deleted by the OS driver
613 bfa_fcb_port_delete(port
->fcs
->bfad
, port
->port_cfg
.roles
,
614 port
->fabric
->vf_drv
,
615 port
->vport
? port
->vport
->vport_drv
: NULL
);
616 bfa_fcs_vport_delete_comp(port
->vport
);
618 bfa_fcs_fabric_port_delete_comp(port
->fabric
);
625 * fcs_lport_api BFA FCS port API
628 * Module initialization
631 bfa_fcs_port_modinit(struct bfa_fcs_s
*fcs
)
640 bfa_fcs_port_modexit(struct bfa_fcs_s
*fcs
)
642 bfa_fcs_modexit_comp(fcs
);
646 * Unsolicited frame receive handling.
649 bfa_fcs_port_uf_recv(struct bfa_fcs_port_s
*lport
, struct fchs_s
*fchs
,
652 u32 pid
= fchs
->s_id
;
653 struct bfa_fcs_rport_s
*rport
= NULL
;
654 struct fc_els_cmd_s
*els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
656 bfa_stats(lport
, uf_recvs
);
658 if (!bfa_fcs_port_is_online(lport
)) {
659 bfa_stats(lport
, uf_recv_drops
);
664 * First, handle ELSs that donot require a login.
669 if ((fchs
->type
== FC_TYPE_ELS
) &&
670 (els_cmd
->els_code
== FC_ELS_PLOGI
)) {
671 bfa_fcs_port_plogi(lport
, fchs
, (struct fc_logi_s
*) els_cmd
);
676 * Handle ECHO separately.
678 if ((fchs
->type
== FC_TYPE_ELS
) && (els_cmd
->els_code
== FC_ELS_ECHO
)) {
679 bfa_fcs_port_echo(lport
, fchs
,
680 (struct fc_echo_s
*) els_cmd
, len
);
685 * Handle RNID separately.
687 if ((fchs
->type
== FC_TYPE_ELS
) && (els_cmd
->els_code
== FC_ELS_RNID
)) {
688 bfa_fcs_port_rnid(lport
, fchs
,
689 (struct fc_rnid_cmd_s
*) els_cmd
, len
);
694 * look for a matching remote port ID
696 rport
= bfa_fcs_port_get_rport_by_pid(lport
, pid
);
698 bfa_trc(rport
->fcs
, fchs
->s_id
);
699 bfa_trc(rport
->fcs
, fchs
->d_id
);
700 bfa_trc(rport
->fcs
, fchs
->type
);
702 bfa_fcs_rport_uf_recv(rport
, fchs
, len
);
707 * Only handles ELS frames for now.
709 if (fchs
->type
!= FC_TYPE_ELS
) {
710 bfa_trc(lport
->fcs
, fchs
->type
);
715 bfa_trc(lport
->fcs
, els_cmd
->els_code
);
716 if (els_cmd
->els_code
== FC_ELS_RSCN
) {
717 bfa_fcs_port_scn_process_rscn(lport
, fchs
, len
);
721 if (els_cmd
->els_code
== FC_ELS_LOGO
) {
723 * @todo Handle LOGO frames received.
725 bfa_trc(lport
->fcs
, els_cmd
->els_code
);
729 if (els_cmd
->els_code
== FC_ELS_PRLI
) {
731 * @todo Handle PRLI frames received.
733 bfa_trc(lport
->fcs
, els_cmd
->els_code
);
738 * Unhandled ELS frames. Send a LS_RJT.
740 bfa_fcs_port_send_ls_rjt(lport
, fchs
, FC_LS_RJT_RSN_CMD_NOT_SUPP
,
741 FC_LS_RJT_EXP_NO_ADDL_INFO
);
746 * PID based Lookup for a R-Port in the Port R-Port Queue
748 struct bfa_fcs_rport_s
*
749 bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s
*port
, u32 pid
)
751 struct bfa_fcs_rport_s
*rport
;
752 struct list_head
*qe
;
754 list_for_each(qe
, &port
->rport_q
) {
755 rport
= (struct bfa_fcs_rport_s
*)qe
;
756 if (rport
->pid
== pid
)
760 bfa_trc(port
->fcs
, pid
);
765 * PWWN based Lookup for a R-Port in the Port R-Port Queue
767 struct bfa_fcs_rport_s
*
768 bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s
*port
, wwn_t pwwn
)
770 struct bfa_fcs_rport_s
*rport
;
771 struct list_head
*qe
;
773 list_for_each(qe
, &port
->rport_q
) {
774 rport
= (struct bfa_fcs_rport_s
*)qe
;
775 if (wwn_is_equal(rport
->pwwn
, pwwn
))
779 bfa_trc(port
->fcs
, pwwn
);
784 * NWWN based Lookup for a R-Port in the Port R-Port Queue
786 struct bfa_fcs_rport_s
*
787 bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s
*port
, wwn_t nwwn
)
789 struct bfa_fcs_rport_s
*rport
;
790 struct list_head
*qe
;
792 list_for_each(qe
, &port
->rport_q
) {
793 rport
= (struct bfa_fcs_rport_s
*)qe
;
794 if (wwn_is_equal(rport
->nwwn
, nwwn
))
798 bfa_trc(port
->fcs
, nwwn
);
803 * Called by rport module when new rports are discovered.
806 bfa_fcs_port_add_rport(struct bfa_fcs_port_s
*port
,
807 struct bfa_fcs_rport_s
*rport
)
809 list_add_tail(&rport
->qe
, &port
->rport_q
);
814 * Called by rport module to when rports are deleted.
817 bfa_fcs_port_del_rport(struct bfa_fcs_port_s
*port
,
818 struct bfa_fcs_rport_s
*rport
)
820 bfa_assert(bfa_q_is_on_q(&port
->rport_q
, rport
));
821 list_del(&rport
->qe
);
824 bfa_sm_send_event(port
, BFA_FCS_PORT_SM_DELRPORT
);
828 * Called by fabric for base port when fabric login is complete.
829 * Called by vport for virtual ports when FDISC is complete.
832 bfa_fcs_port_online(struct bfa_fcs_port_s
*port
)
834 bfa_sm_send_event(port
, BFA_FCS_PORT_SM_ONLINE
);
838 * Called by fabric for base port when fabric goes offline.
839 * Called by vport for virtual ports when virtual port becomes offline.
842 bfa_fcs_port_offline(struct bfa_fcs_port_s
*port
)
844 bfa_sm_send_event(port
, BFA_FCS_PORT_SM_OFFLINE
);
848 * Called by fabric to delete base lport and associated resources.
850 * Called by vport to delete lport and associated resources. Should call
851 * bfa_fcs_vport_delete_comp() for vports on completion.
854 bfa_fcs_port_delete(struct bfa_fcs_port_s
*port
)
856 bfa_sm_send_event(port
, BFA_FCS_PORT_SM_DELETE
);
860 * Called by fabric in private loop topology to process LIP event.
863 bfa_fcs_port_lip(struct bfa_fcs_port_s
*port
)
868 * Return TRUE if port is online, else return FALSE
871 bfa_fcs_port_is_online(struct bfa_fcs_port_s
*port
)
873 return (bfa_sm_cmp_state(port
, bfa_fcs_port_sm_online
));
877 * Logical port initialization of base or virtual port.
878 * Called by fabric for base port or by vport for virtual ports.
881 bfa_fcs_lport_init(struct bfa_fcs_port_s
*lport
, struct bfa_fcs_s
*fcs
,
882 u16 vf_id
, struct bfa_port_cfg_s
*port_cfg
,
883 struct bfa_fcs_vport_s
*vport
)
886 lport
->fabric
= bfa_fcs_vf_lookup(fcs
, vf_id
);
887 bfa_os_assign(lport
->port_cfg
, *port_cfg
);
888 lport
->vport
= vport
;
889 lport
->lp_tag
= (vport
) ? bfa_lps_get_tag(vport
->lps
) :
890 bfa_lps_get_tag(lport
->fabric
->lps
);
892 INIT_LIST_HEAD(&lport
->rport_q
);
893 lport
->num_rports
= 0;
896 bfa_fcb_port_new(fcs
->bfad
, lport
, lport
->port_cfg
.roles
,
897 lport
->fabric
->vf_drv
,
898 vport
? vport
->vport_drv
: NULL
);
899 bfa_fcs_port_aen_post(lport
, BFA_LPORT_AEN_NEW
);
901 bfa_sm_set_state(lport
, bfa_fcs_port_sm_uninit
);
902 bfa_sm_send_event(lport
, BFA_FCS_PORT_SM_CREATE
);
912 bfa_fcs_port_get_attr(struct bfa_fcs_port_s
*port
,
913 struct bfa_port_attr_s
*port_attr
)
915 if (bfa_sm_cmp_state(port
, bfa_fcs_port_sm_online
))
916 port_attr
->pid
= port
->pid
;
920 port_attr
->port_cfg
= port
->port_cfg
;
923 port_attr
->port_type
= bfa_fcs_fabric_port_type(port
->fabric
);
924 port_attr
->loopback
= bfa_fcs_fabric_is_loopback(port
->fabric
);
925 port_attr
->fabric_name
= bfa_fcs_port_get_fabric_name(port
);
926 memcpy(port_attr
->fabric_ip_addr
,
927 bfa_fcs_port_get_fabric_ipaddr(port
),
928 BFA_FCS_FABRIC_IPADDR_SZ
);
930 if (port
->vport
!= NULL
)
931 port_attr
->port_type
= BFA_PPORT_TYPE_VPORT
;
934 port_attr
->port_type
= BFA_PPORT_TYPE_UNKNOWN
;
935 port_attr
->state
= BFA_PORT_UNINIT
;