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
);
42 * fcs_itnim_sm FCS itnim state machine events
45 enum bfa_fcs_itnim_event
{
46 BFA_FCS_ITNIM_SM_ONLINE
= 1, /* rport online event */
47 BFA_FCS_ITNIM_SM_OFFLINE
= 2, /* rport offline */
48 BFA_FCS_ITNIM_SM_FRMSENT
= 3, /* prli frame is sent */
49 BFA_FCS_ITNIM_SM_RSP_OK
= 4, /* good response */
50 BFA_FCS_ITNIM_SM_RSP_ERROR
= 5, /* error response */
51 BFA_FCS_ITNIM_SM_TIMEOUT
= 6, /* delay timeout */
52 BFA_FCS_ITNIM_SM_HCB_OFFLINE
= 7, /* BFA online callback */
53 BFA_FCS_ITNIM_SM_HCB_ONLINE
= 8, /* BFA offline callback */
54 BFA_FCS_ITNIM_SM_INITIATOR
= 9, /* rport is initiator */
55 BFA_FCS_ITNIM_SM_DELETE
= 10, /* delete event from rport */
56 BFA_FCS_ITNIM_SM_PRLO
= 11, /* delete event from rport */
59 static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
60 enum bfa_fcs_itnim_event event
);
61 static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
62 enum bfa_fcs_itnim_event event
);
63 static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
64 enum bfa_fcs_itnim_event event
);
65 static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
66 enum bfa_fcs_itnim_event event
);
67 static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
68 enum bfa_fcs_itnim_event event
);
69 static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
70 enum bfa_fcs_itnim_event event
);
71 static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
72 enum bfa_fcs_itnim_event event
);
73 static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s
*itnim
,
74 enum bfa_fcs_itnim_event event
);
76 static struct bfa_sm_table_s itnim_sm_table
[] = {
77 {BFA_SM(bfa_fcs_itnim_sm_offline
), BFA_ITNIM_OFFLINE
},
78 {BFA_SM(bfa_fcs_itnim_sm_prli_send
), BFA_ITNIM_PRLI_SEND
},
79 {BFA_SM(bfa_fcs_itnim_sm_prli
), BFA_ITNIM_PRLI_SENT
},
80 {BFA_SM(bfa_fcs_itnim_sm_prli_retry
), BFA_ITNIM_PRLI_RETRY
},
81 {BFA_SM(bfa_fcs_itnim_sm_hcb_online
), BFA_ITNIM_HCB_ONLINE
},
82 {BFA_SM(bfa_fcs_itnim_sm_online
), BFA_ITNIM_ONLINE
},
83 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline
), BFA_ITNIM_HCB_OFFLINE
},
84 {BFA_SM(bfa_fcs_itnim_sm_initiator
), BFA_ITNIM_INITIATIOR
},
88 * fcs_itnim_sm FCS itnim state machine
92 bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s
*itnim
,
93 enum bfa_fcs_itnim_event event
)
95 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
96 bfa_trc(itnim
->fcs
, event
);
99 case BFA_FCS_ITNIM_SM_ONLINE
:
100 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
101 itnim
->prli_retries
= 0;
102 bfa_fcs_itnim_send_prli(itnim
, NULL
);
105 case BFA_FCS_ITNIM_SM_OFFLINE
:
106 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
109 case BFA_FCS_ITNIM_SM_INITIATOR
:
110 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
113 case BFA_FCS_ITNIM_SM_DELETE
:
114 bfa_fcs_itnim_free(itnim
);
118 bfa_sm_fault(itnim
->fcs
, event
);
124 bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s
*itnim
,
125 enum bfa_fcs_itnim_event event
)
127 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
128 bfa_trc(itnim
->fcs
, event
);
131 case BFA_FCS_ITNIM_SM_FRMSENT
:
132 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli
);
135 case BFA_FCS_ITNIM_SM_INITIATOR
:
136 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
137 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
140 case BFA_FCS_ITNIM_SM_OFFLINE
:
141 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
142 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
143 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
146 case BFA_FCS_ITNIM_SM_DELETE
:
147 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
148 bfa_fcxp_walloc_cancel(itnim
->fcs
->bfa
, &itnim
->fcxp_wqe
);
149 bfa_fcs_itnim_free(itnim
);
153 bfa_sm_fault(itnim
->fcs
, event
);
158 bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s
*itnim
,
159 enum bfa_fcs_itnim_event event
)
161 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
162 bfa_trc(itnim
->fcs
, event
);
165 case BFA_FCS_ITNIM_SM_RSP_OK
:
166 if (itnim
->rport
->scsi_function
== BFA_RPORT_INITIATOR
) {
167 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
169 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_online
);
170 bfa_itnim_online(itnim
->bfa_itnim
, itnim
->seq_rec
);
174 case BFA_FCS_ITNIM_SM_RSP_ERROR
:
175 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_retry
);
176 bfa_timer_start(itnim
->fcs
->bfa
, &itnim
->timer
,
177 bfa_fcs_itnim_timeout
, itnim
,
178 BFA_FCS_RETRY_TIMEOUT
);
181 case BFA_FCS_ITNIM_SM_OFFLINE
:
182 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
183 bfa_fcxp_discard(itnim
->fcxp
);
184 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
187 case BFA_FCS_ITNIM_SM_INITIATOR
:
188 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
189 bfa_fcxp_discard(itnim
->fcxp
);
192 case BFA_FCS_ITNIM_SM_DELETE
:
193 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
194 bfa_fcxp_discard(itnim
->fcxp
);
195 bfa_fcs_itnim_free(itnim
);
199 bfa_sm_fault(itnim
->fcs
, event
);
204 bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s
*itnim
,
205 enum bfa_fcs_itnim_event event
)
207 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
208 bfa_trc(itnim
->fcs
, event
);
211 case BFA_FCS_ITNIM_SM_TIMEOUT
:
212 if (itnim
->prli_retries
< BFA_FCS_RPORT_MAX_RETRIES
) {
213 itnim
->prli_retries
++;
214 bfa_trc(itnim
->fcs
, itnim
->prli_retries
);
215 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_prli_send
);
216 bfa_fcs_itnim_send_prli(itnim
, NULL
);
218 /* invoke target offline */
219 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
220 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
225 case BFA_FCS_ITNIM_SM_OFFLINE
:
226 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
227 bfa_timer_stop(&itnim
->timer
);
228 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
231 case BFA_FCS_ITNIM_SM_INITIATOR
:
232 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_initiator
);
233 bfa_timer_stop(&itnim
->timer
);
236 case BFA_FCS_ITNIM_SM_DELETE
:
237 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
238 bfa_timer_stop(&itnim
->timer
);
239 bfa_fcs_itnim_free(itnim
);
243 bfa_sm_fault(itnim
->fcs
, event
);
248 bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s
*itnim
,
249 enum bfa_fcs_itnim_event event
)
251 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
252 char lpwwn_buf
[BFA_STRING_32
];
253 char rpwwn_buf
[BFA_STRING_32
];
255 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
256 bfa_trc(itnim
->fcs
, event
);
259 case BFA_FCS_ITNIM_SM_HCB_ONLINE
:
260 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_online
);
261 bfa_fcb_itnim_online(itnim
->itnim_drv
);
262 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
263 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
264 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
265 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
266 rpwwn_buf
, lpwwn_buf
);
269 case BFA_FCS_ITNIM_SM_OFFLINE
:
270 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
271 bfa_itnim_offline(itnim
->bfa_itnim
);
272 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
275 case BFA_FCS_ITNIM_SM_DELETE
:
276 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
277 bfa_fcs_itnim_free(itnim
);
281 bfa_sm_fault(itnim
->fcs
, event
);
286 bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s
*itnim
,
287 enum bfa_fcs_itnim_event event
)
289 struct bfad_s
*bfad
= (struct bfad_s
*)itnim
->fcs
->bfad
;
290 char lpwwn_buf
[BFA_STRING_32
];
291 char rpwwn_buf
[BFA_STRING_32
];
293 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
294 bfa_trc(itnim
->fcs
, event
);
297 case BFA_FCS_ITNIM_SM_OFFLINE
:
298 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_hcb_offline
);
299 bfa_fcb_itnim_offline(itnim
->itnim_drv
);
300 bfa_itnim_offline(itnim
->bfa_itnim
);
301 wwn2str(lpwwn_buf
, bfa_fcs_lport_get_pwwn(itnim
->rport
->port
));
302 wwn2str(rpwwn_buf
, itnim
->rport
->pwwn
);
303 if (bfa_fcs_lport_is_online(itnim
->rport
->port
) == BFA_TRUE
)
304 BFA_LOG(KERN_ERR
, bfad
, bfa_log_level
,
305 "Target (WWN = %s) connectivity lost for "
306 "initiator (WWN = %s)\n", rpwwn_buf
, lpwwn_buf
);
308 BFA_LOG(KERN_INFO
, bfad
, bfa_log_level
,
309 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
310 rpwwn_buf
, lpwwn_buf
);
313 case BFA_FCS_ITNIM_SM_DELETE
:
314 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
315 bfa_fcs_itnim_free(itnim
);
319 bfa_sm_fault(itnim
->fcs
, event
);
324 bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s
*itnim
,
325 enum bfa_fcs_itnim_event event
)
327 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
328 bfa_trc(itnim
->fcs
, event
);
331 case BFA_FCS_ITNIM_SM_HCB_OFFLINE
:
332 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
333 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_FC4_OFFLINE
);
336 case BFA_FCS_ITNIM_SM_DELETE
:
337 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
338 bfa_fcs_itnim_free(itnim
);
342 bfa_sm_fault(itnim
->fcs
, event
);
347 * This state is set when a discovered rport is also in intiator mode.
348 * This ITN is marked as no_op and is not active and will not be truned into
352 bfa_fcs_itnim_sm_initiator(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_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_RSP_ERROR
:
365 case BFA_FCS_ITNIM_SM_ONLINE
:
366 case BFA_FCS_ITNIM_SM_INITIATOR
:
369 case BFA_FCS_ITNIM_SM_DELETE
:
370 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
371 bfa_fcs_itnim_free(itnim
);
375 bfa_sm_fault(itnim
->fcs
, event
);
380 bfa_fcs_itnim_send_prli(void *itnim_cbarg
, struct bfa_fcxp_s
*fcxp_alloced
)
382 struct bfa_fcs_itnim_s
*itnim
= itnim_cbarg
;
383 struct bfa_fcs_rport_s
*rport
= itnim
->rport
;
384 struct bfa_fcs_lport_s
*port
= rport
->port
;
386 struct bfa_fcxp_s
*fcxp
;
389 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
391 fcxp
= fcxp_alloced
? fcxp_alloced
: bfa_fcs_fcxp_alloc(port
->fcs
);
393 itnim
->stats
.fcxp_alloc_wait
++;
394 bfa_fcs_fcxp_alloc_wait(port
->fcs
->bfa
, &itnim
->fcxp_wqe
,
395 bfa_fcs_itnim_send_prli
, itnim
);
400 len
= fc_prli_build(&fchs
, bfa_fcxp_get_reqbuf(fcxp
),
401 itnim
->rport
->pid
, bfa_fcs_lport_get_fcid(port
), 0);
403 bfa_fcxp_send(fcxp
, rport
->bfa_rport
, port
->fabric
->vf_id
, port
->lp_tag
,
404 BFA_FALSE
, FC_CLASS_3
, len
, &fchs
,
405 bfa_fcs_itnim_prli_response
, (void *)itnim
,
406 FC_MAX_PDUSZ
, FC_ELS_TOV
);
408 itnim
->stats
.prli_sent
++;
409 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_FRMSENT
);
413 bfa_fcs_itnim_prli_response(void *fcsarg
, struct bfa_fcxp_s
*fcxp
, void *cbarg
,
414 bfa_status_t req_status
, u32 rsp_len
,
415 u32 resid_len
, struct fchs_s
*rsp_fchs
)
417 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
418 struct fc_els_cmd_s
*els_cmd
;
419 struct fc_prli_s
*prli_resp
;
420 struct fc_ls_rjt_s
*ls_rjt
;
421 struct fc_prli_params_s
*sparams
;
423 bfa_trc(itnim
->fcs
, req_status
);
428 if (req_status
!= BFA_STATUS_OK
) {
429 itnim
->stats
.prli_rsp_err
++;
430 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
434 els_cmd
= (struct fc_els_cmd_s
*) BFA_FCXP_RSP_PLD(fcxp
);
436 if (els_cmd
->els_code
== FC_ELS_ACC
) {
437 prli_resp
= (struct fc_prli_s
*) els_cmd
;
439 if (fc_prli_rsp_parse(prli_resp
, rsp_len
) != FC_PARSE_OK
) {
440 bfa_trc(itnim
->fcs
, rsp_len
);
442 * Check if this r-port is also in Initiator mode.
443 * If so, we need to set this ITN as a no-op.
445 if (prli_resp
->parampage
.servparams
.initiator
) {
446 bfa_trc(itnim
->fcs
, prli_resp
->parampage
.type
);
447 itnim
->rport
->scsi_function
=
449 itnim
->stats
.prli_rsp_acc
++;
450 bfa_sm_send_event(itnim
,
451 BFA_FCS_ITNIM_SM_RSP_OK
);
455 itnim
->stats
.prli_rsp_parse_err
++;
458 itnim
->rport
->scsi_function
= BFA_RPORT_TARGET
;
460 sparams
= &prli_resp
->parampage
.servparams
;
461 itnim
->seq_rec
= sparams
->retry
;
462 itnim
->rec_support
= sparams
->rec_support
;
463 itnim
->task_retry_id
= sparams
->task_retry_id
;
464 itnim
->conf_comp
= sparams
->confirm
;
466 itnim
->stats
.prli_rsp_acc
++;
467 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_OK
);
469 ls_rjt
= (struct fc_ls_rjt_s
*) BFA_FCXP_RSP_PLD(fcxp
);
471 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code
);
472 bfa_trc(itnim
->fcs
, ls_rjt
->reason_code_expl
);
474 itnim
->stats
.prli_rsp_rjt
++;
475 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_RSP_ERROR
);
480 bfa_fcs_itnim_timeout(void *arg
)
482 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) arg
;
484 itnim
->stats
.timeout
++;
485 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_TIMEOUT
);
489 bfa_fcs_itnim_free(struct bfa_fcs_itnim_s
*itnim
)
491 bfa_itnim_delete(itnim
->bfa_itnim
);
492 bfa_fcb_itnim_free(itnim
->fcs
->bfad
, itnim
->itnim_drv
);
498 * itnim_public FCS ITNIM public interfaces
502 * Called by rport when a new rport is created.
504 * @param[in] rport - remote port.
506 struct bfa_fcs_itnim_s
*
507 bfa_fcs_itnim_create(struct bfa_fcs_rport_s
*rport
)
509 struct bfa_fcs_lport_s
*port
= rport
->port
;
510 struct bfa_fcs_itnim_s
*itnim
;
511 struct bfad_itnim_s
*itnim_drv
;
512 struct bfa_itnim_s
*bfa_itnim
;
515 * call bfad to allocate the itnim
517 bfa_fcb_itnim_alloc(port
->fcs
->bfad
, &itnim
, &itnim_drv
);
519 bfa_trc(port
->fcs
, rport
->pwwn
);
526 itnim
->rport
= rport
;
527 itnim
->fcs
= rport
->fcs
;
528 itnim
->itnim_drv
= itnim_drv
;
531 * call BFA to create the itnim
534 bfa_itnim_create(port
->fcs
->bfa
, rport
->bfa_rport
, itnim
);
536 if (bfa_itnim
== NULL
) {
537 bfa_trc(port
->fcs
, rport
->pwwn
);
538 bfa_fcb_itnim_free(port
->fcs
->bfad
, itnim_drv
);
543 itnim
->bfa_itnim
= bfa_itnim
;
544 itnim
->seq_rec
= BFA_FALSE
;
545 itnim
->rec_support
= BFA_FALSE
;
546 itnim
->conf_comp
= BFA_FALSE
;
547 itnim
->task_retry_id
= BFA_FALSE
;
552 bfa_sm_set_state(itnim
, bfa_fcs_itnim_sm_offline
);
558 * Called by rport to delete the instance of FCPIM.
560 * @param[in] rport - remote port.
563 bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s
*itnim
)
565 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
566 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_DELETE
);
570 * Notification from rport that PLOGI is complete to initiate FC-4 session.
573 bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s
*itnim
)
575 itnim
->stats
.onlines
++;
577 if (!BFA_FCS_PID_IS_WKA(itnim
->rport
->pid
)) {
578 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_ONLINE
);
581 * For well known addresses, we set the itnim to initiator
584 itnim
->stats
.initiator
++;
585 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
590 * Called by rport to handle a remote device offline.
593 bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s
*itnim
)
595 itnim
->stats
.offlines
++;
596 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_OFFLINE
);
600 * Called by rport when remote port is known to be an initiator from
604 bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s
*itnim
)
606 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
607 itnim
->stats
.initiator
++;
608 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_INITIATOR
);
612 * Called by rport to check if the itnim is online.
615 bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s
*itnim
)
617 bfa_trc(itnim
->fcs
, itnim
->rport
->pid
);
618 switch (bfa_sm_to_state(itnim_sm_table
, itnim
->sm
)) {
619 case BFA_ITNIM_ONLINE
:
620 case BFA_ITNIM_INITIATIOR
:
621 return BFA_STATUS_OK
;
624 return BFA_STATUS_NO_FCPIM_NEXUS
;
629 * BFA completion callback for bfa_itnim_online().
632 bfa_cb_itnim_online(void *cbarg
)
634 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cbarg
;
636 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
637 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_ONLINE
);
641 * BFA completion callback for bfa_itnim_offline().
644 bfa_cb_itnim_offline(void *cb_arg
)
646 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
648 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
649 bfa_sm_send_event(itnim
, BFA_FCS_ITNIM_SM_HCB_OFFLINE
);
653 * Mark the beginning of PATH TOV handling. IO completion callbacks
657 bfa_cb_itnim_tov_begin(void *cb_arg
)
659 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
661 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
665 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
668 bfa_cb_itnim_tov(void *cb_arg
)
670 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
671 struct bfad_itnim_s
*itnim_drv
= itnim
->itnim_drv
;
673 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
674 itnim_drv
->state
= ITNIM_STATE_TIMEOUT
;
678 * BFA notification to FCS/driver for second level error recovery.
680 * Atleast one I/O request has timedout and target is unresponsive to
681 * repeated abort requests. Second level error recovery should be initiated
682 * by starting implicit logout and recovery procedures.
685 bfa_cb_itnim_sler(void *cb_arg
)
687 struct bfa_fcs_itnim_s
*itnim
= (struct bfa_fcs_itnim_s
*) cb_arg
;
690 bfa_trc(itnim
->fcs
, itnim
->rport
->pwwn
);
691 bfa_sm_send_event(itnim
->rport
, RPSM_EVENT_LOGO_IMP
);
694 struct bfa_fcs_itnim_s
*
695 bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
697 struct bfa_fcs_rport_s
*rport
;
698 rport
= bfa_fcs_rport_lookup(port
, rpwwn
);
703 WARN_ON(rport
->itnim
== NULL
);
708 bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
709 struct bfa_itnim_attr_s
*attr
)
711 struct bfa_fcs_itnim_s
*itnim
= NULL
;
713 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
716 return BFA_STATUS_NO_FCPIM_NEXUS
;
718 attr
->state
= bfa_sm_to_state(itnim_sm_table
, itnim
->sm
);
719 attr
->retry
= itnim
->seq_rec
;
720 attr
->rec_support
= itnim
->rec_support
;
721 attr
->conf_comp
= itnim
->conf_comp
;
722 attr
->task_retry_id
= itnim
->task_retry_id
;
723 return BFA_STATUS_OK
;
727 bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
,
728 struct bfa_itnim_stats_s
*stats
)
730 struct bfa_fcs_itnim_s
*itnim
= NULL
;
732 WARN_ON(port
== NULL
);
734 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
737 return BFA_STATUS_NO_FCPIM_NEXUS
;
739 memcpy(stats
, &itnim
->stats
, sizeof(struct bfa_itnim_stats_s
));
741 return BFA_STATUS_OK
;
745 bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s
*port
, wwn_t rpwwn
)
747 struct bfa_fcs_itnim_s
*itnim
= NULL
;
749 WARN_ON(port
== NULL
);
751 itnim
= bfa_fcs_itnim_lookup(port
, rpwwn
);
754 return BFA_STATUS_NO_FCPIM_NEXUS
;
756 memset(&itnim
->stats
, 0, sizeof(struct bfa_itnim_stats_s
));
757 return BFA_STATUS_OK
;
761 bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s
*itnim
,
762 struct fchs_s
*fchs
, u16 len
)
764 struct fc_els_cmd_s
*els_cmd
;
766 bfa_trc(itnim
->fcs
, fchs
->type
);
768 if (fchs
->type
!= FC_TYPE_ELS
)
771 els_cmd
= (struct fc_els_cmd_s
*) (fchs
+ 1);
773 bfa_trc(itnim
->fcs
, els_cmd
->els_code
);
775 switch (els_cmd
->els_code
) {
777 bfa_fcs_rport_prlo(itnim
->rport
, fchs
->ox_id
);