blob: 29b4108be269f337dca6ea9e6def5d392b6db979 [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Jing Huang7725ccf2009-09-23 17:46:15 -07003 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
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
11 *
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.
16 */
17
Jing Huang5fbe25c2010-10-18 17:17:23 -070018/*
Jing Huang7725ccf2009-09-23 17:46:15 -070019 * fcpim.c - FCP initiator mode i-t nexus state machine
20 */
21
Maggie Zhangf16a1752010-12-09 19:12:32 -080022#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070023#include "bfa_fcs.h"
24#include "bfa_fcbuild.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070025#include "bfad_im.h"
Jing Huang7725ccf2009-09-23 17:46:15 -070026
27BFA_TRC_FILE(FCS, FCPIM);
28
29/*
30 * forward declarations
31 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070032static void bfa_fcs_itnim_timeout(void *arg);
33static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
34static void bfa_fcs_itnim_send_prli(void *itnim_cbarg,
Jing Huang7725ccf2009-09-23 17:46:15 -070035 struct bfa_fcxp_s *fcxp_alloced);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070036static 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);
Jing Huang7725ccf2009-09-23 17:46:15 -070040
Jing Huang5fbe25c2010-10-18 17:17:23 -070041/*
Jing Huang7725ccf2009-09-23 17:46:15 -070042 * fcs_itnim_sm FCS itnim state machine events
43 */
44
45enum 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 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070052 BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
53 BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
Jing Huang7725ccf2009-09-23 17:46:15 -070054 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 */
Krishna Gudipatid7be54c2011-06-24 20:24:52 -070057 BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
Jing Huang7725ccf2009-09-23 17:46:15 -070058};
59
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070060static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070061 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070062static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070063 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070064static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070065 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070066static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070067 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070068static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070069 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070070static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070071 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070072static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070073 enum bfa_fcs_itnim_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070074static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
Jing Huang7725ccf2009-09-23 17:46:15 -070075 enum bfa_fcs_itnim_event event);
76
77static struct bfa_sm_table_s itnim_sm_table[] = {
78 {BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
79 {BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
80 {BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
81 {BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
82 {BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
83 {BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
84 {BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
85 {BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
86};
87
Jing Huang5fbe25c2010-10-18 17:17:23 -070088/*
Jing Huang7725ccf2009-09-23 17:46:15 -070089 * fcs_itnim_sm FCS itnim state machine
90 */
91
92static void
93bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070094 enum bfa_fcs_itnim_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -070095{
96 bfa_trc(itnim->fcs, itnim->rport->pwwn);
97 bfa_trc(itnim->fcs, event);
98
99 switch (event) {
100 case BFA_FCS_ITNIM_SM_ONLINE:
101 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
Jing Huang41188cf2010-07-08 19:52:00 -0700102 itnim->prli_retries = 0;
Jing Huang7725ccf2009-09-23 17:46:15 -0700103 bfa_fcs_itnim_send_prli(itnim, NULL);
104 break;
105
106 case BFA_FCS_ITNIM_SM_OFFLINE:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800107 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700108 break;
109
110 case BFA_FCS_ITNIM_SM_INITIATOR:
111 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
112 break;
113
114 case BFA_FCS_ITNIM_SM_DELETE:
115 bfa_fcs_itnim_free(itnim);
116 break;
117
118 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800119 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700120 }
121
122}
123
124static void
125bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700126 enum bfa_fcs_itnim_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700127{
128 bfa_trc(itnim->fcs, itnim->rport->pwwn);
129 bfa_trc(itnim->fcs, event);
130
131 switch (event) {
132 case BFA_FCS_ITNIM_SM_FRMSENT:
133 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
134 break;
135
136 case BFA_FCS_ITNIM_SM_INITIATOR:
137 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
138 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
139 break;
140
141 case BFA_FCS_ITNIM_SM_OFFLINE:
142 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
143 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800144 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700145 break;
146
147 case BFA_FCS_ITNIM_SM_DELETE:
148 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
149 bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
150 bfa_fcs_itnim_free(itnim);
151 break;
152
153 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800154 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700155 }
156}
157
158static void
159bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700160 enum bfa_fcs_itnim_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700161{
162 bfa_trc(itnim->fcs, itnim->rport->pwwn);
163 bfa_trc(itnim->fcs, event);
164
165 switch (event) {
166 case BFA_FCS_ITNIM_SM_RSP_OK:
Jing Huang4b5e7592010-07-08 19:55:41 -0700167 if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) {
168 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
169 } else {
170 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
171 bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
172 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700173 break;
174
175 case BFA_FCS_ITNIM_SM_RSP_ERROR:
176 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
177 bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
178 bfa_fcs_itnim_timeout, itnim,
179 BFA_FCS_RETRY_TIMEOUT);
180 break;
181
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700182 case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
183 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
184 break;
185
Jing Huang7725ccf2009-09-23 17:46:15 -0700186 case BFA_FCS_ITNIM_SM_OFFLINE:
187 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
188 bfa_fcxp_discard(itnim->fcxp);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800189 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700190 break;
191
192 case BFA_FCS_ITNIM_SM_INITIATOR:
193 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
Jing Huang4b5e7592010-07-08 19:55:41 -0700194 bfa_fcxp_discard(itnim->fcxp);
Jing Huang7725ccf2009-09-23 17:46:15 -0700195 break;
196
197 case BFA_FCS_ITNIM_SM_DELETE:
198 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
199 bfa_fcxp_discard(itnim->fcxp);
200 bfa_fcs_itnim_free(itnim);
201 break;
202
203 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800204 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700205 }
206}
207
208static void
209bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
210 enum bfa_fcs_itnim_event event)
211{
212 bfa_trc(itnim->fcs, itnim->rport->pwwn);
213 bfa_trc(itnim->fcs, event);
214
215 switch (event) {
216 case BFA_FCS_ITNIM_SM_TIMEOUT:
Jing Huang41188cf2010-07-08 19:52:00 -0700217 if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
218 itnim->prli_retries++;
219 bfa_trc(itnim->fcs, itnim->prli_retries);
220 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
221 bfa_fcs_itnim_send_prli(itnim, NULL);
222 } else {
223 /* invoke target offline */
224 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800225 bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
Jing Huang41188cf2010-07-08 19:52:00 -0700226 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700227 break;
228
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700229
Jing Huang7725ccf2009-09-23 17:46:15 -0700230 case BFA_FCS_ITNIM_SM_OFFLINE:
231 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
232 bfa_timer_stop(&itnim->timer);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800233 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700234 break;
235
236 case BFA_FCS_ITNIM_SM_INITIATOR:
237 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
238 bfa_timer_stop(&itnim->timer);
239 break;
240
241 case BFA_FCS_ITNIM_SM_DELETE:
242 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
243 bfa_timer_stop(&itnim->timer);
244 bfa_fcs_itnim_free(itnim);
245 break;
246
247 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800248 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700249 }
250}
251
252static void
253bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
254 enum bfa_fcs_itnim_event event)
255{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700256 struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
257 char lpwwn_buf[BFA_STRING_32];
258 char rpwwn_buf[BFA_STRING_32];
259
Jing Huang7725ccf2009-09-23 17:46:15 -0700260 bfa_trc(itnim->fcs, itnim->rport->pwwn);
261 bfa_trc(itnim->fcs, event);
262
263 switch (event) {
264 case BFA_FCS_ITNIM_SM_HCB_ONLINE:
265 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
266 bfa_fcb_itnim_online(itnim->itnim_drv);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700267 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
268 wwn2str(rpwwn_buf, itnim->rport->pwwn);
Jing Huang88166242010-12-09 17:11:53 -0800269 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700270 "Target (WWN = %s) is online for initiator (WWN = %s)\n",
271 rpwwn_buf, lpwwn_buf);
Jing Huang7725ccf2009-09-23 17:46:15 -0700272 break;
273
274 case BFA_FCS_ITNIM_SM_OFFLINE:
275 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
276 bfa_itnim_offline(itnim->bfa_itnim);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800277 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700278 break;
279
280 case BFA_FCS_ITNIM_SM_DELETE:
281 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
282 bfa_fcs_itnim_free(itnim);
283 break;
284
285 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800286 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700287 }
288}
289
290static void
291bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700292 enum bfa_fcs_itnim_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700293{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700294 struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
295 char lpwwn_buf[BFA_STRING_32];
296 char rpwwn_buf[BFA_STRING_32];
297
Jing Huang7725ccf2009-09-23 17:46:15 -0700298 bfa_trc(itnim->fcs, itnim->rport->pwwn);
299 bfa_trc(itnim->fcs, event);
300
301 switch (event) {
302 case BFA_FCS_ITNIM_SM_OFFLINE:
303 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
304 bfa_fcb_itnim_offline(itnim->itnim_drv);
305 bfa_itnim_offline(itnim->bfa_itnim);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700306 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
307 wwn2str(rpwwn_buf, itnim->rport->pwwn);
308 if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
Jing Huang88166242010-12-09 17:11:53 -0800309 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700310 "Target (WWN = %s) connectivity lost for "
311 "initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700312 else
Jing Huang88166242010-12-09 17:11:53 -0800313 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700314 "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
315 rpwwn_buf, lpwwn_buf);
Jing Huang7725ccf2009-09-23 17:46:15 -0700316 break;
317
318 case BFA_FCS_ITNIM_SM_DELETE:
319 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
320 bfa_fcs_itnim_free(itnim);
321 break;
322
323 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800324 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700325 }
326}
327
328static void
329bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
330 enum bfa_fcs_itnim_event event)
331{
332 bfa_trc(itnim->fcs, itnim->rport->pwwn);
333 bfa_trc(itnim->fcs, event);
334
335 switch (event) {
336 case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
337 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800338 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700339 break;
340
341 case BFA_FCS_ITNIM_SM_DELETE:
342 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
343 bfa_fcs_itnim_free(itnim);
344 break;
345
346 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800347 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700348 }
349}
350
351/*
352 * This state is set when a discovered rport is also in intiator mode.
353 * This ITN is marked as no_op and is not active and will not be truned into
354 * online state.
355 */
356static void
357bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700358 enum bfa_fcs_itnim_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700359{
360 bfa_trc(itnim->fcs, itnim->rport->pwwn);
361 bfa_trc(itnim->fcs, event);
362
363 switch (event) {
364 case BFA_FCS_ITNIM_SM_OFFLINE:
365 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800366 bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700367 break;
368
369 case BFA_FCS_ITNIM_SM_RSP_ERROR:
370 case BFA_FCS_ITNIM_SM_ONLINE:
371 case BFA_FCS_ITNIM_SM_INITIATOR:
372 break;
373
374 case BFA_FCS_ITNIM_SM_DELETE:
375 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
376 bfa_fcs_itnim_free(itnim);
377 break;
378
379 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800380 bfa_sm_fault(itnim->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700381 }
382}
383
Jing Huang7725ccf2009-09-23 17:46:15 -0700384static void
385bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
386{
387 struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
388 struct bfa_fcs_rport_s *rport = itnim->rport;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700389 struct bfa_fcs_lport_s *port = rport->port;
390 struct fchs_s fchs;
Jing Huang7725ccf2009-09-23 17:46:15 -0700391 struct bfa_fcxp_s *fcxp;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700392 int len;
Jing Huang7725ccf2009-09-23 17:46:15 -0700393
394 bfa_trc(itnim->fcs, itnim->rport->pwwn);
395
396 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
397 if (!fcxp) {
398 itnim->stats.fcxp_alloc_wait++;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700399 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
Jing Huang7725ccf2009-09-23 17:46:15 -0700400 bfa_fcs_itnim_send_prli, itnim);
401 return;
402 }
403 itnim->fcxp = fcxp;
404
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700405 len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
406 itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700407
408 bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
409 BFA_FALSE, FC_CLASS_3, len, &fchs,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700410 bfa_fcs_itnim_prli_response, (void *)itnim,
411 FC_MAX_PDUSZ, FC_ELS_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -0700412
413 itnim->stats.prli_sent++;
414 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
415}
416
417static void
418bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
419 bfa_status_t req_status, u32 rsp_len,
420 u32 resid_len, struct fchs_s *rsp_fchs)
421{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700422 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
423 struct fc_els_cmd_s *els_cmd;
424 struct fc_prli_s *prli_resp;
425 struct fc_ls_rjt_s *ls_rjt;
Jing Huang7725ccf2009-09-23 17:46:15 -0700426 struct fc_prli_params_s *sparams;
427
428 bfa_trc(itnim->fcs, req_status);
429
430 /*
431 * Sanity Checks
432 */
433 if (req_status != BFA_STATUS_OK) {
434 itnim->stats.prli_rsp_err++;
435 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
436 return;
437 }
438
439 els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
440
441 if (els_cmd->els_code == FC_ELS_ACC) {
442 prli_resp = (struct fc_prli_s *) els_cmd;
443
444 if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
445 bfa_trc(itnim->fcs, rsp_len);
446 /*
447 * Check if this r-port is also in Initiator mode.
448 * If so, we need to set this ITN as a no-op.
449 */
450 if (prli_resp->parampage.servparams.initiator) {
451 bfa_trc(itnim->fcs, prli_resp->parampage.type);
452 itnim->rport->scsi_function =
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700453 BFA_RPORT_INITIATOR;
Jing Huang7725ccf2009-09-23 17:46:15 -0700454 itnim->stats.prli_rsp_acc++;
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700455 itnim->stats.initiator++;
Jing Huang7725ccf2009-09-23 17:46:15 -0700456 bfa_sm_send_event(itnim,
Jing Huang4b5e7592010-07-08 19:55:41 -0700457 BFA_FCS_ITNIM_SM_RSP_OK);
Jing Huang7725ccf2009-09-23 17:46:15 -0700458 return;
459 }
460
461 itnim->stats.prli_rsp_parse_err++;
462 return;
463 }
464 itnim->rport->scsi_function = BFA_RPORT_TARGET;
465
466 sparams = &prli_resp->parampage.servparams;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700467 itnim->seq_rec = sparams->retry;
468 itnim->rec_support = sparams->rec_support;
Jing Huang7725ccf2009-09-23 17:46:15 -0700469 itnim->task_retry_id = sparams->task_retry_id;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700470 itnim->conf_comp = sparams->confirm;
Jing Huang7725ccf2009-09-23 17:46:15 -0700471
472 itnim->stats.prli_rsp_acc++;
473 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
474 } else {
475 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
476
477 bfa_trc(itnim->fcs, ls_rjt->reason_code);
478 bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
479
480 itnim->stats.prli_rsp_rjt++;
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700481 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
482 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
483 return;
484 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700485 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
486 }
487}
488
489static void
490bfa_fcs_itnim_timeout(void *arg)
491{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700492 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700493
494 itnim->stats.timeout++;
495 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
496}
497
498static void
499bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
500{
501 bfa_itnim_delete(itnim->bfa_itnim);
502 bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
503}
504
505
506
Jing Huang5fbe25c2010-10-18 17:17:23 -0700507/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700508 * itnim_public FCS ITNIM public interfaces
509 */
510
Jing Huang5fbe25c2010-10-18 17:17:23 -0700511/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700512 * Called by rport when a new rport is created.
Jing Huang7725ccf2009-09-23 17:46:15 -0700513 *
514 * @param[in] rport - remote port.
515 */
516struct bfa_fcs_itnim_s *
517bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
518{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700519 struct bfa_fcs_lport_s *port = rport->port;
Jing Huang7725ccf2009-09-23 17:46:15 -0700520 struct bfa_fcs_itnim_s *itnim;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700521 struct bfad_itnim_s *itnim_drv;
Jing Huang7725ccf2009-09-23 17:46:15 -0700522 struct bfa_itnim_s *bfa_itnim;
523
524 /*
525 * call bfad to allocate the itnim
526 */
527 bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
528 if (itnim == NULL) {
529 bfa_trc(port->fcs, rport->pwwn);
530 return NULL;
531 }
532
533 /*
534 * Initialize itnim
535 */
536 itnim->rport = rport;
537 itnim->fcs = rport->fcs;
538 itnim->itnim_drv = itnim_drv;
539
540 /*
541 * call BFA to create the itnim
542 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700543 bfa_itnim =
544 bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
Jing Huang7725ccf2009-09-23 17:46:15 -0700545
546 if (bfa_itnim == NULL) {
547 bfa_trc(port->fcs, rport->pwwn);
548 bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
Jing Huangd4b671c2010-12-26 21:46:35 -0800549 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700550 return NULL;
551 }
552
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700553 itnim->bfa_itnim = bfa_itnim;
554 itnim->seq_rec = BFA_FALSE;
555 itnim->rec_support = BFA_FALSE;
556 itnim->conf_comp = BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -0700557 itnim->task_retry_id = BFA_FALSE;
558
559 /*
560 * Set State machine
561 */
562 bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
563
564 return itnim;
565}
566
Jing Huang5fbe25c2010-10-18 17:17:23 -0700567/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700568 * Called by rport to delete the instance of FCPIM.
Jing Huang7725ccf2009-09-23 17:46:15 -0700569 *
570 * @param[in] rport - remote port.
571 */
572void
573bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
574{
575 bfa_trc(itnim->fcs, itnim->rport->pid);
576 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
577}
578
Jing Huang5fbe25c2010-10-18 17:17:23 -0700579/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700580 * Notification from rport that PLOGI is complete to initiate FC-4 session.
581 */
582void
583bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
584{
585 itnim->stats.onlines++;
586
587 if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
588 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
589 } else {
590 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700591 * For well known addresses, we set the itnim to initiator
592 * state
Jing Huang7725ccf2009-09-23 17:46:15 -0700593 */
594 itnim->stats.initiator++;
595 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
596 }
597}
598
Jing Huang5fbe25c2010-10-18 17:17:23 -0700599/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700600 * Called by rport to handle a remote device offline.
601 */
602void
603bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
604{
605 itnim->stats.offlines++;
606 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
607}
608
Jing Huang5fbe25c2010-10-18 17:17:23 -0700609/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700610 * Called by rport when remote port is known to be an initiator from
611 * PRLI received.
612 */
613void
614bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
615{
616 bfa_trc(itnim->fcs, itnim->rport->pid);
617 itnim->stats.initiator++;
618 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
619}
620
Jing Huang5fbe25c2010-10-18 17:17:23 -0700621/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700622 * Called by rport to check if the itnim is online.
623 */
624bfa_status_t
625bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
626{
627 bfa_trc(itnim->fcs, itnim->rport->pid);
628 switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
629 case BFA_ITNIM_ONLINE:
630 case BFA_ITNIM_INITIATIOR:
631 return BFA_STATUS_OK;
632
633 default:
634 return BFA_STATUS_NO_FCPIM_NEXUS;
Jing Huang7725ccf2009-09-23 17:46:15 -0700635 }
636}
637
Jing Huang5fbe25c2010-10-18 17:17:23 -0700638/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700639 * BFA completion callback for bfa_itnim_online().
640 */
641void
642bfa_cb_itnim_online(void *cbarg)
643{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700644 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700645
646 bfa_trc(itnim->fcs, itnim->rport->pwwn);
647 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
648}
649
Jing Huang5fbe25c2010-10-18 17:17:23 -0700650/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700651 * BFA completion callback for bfa_itnim_offline().
652 */
653void
654bfa_cb_itnim_offline(void *cb_arg)
655{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700656 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700657
658 bfa_trc(itnim->fcs, itnim->rport->pwwn);
659 bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
660}
661
Jing Huang5fbe25c2010-10-18 17:17:23 -0700662/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700663 * Mark the beginning of PATH TOV handling. IO completion callbacks
664 * are still pending.
665 */
666void
667bfa_cb_itnim_tov_begin(void *cb_arg)
668{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700669 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700670
671 bfa_trc(itnim->fcs, itnim->rport->pwwn);
Jing Huang7725ccf2009-09-23 17:46:15 -0700672}
673
Jing Huang5fbe25c2010-10-18 17:17:23 -0700674/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700675 * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
676 */
677void
678bfa_cb_itnim_tov(void *cb_arg)
679{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700680 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
681 struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
Jing Huang7725ccf2009-09-23 17:46:15 -0700682
683 bfa_trc(itnim->fcs, itnim->rport->pwwn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700684 itnim_drv->state = ITNIM_STATE_TIMEOUT;
Jing Huang7725ccf2009-09-23 17:46:15 -0700685}
686
Jing Huang5fbe25c2010-10-18 17:17:23 -0700687/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700688 * BFA notification to FCS/driver for second level error recovery.
Jing Huang7725ccf2009-09-23 17:46:15 -0700689 *
690 * Atleast one I/O request has timedout and target is unresponsive to
691 * repeated abort requests. Second level error recovery should be initiated
692 * by starting implicit logout and recovery procedures.
693 */
694void
695bfa_cb_itnim_sler(void *cb_arg)
696{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700697 struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -0700698
699 itnim->stats.sler++;
700 bfa_trc(itnim->fcs, itnim->rport->pwwn);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800701 bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700702}
703
704struct bfa_fcs_itnim_s *
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700705bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700706{
707 struct bfa_fcs_rport_s *rport;
708 rport = bfa_fcs_rport_lookup(port, rpwwn);
709
710 if (!rport)
711 return NULL;
712
Jing Huangd4b671c2010-12-26 21:46:35 -0800713 WARN_ON(rport->itnim == NULL);
Jing Huangf8ceafd2009-09-25 12:29:54 -0700714 return rport->itnim;
Jing Huang7725ccf2009-09-23 17:46:15 -0700715}
716
717bfa_status_t
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700718bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
Jing Huang7725ccf2009-09-23 17:46:15 -0700719 struct bfa_itnim_attr_s *attr)
720{
721 struct bfa_fcs_itnim_s *itnim = NULL;
722
723 itnim = bfa_fcs_itnim_lookup(port, rpwwn);
724
725 if (itnim == NULL)
726 return BFA_STATUS_NO_FCPIM_NEXUS;
727
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700728 attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
729 attr->retry = itnim->seq_rec;
730 attr->rec_support = itnim->rec_support;
731 attr->conf_comp = itnim->conf_comp;
Jing Huang7725ccf2009-09-23 17:46:15 -0700732 attr->task_retry_id = itnim->task_retry_id;
Jing Huang7725ccf2009-09-23 17:46:15 -0700733 return BFA_STATUS_OK;
734}
735
736bfa_status_t
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700737bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
Jing Huang7725ccf2009-09-23 17:46:15 -0700738 struct bfa_itnim_stats_s *stats)
739{
740 struct bfa_fcs_itnim_s *itnim = NULL;
741
Jing Huangd4b671c2010-12-26 21:46:35 -0800742 WARN_ON(port == NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700743
744 itnim = bfa_fcs_itnim_lookup(port, rpwwn);
745
746 if (itnim == NULL)
747 return BFA_STATUS_NO_FCPIM_NEXUS;
748
Jing Huang6a18b162010-10-18 17:08:54 -0700749 memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
Jing Huang7725ccf2009-09-23 17:46:15 -0700750
751 return BFA_STATUS_OK;
752}
753
754bfa_status_t
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700755bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
Jing Huang7725ccf2009-09-23 17:46:15 -0700756{
757 struct bfa_fcs_itnim_s *itnim = NULL;
758
Jing Huangd4b671c2010-12-26 21:46:35 -0800759 WARN_ON(port == NULL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700760
761 itnim = bfa_fcs_itnim_lookup(port, rpwwn);
762
763 if (itnim == NULL)
764 return BFA_STATUS_NO_FCPIM_NEXUS;
765
Jing Huang6a18b162010-10-18 17:08:54 -0700766 memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
Jing Huang7725ccf2009-09-23 17:46:15 -0700767 return BFA_STATUS_OK;
768}
769
770void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700771bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
772 struct fchs_s *fchs, u16 len)
Jing Huang7725ccf2009-09-23 17:46:15 -0700773{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700774 struct fc_els_cmd_s *els_cmd;
Jing Huang7725ccf2009-09-23 17:46:15 -0700775
776 bfa_trc(itnim->fcs, fchs->type);
777
778 if (fchs->type != FC_TYPE_ELS)
779 return;
780
781 els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
782
783 bfa_trc(itnim->fcs, els_cmd->els_code);
784
785 switch (els_cmd->els_code) {
786 case FC_ELS_PRLO:
Jing Huang4b5e7592010-07-08 19:55:41 -0700787 bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
Jing Huang7725ccf2009-09-23 17:46:15 -0700788 break;
789
790 default:
Jing Huangd4b671c2010-12-26 21:46:35 -0800791 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -0700792 }
793}