1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4 * Copyright (c) 2014- QLogic Corporation.
8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
12 * fcpim.c - FCP initiator mode i-t nexus state machine
17 #include "bfa_fcbuild.h"
19 #include "bfa_fcpim.h"
21 BFA_TRC_FILE(FCS
, FCPIM
);
24 * forward declarations
26 static void bfa_fcs_itnim_timeout(void *arg
);
27 static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
);
28 static void bfa_fcs_itnim_send_prli(void *itnim_cbarg
,
29 struct bfa_fcxp_s
*fcxp_alloced
);
30 static void bfa_fcs_itnim_prli_response(void *fcsarg
,
31 struct bfa_fcxp_s
*fcxp
, void *cbarg
,
32 bfa_status_t req_status
, u32 rsp_len
,
33 u32 resid_len
, struct fchs_s
*rsp_fchs
);
34 static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
35 enum bfa_itnim_aen_event event
);
37 static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
38 enum bfa_fcs_itnim_event event
);
39 static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
40 enum bfa_fcs_itnim_event event
);
41 static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
42 enum bfa_fcs_itnim_event event
);
43 static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
44 enum bfa_fcs_itnim_event event
);
45 static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
46 enum bfa_fcs_itnim_event event
);
47 static void bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
48 enum bfa_fcs_itnim_event event
);
49 static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
50 enum bfa_fcs_itnim_event event
);
51 static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
52 enum bfa_fcs_itnim_event event
);
53 static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
54 enum bfa_fcs_itnim_event event
);
56 struct bfa_fcs_itnim_sm_table_s
{
57 bfa_fcs_itnim_sm_t sm
; /* state machine function */
58 enum bfa_itnim_state state
; /* state machine encoding */
59 char *name
; /* state name for display */
62 static inline enum bfa_itnim_state
63 bfa_fcs_itnim_sm_to_state(struct bfa_fcs_itnim_sm_table_s
*smt
, bfa_fcs_itnim_sm_t sm
)
67 while (smt
[i
].sm
&& smt
[i
].sm
!= sm
)
72 static struct bfa_fcs_itnim_sm_table_s itnim_sm_table
[] = {
73 {BFA_SM(bfa_fcs_itnim_sm_offline
), BFA_ITNIM_OFFLINE
},
74 {BFA_SM(bfa_fcs_itnim_sm_prli_send
), BFA_ITNIM_PRLI_SEND
},
75 {BFA_SM(bfa_fcs_itnim_sm_prli
), BFA_ITNIM_PRLI_SENT
},
76 {BFA_SM(bfa_fcs_itnim_sm_prli_retry
), BFA_ITNIM_PRLI_RETRY
},
77 {BFA_SM(bfa_fcs_itnim_sm_hcb_online
), BFA_ITNIM_HCB_ONLINE
},
78 {BFA_SM(bfa_fcs_itnim_sm_online
), BFA_ITNIM_ONLINE
},
79 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline
), BFA_ITNIM_HCB_OFFLINE
},
80 {BFA_SM(bfa_fcs_itnim_sm_initiator
), BFA_ITNIM_INITIATIOR
},
84 * fcs_itnim_sm FCS itnim state machine
88 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
89 enum bfa_fcs_itnim_event event
)
91 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
92 bfa_trc(itnim
->fcs
, event
);
95 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
96 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
97 itnim
->prli_retries
= 0;
98 bfa_fcs_itnim_send_prli(itnim
, NULL
);
101 case BFA_FCS_ITNIM_SM_OFFLINE
:
102 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
105 case BFA_FCS_ITNIM_SM_INITIATOR
:
106 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
109 case BFA_FCS_ITNIM_SM_DELETE
:
110 bfa_fcs_itnim_free(itnim
);
114 bfa_sm_fault(itnim
->fcs
, event
);
120 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
121 enum bfa_fcs_itnim_event event
)
123 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
124 bfa_trc(itnim
->fcs
, event
);
127 case BFA_FCS_ITNIM_SM_FRMSENT
:
128 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli
);
131 case BFA_FCS_ITNIM_SM_INITIATOR
:
132 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
133 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
134 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
137 case BFA_FCS_ITNIM_SM_OFFLINE
:
138 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
139 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
140 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
143 case BFA_FCS_ITNIM_SM_DELETE
:
144 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
145 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
146 bfa_fcs_itnim_free(itnim
);
150 bfa_sm_fault(itnim
->fcs
, event
);
155 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
156 enum bfa_fcs_itnim_event event
)
158 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
159 bfa_trc(itnim
->fcs
, event
);
162 case BFA_FCS_ITNIM_SM_RSP_OK
:
163 if (itnim
->rport
->scsi_function
== BFA_RPORT_INITIATOR
)
164 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
166 bfa_sm_set_state(itnim
,
167 bfa_fcs_itnim_sm_hal_rport_online
);
169 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
172 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
173 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_retry
);
174 bfa_timer_start(itnim
->fcs
->bfa
, &itnim
->timer
,
175 bfa_fcs_itnim_timeout
, itnim
,
176 BFA_FCS_RETRY_TIMEOUT
);
179 case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
:
180 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
183 case BFA_FCS_ITNIM_SM_OFFLINE
:
184 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
185 bfa_fcxp_discard(itnim
->fcxp
);
186 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
189 case BFA_FCS_ITNIM_SM_INITIATOR
:
190 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
191 bfa_fcxp_discard(itnim
->fcxp
);
192 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
195 case BFA_FCS_ITNIM_SM_DELETE
:
196 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
197 bfa_fcxp_discard(itnim
->fcxp
);
198 bfa_fcs_itnim_free(itnim
);
202 bfa_sm_fault(itnim
->fcs
, event
);
207 bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
208 enum bfa_fcs_itnim_event event
)
210 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
211 bfa_trc(itnim
->fcs
, event
);
214 case BFA_FCS_ITNIM_SM_HAL_ONLINE
:
215 if (!itnim
->bfa_itnim
)
216 itnim
->bfa_itnim
= bfa_itnim_create(itnim
->fcs
->bfa
,
217 itnim
->rport
->bfa_rport
, itnim
);
219 if (itnim
->bfa_itnim
) {
220 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_online
);
221 bfa_itnim_online(itnim
->bfa_itnim
, itnim
->seq_rec
);
223 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
224 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_DELETE
);
229 case BFA_FCS_ITNIM_SM_OFFLINE
:
230 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
231 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
234 case BFA_FCS_ITNIM_SM_DELETE
:
235 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
236 bfa_fcs_itnim_free(itnim
);
240 bfa_sm_fault(itnim
->fcs
, event
);
245 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
246 enum bfa_fcs_itnim_event event
)
248 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
249 bfa_trc(itnim
->fcs
, event
);
252 case BFA_FCS_ITNIM_SM_TIMEOUT
:
253 if (itnim
->prli_retries
< BFA_FCS_RPORT_MAX_RETRIES
) {
254 itnim
->prli_retries
++;
255 bfa_trc(itnim
->fcs
, itnim
->prli_retries
);
256 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
257 bfa_fcs_itnim_send_prli(itnim
, NULL
);
259 /* invoke target offline */
260 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
261 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
266 case BFA_FCS_ITNIM_SM_OFFLINE
:
267 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
268 bfa_timer_stop(&itnim
->timer
);
269 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
272 case BFA_FCS_ITNIM_SM_INITIATOR
:
273 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
274 bfa_timer_stop(&itnim
->timer
);
275 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
278 case BFA_FCS_ITNIM_SM_DELETE
:
279 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
280 bfa_timer_stop(&itnim
->timer
);
281 bfa_fcs_itnim_free(itnim
);
285 bfa_sm_fault(itnim
->fcs
, event
);
290 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
291 enum bfa_fcs_itnim_event event
)
293 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
294 char lpwwn_buf
[BFA_STRING_32
];
295 char rpwwn_buf
[BFA_STRING_32
];
297 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
298 bfa_trc(itnim
->fcs
, event
);
301 case BFA_FCS_ITNIM_SM_HCB_ONLINE
:
302 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_online
);
303 bfa_fcb_itnim_online(itnim
->itnim_drv
);
304 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
305 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
306 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
307 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
308 rpwwn_buf
, lpwwn_buf
);
309 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_ONLINE
);
312 case BFA_FCS_ITNIM_SM_OFFLINE
:
313 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
314 bfa_itnim_offline(itnim
->bfa_itnim
);
317 case BFA_FCS_ITNIM_SM_DELETE
:
318 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
319 bfa_fcs_itnim_free(itnim
);
323 bfa_sm_fault(itnim
->fcs
, event
);
328 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
329 enum bfa_fcs_itnim_event event
)
331 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
332 char lpwwn_buf
[BFA_STRING_32
];
333 char rpwwn_buf
[BFA_STRING_32
];
335 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
336 bfa_trc(itnim
->fcs
, event
);
339 case BFA_FCS_ITNIM_SM_OFFLINE
:
340 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
341 bfa_fcb_itnim_offline(itnim
->itnim_drv
);
342 bfa_itnim_offline(itnim
->bfa_itnim
);
343 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
344 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
345 if (bfa_fcs_lport_is_online(itnim
->rport
->port
) == BFA_TRUE
) {
346 BFA_LOG(KERN_ERR
, bfad
, bfa_log_level
,
347 "Target (WWN = %s) connectivity lost for "
348 "initiator (WWN = %s)\n", rpwwn_buf
, lpwwn_buf
);
349 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_DISCONNECT
);
351 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
352 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
353 rpwwn_buf
, lpwwn_buf
);
354 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_OFFLINE
);
358 case BFA_FCS_ITNIM_SM_DELETE
:
359 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
360 bfa_fcs_itnim_free(itnim
);
364 bfa_sm_fault(itnim
->fcs
, event
);
369 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
370 enum bfa_fcs_itnim_event event
)
372 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
373 bfa_trc(itnim
->fcs
, event
);
376 case BFA_FCS_ITNIM_SM_HCB_OFFLINE
:
377 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
378 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
381 case BFA_FCS_ITNIM_SM_DELETE
:
382 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
383 bfa_fcs_itnim_free(itnim
);
387 bfa_sm_fault(itnim
->fcs
, event
);
392 * This state is set when a discovered rport is also in intiator mode.
393 * This ITN is marked as no_op and is not active and will not be truned into
397 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
398 enum bfa_fcs_itnim_event event
)
400 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
401 bfa_trc(itnim
->fcs
, event
);
404 case BFA_FCS_ITNIM_SM_OFFLINE
:
405 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
406 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
410 * fcs_online is expected here for well known initiator ports
412 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
413 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
416 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
417 case BFA_FCS_ITNIM_SM_INITIATOR
:
420 case BFA_FCS_ITNIM_SM_DELETE
:
421 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
422 bfa_fcs_itnim_free(itnim
);
426 bfa_sm_fault(itnim
->fcs
, event
);
431 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
432 enum bfa_itnim_aen_event event
)
434 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
435 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
436 struct bfa_aen_entry_s
*aen_entry
;
438 /* Don't post events for well known addresses */
439 if (BFA_FCS_PID_IS_WKA(rport
->pid
))
442 bfad_get_aen_entry(bfad
, aen_entry
);
446 aen_entry
->aen_data
.itnim
.vf_id
= rport
->port
->fabric
->vf_id
;
447 aen_entry
->aen_data
.itnim
.ppwwn
= bfa_fcs_lport_get_pwwn(
448 bfa_fcs_get_base_port(itnim
->fcs
));
449 aen_entry
->aen_data
.itnim
.lpwwn
= bfa_fcs_lport_get_pwwn(rport
->port
);
450 aen_entry
->aen_data
.itnim
.rpwwn
= rport
->pwwn
;
452 /* Send the AEN notification */
453 bfad_im_post_vendor_event(aen_entry
, bfad
, ++rport
->fcs
->fcs_aen_seq
,
454 BFA_AEN_CAT_ITNIM
, event
);
458 bfa_fcs_itnim_send_prli(void *itnim_cbarg
, struct bfa_fcxp_s
*fcxp_alloced
)
460 struct bfa_fcs_itnim_s
*itnim
= itnim_cbarg
;
461 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
462 struct bfa_fcs_lport_s
*port
= rport
->port
;
464 struct bfa_fcxp_s
*fcxp
;
467 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
469 fcxp
= fcxp_alloced
? fcxp_alloced
:
470 bfa_fcs_fcxp_alloc(port
->fcs
, BFA_TRUE
);
472 itnim
->stats
.fcxp_alloc_wait
++;
473 bfa_fcs_fcxp_alloc_wait(port
->fcs
->bfa
, &itnim
->fcxp_wqe
,
474 bfa_fcs_itnim_send_prli
, itnim
, BFA_TRUE
);
479 len
= fc_prli_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
480 itnim
->rport
->pid
, bfa_fcs_lport_get_fcid(port
), 0);
482 bfa_fcxp_send(fcxp
, rport
->bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
483 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
,
484 bfa_fcs_itnim_prli_response
, (void *)itnim
,
485 FC_MAX_PDUSZ
, FC_ELS_TOV
);
487 itnim
->stats
.prli_sent
++;
488 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_FRMSENT
);
492 bfa_fcs_itnim_prli_response(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
493 bfa_status_t req_status
, u32 rsp_len
,
494 u32 resid_len
, struct fchs_s
*rsp_fchs
)
496 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
497 struct fc_els_cmd_s
*els_cmd
;
498 struct fc_prli_s
*prli_resp
;
499 struct fc_ls_rjt_s
*ls_rjt
;
500 struct fc_prli_params_s
*sparams
;
502 bfa_trc(itnim
->fcs
, req_status
);
507 if (req_status
!= BFA_STATUS_OK
) {
508 itnim
->stats
.prli_rsp_err
++;
509 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
513 els_cmd
= (struct fc_els_cmd_s
*) BFA_FCXP_RSP_PLD(fcxp
);
515 if (els_cmd
->els_code
== FC_ELS_ACC
) {
516 prli_resp
= (struct fc_prli_s
*) els_cmd
;
518 if (fc_prli_rsp_parse(prli_resp
, rsp_len
) != FC_PARSE_OK
) {
519 bfa_trc(itnim
->fcs
, rsp_len
);
521 * Check if this r-port is also in Initiator mode.
522 * If so, we need to set this ITN as a no-op.
524 if (prli_resp
->parampage
.servparams
.initiator
) {
525 bfa_trc(itnim
->fcs
, prli_resp
->parampage
.type
);
526 itnim
->rport
->scsi_function
=
528 itnim
->stats
.prli_rsp_acc
++;
529 itnim
->stats
.initiator
++;
530 bfa_sm_send_event(itnim
,
531 BFA_FCS_ITNIM_SM_RSP_OK
);
535 itnim
->stats
.prli_rsp_parse_err
++;
538 itnim
->rport
->scsi_function
= BFA_RPORT_TARGET
;
540 sparams
= &prli_resp
->parampage
.servparams
;
541 itnim
->seq_rec
= sparams
->retry
;
542 itnim
->rec_support
= sparams
->rec_support
;
543 itnim
->task_retry_id
= sparams
->task_retry_id
;
544 itnim
->conf_comp
= sparams
->confirm
;
546 itnim
->stats
.prli_rsp_acc
++;
547 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_OK
);
549 ls_rjt
= (struct fc_ls_rjt_s
*) BFA_FCXP_RSP_PLD(fcxp
);
551 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code
);
552 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code_expl
);
554 itnim
->stats
.prli_rsp_rjt
++;
555 if (ls_rjt
->reason_code
== FC_LS_RJT_RSN_CMD_NOT_SUPP
) {
556 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
);
559 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
564 bfa_fcs_itnim_timeout(void *arg
)
566 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) arg
;
568 itnim
->stats
.timeout
++;
569 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_TIMEOUT
);
573 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
)
575 if (itnim
->bfa_itnim
) {
576 bfa_itnim_delete(itnim
->bfa_itnim
);
577 itnim
->bfa_itnim
= NULL
;
580 bfa_fcb_itnim_free(itnim
->fcs
->bfad
, itnim
->itnim_drv
);
586 * itnim_public FCS ITNIM public interfaces
590 * Called by rport when a new rport is created.
592 * @param[in] rport - remote port.
594 struct bfa_fcs_itnim_s
*
595 bfa_fcs_itnim_create(struct bfa_fcs_rport_s
*rport
)
597 struct bfa_fcs_lport_s
*port
= rport
->port
;
598 struct bfa_fcs_itnim_s
*itnim
;
599 struct bfad_itnim_s
*itnim_drv
;
603 * call bfad to allocate the itnim
605 ret
= bfa_fcb_itnim_alloc(port
->fcs
->bfad
, &itnim
, &itnim_drv
);
607 bfa_trc(port
->fcs
, rport
->pwwn
);
614 itnim
->rport
= rport
;
615 itnim
->fcs
= rport
->fcs
;
616 itnim
->itnim_drv
= itnim_drv
;
618 itnim
->bfa_itnim
= NULL
;
619 itnim
->seq_rec
= BFA_FALSE
;
620 itnim
->rec_support
= BFA_FALSE
;
621 itnim
->conf_comp
= BFA_FALSE
;
622 itnim
->task_retry_id
= BFA_FALSE
;
627 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
633 * Called by rport to delete the instance of FCPIM.
635 * @param[in] rport - remote port.
638 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s
*itnim
)
640 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
641 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_DELETE
);
645 * Notification from rport that PLOGI is complete to initiate FC-4 session.
648 bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s
*itnim
)
650 itnim
->stats
.onlines
++;
652 if (!BFA_FCS_PID_IS_WKA(itnim
->rport
->pid
))
653 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HAL_ONLINE
);
657 * Called by rport to handle a remote device offline.
660 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s
*itnim
)
662 itnim
->stats
.offlines
++;
663 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_OFFLINE
);
667 * Called by rport when remote port is known to be an initiator from
671 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s
*itnim
)
673 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
674 itnim
->stats
.initiator
++;
675 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
679 * Called by rport to check if the itnim is online.
682 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s
*itnim
)
684 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
685 switch (bfa_fcs_itnim_sm_to_state(itnim_sm_table
, itnim
->sm
)) {
686 case BFA_ITNIM_ONLINE
:
687 case BFA_ITNIM_INITIATIOR
:
688 return BFA_STATUS_OK
;
691 return BFA_STATUS_NO_FCPIM_NEXUS
;
696 * BFA completion callback for bfa_itnim_online().
699 bfa_cb_itnim_online(void *cbarg
)
701 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
703 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
704 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_ONLINE
);
708 * BFA completion callback for bfa_itnim_offline().
711 bfa_cb_itnim_offline(void *cb_arg
)
713 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
715 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
716 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_OFFLINE
);
720 * Mark the beginning of PATH TOV handling. IO completion callbacks
724 bfa_cb_itnim_tov_begin(void *cb_arg
)
726 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
728 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
732 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
735 bfa_cb_itnim_tov(void *cb_arg
)
737 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
738 struct bfad_itnim_s
*itnim_drv
= itnim
->itnim_drv
;
740 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
741 itnim_drv
->state
= ITNIM_STATE_TIMEOUT
;
745 * BFA notification to FCS/driver for second level error recovery.
747 * Atleast one I/O request has timedout and target is unresponsive to
748 * repeated abort requests. Second level error recovery should be initiated
749 * by starting implicit logout and recovery procedures.
752 bfa_cb_itnim_sler(void *cb_arg
)
754 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
757 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
758 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
761 struct bfa_fcs_itnim_s
*
762 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
764 struct bfa_fcs_rport_s
*rport
;
765 rport
= bfa_fcs_rport_lookup(port
, rpwwn
);
770 WARN_ON(rport
->itnim
== NULL
);
775 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
776 struct bfa_itnim_attr_s
*attr
)
778 struct bfa_fcs_itnim_s
*itnim
= NULL
;
780 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
783 return BFA_STATUS_NO_FCPIM_NEXUS
;
785 attr
->state
= bfa_fcs_itnim_sm_to_state(itnim_sm_table
, itnim
->sm
);
786 attr
->retry
= itnim
->seq_rec
;
787 attr
->rec_support
= itnim
->rec_support
;
788 attr
->conf_comp
= itnim
->conf_comp
;
789 attr
->task_retry_id
= itnim
->task_retry_id
;
790 return BFA_STATUS_OK
;
794 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
795 struct bfa_itnim_stats_s
*stats
)
797 struct bfa_fcs_itnim_s
*itnim
= NULL
;
799 WARN_ON(port
== NULL
);
801 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
804 return BFA_STATUS_NO_FCPIM_NEXUS
;
806 memcpy(stats
, &itnim
->stats
, sizeof(struct bfa_itnim_stats_s
));
808 return BFA_STATUS_OK
;
812 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
814 struct bfa_fcs_itnim_s
*itnim
= NULL
;
816 WARN_ON(port
== NULL
);
818 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
821 return BFA_STATUS_NO_FCPIM_NEXUS
;
823 memset(&itnim
->stats
, 0, sizeof(struct bfa_itnim_stats_s
));
824 return BFA_STATUS_OK
;
828 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s
*itnim
,
829 struct fchs_s
*fchs
, u16 len
)
831 struct fc_els_cmd_s
*els_cmd
;
833 bfa_trc(itnim
->fcs
, fchs
->type
);
835 if (fchs
->type
!= FC_TYPE_ELS
)
838 els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
840 bfa_trc(itnim
->fcs
, els_cmd
->els_code
);
842 switch (els_cmd
->els_code
) {
844 bfa_fcs_rport_prlo(itnim
->rport
, fchs
->ox_id
);