2 * Copyright (c) 2005-2010 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 * fcpim.c - FCP initiator mode i-t nexus state machine
24 #include "bfa_fcbuild.h"
27 BFA_TRC_FILE(FCS
, FCPIM
);
30 * forward declarations
32 static void bfa_fcs_itnim_timeout(void *arg
);
33 static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
);
34 static void bfa_fcs_itnim_send_prli(void *itnim_cbarg
,
35 struct bfa_fcxp_s
*fcxp_alloced
);
36 static void bfa_fcs_itnim_prli_response(void *fcsarg
,
37 struct bfa_fcxp_s
*fcxp
, void *cbarg
,
38 bfa_status_t req_status
, u32 rsp_len
,
39 u32 resid_len
, struct fchs_s
*rsp_fchs
);
40 static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
41 enum bfa_itnim_aen_event event
);
44 * fcs_itnim_sm FCS itnim state machine events
47 enum bfa_fcs_itnim_event
{
48 BFA_FCS_ITNIM_SM_ONLINE
= 1, /* rport online event */
49 BFA_FCS_ITNIM_SM_OFFLINE
= 2, /* rport offline */
50 BFA_FCS_ITNIM_SM_FRMSENT
= 3, /* prli frame is sent */
51 BFA_FCS_ITNIM_SM_RSP_OK
= 4, /* good response */
52 BFA_FCS_ITNIM_SM_RSP_ERROR
= 5, /* error response */
53 BFA_FCS_ITNIM_SM_TIMEOUT
= 6, /* delay timeout */
54 BFA_FCS_ITNIM_SM_HCB_OFFLINE
= 7, /* BFA online callback */
55 BFA_FCS_ITNIM_SM_HCB_ONLINE
= 8, /* BFA offline callback */
56 BFA_FCS_ITNIM_SM_INITIATOR
= 9, /* rport is initiator */
57 BFA_FCS_ITNIM_SM_DELETE
= 10, /* delete event from rport */
58 BFA_FCS_ITNIM_SM_PRLO
= 11, /* delete event from rport */
59 BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
= 12, /* cmd not supported rsp */
62 static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
63 enum bfa_fcs_itnim_event event
);
64 static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
65 enum bfa_fcs_itnim_event event
);
66 static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
67 enum bfa_fcs_itnim_event event
);
68 static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
69 enum bfa_fcs_itnim_event event
);
70 static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
71 enum bfa_fcs_itnim_event event
);
72 static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
73 enum bfa_fcs_itnim_event event
);
74 static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
75 enum bfa_fcs_itnim_event event
);
76 static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
77 enum bfa_fcs_itnim_event event
);
79 static struct bfa_sm_table_s itnim_sm_table
[] = {
80 {BFA_SM(bfa_fcs_itnim_sm_offline
), BFA_ITNIM_OFFLINE
},
81 {BFA_SM(bfa_fcs_itnim_sm_prli_send
), BFA_ITNIM_PRLI_SEND
},
82 {BFA_SM(bfa_fcs_itnim_sm_prli
), BFA_ITNIM_PRLI_SENT
},
83 {BFA_SM(bfa_fcs_itnim_sm_prli_retry
), BFA_ITNIM_PRLI_RETRY
},
84 {BFA_SM(bfa_fcs_itnim_sm_hcb_online
), BFA_ITNIM_HCB_ONLINE
},
85 {BFA_SM(bfa_fcs_itnim_sm_online
), BFA_ITNIM_ONLINE
},
86 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline
), BFA_ITNIM_HCB_OFFLINE
},
87 {BFA_SM(bfa_fcs_itnim_sm_initiator
), BFA_ITNIM_INITIATIOR
},
91 * fcs_itnim_sm FCS itnim state machine
95 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
96 enum bfa_fcs_itnim_event event
)
98 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
99 bfa_trc(itnim
->fcs
, event
);
102 case BFA_FCS_ITNIM_SM_ONLINE
:
103 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
104 itnim
->prli_retries
= 0;
105 bfa_fcs_itnim_send_prli(itnim
, NULL
);
108 case BFA_FCS_ITNIM_SM_OFFLINE
:
109 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
112 case BFA_FCS_ITNIM_SM_INITIATOR
:
113 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
116 case BFA_FCS_ITNIM_SM_DELETE
:
117 bfa_fcs_itnim_free(itnim
);
121 bfa_sm_fault(itnim
->fcs
, event
);
127 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
128 enum bfa_fcs_itnim_event event
)
130 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
131 bfa_trc(itnim
->fcs
, event
);
134 case BFA_FCS_ITNIM_SM_FRMSENT
:
135 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli
);
138 case BFA_FCS_ITNIM_SM_INITIATOR
:
139 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
140 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
143 case BFA_FCS_ITNIM_SM_OFFLINE
:
144 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
145 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
146 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
149 case BFA_FCS_ITNIM_SM_DELETE
:
150 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
151 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
152 bfa_fcs_itnim_free(itnim
);
156 bfa_sm_fault(itnim
->fcs
, event
);
161 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
162 enum bfa_fcs_itnim_event event
)
164 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
165 bfa_trc(itnim
->fcs
, event
);
168 case BFA_FCS_ITNIM_SM_RSP_OK
:
169 if (itnim
->rport
->scsi_function
== BFA_RPORT_INITIATOR
) {
170 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
172 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_online
);
173 bfa_itnim_online(itnim
->bfa_itnim
, itnim
->seq_rec
);
177 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
178 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_retry
);
179 bfa_timer_start(itnim
->fcs
->bfa
, &itnim
->timer
,
180 bfa_fcs_itnim_timeout
, itnim
,
181 BFA_FCS_RETRY_TIMEOUT
);
184 case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
:
185 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
188 case BFA_FCS_ITNIM_SM_OFFLINE
:
189 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
190 bfa_fcxp_discard(itnim
->fcxp
);
191 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
194 case BFA_FCS_ITNIM_SM_INITIATOR
:
195 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
196 bfa_fcxp_discard(itnim
->fcxp
);
199 case BFA_FCS_ITNIM_SM_DELETE
:
200 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
201 bfa_fcxp_discard(itnim
->fcxp
);
202 bfa_fcs_itnim_free(itnim
);
206 bfa_sm_fault(itnim
->fcs
, event
);
211 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
212 enum bfa_fcs_itnim_event event
)
214 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
215 bfa_trc(itnim
->fcs
, event
);
218 case BFA_FCS_ITNIM_SM_TIMEOUT
:
219 if (itnim
->prli_retries
< BFA_FCS_RPORT_MAX_RETRIES
) {
220 itnim
->prli_retries
++;
221 bfa_trc(itnim
->fcs
, itnim
->prli_retries
);
222 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
223 bfa_fcs_itnim_send_prli(itnim
, NULL
);
225 /* invoke target offline */
226 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
227 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
232 case BFA_FCS_ITNIM_SM_OFFLINE
:
233 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
234 bfa_timer_stop(&itnim
->timer
);
235 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
238 case BFA_FCS_ITNIM_SM_INITIATOR
:
239 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
240 bfa_timer_stop(&itnim
->timer
);
243 case BFA_FCS_ITNIM_SM_DELETE
:
244 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
245 bfa_timer_stop(&itnim
->timer
);
246 bfa_fcs_itnim_free(itnim
);
250 bfa_sm_fault(itnim
->fcs
, event
);
255 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
256 enum bfa_fcs_itnim_event event
)
258 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
259 char lpwwn_buf
[BFA_STRING_32
];
260 char rpwwn_buf
[BFA_STRING_32
];
262 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
263 bfa_trc(itnim
->fcs
, event
);
266 case BFA_FCS_ITNIM_SM_HCB_ONLINE
:
267 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_online
);
268 bfa_fcb_itnim_online(itnim
->itnim_drv
);
269 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
270 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
271 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
272 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
273 rpwwn_buf
, lpwwn_buf
);
274 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_ONLINE
);
277 case BFA_FCS_ITNIM_SM_OFFLINE
:
278 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
279 bfa_itnim_offline(itnim
->bfa_itnim
);
280 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
283 case BFA_FCS_ITNIM_SM_DELETE
:
284 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
285 bfa_fcs_itnim_free(itnim
);
289 bfa_sm_fault(itnim
->fcs
, event
);
294 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
295 enum bfa_fcs_itnim_event event
)
297 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
298 char lpwwn_buf
[BFA_STRING_32
];
299 char rpwwn_buf
[BFA_STRING_32
];
301 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
302 bfa_trc(itnim
->fcs
, event
);
305 case BFA_FCS_ITNIM_SM_OFFLINE
:
306 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
307 bfa_fcb_itnim_offline(itnim
->itnim_drv
);
308 bfa_itnim_offline(itnim
->bfa_itnim
);
309 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
310 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
311 if (bfa_fcs_lport_is_online(itnim
->rport
->port
) == BFA_TRUE
) {
312 BFA_LOG(KERN_ERR
, bfad
, bfa_log_level
,
313 "Target (WWN = %s) connectivity lost for "
314 "initiator (WWN = %s)\n", rpwwn_buf
, lpwwn_buf
);
315 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_DISCONNECT
);
317 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
318 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
319 rpwwn_buf
, lpwwn_buf
);
320 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_OFFLINE
);
324 case BFA_FCS_ITNIM_SM_DELETE
:
325 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
326 bfa_fcs_itnim_free(itnim
);
330 bfa_sm_fault(itnim
->fcs
, event
);
335 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
336 enum bfa_fcs_itnim_event event
)
338 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
339 bfa_trc(itnim
->fcs
, event
);
342 case BFA_FCS_ITNIM_SM_HCB_OFFLINE
:
343 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
344 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
347 case BFA_FCS_ITNIM_SM_DELETE
:
348 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
349 bfa_fcs_itnim_free(itnim
);
353 bfa_sm_fault(itnim
->fcs
, event
);
358 * This state is set when a discovered rport is also in intiator mode.
359 * This ITN is marked as no_op and is not active and will not be truned into
363 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
364 enum bfa_fcs_itnim_event event
)
366 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
367 bfa_trc(itnim
->fcs
, event
);
370 case BFA_FCS_ITNIM_SM_OFFLINE
:
371 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
372 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
375 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
376 case BFA_FCS_ITNIM_SM_ONLINE
:
377 case BFA_FCS_ITNIM_SM_INITIATOR
:
380 case BFA_FCS_ITNIM_SM_DELETE
:
381 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
382 bfa_fcs_itnim_free(itnim
);
386 bfa_sm_fault(itnim
->fcs
, event
);
391 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
392 enum bfa_itnim_aen_event event
)
394 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
395 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
396 struct bfa_aen_entry_s
*aen_entry
;
398 /* Don't post events for well known addresses */
399 if (BFA_FCS_PID_IS_WKA(rport
->pid
))
402 bfad_get_aen_entry(bfad
, aen_entry
);
406 aen_entry
->aen_data
.itnim
.vf_id
= rport
->port
->fabric
->vf_id
;
407 aen_entry
->aen_data
.itnim
.ppwwn
= bfa_fcs_lport_get_pwwn(
408 bfa_fcs_get_base_port(itnim
->fcs
));
409 aen_entry
->aen_data
.itnim
.lpwwn
= bfa_fcs_lport_get_pwwn(rport
->port
);
410 aen_entry
->aen_data
.itnim
.rpwwn
= rport
->pwwn
;
412 /* Send the AEN notification */
413 bfad_im_post_vendor_event(aen_entry
, bfad
, ++rport
->fcs
->fcs_aen_seq
,
414 BFA_AEN_CAT_ITNIM
, event
);
418 bfa_fcs_itnim_send_prli(void *itnim_cbarg
, struct bfa_fcxp_s
*fcxp_alloced
)
420 struct bfa_fcs_itnim_s
*itnim
= itnim_cbarg
;
421 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
422 struct bfa_fcs_lport_s
*port
= rport
->port
;
424 struct bfa_fcxp_s
*fcxp
;
427 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
429 fcxp
= fcxp_alloced
? fcxp_alloced
: bfa_fcs_fcxp_alloc(port
->fcs
);
431 itnim
->stats
.fcxp_alloc_wait
++;
432 bfa_fcs_fcxp_alloc_wait(port
->fcs
->bfa
, &itnim
->fcxp_wqe
,
433 bfa_fcs_itnim_send_prli
, itnim
);
438 len
= fc_prli_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
439 itnim
->rport
->pid
, bfa_fcs_lport_get_fcid(port
), 0);
441 bfa_fcxp_send(fcxp
, rport
->bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
442 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
,
443 bfa_fcs_itnim_prli_response
, (void *)itnim
,
444 FC_MAX_PDUSZ
, FC_ELS_TOV
);
446 itnim
->stats
.prli_sent
++;
447 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_FRMSENT
);
451 bfa_fcs_itnim_prli_response(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
452 bfa_status_t req_status
, u32 rsp_len
,
453 u32 resid_len
, struct fchs_s
*rsp_fchs
)
455 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
456 struct fc_els_cmd_s
*els_cmd
;
457 struct fc_prli_s
*prli_resp
;
458 struct fc_ls_rjt_s
*ls_rjt
;
459 struct fc_prli_params_s
*sparams
;
461 bfa_trc(itnim
->fcs
, req_status
);
466 if (req_status
!= BFA_STATUS_OK
) {
467 itnim
->stats
.prli_rsp_err
++;
468 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
472 els_cmd
= (struct fc_els_cmd_s
*) BFA_FCXP_RSP_PLD(fcxp
);
474 if (els_cmd
->els_code
== FC_ELS_ACC
) {
475 prli_resp
= (struct fc_prli_s
*) els_cmd
;
477 if (fc_prli_rsp_parse(prli_resp
, rsp_len
) != FC_PARSE_OK
) {
478 bfa_trc(itnim
->fcs
, rsp_len
);
480 * Check if this r-port is also in Initiator mode.
481 * If so, we need to set this ITN as a no-op.
483 if (prli_resp
->parampage
.servparams
.initiator
) {
484 bfa_trc(itnim
->fcs
, prli_resp
->parampage
.type
);
485 itnim
->rport
->scsi_function
=
487 itnim
->stats
.prli_rsp_acc
++;
488 itnim
->stats
.initiator
++;
489 bfa_sm_send_event(itnim
,
490 BFA_FCS_ITNIM_SM_RSP_OK
);
494 itnim
->stats
.prli_rsp_parse_err
++;
497 itnim
->rport
->scsi_function
= BFA_RPORT_TARGET
;
499 sparams
= &prli_resp
->parampage
.servparams
;
500 itnim
->seq_rec
= sparams
->retry
;
501 itnim
->rec_support
= sparams
->rec_support
;
502 itnim
->task_retry_id
= sparams
->task_retry_id
;
503 itnim
->conf_comp
= sparams
->confirm
;
505 itnim
->stats
.prli_rsp_acc
++;
506 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_OK
);
508 ls_rjt
= (struct fc_ls_rjt_s
*) BFA_FCXP_RSP_PLD(fcxp
);
510 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code
);
511 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code_expl
);
513 itnim
->stats
.prli_rsp_rjt
++;
514 if (ls_rjt
->reason_code
== FC_LS_RJT_RSN_CMD_NOT_SUPP
) {
515 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
);
518 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
523 bfa_fcs_itnim_timeout(void *arg
)
525 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) arg
;
527 itnim
->stats
.timeout
++;
528 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_TIMEOUT
);
532 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
)
534 bfa_itnim_delete(itnim
->bfa_itnim
);
535 bfa_fcb_itnim_free(itnim
->fcs
->bfad
, itnim
->itnim_drv
);
541 * itnim_public FCS ITNIM public interfaces
545 * Called by rport when a new rport is created.
547 * @param[in] rport - remote port.
549 struct bfa_fcs_itnim_s
*
550 bfa_fcs_itnim_create(struct bfa_fcs_rport_s
*rport
)
552 struct bfa_fcs_lport_s
*port
= rport
->port
;
553 struct bfa_fcs_itnim_s
*itnim
;
554 struct bfad_itnim_s
*itnim_drv
;
555 struct bfa_itnim_s
*bfa_itnim
;
558 * call bfad to allocate the itnim
560 bfa_fcb_itnim_alloc(port
->fcs
->bfad
, &itnim
, &itnim_drv
);
562 bfa_trc(port
->fcs
, rport
->pwwn
);
569 itnim
->rport
= rport
;
570 itnim
->fcs
= rport
->fcs
;
571 itnim
->itnim_drv
= itnim_drv
;
574 * call BFA to create the itnim
577 bfa_itnim_create(port
->fcs
->bfa
, rport
->bfa_rport
, itnim
);
579 if (bfa_itnim
== NULL
) {
580 bfa_trc(port
->fcs
, rport
->pwwn
);
581 bfa_fcb_itnim_free(port
->fcs
->bfad
, itnim_drv
);
586 itnim
->bfa_itnim
= bfa_itnim
;
587 itnim
->seq_rec
= BFA_FALSE
;
588 itnim
->rec_support
= BFA_FALSE
;
589 itnim
->conf_comp
= BFA_FALSE
;
590 itnim
->task_retry_id
= BFA_FALSE
;
595 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
601 * Called by rport to delete the instance of FCPIM.
603 * @param[in] rport - remote port.
606 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s
*itnim
)
608 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
609 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_DELETE
);
613 * Notification from rport that PLOGI is complete to initiate FC-4 session.
616 bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s
*itnim
)
618 itnim
->stats
.onlines
++;
620 if (!BFA_FCS_PID_IS_WKA(itnim
->rport
->pid
)) {
621 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_ONLINE
);
624 * For well known addresses, we set the itnim to initiator
627 itnim
->stats
.initiator
++;
628 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
633 * Called by rport to handle a remote device offline.
636 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s
*itnim
)
638 itnim
->stats
.offlines
++;
639 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_OFFLINE
);
643 * Called by rport when remote port is known to be an initiator from
647 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s
*itnim
)
649 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
650 itnim
->stats
.initiator
++;
651 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
655 * Called by rport to check if the itnim is online.
658 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s
*itnim
)
660 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
661 switch (bfa_sm_to_state(itnim_sm_table
, itnim
->sm
)) {
662 case BFA_ITNIM_ONLINE
:
663 case BFA_ITNIM_INITIATIOR
:
664 return BFA_STATUS_OK
;
667 return BFA_STATUS_NO_FCPIM_NEXUS
;
672 * BFA completion callback for bfa_itnim_online().
675 bfa_cb_itnim_online(void *cbarg
)
677 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
679 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
680 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_ONLINE
);
684 * BFA completion callback for bfa_itnim_offline().
687 bfa_cb_itnim_offline(void *cb_arg
)
689 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
691 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
692 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_OFFLINE
);
696 * Mark the beginning of PATH TOV handling. IO completion callbacks
700 bfa_cb_itnim_tov_begin(void *cb_arg
)
702 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
704 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
708 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
711 bfa_cb_itnim_tov(void *cb_arg
)
713 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
714 struct bfad_itnim_s
*itnim_drv
= itnim
->itnim_drv
;
716 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
717 itnim_drv
->state
= ITNIM_STATE_TIMEOUT
;
721 * BFA notification to FCS/driver for second level error recovery.
723 * Atleast one I/O request has timedout and target is unresponsive to
724 * repeated abort requests. Second level error recovery should be initiated
725 * by starting implicit logout and recovery procedures.
728 bfa_cb_itnim_sler(void *cb_arg
)
730 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
733 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
734 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
737 struct bfa_fcs_itnim_s
*
738 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
740 struct bfa_fcs_rport_s
*rport
;
741 rport
= bfa_fcs_rport_lookup(port
, rpwwn
);
746 WARN_ON(rport
->itnim
== NULL
);
751 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
752 struct bfa_itnim_attr_s
*attr
)
754 struct bfa_fcs_itnim_s
*itnim
= NULL
;
756 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
759 return BFA_STATUS_NO_FCPIM_NEXUS
;
761 attr
->state
= bfa_sm_to_state(itnim_sm_table
, itnim
->sm
);
762 attr
->retry
= itnim
->seq_rec
;
763 attr
->rec_support
= itnim
->rec_support
;
764 attr
->conf_comp
= itnim
->conf_comp
;
765 attr
->task_retry_id
= itnim
->task_retry_id
;
766 return BFA_STATUS_OK
;
770 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
771 struct bfa_itnim_stats_s
*stats
)
773 struct bfa_fcs_itnim_s
*itnim
= NULL
;
775 WARN_ON(port
== NULL
);
777 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
780 return BFA_STATUS_NO_FCPIM_NEXUS
;
782 memcpy(stats
, &itnim
->stats
, sizeof(struct bfa_itnim_stats_s
));
784 return BFA_STATUS_OK
;
788 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
790 struct bfa_fcs_itnim_s
*itnim
= NULL
;
792 WARN_ON(port
== NULL
);
794 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
797 return BFA_STATUS_NO_FCPIM_NEXUS
;
799 memset(&itnim
->stats
, 0, sizeof(struct bfa_itnim_stats_s
));
800 return BFA_STATUS_OK
;
804 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s
*itnim
,
805 struct fchs_s
*fchs
, u16 len
)
807 struct fc_els_cmd_s
*els_cmd
;
809 bfa_trc(itnim
->fcs
, fchs
->type
);
811 if (fchs
->type
!= FC_TYPE_ELS
)
814 els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
816 bfa_trc(itnim
->fcs
, els_cmd
->els_code
);
818 switch (els_cmd
->els_code
) {
820 bfa_fcs_rport_prlo(itnim
->rport
, fchs
->ox_id
);