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
);
43 static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
44 enum bfa_fcs_itnim_event event
);
45 static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
46 enum bfa_fcs_itnim_event event
);
47 static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
48 enum bfa_fcs_itnim_event event
);
49 static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
50 enum bfa_fcs_itnim_event event
);
51 static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
52 enum bfa_fcs_itnim_event event
);
53 static void bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
54 enum bfa_fcs_itnim_event event
);
55 static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
56 enum bfa_fcs_itnim_event event
);
57 static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
58 enum bfa_fcs_itnim_event event
);
59 static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
60 enum bfa_fcs_itnim_event event
);
62 static struct bfa_sm_table_s itnim_sm_table
[] = {
63 {BFA_SM(bfa_fcs_itnim_sm_offline
), BFA_ITNIM_OFFLINE
},
64 {BFA_SM(bfa_fcs_itnim_sm_prli_send
), BFA_ITNIM_PRLI_SEND
},
65 {BFA_SM(bfa_fcs_itnim_sm_prli
), BFA_ITNIM_PRLI_SENT
},
66 {BFA_SM(bfa_fcs_itnim_sm_prli_retry
), BFA_ITNIM_PRLI_RETRY
},
67 {BFA_SM(bfa_fcs_itnim_sm_hcb_online
), BFA_ITNIM_HCB_ONLINE
},
68 {BFA_SM(bfa_fcs_itnim_sm_online
), BFA_ITNIM_ONLINE
},
69 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline
), BFA_ITNIM_HCB_OFFLINE
},
70 {BFA_SM(bfa_fcs_itnim_sm_initiator
), BFA_ITNIM_INITIATIOR
},
74 * fcs_itnim_sm FCS itnim state machine
78 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
79 enum bfa_fcs_itnim_event event
)
81 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
82 bfa_trc(itnim
->fcs
, event
);
85 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
86 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
87 itnim
->prli_retries
= 0;
88 bfa_fcs_itnim_send_prli(itnim
, NULL
);
91 case BFA_FCS_ITNIM_SM_OFFLINE
:
92 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
95 case BFA_FCS_ITNIM_SM_INITIATOR
:
96 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
99 case BFA_FCS_ITNIM_SM_DELETE
:
100 bfa_fcs_itnim_free(itnim
);
104 bfa_sm_fault(itnim
->fcs
, event
);
110 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
111 enum bfa_fcs_itnim_event event
)
113 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
114 bfa_trc(itnim
->fcs
, event
);
117 case BFA_FCS_ITNIM_SM_FRMSENT
:
118 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli
);
121 case BFA_FCS_ITNIM_SM_INITIATOR
:
122 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
123 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
124 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
127 case BFA_FCS_ITNIM_SM_OFFLINE
:
128 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
129 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
130 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
133 case BFA_FCS_ITNIM_SM_DELETE
:
134 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
135 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
136 bfa_fcs_itnim_free(itnim
);
140 bfa_sm_fault(itnim
->fcs
, event
);
145 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
146 enum bfa_fcs_itnim_event event
)
148 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
149 bfa_trc(itnim
->fcs
, event
);
152 case BFA_FCS_ITNIM_SM_RSP_OK
:
153 if (itnim
->rport
->scsi_function
== BFA_RPORT_INITIATOR
)
154 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
156 bfa_sm_set_state(itnim
,
157 bfa_fcs_itnim_sm_hal_rport_online
);
159 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
162 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
163 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_retry
);
164 bfa_timer_start(itnim
->fcs
->bfa
, &itnim
->timer
,
165 bfa_fcs_itnim_timeout
, itnim
,
166 BFA_FCS_RETRY_TIMEOUT
);
169 case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
:
170 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
173 case BFA_FCS_ITNIM_SM_OFFLINE
:
174 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
175 bfa_fcxp_discard(itnim
->fcxp
);
176 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
179 case BFA_FCS_ITNIM_SM_INITIATOR
:
180 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
181 bfa_fcxp_discard(itnim
->fcxp
);
182 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
185 case BFA_FCS_ITNIM_SM_DELETE
:
186 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
187 bfa_fcxp_discard(itnim
->fcxp
);
188 bfa_fcs_itnim_free(itnim
);
192 bfa_sm_fault(itnim
->fcs
, event
);
197 bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s
*itnim
,
198 enum bfa_fcs_itnim_event event
)
200 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
201 bfa_trc(itnim
->fcs
, event
);
204 case BFA_FCS_ITNIM_SM_HAL_ONLINE
:
205 if (!itnim
->bfa_itnim
)
206 itnim
->bfa_itnim
= bfa_itnim_create(itnim
->fcs
->bfa
,
207 itnim
->rport
->bfa_rport
, itnim
);
209 if (itnim
->bfa_itnim
) {
210 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_online
);
211 bfa_itnim_online(itnim
->bfa_itnim
, itnim
->seq_rec
);
213 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
214 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_DELETE
);
219 case BFA_FCS_ITNIM_SM_OFFLINE
:
220 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
221 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
224 case BFA_FCS_ITNIM_SM_DELETE
:
225 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
226 bfa_fcs_itnim_free(itnim
);
230 bfa_sm_fault(itnim
->fcs
, event
);
235 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
236 enum bfa_fcs_itnim_event event
)
238 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
239 bfa_trc(itnim
->fcs
, event
);
242 case BFA_FCS_ITNIM_SM_TIMEOUT
:
243 if (itnim
->prli_retries
< BFA_FCS_RPORT_MAX_RETRIES
) {
244 itnim
->prli_retries
++;
245 bfa_trc(itnim
->fcs
, itnim
->prli_retries
);
246 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
247 bfa_fcs_itnim_send_prli(itnim
, NULL
);
249 /* invoke target offline */
250 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
251 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
256 case BFA_FCS_ITNIM_SM_OFFLINE
:
257 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
258 bfa_timer_stop(&itnim
->timer
);
259 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
262 case BFA_FCS_ITNIM_SM_INITIATOR
:
263 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
264 bfa_timer_stop(&itnim
->timer
);
265 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
268 case BFA_FCS_ITNIM_SM_DELETE
:
269 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
270 bfa_timer_stop(&itnim
->timer
);
271 bfa_fcs_itnim_free(itnim
);
275 bfa_sm_fault(itnim
->fcs
, event
);
280 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
281 enum bfa_fcs_itnim_event event
)
283 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
284 char lpwwn_buf
[BFA_STRING_32
];
285 char rpwwn_buf
[BFA_STRING_32
];
287 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
288 bfa_trc(itnim
->fcs
, event
);
291 case BFA_FCS_ITNIM_SM_HCB_ONLINE
:
292 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_online
);
293 bfa_fcb_itnim_online(itnim
->itnim_drv
);
294 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
295 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
296 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
297 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
298 rpwwn_buf
, lpwwn_buf
);
299 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_ONLINE
);
302 case BFA_FCS_ITNIM_SM_OFFLINE
:
303 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
304 bfa_itnim_offline(itnim
->bfa_itnim
);
307 case BFA_FCS_ITNIM_SM_DELETE
:
308 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
309 bfa_fcs_itnim_free(itnim
);
313 bfa_sm_fault(itnim
->fcs
, event
);
318 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
319 enum bfa_fcs_itnim_event event
)
321 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
322 char lpwwn_buf
[BFA_STRING_32
];
323 char rpwwn_buf
[BFA_STRING_32
];
325 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
326 bfa_trc(itnim
->fcs
, event
);
329 case BFA_FCS_ITNIM_SM_OFFLINE
:
330 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
331 bfa_fcb_itnim_offline(itnim
->itnim_drv
);
332 bfa_itnim_offline(itnim
->bfa_itnim
);
333 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
334 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
335 if (bfa_fcs_lport_is_online(itnim
->rport
->port
) == BFA_TRUE
) {
336 BFA_LOG(KERN_ERR
, bfad
, bfa_log_level
,
337 "Target (WWN = %s) connectivity lost for "
338 "initiator (WWN = %s)\n", rpwwn_buf
, lpwwn_buf
);
339 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_DISCONNECT
);
341 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
342 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
343 rpwwn_buf
, lpwwn_buf
);
344 bfa_fcs_itnim_aen_post(itnim
, BFA_ITNIM_AEN_OFFLINE
);
348 case BFA_FCS_ITNIM_SM_DELETE
:
349 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
350 bfa_fcs_itnim_free(itnim
);
354 bfa_sm_fault(itnim
->fcs
, event
);
359 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
360 enum bfa_fcs_itnim_event event
)
362 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
363 bfa_trc(itnim
->fcs
, event
);
366 case BFA_FCS_ITNIM_SM_HCB_OFFLINE
:
367 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
368 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
371 case BFA_FCS_ITNIM_SM_DELETE
:
372 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
373 bfa_fcs_itnim_free(itnim
);
377 bfa_sm_fault(itnim
->fcs
, event
);
382 * This state is set when a discovered rport is also in intiator mode.
383 * This ITN is marked as no_op and is not active and will not be truned into
387 bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
388 enum bfa_fcs_itnim_event event
)
390 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
391 bfa_trc(itnim
->fcs
, event
);
394 case BFA_FCS_ITNIM_SM_OFFLINE
:
395 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
396 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
400 * fcs_online is expected here for well known initiator ports
402 case BFA_FCS_ITNIM_SM_FCS_ONLINE
:
403 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_FCS_ONLINE
);
406 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
407 case BFA_FCS_ITNIM_SM_INITIATOR
:
410 case BFA_FCS_ITNIM_SM_DELETE
:
411 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
412 bfa_fcs_itnim_free(itnim
);
416 bfa_sm_fault(itnim
->fcs
, event
);
421 bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s
*itnim
,
422 enum bfa_itnim_aen_event event
)
424 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
425 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
426 struct bfa_aen_entry_s
*aen_entry
;
428 /* Don't post events for well known addresses */
429 if (BFA_FCS_PID_IS_WKA(rport
->pid
))
432 bfad_get_aen_entry(bfad
, aen_entry
);
436 aen_entry
->aen_data
.itnim
.vf_id
= rport
->port
->fabric
->vf_id
;
437 aen_entry
->aen_data
.itnim
.ppwwn
= bfa_fcs_lport_get_pwwn(
438 bfa_fcs_get_base_port(itnim
->fcs
));
439 aen_entry
->aen_data
.itnim
.lpwwn
= bfa_fcs_lport_get_pwwn(rport
->port
);
440 aen_entry
->aen_data
.itnim
.rpwwn
= rport
->pwwn
;
442 /* Send the AEN notification */
443 bfad_im_post_vendor_event(aen_entry
, bfad
, ++rport
->fcs
->fcs_aen_seq
,
444 BFA_AEN_CAT_ITNIM
, event
);
448 bfa_fcs_itnim_send_prli(void *itnim_cbarg
, struct bfa_fcxp_s
*fcxp_alloced
)
450 struct bfa_fcs_itnim_s
*itnim
= itnim_cbarg
;
451 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
452 struct bfa_fcs_lport_s
*port
= rport
->port
;
454 struct bfa_fcxp_s
*fcxp
;
457 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
459 fcxp
= fcxp_alloced
? fcxp_alloced
:
460 bfa_fcs_fcxp_alloc(port
->fcs
, BFA_TRUE
);
462 itnim
->stats
.fcxp_alloc_wait
++;
463 bfa_fcs_fcxp_alloc_wait(port
->fcs
->bfa
, &itnim
->fcxp_wqe
,
464 bfa_fcs_itnim_send_prli
, itnim
, BFA_TRUE
);
469 len
= fc_prli_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
470 itnim
->rport
->pid
, bfa_fcs_lport_get_fcid(port
), 0);
472 bfa_fcxp_send(fcxp
, rport
->bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
473 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
,
474 bfa_fcs_itnim_prli_response
, (void *)itnim
,
475 FC_MAX_PDUSZ
, FC_ELS_TOV
);
477 itnim
->stats
.prli_sent
++;
478 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_FRMSENT
);
482 bfa_fcs_itnim_prli_response(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
483 bfa_status_t req_status
, u32 rsp_len
,
484 u32 resid_len
, struct fchs_s
*rsp_fchs
)
486 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
487 struct fc_els_cmd_s
*els_cmd
;
488 struct fc_prli_s
*prli_resp
;
489 struct fc_ls_rjt_s
*ls_rjt
;
490 struct fc_prli_params_s
*sparams
;
492 bfa_trc(itnim
->fcs
, req_status
);
497 if (req_status
!= BFA_STATUS_OK
) {
498 itnim
->stats
.prli_rsp_err
++;
499 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
503 els_cmd
= (struct fc_els_cmd_s
*) BFA_FCXP_RSP_PLD(fcxp
);
505 if (els_cmd
->els_code
== FC_ELS_ACC
) {
506 prli_resp
= (struct fc_prli_s
*) els_cmd
;
508 if (fc_prli_rsp_parse(prli_resp
, rsp_len
) != FC_PARSE_OK
) {
509 bfa_trc(itnim
->fcs
, rsp_len
);
511 * Check if this r-port is also in Initiator mode.
512 * If so, we need to set this ITN as a no-op.
514 if (prli_resp
->parampage
.servparams
.initiator
) {
515 bfa_trc(itnim
->fcs
, prli_resp
->parampage
.type
);
516 itnim
->rport
->scsi_function
=
518 itnim
->stats
.prli_rsp_acc
++;
519 itnim
->stats
.initiator
++;
520 bfa_sm_send_event(itnim
,
521 BFA_FCS_ITNIM_SM_RSP_OK
);
525 itnim
->stats
.prli_rsp_parse_err
++;
528 itnim
->rport
->scsi_function
= BFA_RPORT_TARGET
;
530 sparams
= &prli_resp
->parampage
.servparams
;
531 itnim
->seq_rec
= sparams
->retry
;
532 itnim
->rec_support
= sparams
->rec_support
;
533 itnim
->task_retry_id
= sparams
->task_retry_id
;
534 itnim
->conf_comp
= sparams
->confirm
;
536 itnim
->stats
.prli_rsp_acc
++;
537 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_OK
);
539 ls_rjt
= (struct fc_ls_rjt_s
*) BFA_FCXP_RSP_PLD(fcxp
);
541 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code
);
542 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code_expl
);
544 itnim
->stats
.prli_rsp_rjt
++;
545 if (ls_rjt
->reason_code
== FC_LS_RJT_RSN_CMD_NOT_SUPP
) {
546 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP
);
549 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
554 bfa_fcs_itnim_timeout(void *arg
)
556 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) arg
;
558 itnim
->stats
.timeout
++;
559 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_TIMEOUT
);
563 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
)
565 if (itnim
->bfa_itnim
) {
566 bfa_itnim_delete(itnim
->bfa_itnim
);
567 itnim
->bfa_itnim
= NULL
;
570 bfa_fcb_itnim_free(itnim
->fcs
->bfad
, itnim
->itnim_drv
);
576 * itnim_public FCS ITNIM public interfaces
580 * Called by rport when a new rport is created.
582 * @param[in] rport - remote port.
584 struct bfa_fcs_itnim_s
*
585 bfa_fcs_itnim_create(struct bfa_fcs_rport_s
*rport
)
587 struct bfa_fcs_lport_s
*port
= rport
->port
;
588 struct bfa_fcs_itnim_s
*itnim
;
589 struct bfad_itnim_s
*itnim_drv
;
592 * call bfad to allocate the itnim
594 bfa_fcb_itnim_alloc(port
->fcs
->bfad
, &itnim
, &itnim_drv
);
596 bfa_trc(port
->fcs
, rport
->pwwn
);
603 itnim
->rport
= rport
;
604 itnim
->fcs
= rport
->fcs
;
605 itnim
->itnim_drv
= itnim_drv
;
607 itnim
->bfa_itnim
= NULL
;
608 itnim
->seq_rec
= BFA_FALSE
;
609 itnim
->rec_support
= BFA_FALSE
;
610 itnim
->conf_comp
= BFA_FALSE
;
611 itnim
->task_retry_id
= BFA_FALSE
;
616 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
622 * Called by rport to delete the instance of FCPIM.
624 * @param[in] rport - remote port.
627 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s
*itnim
)
629 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
630 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_DELETE
);
634 * Notification from rport that PLOGI is complete to initiate FC-4 session.
637 bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s
*itnim
)
639 itnim
->stats
.onlines
++;
641 if (!BFA_FCS_PID_IS_WKA(itnim
->rport
->pid
))
642 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HAL_ONLINE
);
646 * Called by rport to handle a remote device offline.
649 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s
*itnim
)
651 itnim
->stats
.offlines
++;
652 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_OFFLINE
);
656 * Called by rport when remote port is known to be an initiator from
660 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s
*itnim
)
662 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
663 itnim
->stats
.initiator
++;
664 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
668 * Called by rport to check if the itnim is online.
671 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s
*itnim
)
673 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
674 switch (bfa_sm_to_state(itnim_sm_table
, itnim
->sm
)) {
675 case BFA_ITNIM_ONLINE
:
676 case BFA_ITNIM_INITIATIOR
:
677 return BFA_STATUS_OK
;
680 return BFA_STATUS_NO_FCPIM_NEXUS
;
685 * BFA completion callback for bfa_itnim_online().
688 bfa_cb_itnim_online(void *cbarg
)
690 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
692 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
693 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_ONLINE
);
697 * BFA completion callback for bfa_itnim_offline().
700 bfa_cb_itnim_offline(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
);
705 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_OFFLINE
);
709 * Mark the beginning of PATH TOV handling. IO completion callbacks
713 bfa_cb_itnim_tov_begin(void *cb_arg
)
715 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
717 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
721 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
724 bfa_cb_itnim_tov(void *cb_arg
)
726 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
727 struct bfad_itnim_s
*itnim_drv
= itnim
->itnim_drv
;
729 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
730 itnim_drv
->state
= ITNIM_STATE_TIMEOUT
;
734 * BFA notification to FCS/driver for second level error recovery.
736 * Atleast one I/O request has timedout and target is unresponsive to
737 * repeated abort requests. Second level error recovery should be initiated
738 * by starting implicit logout and recovery procedures.
741 bfa_cb_itnim_sler(void *cb_arg
)
743 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
746 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
747 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
750 struct bfa_fcs_itnim_s
*
751 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
753 struct bfa_fcs_rport_s
*rport
;
754 rport
= bfa_fcs_rport_lookup(port
, rpwwn
);
759 WARN_ON(rport
->itnim
== NULL
);
764 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
765 struct bfa_itnim_attr_s
*attr
)
767 struct bfa_fcs_itnim_s
*itnim
= NULL
;
769 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
772 return BFA_STATUS_NO_FCPIM_NEXUS
;
774 attr
->state
= bfa_sm_to_state(itnim_sm_table
, itnim
->sm
);
775 attr
->retry
= itnim
->seq_rec
;
776 attr
->rec_support
= itnim
->rec_support
;
777 attr
->conf_comp
= itnim
->conf_comp
;
778 attr
->task_retry_id
= itnim
->task_retry_id
;
779 return BFA_STATUS_OK
;
783 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
784 struct bfa_itnim_stats_s
*stats
)
786 struct bfa_fcs_itnim_s
*itnim
= NULL
;
788 WARN_ON(port
== NULL
);
790 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
793 return BFA_STATUS_NO_FCPIM_NEXUS
;
795 memcpy(stats
, &itnim
->stats
, sizeof(struct bfa_itnim_stats_s
));
797 return BFA_STATUS_OK
;
801 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
803 struct bfa_fcs_itnim_s
*itnim
= NULL
;
805 WARN_ON(port
== NULL
);
807 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
810 return BFA_STATUS_NO_FCPIM_NEXUS
;
812 memset(&itnim
->stats
, 0, sizeof(struct bfa_itnim_stats_s
));
813 return BFA_STATUS_OK
;
817 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s
*itnim
,
818 struct fchs_s
*fchs
, u16 len
)
820 struct fc_els_cmd_s
*els_cmd
;
822 bfa_trc(itnim
->fcs
, fchs
->type
);
824 if (fchs
->type
!= FC_TYPE_ELS
)
827 els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
829 bfa_trc(itnim
->fcs
, els_cmd
->els_code
);
831 switch (els_cmd
->els_code
) {
833 bfa_fcs_rport_prlo(itnim
->rport
, fchs
->ox_id
);