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