2 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
3 * Copyright (c) 2014- QLogic Corporation.
7 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License (GPL) Version 2 as
11 * published by the Free Software Foundation
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
20 * fcpim.c - FCP initiator mode i-t nexus state machine
25 #include "bfa_fcbuild.h"
28 BFA_TRC_FILE(FCS
, FCPIM
);
31 * forward declarations
33 static void bfa_fcs_itnim_timeout(void *arg
);
34 static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
);
35 static void bfa_fcs_itnim_send_prli(void *itnim_cbarg
,
36 struct bfa_fcxp_s
*fcxp_alloced
);
37 static void bfa_fcs_itnim_prli_response(void *fcsarg
,
38 struct bfa_fcxp_s
*fcxp
, void *cbarg
,
39 bfa_status_t req_status
, u32 rsp_len
,
40 u32 resid_len
, struct fchs_s
*rsp_fchs
);
41 static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
42 enum bfa_itnim_aen_event event
);
44 static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
45 enum bfa_fcs_itnim_event event
);
46 static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
47 enum bfa_fcs_itnim_event event
);
48 static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
49 enum bfa_fcs_itnim_event event
);
50 static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
51 enum bfa_fcs_itnim_event event
);
52 static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
53 enum bfa_fcs_itnim_event event
);
54 static void bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
55 enum bfa_fcs_itnim_event event
);
56 static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
57 enum bfa_fcs_itnim_event event
);
58 static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
59 enum bfa_fcs_itnim_event event
);
60 static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
61 enum bfa_fcs_itnim_event event
);
63 static struct bfa_sm_table_s itnim_sm_table
[] = {
64 {BFA_SM(bfa_fcs_itnim_sm_offline
), BFA_ITNIM_OFFLINE
},
65 {BFA_SM(bfa_fcs_itnim_sm_prli_send
), BFA_ITNIM_PRLI_SEND
},
66 {BFA_SM(bfa_fcs_itnim_sm_prli
), BFA_ITNIM_PRLI_SENT
},
67 {BFA_SM(bfa_fcs_itnim_sm_prli_retry
), BFA_ITNIM_PRLI_RETRY
},
68 {BFA_SM(bfa_fcs_itnim_sm_hcb_online
), BFA_ITNIM_HCB_ONLINE
},
69 {BFA_SM(bfa_fcs_itnim_sm_online
), BFA_ITNIM_ONLINE
},
70 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline
), BFA_ITNIM_HCB_OFFLINE
},
71 {BFA_SM(bfa_fcs_itnim_sm_initiator
), BFA_ITNIM_INITIATIOR
},
75 * fcs_itnim_sm FCS itnim state machine
79 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
80 enum bfa_fcs_itnim_event event
)
82 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
83 bfa_trc(itnim
->fcs
, event
);
86 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
87 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
88 itnim
->prli_retries
= 0;
89 bfa_fcs_itnim_send_prli(itnim
, NULL
);
92 case BFA_FCS_ITNIM_SM_OFFLINE
:
93 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
96 case BFA_FCS_ITNIM_SM_INITIATOR
:
97 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
100 case BFA_FCS_ITNIM_SM_DELETE
:
101 bfa_fcs_itnim_free(itnim
);
105 bfa_sm_fault(itnim
->fcs
, event
);
111 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
112 enum bfa_fcs_itnim_event event
)
114 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
115 bfa_trc(itnim
->fcs
, event
);
118 case BFA_FCS_ITNIM_SM_FRMSENT
:
119 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli
);
122 case BFA_FCS_ITNIM_SM_INITIATOR
:
123 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
124 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
125 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
128 case BFA_FCS_ITNIM_SM_OFFLINE
:
129 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
130 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
131 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
134 case BFA_FCS_ITNIM_SM_DELETE
:
135 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
136 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
137 bfa_fcs_itnim_free(itnim
);
141 bfa_sm_fault(itnim
->fcs
, event
);
146 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
147 enum bfa_fcs_itnim_event event
)
149 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
150 bfa_trc(itnim
->fcs
, event
);
153 case BFA_FCS_ITNIM_SM_RSP_OK
:
154 if (itnim
->rport
->scsi_function
== BFA_RPORT_INITIATOR
)
155 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
157 bfa_sm_set_state(itnim
,
158 bfa_fcs_itnim_sm_hal_rport_online
);
160 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
163 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
164 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_retry
);
165 bfa_timer_start(itnim
->fcs
->bfa
, &itnim
->timer
,
166 bfa_fcs_itnim_timeout
, itnim
,
167 BFA_FCS_RETRY_TIMEOUT
);
170 case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
:
171 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
174 case BFA_FCS_ITNIM_SM_OFFLINE
:
175 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
176 bfa_fcxp_discard(itnim
->fcxp
);
177 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
180 case BFA_FCS_ITNIM_SM_INITIATOR
:
181 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
182 bfa_fcxp_discard(itnim
->fcxp
);
183 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
186 case BFA_FCS_ITNIM_SM_DELETE
:
187 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
188 bfa_fcxp_discard(itnim
->fcxp
);
189 bfa_fcs_itnim_free(itnim
);
193 bfa_sm_fault(itnim
->fcs
, event
);
198 bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
199 enum bfa_fcs_itnim_event event
)
201 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
202 bfa_trc(itnim
->fcs
, event
);
205 case BFA_FCS_ITNIM_SM_HAL_ONLINE
:
206 if (!itnim
->bfa_itnim
)
207 itnim
->bfa_itnim
= bfa_itnim_create(itnim
->fcs
->bfa
,
208 itnim
->rport
->bfa_rport
, itnim
);
210 if (itnim
->bfa_itnim
) {
211 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_online
);
212 bfa_itnim_online(itnim
->bfa_itnim
, itnim
->seq_rec
);
214 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
215 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_DELETE
);
220 case BFA_FCS_ITNIM_SM_OFFLINE
:
221 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
222 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
225 case BFA_FCS_ITNIM_SM_DELETE
:
226 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
227 bfa_fcs_itnim_free(itnim
);
231 bfa_sm_fault(itnim
->fcs
, event
);
236 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
237 enum bfa_fcs_itnim_event event
)
239 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
240 bfa_trc(itnim
->fcs
, event
);
243 case BFA_FCS_ITNIM_SM_TIMEOUT
:
244 if (itnim
->prli_retries
< BFA_FCS_RPORT_MAX_RETRIES
) {
245 itnim
->prli_retries
++;
246 bfa_trc(itnim
->fcs
, itnim
->prli_retries
);
247 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
248 bfa_fcs_itnim_send_prli(itnim
, NULL
);
250 /* invoke target offline */
251 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
252 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
257 case BFA_FCS_ITNIM_SM_OFFLINE
:
258 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
259 bfa_timer_stop(&itnim
->timer
);
260 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
263 case BFA_FCS_ITNIM_SM_INITIATOR
:
264 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
265 bfa_timer_stop(&itnim
->timer
);
266 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
269 case BFA_FCS_ITNIM_SM_DELETE
:
270 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
271 bfa_timer_stop(&itnim
->timer
);
272 bfa_fcs_itnim_free(itnim
);
276 bfa_sm_fault(itnim
->fcs
, event
);
281 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
282 enum bfa_fcs_itnim_event event
)
284 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
285 char lpwwn_buf
[BFA_STRING_32
];
286 char rpwwn_buf
[BFA_STRING_32
];
288 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
289 bfa_trc(itnim
->fcs
, event
);
292 case BFA_FCS_ITNIM_SM_HCB_ONLINE
:
293 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_online
);
294 bfa_fcb_itnim_online(itnim
->itnim_drv
);
295 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
296 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
297 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
298 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
299 rpwwn_buf
, lpwwn_buf
);
300 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_ONLINE
);
303 case BFA_FCS_ITNIM_SM_OFFLINE
:
304 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
305 bfa_itnim_offline(itnim
->bfa_itnim
);
308 case BFA_FCS_ITNIM_SM_DELETE
:
309 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
310 bfa_fcs_itnim_free(itnim
);
314 bfa_sm_fault(itnim
->fcs
, event
);
319 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
320 enum bfa_fcs_itnim_event event
)
322 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
323 char lpwwn_buf
[BFA_STRING_32
];
324 char rpwwn_buf
[BFA_STRING_32
];
326 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
327 bfa_trc(itnim
->fcs
, event
);
330 case BFA_FCS_ITNIM_SM_OFFLINE
:
331 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
332 bfa_fcb_itnim_offline(itnim
->itnim_drv
);
333 bfa_itnim_offline(itnim
->bfa_itnim
);
334 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
335 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
336 if (bfa_fcs_lport_is_online(itnim
->rport
->port
) == BFA_TRUE
) {
337 BFA_LOG(KERN_ERR
, bfad
, bfa_log_level
,
338 "Target (WWN = %s) connectivity lost for "
339 "initiator (WWN = %s)\n", rpwwn_buf
, lpwwn_buf
);
340 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_DISCONNECT
);
342 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
343 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
344 rpwwn_buf
, lpwwn_buf
);
345 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_OFFLINE
);
349 case BFA_FCS_ITNIM_SM_DELETE
:
350 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
351 bfa_fcs_itnim_free(itnim
);
355 bfa_sm_fault(itnim
->fcs
, event
);
360 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
361 enum bfa_fcs_itnim_event event
)
363 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
364 bfa_trc(itnim
->fcs
, event
);
367 case BFA_FCS_ITNIM_SM_HCB_OFFLINE
:
368 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
369 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
372 case BFA_FCS_ITNIM_SM_DELETE
:
373 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
374 bfa_fcs_itnim_free(itnim
);
378 bfa_sm_fault(itnim
->fcs
, event
);
383 * This state is set when a discovered rport is also in intiator mode.
384 * This ITN is marked as no_op and is not active and will not be truned into
388 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
389 enum bfa_fcs_itnim_event event
)
391 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
392 bfa_trc(itnim
->fcs
, event
);
395 case BFA_FCS_ITNIM_SM_OFFLINE
:
396 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
397 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
401 * fcs_online is expected here for well known initiator ports
403 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
404 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
407 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
408 case BFA_FCS_ITNIM_SM_INITIATOR
:
411 case BFA_FCS_ITNIM_SM_DELETE
:
412 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
413 bfa_fcs_itnim_free(itnim
);
417 bfa_sm_fault(itnim
->fcs
, event
);
422 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
423 enum bfa_itnim_aen_event event
)
425 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
426 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
427 struct bfa_aen_entry_s
*aen_entry
;
429 /* Don't post events for well known addresses */
430 if (BFA_FCS_PID_IS_WKA(rport
->pid
))
433 bfad_get_aen_entry(bfad
, aen_entry
);
437 aen_entry
->aen_data
.itnim
.vf_id
= rport
->port
->fabric
->vf_id
;
438 aen_entry
->aen_data
.itnim
.ppwwn
= bfa_fcs_lport_get_pwwn(
439 bfa_fcs_get_base_port(itnim
->fcs
));
440 aen_entry
->aen_data
.itnim
.lpwwn
= bfa_fcs_lport_get_pwwn(rport
->port
);
441 aen_entry
->aen_data
.itnim
.rpwwn
= rport
->pwwn
;
443 /* Send the AEN notification */
444 bfad_im_post_vendor_event(aen_entry
, bfad
, ++rport
->fcs
->fcs_aen_seq
,
445 BFA_AEN_CAT_ITNIM
, event
);
449 bfa_fcs_itnim_send_prli(void *itnim_cbarg
, struct bfa_fcxp_s
*fcxp_alloced
)
451 struct bfa_fcs_itnim_s
*itnim
= itnim_cbarg
;
452 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
453 struct bfa_fcs_lport_s
*port
= rport
->port
;
455 struct bfa_fcxp_s
*fcxp
;
458 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
460 fcxp
= fcxp_alloced
? fcxp_alloced
:
461 bfa_fcs_fcxp_alloc(port
->fcs
, BFA_TRUE
);
463 itnim
->stats
.fcxp_alloc_wait
++;
464 bfa_fcs_fcxp_alloc_wait(port
->fcs
->bfa
, &itnim
->fcxp_wqe
,
465 bfa_fcs_itnim_send_prli
, itnim
, BFA_TRUE
);
470 len
= fc_prli_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
471 itnim
->rport
->pid
, bfa_fcs_lport_get_fcid(port
), 0);
473 bfa_fcxp_send(fcxp
, rport
->bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
474 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
,
475 bfa_fcs_itnim_prli_response
, (void *)itnim
,
476 FC_MAX_PDUSZ
, FC_ELS_TOV
);
478 itnim
->stats
.prli_sent
++;
479 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_FRMSENT
);
483 bfa_fcs_itnim_prli_response(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
484 bfa_status_t req_status
, u32 rsp_len
,
485 u32 resid_len
, struct fchs_s
*rsp_fchs
)
487 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
488 struct fc_els_cmd_s
*els_cmd
;
489 struct fc_prli_s
*prli_resp
;
490 struct fc_ls_rjt_s
*ls_rjt
;
491 struct fc_prli_params_s
*sparams
;
493 bfa_trc(itnim
->fcs
, req_status
);
498 if (req_status
!= BFA_STATUS_OK
) {
499 itnim
->stats
.prli_rsp_err
++;
500 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
504 els_cmd
= (struct fc_els_cmd_s
*) BFA_FCXP_RSP_PLD(fcxp
);
506 if (els_cmd
->els_code
== FC_ELS_ACC
) {
507 prli_resp
= (struct fc_prli_s
*) els_cmd
;
509 if (fc_prli_rsp_parse(prli_resp
, rsp_len
) != FC_PARSE_OK
) {
510 bfa_trc(itnim
->fcs
, rsp_len
);
512 * Check if this r-port is also in Initiator mode.
513 * If so, we need to set this ITN as a no-op.
515 if (prli_resp
->parampage
.servparams
.initiator
) {
516 bfa_trc(itnim
->fcs
, prli_resp
->parampage
.type
);
517 itnim
->rport
->scsi_function
=
519 itnim
->stats
.prli_rsp_acc
++;
520 itnim
->stats
.initiator
++;
521 bfa_sm_send_event(itnim
,
522 BFA_FCS_ITNIM_SM_RSP_OK
);
526 itnim
->stats
.prli_rsp_parse_err
++;
529 itnim
->rport
->scsi_function
= BFA_RPORT_TARGET
;
531 sparams
= &prli_resp
->parampage
.servparams
;
532 itnim
->seq_rec
= sparams
->retry
;
533 itnim
->rec_support
= sparams
->rec_support
;
534 itnim
->task_retry_id
= sparams
->task_retry_id
;
535 itnim
->conf_comp
= sparams
->confirm
;
537 itnim
->stats
.prli_rsp_acc
++;
538 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_OK
);
540 ls_rjt
= (struct fc_ls_rjt_s
*) BFA_FCXP_RSP_PLD(fcxp
);
542 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code
);
543 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code_expl
);
545 itnim
->stats
.prli_rsp_rjt
++;
546 if (ls_rjt
->reason_code
== FC_LS_RJT_RSN_CMD_NOT_SUPP
) {
547 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
);
550 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
555 bfa_fcs_itnim_timeout(void *arg
)
557 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) arg
;
559 itnim
->stats
.timeout
++;
560 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_TIMEOUT
);
564 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
)
566 if (itnim
->bfa_itnim
) {
567 bfa_itnim_delete(itnim
->bfa_itnim
);
568 itnim
->bfa_itnim
= NULL
;
571 bfa_fcb_itnim_free(itnim
->fcs
->bfad
, itnim
->itnim_drv
);
577 * itnim_public FCS ITNIM public interfaces
581 * Called by rport when a new rport is created.
583 * @param[in] rport - remote port.
585 struct bfa_fcs_itnim_s
*
586 bfa_fcs_itnim_create(struct bfa_fcs_rport_s
*rport
)
588 struct bfa_fcs_lport_s
*port
= rport
->port
;
589 struct bfa_fcs_itnim_s
*itnim
;
590 struct bfad_itnim_s
*itnim_drv
;
594 * call bfad to allocate the itnim
596 ret
= bfa_fcb_itnim_alloc(port
->fcs
->bfad
, &itnim
, &itnim_drv
);
598 bfa_trc(port
->fcs
, rport
->pwwn
);
605 itnim
->rport
= rport
;
606 itnim
->fcs
= rport
->fcs
;
607 itnim
->itnim_drv
= itnim_drv
;
609 itnim
->bfa_itnim
= NULL
;
610 itnim
->seq_rec
= BFA_FALSE
;
611 itnim
->rec_support
= BFA_FALSE
;
612 itnim
->conf_comp
= BFA_FALSE
;
613 itnim
->task_retry_id
= BFA_FALSE
;
618 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
624 * Called by rport to delete the instance of FCPIM.
626 * @param[in] rport - remote port.
629 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s
*itnim
)
631 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
632 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_DELETE
);
636 * Notification from rport that PLOGI is complete to initiate FC-4 session.
639 bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s
*itnim
)
641 itnim
->stats
.onlines
++;
643 if (!BFA_FCS_PID_IS_WKA(itnim
->rport
->pid
))
644 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HAL_ONLINE
);
648 * Called by rport to handle a remote device offline.
651 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s
*itnim
)
653 itnim
->stats
.offlines
++;
654 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_OFFLINE
);
658 * Called by rport when remote port is known to be an initiator from
662 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s
*itnim
)
664 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
665 itnim
->stats
.initiator
++;
666 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
670 * Called by rport to check if the itnim is online.
673 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s
*itnim
)
675 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
676 switch (bfa_sm_to_state(itnim_sm_table
, itnim
->sm
)) {
677 case BFA_ITNIM_ONLINE
:
678 case BFA_ITNIM_INITIATIOR
:
679 return BFA_STATUS_OK
;
682 return BFA_STATUS_NO_FCPIM_NEXUS
;
687 * BFA completion callback for bfa_itnim_online().
690 bfa_cb_itnim_online(void *cbarg
)
692 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
694 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
695 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_ONLINE
);
699 * BFA completion callback for bfa_itnim_offline().
702 bfa_cb_itnim_offline(void *cb_arg
)
704 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
706 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
707 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_OFFLINE
);
711 * Mark the beginning of PATH TOV handling. IO completion callbacks
715 bfa_cb_itnim_tov_begin(void *cb_arg
)
717 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
719 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
723 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
726 bfa_cb_itnim_tov(void *cb_arg
)
728 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
729 struct bfad_itnim_s
*itnim_drv
= itnim
->itnim_drv
;
731 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
732 itnim_drv
->state
= ITNIM_STATE_TIMEOUT
;
736 * BFA notification to FCS/driver for second level error recovery.
738 * Atleast one I/O request has timedout and target is unresponsive to
739 * repeated abort requests. Second level error recovery should be initiated
740 * by starting implicit logout and recovery procedures.
743 bfa_cb_itnim_sler(void *cb_arg
)
745 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
748 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
749 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
752 struct bfa_fcs_itnim_s
*
753 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
755 struct bfa_fcs_rport_s
*rport
;
756 rport
= bfa_fcs_rport_lookup(port
, rpwwn
);
761 WARN_ON(rport
->itnim
== NULL
);
766 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
767 struct bfa_itnim_attr_s
*attr
)
769 struct bfa_fcs_itnim_s
*itnim
= NULL
;
771 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
774 return BFA_STATUS_NO_FCPIM_NEXUS
;
776 attr
->state
= bfa_sm_to_state(itnim_sm_table
, itnim
->sm
);
777 attr
->retry
= itnim
->seq_rec
;
778 attr
->rec_support
= itnim
->rec_support
;
779 attr
->conf_comp
= itnim
->conf_comp
;
780 attr
->task_retry_id
= itnim
->task_retry_id
;
781 return BFA_STATUS_OK
;
785 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
786 struct bfa_itnim_stats_s
*stats
)
788 struct bfa_fcs_itnim_s
*itnim
= NULL
;
790 WARN_ON(port
== NULL
);
792 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
795 return BFA_STATUS_NO_FCPIM_NEXUS
;
797 memcpy(stats
, &itnim
->stats
, sizeof(struct bfa_itnim_stats_s
));
799 return BFA_STATUS_OK
;
803 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
805 struct bfa_fcs_itnim_s
*itnim
= NULL
;
807 WARN_ON(port
== NULL
);
809 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
812 return BFA_STATUS_NO_FCPIM_NEXUS
;
814 memset(&itnim
->stats
, 0, sizeof(struct bfa_itnim_stats_s
));
815 return BFA_STATUS_OK
;
819 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s
*itnim
,
820 struct fchs_s
*fchs
, u16 len
)
822 struct fc_els_cmd_s
*els_cmd
;
824 bfa_trc(itnim
->fcs
, fchs
->type
);
826 if (fchs
->type
!= FC_TYPE_ELS
)
829 els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
831 bfa_trc(itnim
->fcs
, els_cmd
->els_code
);
833 switch (els_cmd
->els_code
) {
835 bfa_fcs_rport_prlo(itnim
->rport
, fchs
->ox_id
);