xref: /OK3568_Linux_fs/kernel/drivers/scsi/bfa/bfa_fcs_fcpim.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
4*4882a593Smuzhiyun  * Copyright (c) 2014- QLogic Corporation.
5*4882a593Smuzhiyun  * All rights reserved
6*4882a593Smuzhiyun  * www.qlogic.com
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun /*
12*4882a593Smuzhiyun  *  fcpim.c - FCP initiator mode i-t nexus state machine
13*4882a593Smuzhiyun  */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include "bfad_drv.h"
16*4882a593Smuzhiyun #include "bfa_fcs.h"
17*4882a593Smuzhiyun #include "bfa_fcbuild.h"
18*4882a593Smuzhiyun #include "bfad_im.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun BFA_TRC_FILE(FCS, FCPIM);
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /*
23*4882a593Smuzhiyun  * forward declarations
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun static void	bfa_fcs_itnim_timeout(void *arg);
26*4882a593Smuzhiyun static void	bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
27*4882a593Smuzhiyun static void	bfa_fcs_itnim_send_prli(void *itnim_cbarg,
28*4882a593Smuzhiyun 					struct bfa_fcxp_s *fcxp_alloced);
29*4882a593Smuzhiyun static void	bfa_fcs_itnim_prli_response(void *fcsarg,
30*4882a593Smuzhiyun 			 struct bfa_fcxp_s *fcxp, void *cbarg,
31*4882a593Smuzhiyun 			    bfa_status_t req_status, u32 rsp_len,
32*4882a593Smuzhiyun 			    u32 resid_len, struct fchs_s *rsp_fchs);
33*4882a593Smuzhiyun static void	bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
34*4882a593Smuzhiyun 			enum bfa_itnim_aen_event event);
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
37*4882a593Smuzhiyun 					 enum bfa_fcs_itnim_event event);
38*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
39*4882a593Smuzhiyun 					   enum bfa_fcs_itnim_event event);
40*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
41*4882a593Smuzhiyun 				      enum bfa_fcs_itnim_event event);
42*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
43*4882a593Smuzhiyun 					    enum bfa_fcs_itnim_event event);
44*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
45*4882a593Smuzhiyun 					    enum bfa_fcs_itnim_event event);
46*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
47*4882a593Smuzhiyun 					enum bfa_fcs_itnim_event event);
48*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
49*4882a593Smuzhiyun 					enum bfa_fcs_itnim_event event);
50*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
51*4882a593Smuzhiyun 					     enum bfa_fcs_itnim_event event);
52*4882a593Smuzhiyun static void	bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
53*4882a593Smuzhiyun 					   enum bfa_fcs_itnim_event event);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun static struct bfa_sm_table_s itnim_sm_table[] = {
56*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
57*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
58*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
59*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
60*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
61*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
62*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
63*4882a593Smuzhiyun 	{BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun  *  fcs_itnim_sm FCS itnim state machine
68*4882a593Smuzhiyun  */
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)71*4882a593Smuzhiyun bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
72*4882a593Smuzhiyun 		 enum bfa_fcs_itnim_event event)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
75*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	switch (event) {
78*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_FCS_ONLINE:
79*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
80*4882a593Smuzhiyun 		itnim->prli_retries = 0;
81*4882a593Smuzhiyun 		bfa_fcs_itnim_send_prli(itnim, NULL);
82*4882a593Smuzhiyun 		break;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
85*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
86*4882a593Smuzhiyun 		break;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_INITIATOR:
89*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
90*4882a593Smuzhiyun 		break;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
93*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
94*4882a593Smuzhiyun 		break;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	default:
97*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
98*4882a593Smuzhiyun 	}
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)103*4882a593Smuzhiyun bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
104*4882a593Smuzhiyun 		 enum bfa_fcs_itnim_event event)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
107*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	switch (event) {
110*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_FRMSENT:
111*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
112*4882a593Smuzhiyun 		break;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_INITIATOR:
115*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
116*4882a593Smuzhiyun 		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
117*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
118*4882a593Smuzhiyun 		break;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
121*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
122*4882a593Smuzhiyun 		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
123*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
124*4882a593Smuzhiyun 		break;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
127*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
128*4882a593Smuzhiyun 		bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
129*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
130*4882a593Smuzhiyun 		break;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	default:
133*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
134*4882a593Smuzhiyun 	}
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)138*4882a593Smuzhiyun bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
139*4882a593Smuzhiyun 		 enum bfa_fcs_itnim_event event)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
142*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	switch (event) {
145*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_RSP_OK:
146*4882a593Smuzhiyun 		if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR)
147*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
148*4882a593Smuzhiyun 		else
149*4882a593Smuzhiyun 			bfa_sm_set_state(itnim,
150*4882a593Smuzhiyun 				bfa_fcs_itnim_sm_hal_rport_online);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
153*4882a593Smuzhiyun 		break;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_RSP_ERROR:
156*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
157*4882a593Smuzhiyun 		bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
158*4882a593Smuzhiyun 				bfa_fcs_itnim_timeout, itnim,
159*4882a593Smuzhiyun 				BFA_FCS_RETRY_TIMEOUT);
160*4882a593Smuzhiyun 		break;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
163*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
164*4882a593Smuzhiyun 		break;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
167*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
168*4882a593Smuzhiyun 		bfa_fcxp_discard(itnim->fcxp);
169*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
170*4882a593Smuzhiyun 		break;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_INITIATOR:
173*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
174*4882a593Smuzhiyun 		bfa_fcxp_discard(itnim->fcxp);
175*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
176*4882a593Smuzhiyun 		break;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
179*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
180*4882a593Smuzhiyun 		bfa_fcxp_discard(itnim->fcxp);
181*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
182*4882a593Smuzhiyun 		break;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	default:
185*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)190*4882a593Smuzhiyun bfa_fcs_itnim_sm_hal_rport_online(struct bfa_fcs_itnim_s *itnim,
191*4882a593Smuzhiyun 				enum bfa_fcs_itnim_event event)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
194*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	switch (event) {
197*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_HAL_ONLINE:
198*4882a593Smuzhiyun 		if (!itnim->bfa_itnim)
199*4882a593Smuzhiyun 			itnim->bfa_itnim = bfa_itnim_create(itnim->fcs->bfa,
200*4882a593Smuzhiyun 					itnim->rport->bfa_rport, itnim);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 		if (itnim->bfa_itnim) {
203*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
204*4882a593Smuzhiyun 			bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
205*4882a593Smuzhiyun 		} else {
206*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
207*4882a593Smuzhiyun 			bfa_sm_send_event(itnim->rport, RPSM_EVENT_DELETE);
208*4882a593Smuzhiyun 		}
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		break;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
213*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
214*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
215*4882a593Smuzhiyun 		break;
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
218*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
219*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
220*4882a593Smuzhiyun 		break;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	default:
223*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)228*4882a593Smuzhiyun bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
229*4882a593Smuzhiyun 			    enum bfa_fcs_itnim_event event)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
232*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	switch (event) {
235*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_TIMEOUT:
236*4882a593Smuzhiyun 		if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
237*4882a593Smuzhiyun 			itnim->prli_retries++;
238*4882a593Smuzhiyun 			bfa_trc(itnim->fcs, itnim->prli_retries);
239*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
240*4882a593Smuzhiyun 			bfa_fcs_itnim_send_prli(itnim, NULL);
241*4882a593Smuzhiyun 		} else {
242*4882a593Smuzhiyun 			/* invoke target offline */
243*4882a593Smuzhiyun 			bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
244*4882a593Smuzhiyun 			bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
245*4882a593Smuzhiyun 		}
246*4882a593Smuzhiyun 		break;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
250*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
251*4882a593Smuzhiyun 		bfa_timer_stop(&itnim->timer);
252*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
253*4882a593Smuzhiyun 		break;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_INITIATOR:
256*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
257*4882a593Smuzhiyun 		bfa_timer_stop(&itnim->timer);
258*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
259*4882a593Smuzhiyun 		break;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
262*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
263*4882a593Smuzhiyun 		bfa_timer_stop(&itnim->timer);
264*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
265*4882a593Smuzhiyun 		break;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	default:
268*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)273*4882a593Smuzhiyun bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
274*4882a593Smuzhiyun 			    enum bfa_fcs_itnim_event event)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
277*4882a593Smuzhiyun 	char	lpwwn_buf[BFA_STRING_32];
278*4882a593Smuzhiyun 	char	rpwwn_buf[BFA_STRING_32];
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
281*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	switch (event) {
284*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_HCB_ONLINE:
285*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
286*4882a593Smuzhiyun 		bfa_fcb_itnim_online(itnim->itnim_drv);
287*4882a593Smuzhiyun 		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
288*4882a593Smuzhiyun 		wwn2str(rpwwn_buf, itnim->rport->pwwn);
289*4882a593Smuzhiyun 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
290*4882a593Smuzhiyun 		"Target (WWN = %s) is online for initiator (WWN = %s)\n",
291*4882a593Smuzhiyun 		rpwwn_buf, lpwwn_buf);
292*4882a593Smuzhiyun 		bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE);
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
296*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
297*4882a593Smuzhiyun 		bfa_itnim_offline(itnim->bfa_itnim);
298*4882a593Smuzhiyun 		break;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
301*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
302*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
303*4882a593Smuzhiyun 		break;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	default:
306*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)311*4882a593Smuzhiyun bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
312*4882a593Smuzhiyun 		 enum bfa_fcs_itnim_event event)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
315*4882a593Smuzhiyun 	char	lpwwn_buf[BFA_STRING_32];
316*4882a593Smuzhiyun 	char	rpwwn_buf[BFA_STRING_32];
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
319*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	switch (event) {
322*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
323*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
324*4882a593Smuzhiyun 		bfa_fcb_itnim_offline(itnim->itnim_drv);
325*4882a593Smuzhiyun 		bfa_itnim_offline(itnim->bfa_itnim);
326*4882a593Smuzhiyun 		wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
327*4882a593Smuzhiyun 		wwn2str(rpwwn_buf, itnim->rport->pwwn);
328*4882a593Smuzhiyun 		if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE) {
329*4882a593Smuzhiyun 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
330*4882a593Smuzhiyun 			"Target (WWN = %s) connectivity lost for "
331*4882a593Smuzhiyun 			"initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
332*4882a593Smuzhiyun 			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT);
333*4882a593Smuzhiyun 		} else {
334*4882a593Smuzhiyun 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
335*4882a593Smuzhiyun 			"Target (WWN = %s) offlined by initiator (WWN = %s)\n",
336*4882a593Smuzhiyun 			rpwwn_buf, lpwwn_buf);
337*4882a593Smuzhiyun 			bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE);
338*4882a593Smuzhiyun 		}
339*4882a593Smuzhiyun 		break;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
342*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
343*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
344*4882a593Smuzhiyun 		break;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	default:
347*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
348*4882a593Smuzhiyun 	}
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)352*4882a593Smuzhiyun bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
353*4882a593Smuzhiyun 			     enum bfa_fcs_itnim_event event)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
356*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	switch (event) {
359*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
360*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
361*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
362*4882a593Smuzhiyun 		break;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
365*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
366*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
367*4882a593Smuzhiyun 		break;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	default:
370*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
371*4882a593Smuzhiyun 	}
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun /*
375*4882a593Smuzhiyun  * This state is set when a discovered rport is also in intiator mode.
376*4882a593Smuzhiyun  * This ITN is marked as no_op and is not active and will not be truned into
377*4882a593Smuzhiyun  * online state.
378*4882a593Smuzhiyun  */
379*4882a593Smuzhiyun static void
bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s * itnim,enum bfa_fcs_itnim_event event)380*4882a593Smuzhiyun bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
381*4882a593Smuzhiyun 		 enum bfa_fcs_itnim_event event)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
384*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, event);
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	switch (event) {
387*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_OFFLINE:
388*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
389*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
390*4882a593Smuzhiyun 		break;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	/*
393*4882a593Smuzhiyun 	 * fcs_online is expected here for well known initiator ports
394*4882a593Smuzhiyun 	 */
395*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_FCS_ONLINE:
396*4882a593Smuzhiyun 		bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_FCS_ONLINE);
397*4882a593Smuzhiyun 		break;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_RSP_ERROR:
400*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_INITIATOR:
401*4882a593Smuzhiyun 		break;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	case BFA_FCS_ITNIM_SM_DELETE:
404*4882a593Smuzhiyun 		bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
405*4882a593Smuzhiyun 		bfa_fcs_itnim_free(itnim);
406*4882a593Smuzhiyun 		break;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	default:
409*4882a593Smuzhiyun 		bfa_sm_fault(itnim->fcs, event);
410*4882a593Smuzhiyun 	}
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun static void
bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s * itnim,enum bfa_itnim_aen_event event)414*4882a593Smuzhiyun bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim,
415*4882a593Smuzhiyun 			enum bfa_itnim_aen_event event)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun 	struct bfa_fcs_rport_s *rport = itnim->rport;
418*4882a593Smuzhiyun 	struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
419*4882a593Smuzhiyun 	struct bfa_aen_entry_s	*aen_entry;
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	/* Don't post events for well known addresses */
422*4882a593Smuzhiyun 	if (BFA_FCS_PID_IS_WKA(rport->pid))
423*4882a593Smuzhiyun 		return;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	bfad_get_aen_entry(bfad, aen_entry);
426*4882a593Smuzhiyun 	if (!aen_entry)
427*4882a593Smuzhiyun 		return;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	aen_entry->aen_data.itnim.vf_id = rport->port->fabric->vf_id;
430*4882a593Smuzhiyun 	aen_entry->aen_data.itnim.ppwwn = bfa_fcs_lport_get_pwwn(
431*4882a593Smuzhiyun 					bfa_fcs_get_base_port(itnim->fcs));
432*4882a593Smuzhiyun 	aen_entry->aen_data.itnim.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
433*4882a593Smuzhiyun 	aen_entry->aen_data.itnim.rpwwn = rport->pwwn;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	/* Send the AEN notification */
436*4882a593Smuzhiyun 	bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
437*4882a593Smuzhiyun 				  BFA_AEN_CAT_ITNIM, event);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun static void
bfa_fcs_itnim_send_prli(void * itnim_cbarg,struct bfa_fcxp_s * fcxp_alloced)441*4882a593Smuzhiyun bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
444*4882a593Smuzhiyun 	struct bfa_fcs_rport_s *rport = itnim->rport;
445*4882a593Smuzhiyun 	struct bfa_fcs_lport_s *port = rport->port;
446*4882a593Smuzhiyun 	struct fchs_s	fchs;
447*4882a593Smuzhiyun 	struct bfa_fcxp_s *fcxp;
448*4882a593Smuzhiyun 	int		len;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	fcxp = fcxp_alloced ? fcxp_alloced :
453*4882a593Smuzhiyun 	       bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
454*4882a593Smuzhiyun 	if (!fcxp) {
455*4882a593Smuzhiyun 		itnim->stats.fcxp_alloc_wait++;
456*4882a593Smuzhiyun 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
457*4882a593Smuzhiyun 				bfa_fcs_itnim_send_prli, itnim, BFA_TRUE);
458*4882a593Smuzhiyun 		return;
459*4882a593Smuzhiyun 	}
460*4882a593Smuzhiyun 	itnim->fcxp = fcxp;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
463*4882a593Smuzhiyun 			    itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
466*4882a593Smuzhiyun 		      BFA_FALSE, FC_CLASS_3, len, &fchs,
467*4882a593Smuzhiyun 		      bfa_fcs_itnim_prli_response, (void *)itnim,
468*4882a593Smuzhiyun 		      FC_MAX_PDUSZ, FC_ELS_TOV);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	itnim->stats.prli_sent++;
471*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun static void
bfa_fcs_itnim_prli_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)475*4882a593Smuzhiyun bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
476*4882a593Smuzhiyun 			    bfa_status_t req_status, u32 rsp_len,
477*4882a593Smuzhiyun 			    u32 resid_len, struct fchs_s *rsp_fchs)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
480*4882a593Smuzhiyun 	struct fc_els_cmd_s *els_cmd;
481*4882a593Smuzhiyun 	struct fc_prli_s *prli_resp;
482*4882a593Smuzhiyun 	struct fc_ls_rjt_s *ls_rjt;
483*4882a593Smuzhiyun 	struct fc_prli_params_s *sparams;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, req_status);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	/*
488*4882a593Smuzhiyun 	 * Sanity Checks
489*4882a593Smuzhiyun 	 */
490*4882a593Smuzhiyun 	if (req_status != BFA_STATUS_OK) {
491*4882a593Smuzhiyun 		itnim->stats.prli_rsp_err++;
492*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
493*4882a593Smuzhiyun 		return;
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	if (els_cmd->els_code == FC_ELS_ACC) {
499*4882a593Smuzhiyun 		prli_resp = (struct fc_prli_s *) els_cmd;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 		if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
502*4882a593Smuzhiyun 			bfa_trc(itnim->fcs, rsp_len);
503*4882a593Smuzhiyun 			/*
504*4882a593Smuzhiyun 			 * Check if this  r-port is also in Initiator mode.
505*4882a593Smuzhiyun 			 * If so, we need to set this ITN as a no-op.
506*4882a593Smuzhiyun 			 */
507*4882a593Smuzhiyun 			if (prli_resp->parampage.servparams.initiator) {
508*4882a593Smuzhiyun 				bfa_trc(itnim->fcs, prli_resp->parampage.type);
509*4882a593Smuzhiyun 				itnim->rport->scsi_function =
510*4882a593Smuzhiyun 						BFA_RPORT_INITIATOR;
511*4882a593Smuzhiyun 				itnim->stats.prli_rsp_acc++;
512*4882a593Smuzhiyun 				itnim->stats.initiator++;
513*4882a593Smuzhiyun 				bfa_sm_send_event(itnim,
514*4882a593Smuzhiyun 						  BFA_FCS_ITNIM_SM_RSP_OK);
515*4882a593Smuzhiyun 				return;
516*4882a593Smuzhiyun 			}
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 			itnim->stats.prli_rsp_parse_err++;
519*4882a593Smuzhiyun 			return;
520*4882a593Smuzhiyun 		}
521*4882a593Smuzhiyun 		itnim->rport->scsi_function = BFA_RPORT_TARGET;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 		sparams = &prli_resp->parampage.servparams;
524*4882a593Smuzhiyun 		itnim->seq_rec	     = sparams->retry;
525*4882a593Smuzhiyun 		itnim->rec_support   = sparams->rec_support;
526*4882a593Smuzhiyun 		itnim->task_retry_id = sparams->task_retry_id;
527*4882a593Smuzhiyun 		itnim->conf_comp     = sparams->confirm;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 		itnim->stats.prli_rsp_acc++;
530*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
531*4882a593Smuzhiyun 	} else {
532*4882a593Smuzhiyun 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 		bfa_trc(itnim->fcs, ls_rjt->reason_code);
535*4882a593Smuzhiyun 		bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		itnim->stats.prli_rsp_rjt++;
538*4882a593Smuzhiyun 		if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
539*4882a593Smuzhiyun 			bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
540*4882a593Smuzhiyun 			return;
541*4882a593Smuzhiyun 		}
542*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static void
bfa_fcs_itnim_timeout(void * arg)547*4882a593Smuzhiyun bfa_fcs_itnim_timeout(void *arg)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	itnim->stats.timeout++;
552*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun static void
bfa_fcs_itnim_free(struct bfa_fcs_itnim_s * itnim)556*4882a593Smuzhiyun bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 	if (itnim->bfa_itnim) {
559*4882a593Smuzhiyun 		bfa_itnim_delete(itnim->bfa_itnim);
560*4882a593Smuzhiyun 		itnim->bfa_itnim = NULL;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun /*
569*4882a593Smuzhiyun  *  itnim_public FCS ITNIM public interfaces
570*4882a593Smuzhiyun  */
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun /*
573*4882a593Smuzhiyun  *	Called by rport when a new rport is created.
574*4882a593Smuzhiyun  *
575*4882a593Smuzhiyun  * @param[in] rport	-  remote port.
576*4882a593Smuzhiyun  */
577*4882a593Smuzhiyun struct bfa_fcs_itnim_s *
bfa_fcs_itnim_create(struct bfa_fcs_rport_s * rport)578*4882a593Smuzhiyun bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	struct bfa_fcs_lport_s *port = rport->port;
581*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim;
582*4882a593Smuzhiyun 	struct bfad_itnim_s   *itnim_drv;
583*4882a593Smuzhiyun 	int ret;
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	/*
586*4882a593Smuzhiyun 	 * call bfad to allocate the itnim
587*4882a593Smuzhiyun 	 */
588*4882a593Smuzhiyun 	ret = bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
589*4882a593Smuzhiyun 	if (ret) {
590*4882a593Smuzhiyun 		bfa_trc(port->fcs, rport->pwwn);
591*4882a593Smuzhiyun 		return NULL;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	/*
595*4882a593Smuzhiyun 	 * Initialize itnim
596*4882a593Smuzhiyun 	 */
597*4882a593Smuzhiyun 	itnim->rport = rport;
598*4882a593Smuzhiyun 	itnim->fcs = rport->fcs;
599*4882a593Smuzhiyun 	itnim->itnim_drv = itnim_drv;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	itnim->bfa_itnim     = NULL;
602*4882a593Smuzhiyun 	itnim->seq_rec	     = BFA_FALSE;
603*4882a593Smuzhiyun 	itnim->rec_support   = BFA_FALSE;
604*4882a593Smuzhiyun 	itnim->conf_comp     = BFA_FALSE;
605*4882a593Smuzhiyun 	itnim->task_retry_id = BFA_FALSE;
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	/*
608*4882a593Smuzhiyun 	 * Set State machine
609*4882a593Smuzhiyun 	 */
610*4882a593Smuzhiyun 	bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	return itnim;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun /*
616*4882a593Smuzhiyun  *	Called by rport to delete  the instance of FCPIM.
617*4882a593Smuzhiyun  *
618*4882a593Smuzhiyun  * @param[in] rport	-  remote port.
619*4882a593Smuzhiyun  */
620*4882a593Smuzhiyun void
bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s * itnim)621*4882a593Smuzhiyun bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pid);
624*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun /*
628*4882a593Smuzhiyun  * Notification from rport that PLOGI is complete to initiate FC-4 session.
629*4882a593Smuzhiyun  */
630*4882a593Smuzhiyun void
bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s * itnim)631*4882a593Smuzhiyun bfa_fcs_itnim_brp_online(struct bfa_fcs_itnim_s *itnim)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	itnim->stats.onlines++;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid))
636*4882a593Smuzhiyun 		bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HAL_ONLINE);
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun /*
640*4882a593Smuzhiyun  * Called by rport to handle a remote device offline.
641*4882a593Smuzhiyun  */
642*4882a593Smuzhiyun void
bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s * itnim)643*4882a593Smuzhiyun bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun 	itnim->stats.offlines++;
646*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun /*
650*4882a593Smuzhiyun  * Called by rport when remote port is known to be an initiator from
651*4882a593Smuzhiyun  * PRLI received.
652*4882a593Smuzhiyun  */
653*4882a593Smuzhiyun void
bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s * itnim)654*4882a593Smuzhiyun bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pid);
657*4882a593Smuzhiyun 	itnim->stats.initiator++;
658*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun /*
662*4882a593Smuzhiyun  * Called by rport to check if the itnim is online.
663*4882a593Smuzhiyun  */
664*4882a593Smuzhiyun bfa_status_t
bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s * itnim)665*4882a593Smuzhiyun bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pid);
668*4882a593Smuzhiyun 	switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
669*4882a593Smuzhiyun 	case BFA_ITNIM_ONLINE:
670*4882a593Smuzhiyun 	case BFA_ITNIM_INITIATIOR:
671*4882a593Smuzhiyun 		return BFA_STATUS_OK;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	default:
674*4882a593Smuzhiyun 		return BFA_STATUS_NO_FCPIM_NEXUS;
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun /*
679*4882a593Smuzhiyun  * BFA completion callback for bfa_itnim_online().
680*4882a593Smuzhiyun  */
681*4882a593Smuzhiyun void
bfa_cb_itnim_online(void * cbarg)682*4882a593Smuzhiyun bfa_cb_itnim_online(void *cbarg)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
687*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun /*
691*4882a593Smuzhiyun  * BFA completion callback for bfa_itnim_offline().
692*4882a593Smuzhiyun  */
693*4882a593Smuzhiyun void
bfa_cb_itnim_offline(void * cb_arg)694*4882a593Smuzhiyun bfa_cb_itnim_offline(void *cb_arg)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
699*4882a593Smuzhiyun 	bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun /*
703*4882a593Smuzhiyun  * Mark the beginning of PATH TOV handling. IO completion callbacks
704*4882a593Smuzhiyun  * are still pending.
705*4882a593Smuzhiyun  */
706*4882a593Smuzhiyun void
bfa_cb_itnim_tov_begin(void * cb_arg)707*4882a593Smuzhiyun bfa_cb_itnim_tov_begin(void *cb_arg)
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun /*
715*4882a593Smuzhiyun  * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
716*4882a593Smuzhiyun  */
717*4882a593Smuzhiyun void
bfa_cb_itnim_tov(void * cb_arg)718*4882a593Smuzhiyun bfa_cb_itnim_tov(void *cb_arg)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
721*4882a593Smuzhiyun 	struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
724*4882a593Smuzhiyun 	itnim_drv->state = ITNIM_STATE_TIMEOUT;
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun /*
728*4882a593Smuzhiyun  *		BFA notification to FCS/driver for second level error recovery.
729*4882a593Smuzhiyun  *
730*4882a593Smuzhiyun  * Atleast one I/O request has timedout and target is unresponsive to
731*4882a593Smuzhiyun  * repeated abort requests. Second level error recovery should be initiated
732*4882a593Smuzhiyun  * by starting implicit logout and recovery procedures.
733*4882a593Smuzhiyun  */
734*4882a593Smuzhiyun void
bfa_cb_itnim_sler(void * cb_arg)735*4882a593Smuzhiyun bfa_cb_itnim_sler(void *cb_arg)
736*4882a593Smuzhiyun {
737*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	itnim->stats.sler++;
740*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, itnim->rport->pwwn);
741*4882a593Smuzhiyun 	bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun struct bfa_fcs_itnim_s *
bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s * port,wwn_t rpwwn)745*4882a593Smuzhiyun bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun 	struct bfa_fcs_rport_s *rport;
748*4882a593Smuzhiyun 	rport = bfa_fcs_rport_lookup(port, rpwwn);
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	if (!rport)
751*4882a593Smuzhiyun 		return NULL;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	WARN_ON(rport->itnim == NULL);
754*4882a593Smuzhiyun 	return rport->itnim;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun bfa_status_t
bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s * port,wwn_t rpwwn,struct bfa_itnim_attr_s * attr)758*4882a593Smuzhiyun bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
759*4882a593Smuzhiyun 		       struct bfa_itnim_attr_s *attr)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = NULL;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	if (itnim == NULL)
766*4882a593Smuzhiyun 		return BFA_STATUS_NO_FCPIM_NEXUS;
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	attr->state	    = bfa_sm_to_state(itnim_sm_table, itnim->sm);
769*4882a593Smuzhiyun 	attr->retry	    = itnim->seq_rec;
770*4882a593Smuzhiyun 	attr->rec_support   = itnim->rec_support;
771*4882a593Smuzhiyun 	attr->conf_comp	    = itnim->conf_comp;
772*4882a593Smuzhiyun 	attr->task_retry_id = itnim->task_retry_id;
773*4882a593Smuzhiyun 	return BFA_STATUS_OK;
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun bfa_status_t
bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s * port,wwn_t rpwwn,struct bfa_itnim_stats_s * stats)777*4882a593Smuzhiyun bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
778*4882a593Smuzhiyun 			struct bfa_itnim_stats_s *stats)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = NULL;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	WARN_ON(port == NULL);
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	if (itnim == NULL)
787*4882a593Smuzhiyun 		return BFA_STATUS_NO_FCPIM_NEXUS;
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	return BFA_STATUS_OK;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun bfa_status_t
bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s * port,wwn_t rpwwn)795*4882a593Smuzhiyun bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun 	struct bfa_fcs_itnim_s *itnim = NULL;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	WARN_ON(port == NULL);
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	itnim = bfa_fcs_itnim_lookup(port, rpwwn);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	if (itnim == NULL)
804*4882a593Smuzhiyun 		return BFA_STATUS_NO_FCPIM_NEXUS;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
807*4882a593Smuzhiyun 	return BFA_STATUS_OK;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun void
bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s * itnim,struct fchs_s * fchs,u16 len)811*4882a593Smuzhiyun bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
812*4882a593Smuzhiyun 			struct fchs_s *fchs, u16 len)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun 	struct fc_els_cmd_s *els_cmd;
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, fchs->type);
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun 	if (fchs->type != FC_TYPE_ELS)
819*4882a593Smuzhiyun 		return;
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	bfa_trc(itnim->fcs, els_cmd->els_code);
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	switch (els_cmd->els_code) {
826*4882a593Smuzhiyun 	case FC_ELS_PRLO:
827*4882a593Smuzhiyun 		bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
828*4882a593Smuzhiyun 		break;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	default:
831*4882a593Smuzhiyun 		WARN_ON(1);
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun }
834