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"
20 BFA_TRC_FILE(FCS
, FCPIM
);
23 * forward declarations
25 static void bfa_fcs_itnim_timeout(void *arg
);
26 static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
);
27 static void bfa_fcs_itnim_send_prli(void *itnim_cbarg
,
28 struct bfa_fcxp_s
*fcxp_alloced
);
29 static void bfa_fcs_itnim_prli_response(void *fcsarg
,
30 struct bfa_fcxp_s
*fcxp
, void *cbarg
,
31 bfa_status_t req_status
, u32 rsp_len
,
32 u32 resid_len
, struct fchs_s
*rsp_fchs
);
33 static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
34 enum bfa_itnim_aen_event event
);
36 static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
37 enum bfa_fcs_itnim_event event
);
38 static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
39 enum bfa_fcs_itnim_event event
);
40 static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
41 enum bfa_fcs_itnim_event event
);
42 static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
43 enum bfa_fcs_itnim_event event
);
44 static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
45 enum bfa_fcs_itnim_event event
);
46 static void bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
47 enum bfa_fcs_itnim_event event
);
48 static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
49 enum bfa_fcs_itnim_event event
);
50 static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
51 enum bfa_fcs_itnim_event event
);
52 static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
53 enum bfa_fcs_itnim_event event
);
55 static struct bfa_sm_table_s itnim_sm_table
[] = {
56 {BFA_SM(bfa_fcs_itnim_sm_offline
), BFA_ITNIM_OFFLINE
},
57 {BFA_SM(bfa_fcs_itnim_sm_prli_send
), BFA_ITNIM_PRLI_SEND
},
58 {BFA_SM(bfa_fcs_itnim_sm_prli
), BFA_ITNIM_PRLI_SENT
},
59 {BFA_SM(bfa_fcs_itnim_sm_prli_retry
), BFA_ITNIM_PRLI_RETRY
},
60 {BFA_SM(bfa_fcs_itnim_sm_hcb_online
), BFA_ITNIM_HCB_ONLINE
},
61 {BFA_SM(bfa_fcs_itnim_sm_online
), BFA_ITNIM_ONLINE
},
62 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline
), BFA_ITNIM_HCB_OFFLINE
},
63 {BFA_SM(bfa_fcs_itnim_sm_initiator
), BFA_ITNIM_INITIATIOR
},
67 * fcs_itnim_sm FCS itnim state machine
71 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
72 enum bfa_fcs_itnim_event event
)
74 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
75 bfa_trc(itnim
->fcs
, event
);
78 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
79 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
80 itnim
->prli_retries
= 0;
81 bfa_fcs_itnim_send_prli(itnim
, NULL
);
84 case BFA_FCS_ITNIM_SM_OFFLINE
:
85 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
88 case BFA_FCS_ITNIM_SM_INITIATOR
:
89 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
92 case BFA_FCS_ITNIM_SM_DELETE
:
93 bfa_fcs_itnim_free(itnim
);
97 bfa_sm_fault(itnim
->fcs
, event
);
103 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
104 enum bfa_fcs_itnim_event event
)
106 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
107 bfa_trc(itnim
->fcs
, event
);
110 case BFA_FCS_ITNIM_SM_FRMSENT
:
111 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli
);
114 case BFA_FCS_ITNIM_SM_INITIATOR
:
115 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
116 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
117 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
120 case BFA_FCS_ITNIM_SM_OFFLINE
:
121 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
122 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
123 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
126 case BFA_FCS_ITNIM_SM_DELETE
:
127 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
128 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
129 bfa_fcs_itnim_free(itnim
);
133 bfa_sm_fault(itnim
->fcs
, event
);
138 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
139 enum bfa_fcs_itnim_event event
)
141 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
142 bfa_trc(itnim
->fcs
, event
);
145 case BFA_FCS_ITNIM_SM_RSP_OK
:
146 if (itnim
->rport
->scsi_function
== BFA_RPORT_INITIATOR
)
147 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
149 bfa_sm_set_state(itnim
,
150 bfa_fcs_itnim_sm_hal_rport_online
);
152 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
155 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
156 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_retry
);
157 bfa_timer_start(itnim
->fcs
->bfa
, &itnim
->timer
,
158 bfa_fcs_itnim_timeout
, itnim
,
159 BFA_FCS_RETRY_TIMEOUT
);
162 case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
:
163 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
166 case BFA_FCS_ITNIM_SM_OFFLINE
:
167 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
168 bfa_fcxp_discard(itnim
->fcxp
);
169 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
172 case BFA_FCS_ITNIM_SM_INITIATOR
:
173 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
174 bfa_fcxp_discard(itnim
->fcxp
);
175 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
178 case BFA_FCS_ITNIM_SM_DELETE
:
179 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
180 bfa_fcxp_discard(itnim
->fcxp
);
181 bfa_fcs_itnim_free(itnim
);
185 bfa_sm_fault(itnim
->fcs
, event
);
190 bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
191 enum bfa_fcs_itnim_event event
)
193 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
194 bfa_trc(itnim
->fcs
, event
);
197 case BFA_FCS_ITNIM_SM_HAL_ONLINE
:
198 if (!itnim
->bfa_itnim
)
199 itnim
->bfa_itnim
= bfa_itnim_create(itnim
->fcs
->bfa
,
200 itnim
->rport
->bfa_rport
, itnim
);
202 if (itnim
->bfa_itnim
) {
203 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_online
);
204 bfa_itnim_online(itnim
->bfa_itnim
, itnim
->seq_rec
);
206 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
207 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_DELETE
);
212 case BFA_FCS_ITNIM_SM_OFFLINE
:
213 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
214 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
217 case BFA_FCS_ITNIM_SM_DELETE
:
218 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
219 bfa_fcs_itnim_free(itnim
);
223 bfa_sm_fault(itnim
->fcs
, event
);
228 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
229 enum bfa_fcs_itnim_event event
)
231 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
232 bfa_trc(itnim
->fcs
, event
);
235 case BFA_FCS_ITNIM_SM_TIMEOUT
:
236 if (itnim
->prli_retries
< BFA_FCS_RPORT_MAX_RETRIES
) {
237 itnim
->prli_retries
++;
238 bfa_trc(itnim
->fcs
, itnim
->prli_retries
);
239 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
240 bfa_fcs_itnim_send_prli(itnim
, NULL
);
242 /* invoke target offline */
243 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
244 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
249 case BFA_FCS_ITNIM_SM_OFFLINE
:
250 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
251 bfa_timer_stop(&itnim
->timer
);
252 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
255 case BFA_FCS_ITNIM_SM_INITIATOR
:
256 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
257 bfa_timer_stop(&itnim
->timer
);
258 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
261 case BFA_FCS_ITNIM_SM_DELETE
:
262 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
263 bfa_timer_stop(&itnim
->timer
);
264 bfa_fcs_itnim_free(itnim
);
268 bfa_sm_fault(itnim
->fcs
, event
);
273 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
274 enum bfa_fcs_itnim_event event
)
276 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
277 char lpwwn_buf
[BFA_STRING_32
];
278 char rpwwn_buf
[BFA_STRING_32
];
280 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
281 bfa_trc(itnim
->fcs
, event
);
284 case BFA_FCS_ITNIM_SM_HCB_ONLINE
:
285 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_online
);
286 bfa_fcb_itnim_online(itnim
->itnim_drv
);
287 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
288 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
289 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
290 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
291 rpwwn_buf
, lpwwn_buf
);
292 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_ONLINE
);
295 case BFA_FCS_ITNIM_SM_OFFLINE
:
296 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
297 bfa_itnim_offline(itnim
->bfa_itnim
);
300 case BFA_FCS_ITNIM_SM_DELETE
:
301 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
302 bfa_fcs_itnim_free(itnim
);
306 bfa_sm_fault(itnim
->fcs
, event
);
311 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
312 enum bfa_fcs_itnim_event event
)
314 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
315 char lpwwn_buf
[BFA_STRING_32
];
316 char rpwwn_buf
[BFA_STRING_32
];
318 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
319 bfa_trc(itnim
->fcs
, event
);
322 case BFA_FCS_ITNIM_SM_OFFLINE
:
323 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
324 bfa_fcb_itnim_offline(itnim
->itnim_drv
);
325 bfa_itnim_offline(itnim
->bfa_itnim
);
326 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
327 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
328 if (bfa_fcs_lport_is_online(itnim
->rport
->port
) == BFA_TRUE
) {
329 BFA_LOG(KERN_ERR
, bfad
, bfa_log_level
,
330 "Target (WWN = %s) connectivity lost for "
331 "initiator (WWN = %s)\n", rpwwn_buf
, lpwwn_buf
);
332 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_DISCONNECT
);
334 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
335 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
336 rpwwn_buf
, lpwwn_buf
);
337 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_OFFLINE
);
341 case BFA_FCS_ITNIM_SM_DELETE
:
342 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
343 bfa_fcs_itnim_free(itnim
);
347 bfa_sm_fault(itnim
->fcs
, event
);
352 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
353 enum bfa_fcs_itnim_event event
)
355 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
356 bfa_trc(itnim
->fcs
, event
);
359 case BFA_FCS_ITNIM_SM_HCB_OFFLINE
:
360 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
361 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
364 case BFA_FCS_ITNIM_SM_DELETE
:
365 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
366 bfa_fcs_itnim_free(itnim
);
370 bfa_sm_fault(itnim
->fcs
, event
);
375 * This state is set when a discovered rport is also in intiator mode.
376 * This ITN is marked as no_op and is not active and will not be truned into
380 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
381 enum bfa_fcs_itnim_event event
)
383 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
384 bfa_trc(itnim
->fcs
, event
);
387 case BFA_FCS_ITNIM_SM_OFFLINE
:
388 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
389 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
393 * fcs_online is expected here for well known initiator ports
395 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
396 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
399 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
400 case BFA_FCS_ITNIM_SM_INITIATOR
:
403 case BFA_FCS_ITNIM_SM_DELETE
:
404 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
405 bfa_fcs_itnim_free(itnim
);
409 bfa_sm_fault(itnim
->fcs
, event
);
414 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
415 enum bfa_itnim_aen_event event
)
417 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
418 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
419 struct bfa_aen_entry_s
*aen_entry
;
421 /* Don't post events for well known addresses */
422 if (BFA_FCS_PID_IS_WKA(rport
->pid
))
425 bfad_get_aen_entry(bfad
, aen_entry
);
429 aen_entry
->aen_data
.itnim
.vf_id
= rport
->port
->fabric
->vf_id
;
430 aen_entry
->aen_data
.itnim
.ppwwn
= bfa_fcs_lport_get_pwwn(
431 bfa_fcs_get_base_port(itnim
->fcs
));
432 aen_entry
->aen_data
.itnim
.lpwwn
= bfa_fcs_lport_get_pwwn(rport
->port
);
433 aen_entry
->aen_data
.itnim
.rpwwn
= rport
->pwwn
;
435 /* Send the AEN notification */
436 bfad_im_post_vendor_event(aen_entry
, bfad
, ++rport
->fcs
->fcs_aen_seq
,
437 BFA_AEN_CAT_ITNIM
, event
);
441 bfa_fcs_itnim_send_prli(void *itnim_cbarg
, struct bfa_fcxp_s
*fcxp_alloced
)
443 struct bfa_fcs_itnim_s
*itnim
= itnim_cbarg
;
444 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
445 struct bfa_fcs_lport_s
*port
= rport
->port
;
447 struct bfa_fcxp_s
*fcxp
;
450 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
452 fcxp
= fcxp_alloced
? fcxp_alloced
:
453 bfa_fcs_fcxp_alloc(port
->fcs
, BFA_TRUE
);
455 itnim
->stats
.fcxp_alloc_wait
++;
456 bfa_fcs_fcxp_alloc_wait(port
->fcs
->bfa
, &itnim
->fcxp_wqe
,
457 bfa_fcs_itnim_send_prli
, itnim
, BFA_TRUE
);
462 len
= fc_prli_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
463 itnim
->rport
->pid
, bfa_fcs_lport_get_fcid(port
), 0);
465 bfa_fcxp_send(fcxp
, rport
->bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
466 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
,
467 bfa_fcs_itnim_prli_response
, (void *)itnim
,
468 FC_MAX_PDUSZ
, FC_ELS_TOV
);
470 itnim
->stats
.prli_sent
++;
471 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_FRMSENT
);
475 bfa_fcs_itnim_prli_response(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
476 bfa_status_t req_status
, u32 rsp_len
,
477 u32 resid_len
, struct fchs_s
*rsp_fchs
)
479 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
480 struct fc_els_cmd_s
*els_cmd
;
481 struct fc_prli_s
*prli_resp
;
482 struct fc_ls_rjt_s
*ls_rjt
;
483 struct fc_prli_params_s
*sparams
;
485 bfa_trc(itnim
->fcs
, req_status
);
490 if (req_status
!= BFA_STATUS_OK
) {
491 itnim
->stats
.prli_rsp_err
++;
492 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
496 els_cmd
= (struct fc_els_cmd_s
*) BFA_FCXP_RSP_PLD(fcxp
);
498 if (els_cmd
->els_code
== FC_ELS_ACC
) {
499 prli_resp
= (struct fc_prli_s
*) els_cmd
;
501 if (fc_prli_rsp_parse(prli_resp
, rsp_len
) != FC_PARSE_OK
) {
502 bfa_trc(itnim
->fcs
, rsp_len
);
504 * Check if this r-port is also in Initiator mode.
505 * If so, we need to set this ITN as a no-op.
507 if (prli_resp
->parampage
.servparams
.initiator
) {
508 bfa_trc(itnim
->fcs
, prli_resp
->parampage
.type
);
509 itnim
->rport
->scsi_function
=
511 itnim
->stats
.prli_rsp_acc
++;
512 itnim
->stats
.initiator
++;
513 bfa_sm_send_event(itnim
,
514 BFA_FCS_ITNIM_SM_RSP_OK
);
518 itnim
->stats
.prli_rsp_parse_err
++;
521 itnim
->rport
->scsi_function
= BFA_RPORT_TARGET
;
523 sparams
= &prli_resp
->parampage
.servparams
;
524 itnim
->seq_rec
= sparams
->retry
;
525 itnim
->rec_support
= sparams
->rec_support
;
526 itnim
->task_retry_id
= sparams
->task_retry_id
;
527 itnim
->conf_comp
= sparams
->confirm
;
529 itnim
->stats
.prli_rsp_acc
++;
530 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_OK
);
532 ls_rjt
= (struct fc_ls_rjt_s
*) BFA_FCXP_RSP_PLD(fcxp
);
534 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code
);
535 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code_expl
);
537 itnim
->stats
.prli_rsp_rjt
++;
538 if (ls_rjt
->reason_code
== FC_LS_RJT_RSN_CMD_NOT_SUPP
) {
539 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
);
542 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
547 bfa_fcs_itnim_timeout(void *arg
)
549 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) arg
;
551 itnim
->stats
.timeout
++;
552 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_TIMEOUT
);
556 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
)
558 if (itnim
->bfa_itnim
) {
559 bfa_itnim_delete(itnim
->bfa_itnim
);
560 itnim
->bfa_itnim
= NULL
;
563 bfa_fcb_itnim_free(itnim
->fcs
->bfad
, itnim
->itnim_drv
);
569 * itnim_public FCS ITNIM public interfaces
573 * Called by rport when a new rport is created.
575 * @param[in] rport - remote port.
577 struct bfa_fcs_itnim_s
*
578 bfa_fcs_itnim_create(struct bfa_fcs_rport_s
*rport
)
580 struct bfa_fcs_lport_s
*port
= rport
->port
;
581 struct bfa_fcs_itnim_s
*itnim
;
582 struct bfad_itnim_s
*itnim_drv
;
586 * call bfad to allocate the itnim
588 ret
= bfa_fcb_itnim_alloc(port
->fcs
->bfad
, &itnim
, &itnim_drv
);
590 bfa_trc(port
->fcs
, rport
->pwwn
);
597 itnim
->rport
= rport
;
598 itnim
->fcs
= rport
->fcs
;
599 itnim
->itnim_drv
= itnim_drv
;
601 itnim
->bfa_itnim
= NULL
;
602 itnim
->seq_rec
= BFA_FALSE
;
603 itnim
->rec_support
= BFA_FALSE
;
604 itnim
->conf_comp
= BFA_FALSE
;
605 itnim
->task_retry_id
= BFA_FALSE
;
610 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
616 * Called by rport to delete the instance of FCPIM.
618 * @param[in] rport - remote port.
621 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s
*itnim
)
623 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
624 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_DELETE
);
628 * Notification from rport that PLOGI is complete to initiate FC-4 session.
631 bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s
*itnim
)
633 itnim
->stats
.onlines
++;
635 if (!BFA_FCS_PID_IS_WKA(itnim
->rport
->pid
))
636 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HAL_ONLINE
);
640 * Called by rport to handle a remote device offline.
643 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s
*itnim
)
645 itnim
->stats
.offlines
++;
646 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_OFFLINE
);
650 * Called by rport when remote port is known to be an initiator from
654 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s
*itnim
)
656 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
657 itnim
->stats
.initiator
++;
658 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
662 * Called by rport to check if the itnim is online.
665 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s
*itnim
)
667 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
668 switch (bfa_sm_to_state(itnim_sm_table
, itnim
->sm
)) {
669 case BFA_ITNIM_ONLINE
:
670 case BFA_ITNIM_INITIATIOR
:
671 return BFA_STATUS_OK
;
674 return BFA_STATUS_NO_FCPIM_NEXUS
;
679 * BFA completion callback for bfa_itnim_online().
682 bfa_cb_itnim_online(void *cbarg
)
684 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
686 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
687 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_ONLINE
);
691 * BFA completion callback for bfa_itnim_offline().
694 bfa_cb_itnim_offline(void *cb_arg
)
696 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
698 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
699 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_OFFLINE
);
703 * Mark the beginning of PATH TOV handling. IO completion callbacks
707 bfa_cb_itnim_tov_begin(void *cb_arg
)
709 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
711 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
715 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
718 bfa_cb_itnim_tov(void *cb_arg
)
720 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
721 struct bfad_itnim_s
*itnim_drv
= itnim
->itnim_drv
;
723 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
724 itnim_drv
->state
= ITNIM_STATE_TIMEOUT
;
728 * BFA notification to FCS/driver for second level error recovery.
730 * Atleast one I/O request has timedout and target is unresponsive to
731 * repeated abort requests. Second level error recovery should be initiated
732 * by starting implicit logout and recovery procedures.
735 bfa_cb_itnim_sler(void *cb_arg
)
737 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
740 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
741 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
744 struct bfa_fcs_itnim_s
*
745 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
747 struct bfa_fcs_rport_s
*rport
;
748 rport
= bfa_fcs_rport_lookup(port
, rpwwn
);
753 WARN_ON(rport
->itnim
== NULL
);
758 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
759 struct bfa_itnim_attr_s
*attr
)
761 struct bfa_fcs_itnim_s
*itnim
= NULL
;
763 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
766 return BFA_STATUS_NO_FCPIM_NEXUS
;
768 attr
->state
= bfa_sm_to_state(itnim_sm_table
, itnim
->sm
);
769 attr
->retry
= itnim
->seq_rec
;
770 attr
->rec_support
= itnim
->rec_support
;
771 attr
->conf_comp
= itnim
->conf_comp
;
772 attr
->task_retry_id
= itnim
->task_retry_id
;
773 return BFA_STATUS_OK
;
777 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
778 struct bfa_itnim_stats_s
*stats
)
780 struct bfa_fcs_itnim_s
*itnim
= NULL
;
782 WARN_ON(port
== NULL
);
784 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
787 return BFA_STATUS_NO_FCPIM_NEXUS
;
789 memcpy(stats
, &itnim
->stats
, sizeof(struct bfa_itnim_stats_s
));
791 return BFA_STATUS_OK
;
795 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
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 memset(&itnim
->stats
, 0, sizeof(struct bfa_itnim_stats_s
));
807 return BFA_STATUS_OK
;
811 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s
*itnim
,
812 struct fchs_s
*fchs
, u16 len
)
814 struct fc_els_cmd_s
*els_cmd
;
816 bfa_trc(itnim
->fcs
, fchs
->type
);
818 if (fchs
->type
!= FC_TYPE_ELS
)
821 els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
823 bfa_trc(itnim
->fcs
, els_cmd
->els_code
);
825 switch (els_cmd
->els_code
) {
827 bfa_fcs_rport_prlo(itnim
->rport
, fchs
->ox_id
);