blob: 58ac643ba9f34d40a43c180342b896602eee55b5 [file] [log] [blame]
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001/*
2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3 * 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/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070019 * rport.c Remote port implementation.
20 */
21
Maggie Zhangf16a1752010-12-09 19:12:32 -080022#include "bfad_drv.h"
Krishna Gudipati7826f302011-07-20 16:59:13 -070023#include "bfad_im.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070024#include "bfa_fcs.h"
25#include "bfa_fcbuild.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070026
27BFA_TRC_FILE(FCS, RPORT);
28
29static u32
30bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
31 /* In millisecs */
32/*
Krishna Gudipati61ba4392012-08-22 19:52:58 -070033 * bfa_fcs_rport_max_logins is max count of bfa_fcs_rports
34 * whereas DEF_CFG_NUM_RPORTS is max count of bfa_rports
35 */
36static u32 bfa_fcs_rport_max_logins = BFA_FCS_MAX_RPORT_LOGINS;
37
38/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070039 * forward declarations
40 */
41static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
42 struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
43static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
44static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
Krishna Gudipati61ba4392012-08-22 19:52:58 -070045static void bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport);
46static void bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport);
47static void bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport);
48static void bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070049static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
50 struct fc_logi_s *plogi);
51static void bfa_fcs_rport_timeout(void *arg);
52static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
53 struct bfa_fcxp_s *fcxp_alloced);
54static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
55 struct bfa_fcxp_s *fcxp_alloced);
56static void bfa_fcs_rport_plogi_response(void *fcsarg,
57 struct bfa_fcxp_s *fcxp, void *cbarg,
58 bfa_status_t req_status, u32 rsp_len,
59 u32 resid_len, struct fchs_s *rsp_fchs);
60static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
61 struct bfa_fcxp_s *fcxp_alloced);
62static void bfa_fcs_rport_adisc_response(void *fcsarg,
63 struct bfa_fcxp_s *fcxp, void *cbarg,
64 bfa_status_t req_status, u32 rsp_len,
65 u32 resid_len, struct fchs_s *rsp_fchs);
66static void bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
67 struct bfa_fcxp_s *fcxp_alloced);
68static void bfa_fcs_rport_gidpn_response(void *fcsarg,
69 struct bfa_fcxp_s *fcxp, void *cbarg,
70 bfa_status_t req_status, u32 rsp_len,
71 u32 resid_len, struct fchs_s *rsp_fchs);
72static void bfa_fcs_rport_gpnid_response(void *fcsarg,
73 struct bfa_fcxp_s *fcxp, void *cbarg,
74 bfa_status_t req_status, u32 rsp_len,
75 u32 resid_len, struct fchs_s *rsp_fchs);
76static void bfa_fcs_rport_send_logo(void *rport_cbarg,
77 struct bfa_fcxp_s *fcxp_alloced);
78static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
79static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
80 struct fchs_s *rx_fchs, u16 len);
81static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
82 struct fchs_s *rx_fchs, u8 reason_code,
83 u8 reason_code_expl);
84static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
85 struct fchs_s *rx_fchs, u16 len);
86static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
Krishna Gudipati61ba4392012-08-22 19:52:58 -070087static void bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070088
89static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
90 enum rport_event event);
91static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
92 enum rport_event event);
93static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
94 enum rport_event event);
95static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
96 enum rport_event event);
97static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
98 enum rport_event event);
Krishna Gudipati61ba4392012-08-22 19:52:58 -070099static void bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
100 enum rport_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700101static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
102 enum rport_event event);
103static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
104 enum rport_event event);
105static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
106 enum rport_event event);
107static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
108 enum rport_event event);
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700109static void bfa_fcs_rport_sm_adisc_online_sending(
110 struct bfa_fcs_rport_s *rport, enum rport_event event);
111static void bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
112 enum rport_event event);
113static void bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s
114 *rport, enum rport_event event);
115static void bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700116 enum rport_event event);
117static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
118 enum rport_event event);
119static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
120 enum rport_event event);
121static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
122 enum rport_event event);
123static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
124 enum rport_event event);
125static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
126 enum rport_event event);
127static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
128 enum rport_event event);
129static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
130 enum rport_event event);
131static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
132 enum rport_event event);
133static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
134 enum rport_event event);
135static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
136 enum rport_event event);
137static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
138 enum rport_event event);
139static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
140 enum rport_event event);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700141static void bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
142 enum rport_event event);
143static void bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
144 enum rport_event event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700145
146static struct bfa_sm_table_s rport_sm_table[] = {
147 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
148 {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
149 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
150 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
151 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700152 {BFA_SM(bfa_fcs_rport_sm_fc4_fcs_online), BFA_RPORT_ONLINE},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700153 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
154 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
155 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
156 {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700157 {BFA_SM(bfa_fcs_rport_sm_adisc_online_sending), BFA_RPORT_ADISC},
158 {BFA_SM(bfa_fcs_rport_sm_adisc_online), BFA_RPORT_ADISC},
159 {BFA_SM(bfa_fcs_rport_sm_adisc_offline_sending), BFA_RPORT_ADISC},
160 {BFA_SM(bfa_fcs_rport_sm_adisc_offline), BFA_RPORT_ADISC},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700161 {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
162 {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
163 {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
164 {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
165 {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
166 {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
167 {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
168 {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
169 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
170 {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
171 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
172};
173
Jing Huang5fbe25c2010-10-18 17:17:23 -0700174/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700175 * Beginning state.
176 */
177static void
178bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
179{
180 bfa_trc(rport->fcs, rport->pwwn);
181 bfa_trc(rport->fcs, rport->pid);
182 bfa_trc(rport->fcs, event);
183
184 switch (event) {
185 case RPSM_EVENT_PLOGI_SEND:
186 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
187 rport->plogi_retries = 0;
188 bfa_fcs_rport_send_plogi(rport, NULL);
189 break;
190
191 case RPSM_EVENT_PLOGI_RCVD:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700192 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
193 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700194 break;
195
196 case RPSM_EVENT_PLOGI_COMP:
197 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
198 bfa_fcs_rport_hal_online(rport);
199 break;
200
201 case RPSM_EVENT_ADDRESS_CHANGE:
202 case RPSM_EVENT_ADDRESS_DISC:
203 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
204 rport->ns_retries = 0;
205 bfa_fcs_rport_send_nsdisc(rport, NULL);
206 break;
207 default:
208 bfa_sm_fault(rport->fcs, event);
209 }
210}
211
Jing Huang5fbe25c2010-10-18 17:17:23 -0700212/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700213 * PLOGI is being sent.
214 */
215static void
216bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
217 enum rport_event event)
218{
219 bfa_trc(rport->fcs, rport->pwwn);
220 bfa_trc(rport->fcs, rport->pid);
221 bfa_trc(rport->fcs, event);
222
223 switch (event) {
224 case RPSM_EVENT_FCXP_SENT:
225 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
226 break;
227
228 case RPSM_EVENT_DELETE:
229 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
230 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
231 bfa_fcs_rport_free(rport);
232 break;
233
234 case RPSM_EVENT_PLOGI_RCVD:
235 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
236 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
237 bfa_fcs_rport_send_plogiacc(rport, NULL);
238 break;
239
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700240 case RPSM_EVENT_SCN_OFFLINE:
241 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
242 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
243 bfa_timer_start(rport->fcs->bfa, &rport->timer,
244 bfa_fcs_rport_timeout, rport,
245 bfa_fcs_rport_del_timeout);
246 break;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700247 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700248 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700249 /* query the NS */
250 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700251 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
252 BFA_PORT_TOPOLOGY_LOOP));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700253 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
254 rport->ns_retries = 0;
255 bfa_fcs_rport_send_nsdisc(rport, NULL);
256 break;
257
258 case RPSM_EVENT_LOGO_IMP:
259 rport->pid = 0;
260 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
261 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
262 bfa_timer_start(rport->fcs->bfa, &rport->timer,
263 bfa_fcs_rport_timeout, rport,
264 bfa_fcs_rport_del_timeout);
265 break;
266
267
268 default:
269 bfa_sm_fault(rport->fcs, event);
270 }
271}
272
Jing Huang5fbe25c2010-10-18 17:17:23 -0700273/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700274 * PLOGI is being sent.
275 */
276static void
277bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
278 enum rport_event event)
279{
280 bfa_trc(rport->fcs, rport->pwwn);
281 bfa_trc(rport->fcs, rport->pid);
282 bfa_trc(rport->fcs, event);
283
284 switch (event) {
285 case RPSM_EVENT_FCXP_SENT:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700286 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
287 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700288 break;
289
290 case RPSM_EVENT_DELETE:
291 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
292 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
293 bfa_fcs_rport_free(rport);
294 break;
295
296 case RPSM_EVENT_PLOGI_RCVD:
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700297 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700298 case RPSM_EVENT_FAB_SCN:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700299 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700300 * Ignore, SCN is possibly online notification.
301 */
302 break;
303
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700304 case RPSM_EVENT_SCN_OFFLINE:
305 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
306 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
307 bfa_timer_start(rport->fcs->bfa, &rport->timer,
308 bfa_fcs_rport_timeout, rport,
309 bfa_fcs_rport_del_timeout);
310 break;
311
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700312 case RPSM_EVENT_ADDRESS_CHANGE:
313 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
314 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
315 rport->ns_retries = 0;
316 bfa_fcs_rport_send_nsdisc(rport, NULL);
317 break;
318
319 case RPSM_EVENT_LOGO_IMP:
320 rport->pid = 0;
321 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
322 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
323 bfa_timer_start(rport->fcs->bfa, &rport->timer,
324 bfa_fcs_rport_timeout, rport,
325 bfa_fcs_rport_del_timeout);
326 break;
327
328 case RPSM_EVENT_HCB_OFFLINE:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700329 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700330 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
331 */
332 break;
333
334 default:
335 bfa_sm_fault(rport->fcs, event);
336 }
337}
338
Jing Huang5fbe25c2010-10-18 17:17:23 -0700339/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700340 * PLOGI is sent.
341 */
342static void
343bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
344 enum rport_event event)
345{
346 bfa_trc(rport->fcs, rport->pwwn);
347 bfa_trc(rport->fcs, rport->pid);
348 bfa_trc(rport->fcs, event);
349
350 switch (event) {
351 case RPSM_EVENT_TIMEOUT:
352 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
353 bfa_fcs_rport_send_plogi(rport, NULL);
354 break;
355
356 case RPSM_EVENT_DELETE:
357 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
358 bfa_timer_stop(&rport->timer);
359 bfa_fcs_rport_free(rport);
360 break;
361
362 case RPSM_EVENT_PRLO_RCVD:
363 case RPSM_EVENT_LOGO_RCVD:
364 break;
365
366 case RPSM_EVENT_PLOGI_RCVD:
367 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
368 bfa_timer_stop(&rport->timer);
369 bfa_fcs_rport_send_plogiacc(rport, NULL);
370 break;
371
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700372 case RPSM_EVENT_SCN_OFFLINE:
373 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700374 bfa_timer_stop(&rport->timer);
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700375 bfa_timer_start(rport->fcs->bfa, &rport->timer,
376 bfa_fcs_rport_timeout, rport,
377 bfa_fcs_rport_del_timeout);
378 break;
379
380 case RPSM_EVENT_ADDRESS_CHANGE:
381 case RPSM_EVENT_FAB_SCN:
382 bfa_timer_stop(&rport->timer);
383 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
384 BFA_PORT_TOPOLOGY_LOOP));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700385 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
386 rport->ns_retries = 0;
387 bfa_fcs_rport_send_nsdisc(rport, NULL);
388 break;
389
390 case RPSM_EVENT_LOGO_IMP:
391 rport->pid = 0;
392 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
393 bfa_timer_stop(&rport->timer);
394 bfa_timer_start(rport->fcs->bfa, &rport->timer,
395 bfa_fcs_rport_timeout, rport,
396 bfa_fcs_rport_del_timeout);
397 break;
398
399 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700400 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700401 bfa_timer_stop(&rport->timer);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700402 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700403 break;
404
405 default:
406 bfa_sm_fault(rport->fcs, event);
407 }
408}
409
Jing Huang5fbe25c2010-10-18 17:17:23 -0700410/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700411 * PLOGI is sent.
412 */
413static void
414bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
415{
416 bfa_trc(rport->fcs, rport->pwwn);
417 bfa_trc(rport->fcs, rport->pid);
418 bfa_trc(rport->fcs, event);
419
420 switch (event) {
421 case RPSM_EVENT_ACCEPTED:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700422 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700423 rport->plogi_retries = 0;
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700424 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700425 break;
426
427 case RPSM_EVENT_LOGO_RCVD:
428 bfa_fcs_rport_send_logo_acc(rport);
429 /*
430 * !! fall through !!
431 */
432 case RPSM_EVENT_PRLO_RCVD:
433 if (rport->prlo == BFA_TRUE)
434 bfa_fcs_rport_send_prlo_acc(rport);
435
436 bfa_fcxp_discard(rport->fcxp);
437 /*
438 * !! fall through !!
439 */
440 case RPSM_EVENT_FAILED:
441 if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
442 rport->plogi_retries++;
443 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
444 bfa_timer_start(rport->fcs->bfa, &rport->timer,
445 bfa_fcs_rport_timeout, rport,
446 BFA_FCS_RETRY_TIMEOUT);
447 } else {
448 bfa_stats(rport->port, rport_del_max_plogi_retry);
Krishna Gudipatiee1a4a42012-08-22 19:50:43 -0700449 rport->old_pid = rport->pid;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700450 rport->pid = 0;
451 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
452 bfa_timer_start(rport->fcs->bfa, &rport->timer,
453 bfa_fcs_rport_timeout, rport,
454 bfa_fcs_rport_del_timeout);
455 }
456 break;
457
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700458 case RPSM_EVENT_SCN_ONLINE:
459 break;
460
461 case RPSM_EVENT_SCN_OFFLINE:
462 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
463 bfa_fcxp_discard(rport->fcxp);
464 bfa_timer_start(rport->fcs->bfa, &rport->timer,
465 bfa_fcs_rport_timeout, rport,
466 bfa_fcs_rport_del_timeout);
467 break;
468
469 case RPSM_EVENT_PLOGI_RETRY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700470 rport->plogi_retries = 0;
471 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
472 bfa_timer_start(rport->fcs->bfa, &rport->timer,
473 bfa_fcs_rport_timeout, rport,
474 (FC_RA_TOV * 1000));
475 break;
476
477 case RPSM_EVENT_LOGO_IMP:
478 rport->pid = 0;
479 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
480 bfa_fcxp_discard(rport->fcxp);
481 bfa_timer_start(rport->fcs->bfa, &rport->timer,
482 bfa_fcs_rport_timeout, rport,
483 bfa_fcs_rport_del_timeout);
484 break;
485
486 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700487 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700488 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700489 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
490 BFA_PORT_TOPOLOGY_LOOP));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700491 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
492 rport->ns_retries = 0;
493 bfa_fcs_rport_send_nsdisc(rport, NULL);
494 break;
495
496 case RPSM_EVENT_PLOGI_RCVD:
497 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
498 bfa_fcxp_discard(rport->fcxp);
499 bfa_fcs_rport_send_plogiacc(rport, NULL);
500 break;
501
502 case RPSM_EVENT_DELETE:
503 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
504 bfa_fcxp_discard(rport->fcxp);
505 bfa_fcs_rport_free(rport);
506 break;
507
508 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700509 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700510 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700511 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700512 break;
513
514 default:
515 bfa_sm_fault(rport->fcs, event);
516 }
517}
518
Jing Huang5fbe25c2010-10-18 17:17:23 -0700519/*
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700520 * PLOGI is done. Await bfa_fcs_itnim to ascertain the scsi function
521 */
522static void
523bfa_fcs_rport_sm_fc4_fcs_online(struct bfa_fcs_rport_s *rport,
524 enum rport_event event)
525{
526 bfa_trc(rport->fcs, rport->pwwn);
527 bfa_trc(rport->fcs, rport->pid);
528 bfa_trc(rport->fcs, event);
529
530 switch (event) {
531 case RPSM_EVENT_FC4_FCS_ONLINE:
532 if (rport->scsi_function == BFA_RPORT_INITIATOR) {
533 if (!BFA_FCS_PID_IS_WKA(rport->pid))
534 bfa_fcs_rpf_rport_online(rport);
535 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
536 break;
537 }
538
539 if (!rport->bfa_rport)
540 rport->bfa_rport =
541 bfa_rport_create(rport->fcs->bfa, rport);
542
543 if (rport->bfa_rport) {
544 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
545 bfa_fcs_rport_hal_online(rport);
546 } else {
547 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
548 bfa_fcs_rport_fcs_offline_action(rport);
549 }
550 break;
551
552 case RPSM_EVENT_PLOGI_RCVD:
553 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
554 rport->plogi_pending = BFA_TRUE;
555 bfa_fcs_rport_fcs_offline_action(rport);
556 break;
557
558 case RPSM_EVENT_PLOGI_COMP:
559 case RPSM_EVENT_LOGO_IMP:
560 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700561 case RPSM_EVENT_FAB_SCN:
562 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700563 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
564 bfa_fcs_rport_fcs_offline_action(rport);
565 break;
566
567 case RPSM_EVENT_LOGO_RCVD:
568 case RPSM_EVENT_PRLO_RCVD:
569 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
570 bfa_fcs_rport_fcs_offline_action(rport);
571 break;
572
573 case RPSM_EVENT_DELETE:
574 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
575 bfa_fcs_rport_fcs_offline_action(rport);
576 break;
577
578 default:
579 bfa_sm_fault(rport->fcs, event);
580 break;
581 }
582}
583
584/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700585 * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
586 * are offline.
587 */
588static void
589bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
590 enum rport_event event)
591{
592 bfa_trc(rport->fcs, rport->pwwn);
593 bfa_trc(rport->fcs, rport->pid);
594 bfa_trc(rport->fcs, event);
595
596 switch (event) {
597 case RPSM_EVENT_HCB_ONLINE:
598 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700599 bfa_fcs_rport_hal_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700600 break;
601
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700602 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700603 break;
604
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700605 case RPSM_EVENT_PRLO_RCVD:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700606 case RPSM_EVENT_LOGO_RCVD:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700607 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
608 bfa_fcs_rport_fcs_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700609 break;
610
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700611 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700612 case RPSM_EVENT_LOGO_IMP:
613 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700614 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700615 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
616 bfa_fcs_rport_fcs_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700617 break;
618
619 case RPSM_EVENT_PLOGI_RCVD:
Krishna Gudipatid7be54c2011-06-24 20:24:52 -0700620 rport->plogi_pending = BFA_TRUE;
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700621 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
622 bfa_fcs_rport_fcs_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700623 break;
624
625 case RPSM_EVENT_DELETE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700626 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
627 bfa_fcs_rport_fcs_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700628 break;
629
630 default:
631 bfa_sm_fault(rport->fcs, event);
632 }
633}
634
Jing Huang5fbe25c2010-10-18 17:17:23 -0700635/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700636 * Rport is ONLINE. FC-4s active.
637 */
638static void
639bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
640{
641 bfa_trc(rport->fcs, rport->pwwn);
642 bfa_trc(rport->fcs, rport->pid);
643 bfa_trc(rport->fcs, event);
644
645 switch (event) {
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700646 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700647 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
648 bfa_sm_set_state(rport,
649 bfa_fcs_rport_sm_nsquery_sending);
650 rport->ns_retries = 0;
651 bfa_fcs_rport_send_nsdisc(rport, NULL);
652 } else {
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700653 bfa_sm_set_state(rport,
654 bfa_fcs_rport_sm_adisc_online_sending);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700655 bfa_fcs_rport_send_adisc(rport, NULL);
656 }
657 break;
658
659 case RPSM_EVENT_PLOGI_RCVD:
660 case RPSM_EVENT_LOGO_IMP:
661 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700662 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700663 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700664 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700665 break;
666
667 case RPSM_EVENT_DELETE:
668 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700669 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700670 break;
671
672 case RPSM_EVENT_LOGO_RCVD:
673 case RPSM_EVENT_PRLO_RCVD:
674 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700675 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700676 break;
677
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700678 case RPSM_EVENT_SCN_ONLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700679 case RPSM_EVENT_PLOGI_COMP:
680 break;
681
682 default:
683 bfa_sm_fault(rport->fcs, event);
684 }
685}
686
Jing Huang5fbe25c2010-10-18 17:17:23 -0700687/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700688 * An SCN event is received in ONLINE state. NS query is being sent
689 * prior to ADISC authentication with rport. FC-4s are paused.
690 */
691static void
692bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
693 enum rport_event event)
694{
695 bfa_trc(rport->fcs, rport->pwwn);
696 bfa_trc(rport->fcs, rport->pid);
697 bfa_trc(rport->fcs, event);
698
699 switch (event) {
700 case RPSM_EVENT_FCXP_SENT:
701 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
702 break;
703
704 case RPSM_EVENT_DELETE:
705 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
706 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700707 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700708 break;
709
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700710 case RPSM_EVENT_FAB_SCN:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700711 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700712 * ignore SCN, wait for response to query itself
713 */
714 break;
715
716 case RPSM_EVENT_LOGO_RCVD:
717 case RPSM_EVENT_PRLO_RCVD:
718 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
719 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700720 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700721 break;
722
723 case RPSM_EVENT_LOGO_IMP:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700724 case RPSM_EVENT_PLOGI_RCVD:
725 case RPSM_EVENT_ADDRESS_CHANGE:
726 case RPSM_EVENT_PLOGI_COMP:
727 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
728 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700729 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700730 break;
731
732 default:
733 bfa_sm_fault(rport->fcs, event);
734 }
735}
736
Jing Huang5fbe25c2010-10-18 17:17:23 -0700737/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700738 * An SCN event is received in ONLINE state. NS query is sent to rport.
739 * FC-4s are paused.
740 */
741static void
742bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
743{
744 bfa_trc(rport->fcs, rport->pwwn);
745 bfa_trc(rport->fcs, rport->pid);
746 bfa_trc(rport->fcs, event);
747
748 switch (event) {
749 case RPSM_EVENT_ACCEPTED:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700750 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online_sending);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700751 bfa_fcs_rport_send_adisc(rport, NULL);
752 break;
753
754 case RPSM_EVENT_FAILED:
755 rport->ns_retries++;
756 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
757 bfa_sm_set_state(rport,
758 bfa_fcs_rport_sm_nsquery_sending);
759 bfa_fcs_rport_send_nsdisc(rport, NULL);
760 } else {
761 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700762 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700763 }
764 break;
765
766 case RPSM_EVENT_DELETE:
767 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
768 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700769 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700770 break;
771
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700772 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700773 break;
774
775 case RPSM_EVENT_LOGO_RCVD:
776 case RPSM_EVENT_PRLO_RCVD:
777 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
778 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700779 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700780 break;
781
782 case RPSM_EVENT_PLOGI_COMP:
783 case RPSM_EVENT_ADDRESS_CHANGE:
784 case RPSM_EVENT_PLOGI_RCVD:
785 case RPSM_EVENT_LOGO_IMP:
786 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
787 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700788 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700789 break;
790
791 default:
792 bfa_sm_fault(rport->fcs, event);
793 }
794}
795
Jing Huang5fbe25c2010-10-18 17:17:23 -0700796/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700797 * An SCN event is received in ONLINE state. ADISC is being sent for
798 * authenticating with rport. FC-4s are paused.
799 */
800static void
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700801bfa_fcs_rport_sm_adisc_online_sending(struct bfa_fcs_rport_s *rport,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700802 enum rport_event event)
803{
804 bfa_trc(rport->fcs, rport->pwwn);
805 bfa_trc(rport->fcs, rport->pid);
806 bfa_trc(rport->fcs, event);
807
808 switch (event) {
809 case RPSM_EVENT_FCXP_SENT:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700810 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700811 break;
812
813 case RPSM_EVENT_DELETE:
814 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
815 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700816 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700817 break;
818
819 case RPSM_EVENT_LOGO_IMP:
820 case RPSM_EVENT_ADDRESS_CHANGE:
821 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
822 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700823 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700824 break;
825
826 case RPSM_EVENT_LOGO_RCVD:
827 case RPSM_EVENT_PRLO_RCVD:
828 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
829 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700830 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700831 break;
832
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700833 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700834 break;
835
836 case RPSM_EVENT_PLOGI_RCVD:
837 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
838 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700839 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700840 break;
841
842 default:
843 bfa_sm_fault(rport->fcs, event);
844 }
845}
846
Jing Huang5fbe25c2010-10-18 17:17:23 -0700847/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700848 * An SCN event is received in ONLINE state. ADISC is to rport.
849 * FC-4s are paused.
850 */
851static void
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700852bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport,
853 enum rport_event event)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700854{
855 bfa_trc(rport->fcs, rport->pwwn);
856 bfa_trc(rport->fcs, rport->pid);
857 bfa_trc(rport->fcs, event);
858
859 switch (event) {
860 case RPSM_EVENT_ACCEPTED:
861 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
862 break;
863
864 case RPSM_EVENT_PLOGI_RCVD:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700865 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700866 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
867 * At least go offline when a PLOGI is received.
868 */
869 bfa_fcxp_discard(rport->fcxp);
870 /*
871 * !!! fall through !!!
872 */
873
874 case RPSM_EVENT_FAILED:
875 case RPSM_EVENT_ADDRESS_CHANGE:
876 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700877 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700878 break;
879
880 case RPSM_EVENT_DELETE:
881 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
882 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700883 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700884 break;
885
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700886 case RPSM_EVENT_FAB_SCN:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700887 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700888 * already processing RSCN
889 */
890 break;
891
892 case RPSM_EVENT_LOGO_IMP:
893 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
894 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700895 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700896 break;
897
898 case RPSM_EVENT_LOGO_RCVD:
899 case RPSM_EVENT_PRLO_RCVD:
900 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
901 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -0700902 bfa_fcs_rport_hal_offline_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700903 break;
904
905 default:
906 bfa_sm_fault(rport->fcs, event);
907 }
908}
909
Jing Huang5fbe25c2010-10-18 17:17:23 -0700910/*
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -0700911 * ADISC is being sent for authenticating with rport
912 * Already did offline actions.
913 */
914static void
915bfa_fcs_rport_sm_adisc_offline_sending(struct bfa_fcs_rport_s *rport,
916 enum rport_event event)
917{
918 bfa_trc(rport->fcs, rport->pwwn);
919 bfa_trc(rport->fcs, rport->pid);
920 bfa_trc(rport->fcs, event);
921
922 switch (event) {
923 case RPSM_EVENT_FCXP_SENT:
924 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_offline);
925 break;
926
927 case RPSM_EVENT_DELETE:
928 case RPSM_EVENT_SCN_OFFLINE:
929 case RPSM_EVENT_LOGO_IMP:
930 case RPSM_EVENT_LOGO_RCVD:
931 case RPSM_EVENT_PRLO_RCVD:
932 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
933 bfa_fcxp_walloc_cancel(rport->fcs->bfa,
934 &rport->fcxp_wqe);
935 bfa_timer_start(rport->fcs->bfa, &rport->timer,
936 bfa_fcs_rport_timeout, rport,
937 bfa_fcs_rport_del_timeout);
938 break;
939
940 case RPSM_EVENT_PLOGI_RCVD:
941 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
942 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
943 bfa_fcs_rport_send_plogiacc(rport, NULL);
944 break;
945
946 default:
947 bfa_sm_fault(rport->fcs, event);
948 }
949}
950
951/*
952 * ADISC to rport
953 * Already did offline actions
954 */
955static void
956bfa_fcs_rport_sm_adisc_offline(struct bfa_fcs_rport_s *rport,
957 enum rport_event event)
958{
959 bfa_trc(rport->fcs, rport->pwwn);
960 bfa_trc(rport->fcs, rport->pid);
961 bfa_trc(rport->fcs, event);
962
963 switch (event) {
964 case RPSM_EVENT_ACCEPTED:
965 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
966 bfa_fcs_rport_hal_online(rport);
967 break;
968
969 case RPSM_EVENT_PLOGI_RCVD:
970 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
971 bfa_fcxp_discard(rport->fcxp);
972 bfa_fcs_rport_send_plogiacc(rport, NULL);
973 break;
974
975 case RPSM_EVENT_FAILED:
976 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
977 bfa_timer_start(rport->fcs->bfa, &rport->timer,
978 bfa_fcs_rport_timeout, rport,
979 bfa_fcs_rport_del_timeout);
980 break;
981
982 case RPSM_EVENT_DELETE:
983 case RPSM_EVENT_SCN_OFFLINE:
984 case RPSM_EVENT_LOGO_IMP:
985 case RPSM_EVENT_LOGO_RCVD:
986 case RPSM_EVENT_PRLO_RCVD:
987 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
988 bfa_fcxp_discard(rport->fcxp);
989 bfa_timer_start(rport->fcs->bfa, &rport->timer,
990 bfa_fcs_rport_timeout, rport,
991 bfa_fcs_rport_del_timeout);
992 break;
993
994 default:
995 bfa_sm_fault(rport->fcs, event);
996 }
997}
998
999/*
1000 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001001 */
1002static void
1003bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
1004 enum rport_event event)
1005{
1006 bfa_trc(rport->fcs, rport->pwwn);
1007 bfa_trc(rport->fcs, rport->pid);
1008 bfa_trc(rport->fcs, event);
1009
1010 switch (event) {
1011 case RPSM_EVENT_FC4_OFFLINE:
1012 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001013 bfa_fcs_rport_hal_offline(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001014 break;
1015
1016 case RPSM_EVENT_DELETE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001017 if (rport->pid && (rport->prlo == BFA_TRUE))
1018 bfa_fcs_rport_send_prlo_acc(rport);
1019 if (rport->pid && (rport->prlo == BFA_FALSE))
1020 bfa_fcs_rport_send_logo_acc(rport);
1021
1022 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001023 break;
1024
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001025 case RPSM_EVENT_SCN_ONLINE:
1026 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001027 case RPSM_EVENT_HCB_ONLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001028 case RPSM_EVENT_LOGO_RCVD:
1029 case RPSM_EVENT_PRLO_RCVD:
1030 case RPSM_EVENT_ADDRESS_CHANGE:
1031 break;
1032
1033 default:
1034 bfa_sm_fault(rport->fcs, event);
1035 }
1036}
1037
Jing Huang5fbe25c2010-10-18 17:17:23 -07001038/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001039 * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
1040 * callback.
1041 */
1042static void
1043bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
1044 enum rport_event event)
1045{
1046 bfa_trc(rport->fcs, rport->pwwn);
1047 bfa_trc(rport->fcs, rport->pid);
1048 bfa_trc(rport->fcs, event);
1049
1050 switch (event) {
1051 case RPSM_EVENT_FC4_OFFLINE:
1052 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001053 bfa_fcs_rport_hal_offline(rport);
1054 break;
1055
1056 case RPSM_EVENT_LOGO_RCVD:
1057 bfa_fcs_rport_send_logo_acc(rport);
1058 case RPSM_EVENT_PRLO_RCVD:
1059 if (rport->prlo == BFA_TRUE)
1060 bfa_fcs_rport_send_prlo_acc(rport);
1061 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_off_delete);
1062 break;
1063
1064 case RPSM_EVENT_HCB_ONLINE:
1065 case RPSM_EVENT_DELETE:
1066 /* Rport is being deleted */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001067 break;
1068
1069 default:
1070 bfa_sm_fault(rport->fcs, event);
1071 }
1072}
1073
Jing Huang5fbe25c2010-10-18 17:17:23 -07001074/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001075 * Rport is going offline. Awaiting FC-4 offline completion callback.
1076 */
1077static void
1078bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
1079 enum rport_event event)
1080{
1081 bfa_trc(rport->fcs, rport->pwwn);
1082 bfa_trc(rport->fcs, rport->pid);
1083 bfa_trc(rport->fcs, event);
1084
1085 switch (event) {
1086 case RPSM_EVENT_FC4_OFFLINE:
1087 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001088 bfa_fcs_rport_hal_offline(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001089 break;
1090
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001091 case RPSM_EVENT_SCN_ONLINE:
1092 break;
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001093 case RPSM_EVENT_LOGO_RCVD:
1094 /*
1095 * Rport is going offline. Just ack the logo
1096 */
1097 bfa_fcs_rport_send_logo_acc(rport);
1098 break;
1099
1100 case RPSM_EVENT_PRLO_RCVD:
1101 bfa_fcs_rport_send_prlo_acc(rport);
1102 break;
1103
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001104 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001105 case RPSM_EVENT_HCB_ONLINE:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001106 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001107 case RPSM_EVENT_LOGO_IMP:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001108 case RPSM_EVENT_ADDRESS_CHANGE:
Jing Huang5fbe25c2010-10-18 17:17:23 -07001109 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001110 * rport is already going offline.
1111 * SCN - ignore and wait till transitioning to offline state
1112 */
1113 break;
1114
1115 case RPSM_EVENT_DELETE:
1116 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
1117 break;
1118
1119 default:
1120 bfa_sm_fault(rport->fcs, event);
1121 }
1122}
1123
Jing Huang5fbe25c2010-10-18 17:17:23 -07001124/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001125 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
1126 * callback.
1127 */
1128static void
1129bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
1130 enum rport_event event)
1131{
1132 bfa_trc(rport->fcs, rport->pwwn);
1133 bfa_trc(rport->fcs, rport->pid);
1134 bfa_trc(rport->fcs, event);
1135
1136 switch (event) {
1137 case RPSM_EVENT_HCB_OFFLINE:
Krishna Gudipatid7be54c2011-06-24 20:24:52 -07001138 if (bfa_fcs_lport_is_online(rport->port) &&
1139 (rport->plogi_pending)) {
1140 rport->plogi_pending = BFA_FALSE;
1141 bfa_sm_set_state(rport,
1142 bfa_fcs_rport_sm_plogiacc_sending);
1143 bfa_fcs_rport_send_plogiacc(rport, NULL);
1144 break;
1145 }
1146 /*
1147 * !! fall through !!
1148 */
1149
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001150 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001151 if (!bfa_fcs_lport_is_online(rport->port)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001152 rport->pid = 0;
1153 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1154 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1155 bfa_fcs_rport_timeout, rport,
1156 bfa_fcs_rport_del_timeout);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001157 break;
1158 }
1159 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
1160 bfa_sm_set_state(rport,
1161 bfa_fcs_rport_sm_nsdisc_sending);
1162 rport->ns_retries = 0;
1163 bfa_fcs_rport_send_nsdisc(rport, NULL);
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001164 } else if (bfa_fcport_get_topology(rport->port->fcs->bfa) ==
1165 BFA_PORT_TOPOLOGY_LOOP) {
1166 if (rport->scn_online) {
1167 bfa_sm_set_state(rport,
1168 bfa_fcs_rport_sm_adisc_offline_sending);
1169 bfa_fcs_rport_send_adisc(rport, NULL);
1170 } else {
1171 bfa_sm_set_state(rport,
1172 bfa_fcs_rport_sm_offline);
1173 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1174 bfa_fcs_rport_timeout, rport,
1175 bfa_fcs_rport_del_timeout);
1176 }
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001177 } else {
1178 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1179 rport->plogi_retries = 0;
1180 bfa_fcs_rport_send_plogi(rport, NULL);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001181 }
1182 break;
1183
1184 case RPSM_EVENT_DELETE:
1185 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1186 bfa_fcs_rport_free(rport);
1187 break;
1188
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001189 case RPSM_EVENT_SCN_ONLINE:
1190 case RPSM_EVENT_SCN_OFFLINE:
1191 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001192 case RPSM_EVENT_LOGO_RCVD:
1193 case RPSM_EVENT_PRLO_RCVD:
Krishna Gudipatid7be54c2011-06-24 20:24:52 -07001194 case RPSM_EVENT_PLOGI_RCVD:
1195 case RPSM_EVENT_LOGO_IMP:
Jing Huang5fbe25c2010-10-18 17:17:23 -07001196 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001197 * Ignore, already offline.
1198 */
1199 break;
1200
1201 default:
1202 bfa_sm_fault(rport->fcs, event);
1203 }
1204}
1205
Jing Huang5fbe25c2010-10-18 17:17:23 -07001206/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001207 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
1208 * callback to send LOGO accept.
1209 */
1210static void
1211bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
1212 enum rport_event event)
1213{
1214 bfa_trc(rport->fcs, rport->pwwn);
1215 bfa_trc(rport->fcs, rport->pid);
1216 bfa_trc(rport->fcs, event);
1217
1218 switch (event) {
1219 case RPSM_EVENT_HCB_OFFLINE:
1220 case RPSM_EVENT_ADDRESS_CHANGE:
1221 if (rport->pid && (rport->prlo == BFA_TRUE))
1222 bfa_fcs_rport_send_prlo_acc(rport);
1223 if (rport->pid && (rport->prlo == BFA_FALSE))
1224 bfa_fcs_rport_send_logo_acc(rport);
1225 /*
1226 * If the lport is online and if the rport is not a well
1227 * known address port,
1228 * we try to re-discover the r-port.
1229 */
1230 if (bfa_fcs_lport_is_online(rport->port) &&
1231 (!BFA_FCS_PID_IS_WKA(rport->pid))) {
Krishna Gudipatid7be54c2011-06-24 20:24:52 -07001232 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
1233 bfa_sm_set_state(rport,
1234 bfa_fcs_rport_sm_nsdisc_sending);
1235 rport->ns_retries = 0;
1236 bfa_fcs_rport_send_nsdisc(rport, NULL);
1237 } else {
1238 /* For N2N Direct Attach, try to re-login */
1239 bfa_sm_set_state(rport,
1240 bfa_fcs_rport_sm_plogi_sending);
1241 rport->plogi_retries = 0;
1242 bfa_fcs_rport_send_plogi(rport, NULL);
1243 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001244 } else {
1245 /*
1246 * if it is not a well known address, reset the
1247 * pid to 0.
1248 */
1249 if (!BFA_FCS_PID_IS_WKA(rport->pid))
1250 rport->pid = 0;
1251 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1252 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1253 bfa_fcs_rport_timeout, rport,
1254 bfa_fcs_rport_del_timeout);
1255 }
1256 break;
1257
1258 case RPSM_EVENT_DELETE:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001259 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1260 if (rport->pid && (rport->prlo == BFA_TRUE))
1261 bfa_fcs_rport_send_prlo_acc(rport);
1262 if (rport->pid && (rport->prlo == BFA_FALSE))
1263 bfa_fcs_rport_send_logo_acc(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001264 break;
1265
1266 case RPSM_EVENT_LOGO_IMP:
1267 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1268 break;
1269
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001270 case RPSM_EVENT_SCN_ONLINE:
1271 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001272 case RPSM_EVENT_LOGO_RCVD:
1273 case RPSM_EVENT_PRLO_RCVD:
Jing Huang5fbe25c2010-10-18 17:17:23 -07001274 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001275 * Ignore - already processing a LOGO.
1276 */
1277 break;
1278
1279 default:
1280 bfa_sm_fault(rport->fcs, event);
1281 }
1282}
1283
Jing Huang5fbe25c2010-10-18 17:17:23 -07001284/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001285 * Rport is being deleted. FC-4s are offline.
1286 * Awaiting BFA rport offline
1287 * callback to send LOGO.
1288 */
1289static void
1290bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1291 enum rport_event event)
1292{
1293 bfa_trc(rport->fcs, rport->pwwn);
1294 bfa_trc(rport->fcs, rport->pid);
1295 bfa_trc(rport->fcs, event);
1296
1297 switch (event) {
1298 case RPSM_EVENT_HCB_OFFLINE:
1299 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1300 bfa_fcs_rport_send_logo(rport, NULL);
1301 break;
1302
1303 case RPSM_EVENT_LOGO_RCVD:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001304 bfa_fcs_rport_send_logo_acc(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001305 case RPSM_EVENT_PRLO_RCVD:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001306 if (rport->prlo == BFA_TRUE)
1307 bfa_fcs_rport_send_prlo_acc(rport);
1308
1309 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1310 break;
1311
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001312 case RPSM_EVENT_SCN_ONLINE:
1313 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001314 case RPSM_EVENT_ADDRESS_CHANGE:
1315 break;
1316
1317 default:
1318 bfa_sm_fault(rport->fcs, event);
1319 }
1320}
1321
Jing Huang5fbe25c2010-10-18 17:17:23 -07001322/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001323 * Rport is being deleted. FC-4s are offline. LOGO is being sent.
1324 */
1325static void
1326bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1327 enum rport_event event)
1328{
1329 bfa_trc(rport->fcs, rport->pwwn);
1330 bfa_trc(rport->fcs, rport->pid);
1331 bfa_trc(rport->fcs, event);
1332
1333 switch (event) {
1334 case RPSM_EVENT_FCXP_SENT:
1335 /* Once LOGO is sent, we donot wait for the response */
1336 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1337 bfa_fcs_rport_free(rport);
1338 break;
1339
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001340 case RPSM_EVENT_SCN_ONLINE:
1341 case RPSM_EVENT_SCN_OFFLINE:
1342 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001343 case RPSM_EVENT_ADDRESS_CHANGE:
1344 break;
1345
1346 case RPSM_EVENT_LOGO_RCVD:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001347 bfa_fcs_rport_send_logo_acc(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001348 case RPSM_EVENT_PRLO_RCVD:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001349 if (rport->prlo == BFA_TRUE)
1350 bfa_fcs_rport_send_prlo_acc(rport);
1351
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001352 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1353 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1354 bfa_fcs_rport_free(rport);
1355 break;
1356
1357 default:
1358 bfa_sm_fault(rport->fcs, event);
1359 }
1360}
1361
Jing Huang5fbe25c2010-10-18 17:17:23 -07001362/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001363 * Rport is offline. FC-4s are offline. BFA rport is offline.
1364 * Timer active to delete stale rport.
1365 */
1366static void
1367bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1368{
1369 bfa_trc(rport->fcs, rport->pwwn);
1370 bfa_trc(rport->fcs, rport->pid);
1371 bfa_trc(rport->fcs, event);
1372
1373 switch (event) {
1374 case RPSM_EVENT_TIMEOUT:
1375 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1376 bfa_fcs_rport_free(rport);
1377 break;
1378
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001379 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001380 case RPSM_EVENT_ADDRESS_CHANGE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001381 bfa_timer_stop(&rport->timer);
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001382 WARN_ON(!(bfa_fcport_get_topology(rport->port->fcs->bfa) !=
1383 BFA_PORT_TOPOLOGY_LOOP));
1384 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001385 rport->ns_retries = 0;
1386 bfa_fcs_rport_send_nsdisc(rport, NULL);
1387 break;
1388
1389 case RPSM_EVENT_DELETE:
1390 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1391 bfa_timer_stop(&rport->timer);
1392 bfa_fcs_rport_free(rport);
1393 break;
1394
1395 case RPSM_EVENT_PLOGI_RCVD:
1396 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1397 bfa_timer_stop(&rport->timer);
1398 bfa_fcs_rport_send_plogiacc(rport, NULL);
1399 break;
1400
1401 case RPSM_EVENT_LOGO_RCVD:
1402 case RPSM_EVENT_PRLO_RCVD:
1403 case RPSM_EVENT_LOGO_IMP:
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001404 case RPSM_EVENT_SCN_OFFLINE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001405 break;
1406
1407 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001408 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001409 bfa_timer_stop(&rport->timer);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001410 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001411 break;
1412
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001413 case RPSM_EVENT_SCN_ONLINE:
1414 bfa_timer_stop(&rport->timer);
1415 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1416 bfa_fcs_rport_send_plogi(rport, NULL);
1417 break;
1418
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001419 case RPSM_EVENT_PLOGI_SEND:
1420 bfa_timer_stop(&rport->timer);
1421 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1422 rport->plogi_retries = 0;
1423 bfa_fcs_rport_send_plogi(rport, NULL);
1424 break;
1425
1426 default:
1427 bfa_sm_fault(rport->fcs, event);
1428 }
1429}
1430
Jing Huang5fbe25c2010-10-18 17:17:23 -07001431/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001432 * Rport address has changed. Nameserver discovery request is being sent.
1433 */
1434static void
1435bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1436 enum rport_event event)
1437{
1438 bfa_trc(rport->fcs, rport->pwwn);
1439 bfa_trc(rport->fcs, rport->pid);
1440 bfa_trc(rport->fcs, event);
1441
1442 switch (event) {
1443 case RPSM_EVENT_FCXP_SENT:
1444 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
1445 break;
1446
1447 case RPSM_EVENT_DELETE:
1448 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1449 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1450 bfa_fcs_rport_free(rport);
1451 break;
1452
1453 case RPSM_EVENT_PLOGI_RCVD:
1454 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1455 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1456 bfa_fcs_rport_send_plogiacc(rport, NULL);
1457 break;
1458
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001459 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001460 case RPSM_EVENT_LOGO_RCVD:
1461 case RPSM_EVENT_PRLO_RCVD:
1462 case RPSM_EVENT_PLOGI_SEND:
1463 break;
1464
1465 case RPSM_EVENT_ADDRESS_CHANGE:
1466 rport->ns_retries = 0; /* reset the retry count */
1467 break;
1468
1469 case RPSM_EVENT_LOGO_IMP:
1470 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1471 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1472 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1473 bfa_fcs_rport_timeout, rport,
1474 bfa_fcs_rport_del_timeout);
1475 break;
1476
1477 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001478 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001479 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001480 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001481 break;
1482
1483 default:
1484 bfa_sm_fault(rport->fcs, event);
1485 }
1486}
1487
Jing Huang5fbe25c2010-10-18 17:17:23 -07001488/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001489 * Nameserver discovery failed. Waiting for timeout to retry.
1490 */
1491static void
1492bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1493 enum rport_event event)
1494{
1495 bfa_trc(rport->fcs, rport->pwwn);
1496 bfa_trc(rport->fcs, rport->pid);
1497 bfa_trc(rport->fcs, event);
1498
1499 switch (event) {
1500 case RPSM_EVENT_TIMEOUT:
1501 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1502 bfa_fcs_rport_send_nsdisc(rport, NULL);
1503 break;
1504
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001505 case RPSM_EVENT_FAB_SCN:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001506 case RPSM_EVENT_ADDRESS_CHANGE:
1507 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1508 bfa_timer_stop(&rport->timer);
1509 rport->ns_retries = 0;
1510 bfa_fcs_rport_send_nsdisc(rport, NULL);
1511 break;
1512
1513 case RPSM_EVENT_DELETE:
1514 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1515 bfa_timer_stop(&rport->timer);
1516 bfa_fcs_rport_free(rport);
1517 break;
1518
1519 case RPSM_EVENT_PLOGI_RCVD:
1520 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1521 bfa_timer_stop(&rport->timer);
1522 bfa_fcs_rport_send_plogiacc(rport, NULL);
1523 break;
1524
1525 case RPSM_EVENT_LOGO_IMP:
1526 rport->pid = 0;
1527 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1528 bfa_timer_stop(&rport->timer);
1529 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1530 bfa_fcs_rport_timeout, rport,
1531 bfa_fcs_rport_del_timeout);
1532 break;
1533
1534 case RPSM_EVENT_LOGO_RCVD:
1535 bfa_fcs_rport_send_logo_acc(rport);
1536 break;
1537 case RPSM_EVENT_PRLO_RCVD:
1538 bfa_fcs_rport_send_prlo_acc(rport);
1539 break;
1540
1541 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001542 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001543 bfa_timer_stop(&rport->timer);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001544 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001545 break;
1546
1547 default:
1548 bfa_sm_fault(rport->fcs, event);
1549 }
1550}
1551
Jing Huang5fbe25c2010-10-18 17:17:23 -07001552/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001553 * Rport address has changed. Nameserver discovery request is sent.
1554 */
1555static void
1556bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1557 enum rport_event event)
1558{
1559 bfa_trc(rport->fcs, rport->pwwn);
1560 bfa_trc(rport->fcs, rport->pid);
1561 bfa_trc(rport->fcs, event);
1562
1563 switch (event) {
1564 case RPSM_EVENT_ACCEPTED:
1565 case RPSM_EVENT_ADDRESS_CHANGE:
1566 if (rport->pid) {
1567 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1568 bfa_fcs_rport_send_plogi(rport, NULL);
1569 } else {
1570 bfa_sm_set_state(rport,
1571 bfa_fcs_rport_sm_nsdisc_sending);
1572 rport->ns_retries = 0;
1573 bfa_fcs_rport_send_nsdisc(rport, NULL);
1574 }
1575 break;
1576
1577 case RPSM_EVENT_FAILED:
1578 rport->ns_retries++;
1579 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1580 bfa_sm_set_state(rport,
1581 bfa_fcs_rport_sm_nsdisc_sending);
1582 bfa_fcs_rport_send_nsdisc(rport, NULL);
1583 } else {
Krishna Gudipatiee1a4a42012-08-22 19:50:43 -07001584 rport->old_pid = rport->pid;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001585 rport->pid = 0;
1586 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1587 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1588 bfa_fcs_rport_timeout, rport,
1589 bfa_fcs_rport_del_timeout);
1590 };
1591 break;
1592
1593 case RPSM_EVENT_DELETE:
1594 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1595 bfa_fcxp_discard(rport->fcxp);
1596 bfa_fcs_rport_free(rport);
1597 break;
1598
1599 case RPSM_EVENT_PLOGI_RCVD:
1600 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1601 bfa_fcxp_discard(rport->fcxp);
1602 bfa_fcs_rport_send_plogiacc(rport, NULL);
1603 break;
1604
1605 case RPSM_EVENT_LOGO_IMP:
1606 rport->pid = 0;
1607 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1608 bfa_fcxp_discard(rport->fcxp);
1609 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1610 bfa_fcs_rport_timeout, rport,
1611 bfa_fcs_rport_del_timeout);
1612 break;
1613
1614
1615 case RPSM_EVENT_PRLO_RCVD:
1616 bfa_fcs_rport_send_prlo_acc(rport);
1617 break;
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07001618 case RPSM_EVENT_FAB_SCN:
Jing Huang5fbe25c2010-10-18 17:17:23 -07001619 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001620 * ignore, wait for NS query response
1621 */
1622 break;
1623
1624 case RPSM_EVENT_LOGO_RCVD:
Jing Huang5fbe25c2010-10-18 17:17:23 -07001625 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001626 * Not logged-in yet. Accept LOGO.
1627 */
1628 bfa_fcs_rport_send_logo_acc(rport);
1629 break;
1630
1631 case RPSM_EVENT_PLOGI_COMP:
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001632 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_fcs_online);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001633 bfa_fcxp_discard(rport->fcxp);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001634 bfa_fcs_rport_fcs_online_action(rport);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001635 break;
1636
1637 default:
1638 bfa_sm_fault(rport->fcs, event);
1639 }
1640}
1641
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001642/*
1643 * Rport needs to be deleted
1644 * waiting for ITNIM clean up to finish
1645 */
1646static void
1647bfa_fcs_rport_sm_fc4_off_delete(struct bfa_fcs_rport_s *rport,
1648 enum rport_event event)
1649{
1650 bfa_trc(rport->fcs, rport->pwwn);
1651 bfa_trc(rport->fcs, rport->pid);
1652 bfa_trc(rport->fcs, event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001653
Krishna Gudipati61ba4392012-08-22 19:52:58 -07001654 switch (event) {
1655 case RPSM_EVENT_FC4_OFFLINE:
1656 bfa_sm_set_state(rport, bfa_fcs_rport_sm_delete_pending);
1657 bfa_fcs_rport_hal_offline(rport);
1658 break;
1659
1660 case RPSM_EVENT_DELETE:
1661 case RPSM_EVENT_PLOGI_RCVD:
1662 /* Ignore these events */
1663 break;
1664
1665 default:
1666 bfa_sm_fault(rport->fcs, event);
1667 break;
1668 }
1669}
1670
1671/*
1672 * RPort needs to be deleted
1673 * waiting for BFA/FW to finish current processing
1674 */
1675static void
1676bfa_fcs_rport_sm_delete_pending(struct bfa_fcs_rport_s *rport,
1677 enum rport_event event)
1678{
1679 bfa_trc(rport->fcs, rport->pwwn);
1680 bfa_trc(rport->fcs, rport->pid);
1681 bfa_trc(rport->fcs, event);
1682
1683 switch (event) {
1684 case RPSM_EVENT_HCB_OFFLINE:
1685 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1686 bfa_fcs_rport_free(rport);
1687 break;
1688
1689 case RPSM_EVENT_DELETE:
1690 case RPSM_EVENT_LOGO_IMP:
1691 case RPSM_EVENT_PLOGI_RCVD:
1692 /* Ignore these events */
1693 break;
1694
1695 default:
1696 bfa_sm_fault(rport->fcs, event);
1697 }
1698}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001699
Jing Huang5fbe25c2010-10-18 17:17:23 -07001700/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001701 * fcs_rport_private FCS RPORT provate functions
1702 */
1703
1704static void
1705bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1706{
1707 struct bfa_fcs_rport_s *rport = rport_cbarg;
1708 struct bfa_fcs_lport_s *port = rport->port;
1709 struct fchs_s fchs;
1710 int len;
1711 struct bfa_fcxp_s *fcxp;
1712
1713 bfa_trc(rport->fcs, rport->pwwn);
1714
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001715 fcxp = fcxp_alloced ? fcxp_alloced :
1716 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001717 if (!fcxp) {
1718 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001719 bfa_fcs_rport_send_plogi, rport, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001720 return;
1721 }
1722 rport->fcxp = fcxp;
1723
1724 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1725 bfa_fcs_lport_get_fcid(port), 0,
1726 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001727 bfa_fcport_get_maxfrsize(port->fcs->bfa),
1728 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001729
1730 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1731 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
1732 (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1733
1734 rport->stats.plogis++;
1735 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1736}
1737
1738static void
1739bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1740 bfa_status_t req_status, u32 rsp_len,
1741 u32 resid_len, struct fchs_s *rsp_fchs)
1742{
1743 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1744 struct fc_logi_s *plogi_rsp;
1745 struct fc_ls_rjt_s *ls_rjt;
1746 struct bfa_fcs_rport_s *twin;
1747 struct list_head *qe;
1748
1749 bfa_trc(rport->fcs, rport->pwwn);
1750
1751 /*
1752 * Sanity Checks
1753 */
1754 if (req_status != BFA_STATUS_OK) {
1755 bfa_trc(rport->fcs, req_status);
1756 rport->stats.plogi_failed++;
1757 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1758 return;
1759 }
1760
1761 plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1762
Jing Huang5fbe25c2010-10-18 17:17:23 -07001763 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001764 * Check for failure first.
1765 */
1766 if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1767 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1768
1769 bfa_trc(rport->fcs, ls_rjt->reason_code);
1770 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1771
1772 if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&
1773 (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {
1774 rport->stats.rjt_insuff_res++;
1775 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);
1776 return;
1777 }
1778
1779 rport->stats.plogi_rejects++;
1780 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1781 return;
1782 }
1783
Jing Huang5fbe25c2010-10-18 17:17:23 -07001784 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001785 * PLOGI is complete. Make sure this device is not one of the known
1786 * device with a new FC port address.
1787 */
1788 list_for_each(qe, &rport->port->rport_q) {
1789 twin = (struct bfa_fcs_rport_s *) qe;
1790 if (twin == rport)
1791 continue;
1792 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1793 bfa_trc(rport->fcs, twin->pid);
1794 bfa_trc(rport->fcs, rport->pid);
1795
1796 /* Update plogi stats in twin */
1797 twin->stats.plogis += rport->stats.plogis;
1798 twin->stats.plogi_rejects +=
1799 rport->stats.plogi_rejects;
1800 twin->stats.plogi_timeouts +=
1801 rport->stats.plogi_timeouts;
1802 twin->stats.plogi_failed +=
1803 rport->stats.plogi_failed;
1804 twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
1805 twin->stats.plogi_accs++;
1806
Maggie Zhangf7f738122010-12-09 19:08:43 -08001807 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001808
1809 bfa_fcs_rport_update(twin, plogi_rsp);
1810 twin->pid = rsp_fchs->s_id;
1811 bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1812 return;
1813 }
1814 }
1815
Jing Huang5fbe25c2010-10-18 17:17:23 -07001816 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001817 * Normal login path -- no evil twins.
1818 */
1819 rport->stats.plogi_accs++;
1820 bfa_fcs_rport_update(rport, plogi_rsp);
1821 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1822}
1823
1824static void
1825bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1826{
1827 struct bfa_fcs_rport_s *rport = rport_cbarg;
1828 struct bfa_fcs_lport_s *port = rport->port;
1829 struct fchs_s fchs;
1830 int len;
1831 struct bfa_fcxp_s *fcxp;
1832
1833 bfa_trc(rport->fcs, rport->pwwn);
1834 bfa_trc(rport->fcs, rport->reply_oxid);
1835
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001836 fcxp = fcxp_alloced ? fcxp_alloced :
1837 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001838 if (!fcxp) {
1839 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001840 bfa_fcs_rport_send_plogiacc, rport, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001841 return;
1842 }
1843 rport->fcxp = fcxp;
1844
1845 len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1846 rport->pid, bfa_fcs_lport_get_fcid(port),
1847 rport->reply_oxid, port->port_cfg.pwwn,
1848 port->port_cfg.nwwn,
Krishna Gudipatibe540a92011-06-13 15:53:04 -07001849 bfa_fcport_get_maxfrsize(port->fcs->bfa),
1850 bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001851
1852 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1853 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1854
1855 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1856}
1857
1858static void
1859bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1860{
1861 struct bfa_fcs_rport_s *rport = rport_cbarg;
1862 struct bfa_fcs_lport_s *port = rport->port;
1863 struct fchs_s fchs;
1864 int len;
1865 struct bfa_fcxp_s *fcxp;
1866
1867 bfa_trc(rport->fcs, rport->pwwn);
1868
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001869 fcxp = fcxp_alloced ? fcxp_alloced :
1870 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001871 if (!fcxp) {
1872 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001873 bfa_fcs_rport_send_adisc, rport, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001874 return;
1875 }
1876 rport->fcxp = fcxp;
1877
1878 len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1879 bfa_fcs_lport_get_fcid(port), 0,
1880 port->port_cfg.pwwn, port->port_cfg.nwwn);
1881
1882 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1883 FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
1884 rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1885
1886 rport->stats.adisc_sent++;
1887 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1888}
1889
1890static void
1891bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1892 bfa_status_t req_status, u32 rsp_len,
1893 u32 resid_len, struct fchs_s *rsp_fchs)
1894{
1895 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1896 void *pld = bfa_fcxp_get_rspbuf(fcxp);
1897 struct fc_ls_rjt_s *ls_rjt;
1898
1899 if (req_status != BFA_STATUS_OK) {
1900 bfa_trc(rport->fcs, req_status);
1901 rport->stats.adisc_failed++;
1902 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1903 return;
1904 }
1905
1906 if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
1907 rport->nwwn) == FC_PARSE_OK) {
1908 rport->stats.adisc_accs++;
1909 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1910 return;
1911 }
1912
1913 rport->stats.adisc_rejects++;
1914 ls_rjt = pld;
1915 bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1916 bfa_trc(rport->fcs, ls_rjt->reason_code);
1917 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1918 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1919}
1920
1921static void
1922bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1923{
1924 struct bfa_fcs_rport_s *rport = rport_cbarg;
1925 struct bfa_fcs_lport_s *port = rport->port;
1926 struct fchs_s fchs;
1927 struct bfa_fcxp_s *fcxp;
1928 int len;
1929 bfa_cb_fcxp_send_t cbfn;
1930
1931 bfa_trc(rport->fcs, rport->pid);
1932
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001933 fcxp = fcxp_alloced ? fcxp_alloced :
1934 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001935 if (!fcxp) {
1936 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07001937 bfa_fcs_rport_send_nsdisc, rport, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001938 return;
1939 }
1940 rport->fcxp = fcxp;
1941
1942 if (rport->pwwn) {
1943 len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1944 bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);
1945 cbfn = bfa_fcs_rport_gidpn_response;
1946 } else {
1947 len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1948 bfa_fcs_lport_get_fcid(port), 0, rport->pid);
1949 cbfn = bfa_fcs_rport_gpnid_response;
1950 }
1951
1952 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1953 FC_CLASS_3, len, &fchs, cbfn,
1954 (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
1955
1956 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1957}
1958
1959static void
1960bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1961 bfa_status_t req_status, u32 rsp_len,
1962 u32 resid_len, struct fchs_s *rsp_fchs)
1963{
1964 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1965 struct ct_hdr_s *cthdr;
1966 struct fcgs_gidpn_resp_s *gidpn_rsp;
1967 struct bfa_fcs_rport_s *twin;
1968 struct list_head *qe;
1969
1970 bfa_trc(rport->fcs, rport->pwwn);
1971
1972 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07001973 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001974
1975 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1976 /* Check if the pid is the same as before. */
1977 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1978
1979 if (gidpn_rsp->dap == rport->pid) {
1980 /* Device is online */
1981 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1982 } else {
1983 /*
1984 * Device's PID has changed. We need to cleanup
1985 * and re-login. If there is another device with
1986 * the the newly discovered pid, send an scn notice
1987 * so that its new pid can be discovered.
1988 */
1989 list_for_each(qe, &rport->port->rport_q) {
1990 twin = (struct bfa_fcs_rport_s *) qe;
1991 if (twin == rport)
1992 continue;
1993 if (gidpn_rsp->dap == twin->pid) {
1994 bfa_trc(rport->fcs, twin->pid);
1995 bfa_trc(rport->fcs, rport->pid);
1996
1997 twin->pid = 0;
1998 bfa_sm_send_event(twin,
1999 RPSM_EVENT_ADDRESS_CHANGE);
2000 }
2001 }
2002 rport->pid = gidpn_rsp->dap;
2003 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
2004 }
2005 return;
2006 }
2007
2008 /*
2009 * Reject Response
2010 */
2011 switch (cthdr->reason_code) {
2012 case CT_RSN_LOGICAL_BUSY:
2013 /*
2014 * Need to retry
2015 */
2016 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
2017 break;
2018
2019 case CT_RSN_UNABLE_TO_PERF:
2020 /*
2021 * device doesn't exist : Start timer to cleanup this later.
2022 */
2023 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2024 break;
2025
2026 default:
2027 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2028 break;
2029 }
2030}
2031
2032static void
2033bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
2034 bfa_status_t req_status, u32 rsp_len,
2035 u32 resid_len, struct fchs_s *rsp_fchs)
2036{
2037 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2038 struct ct_hdr_s *cthdr;
2039
2040 bfa_trc(rport->fcs, rport->pwwn);
2041
2042 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
Jing Huangba816ea2010-10-18 17:10:50 -07002043 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002044
2045 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2046 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
2047 return;
2048 }
2049
2050 /*
2051 * Reject Response
2052 */
2053 switch (cthdr->reason_code) {
2054 case CT_RSN_LOGICAL_BUSY:
2055 /*
2056 * Need to retry
2057 */
2058 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
2059 break;
2060
2061 case CT_RSN_UNABLE_TO_PERF:
2062 /*
2063 * device doesn't exist : Start timer to cleanup this later.
2064 */
2065 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2066 break;
2067
2068 default:
2069 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
2070 break;
2071 }
2072}
2073
Jing Huang5fbe25c2010-10-18 17:17:23 -07002074/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002075 * Called to send a logout to the rport.
2076 */
2077static void
2078bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2079{
2080 struct bfa_fcs_rport_s *rport = rport_cbarg;
2081 struct bfa_fcs_lport_s *port;
2082 struct fchs_s fchs;
2083 struct bfa_fcxp_s *fcxp;
2084 u16 len;
2085
2086 bfa_trc(rport->fcs, rport->pid);
2087
2088 port = rport->port;
2089
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002090 fcxp = fcxp_alloced ? fcxp_alloced :
2091 bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002092 if (!fcxp) {
2093 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002094 bfa_fcs_rport_send_logo, rport, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002095 return;
2096 }
2097 rport->fcxp = fcxp;
2098
2099 len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
2100 bfa_fcs_lport_get_fcid(port), 0,
2101 bfa_fcs_lport_get_pwwn(port));
2102
2103 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2104 FC_CLASS_3, len, &fchs, NULL,
2105 rport, FC_MAX_PDUSZ, FC_ELS_TOV);
2106
2107 rport->stats.logos++;
2108 bfa_fcxp_discard(rport->fcxp);
2109 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
2110}
2111
Jing Huang5fbe25c2010-10-18 17:17:23 -07002112/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002113 * Send ACC for a LOGO received.
2114 */
2115static void
2116bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
2117{
2118 struct bfa_fcs_rport_s *rport = rport_cbarg;
2119 struct bfa_fcs_lport_s *port;
2120 struct fchs_s fchs;
2121 struct bfa_fcxp_s *fcxp;
2122 u16 len;
2123
2124 bfa_trc(rport->fcs, rport->pid);
2125
2126 port = rport->port;
2127
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002128 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002129 if (!fcxp)
2130 return;
2131
2132 rport->stats.logo_rcvd++;
2133 len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2134 rport->pid, bfa_fcs_lport_get_fcid(port),
2135 rport->reply_oxid);
2136
2137 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2138 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2139}
2140
Jing Huang5fbe25c2010-10-18 17:17:23 -07002141/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002142 * brief
2143 * This routine will be called by bfa_timer on timer timeouts.
2144 *
2145 * param[in] rport - pointer to bfa_fcs_lport_ns_t.
2146 * param[out] rport_status - pointer to return vport status in
2147 *
2148 * return
2149 * void
2150 *
2151 * Special Considerations:
2152 *
2153 * note
2154 */
2155static void
2156bfa_fcs_rport_timeout(void *arg)
2157{
2158 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;
2159
2160 rport->stats.plogi_timeouts++;
2161 bfa_stats(rport->port, rport_plogi_timeouts);
2162 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
2163}
2164
2165static void
2166bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
2167 struct fchs_s *rx_fchs, u16 len)
2168{
2169 struct bfa_fcxp_s *fcxp;
2170 struct fchs_s fchs;
2171 struct bfa_fcs_lport_s *port = rport->port;
2172 struct fc_prli_s *prli;
2173
2174 bfa_trc(port->fcs, rx_fchs->s_id);
2175 bfa_trc(port->fcs, rx_fchs->d_id);
2176
2177 rport->stats.prli_rcvd++;
2178
2179 /*
2180 * We are in Initiator Mode
2181 */
2182 prli = (struct fc_prli_s *) (rx_fchs + 1);
2183
2184 if (prli->parampage.servparams.target) {
2185 /*
2186 * PRLI from a target ?
2187 * Send the Acc.
2188 * PRLI sent by us will be used to transition the IT nexus,
2189 * once the response is received from the target.
2190 */
2191 bfa_trc(port->fcs, rx_fchs->s_id);
2192 rport->scsi_function = BFA_RPORT_TARGET;
2193 } else {
2194 bfa_trc(rport->fcs, prli->parampage.type);
2195 rport->scsi_function = BFA_RPORT_INITIATOR;
2196 bfa_fcs_itnim_is_initiator(rport->itnim);
2197 }
2198
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002199 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002200 if (!fcxp)
2201 return;
2202
2203 len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2204 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2205 rx_fchs->ox_id, port->port_cfg.roles);
2206
2207 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2208 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2209}
2210
2211static void
2212bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
2213 struct fchs_s *rx_fchs, u16 len)
2214{
2215 struct bfa_fcxp_s *fcxp;
2216 struct fchs_s fchs;
2217 struct bfa_fcs_lport_s *port = rport->port;
2218 struct fc_rpsc_speed_info_s speeds;
2219 struct bfa_port_attr_s pport_attr;
2220
2221 bfa_trc(port->fcs, rx_fchs->s_id);
2222 bfa_trc(port->fcs, rx_fchs->d_id);
2223
2224 rport->stats.rpsc_rcvd++;
2225 speeds.port_speed_cap =
2226 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
2227 RPSC_SPEED_CAP_8G;
2228
2229 /*
2230 * get curent speed from pport attributes from BFA
2231 */
2232 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2233
2234 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
2235
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002236 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002237 if (!fcxp)
2238 return;
2239
2240 len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2241 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2242 rx_fchs->ox_id, &speeds);
2243
2244 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2245 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2246}
2247
2248static void
2249bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
2250 struct fchs_s *rx_fchs, u16 len)
2251{
2252 struct bfa_fcxp_s *fcxp;
2253 struct fchs_s fchs;
2254 struct bfa_fcs_lport_s *port = rport->port;
2255 struct fc_adisc_s *adisc;
2256
2257 bfa_trc(port->fcs, rx_fchs->s_id);
2258 bfa_trc(port->fcs, rx_fchs->d_id);
2259
2260 rport->stats.adisc_rcvd++;
2261
2262 adisc = (struct fc_adisc_s *) (rx_fchs + 1);
2263
2264 /*
2265 * Accept if the itnim for this rport is online.
2266 * Else reject the ADISC.
2267 */
2268 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
2269
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002270 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002271 if (!fcxp)
2272 return;
2273
2274 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2275 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2276 rx_fchs->ox_id, port->port_cfg.pwwn,
2277 port->port_cfg.nwwn);
2278
2279 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2280 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2281 FC_MAX_PDUSZ, 0);
2282 } else {
2283 rport->stats.adisc_rejected++;
2284 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
2285 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
2286 FC_LS_RJT_EXP_LOGIN_REQUIRED);
2287 }
2288}
2289
2290static void
2291bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
2292{
2293 struct bfa_fcs_lport_s *port = rport->port;
2294 struct bfa_rport_info_s rport_info;
2295
2296 rport_info.pid = rport->pid;
2297 rport_info.local_pid = port->pid;
2298 rport_info.lp_tag = port->lp_tag;
2299 rport_info.vf_id = port->fabric->vf_id;
2300 rport_info.vf_en = port->fabric->is_vf;
2301 rport_info.fc_class = rport->fc_cos;
2302 rport_info.cisc = rport->cisc;
2303 rport_info.max_frmsz = rport->maxfrsize;
2304 bfa_rport_online(rport->bfa_rport, &rport_info);
2305}
2306
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002307static void
2308bfa_fcs_rport_hal_offline(struct bfa_fcs_rport_s *rport)
2309{
2310 if (rport->bfa_rport)
2311 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_OFFLINE);
2312 else
2313 bfa_cb_rport_offline(rport);
2314}
2315
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002316static struct bfa_fcs_rport_s *
2317bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
2318{
2319 struct bfa_fcs_s *fcs = port->fcs;
2320 struct bfa_fcs_rport_s *rport;
2321 struct bfad_rport_s *rport_drv;
2322
Jing Huang5fbe25c2010-10-18 17:17:23 -07002323 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002324 * allocate rport
2325 */
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002326 if (fcs->num_rport_logins >= bfa_fcs_rport_max_logins) {
2327 bfa_trc(fcs, rpid);
2328 return NULL;
2329 }
2330
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002331 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
2332 != BFA_STATUS_OK) {
2333 bfa_trc(fcs, rpid);
2334 return NULL;
2335 }
2336
2337 /*
2338 * Initialize r-port
2339 */
2340 rport->port = port;
2341 rport->fcs = fcs;
2342 rport->rp_drv = rport_drv;
2343 rport->pid = rpid;
2344 rport->pwwn = pwwn;
Krishna Gudipatiee1a4a42012-08-22 19:50:43 -07002345 rport->old_pid = 0;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002346
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002347 rport->bfa_rport = NULL;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002348
Jing Huang5fbe25c2010-10-18 17:17:23 -07002349 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002350 * allocate FC-4s
2351 */
Jing Huangd4b671c2010-12-26 21:46:35 -08002352 WARN_ON(!bfa_fcs_lport_is_initiator(port));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002353
2354 if (bfa_fcs_lport_is_initiator(port)) {
2355 rport->itnim = bfa_fcs_itnim_create(rport);
2356 if (!rport->itnim) {
2357 bfa_trc(fcs, rpid);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002358 kfree(rport_drv);
2359 return NULL;
2360 }
2361 }
2362
2363 bfa_fcs_lport_add_rport(port, rport);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002364 fcs->num_rport_logins++;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002365
2366 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2367
2368 /* Initialize the Rport Features(RPF) Sub Module */
2369 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2370 bfa_fcs_rpf_init(rport);
2371
2372 return rport;
2373}
2374
2375
2376static void
2377bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2378{
2379 struct bfa_fcs_lport_s *port = rport->port;
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002380 struct bfa_fcs_s *fcs = port->fcs;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002381
Jing Huang5fbe25c2010-10-18 17:17:23 -07002382 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002383 * - delete FC-4s
2384 * - delete BFA rport
2385 * - remove from queue of rports
2386 */
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002387 rport->plogi_pending = BFA_FALSE;
2388
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002389 if (bfa_fcs_lport_is_initiator(port)) {
2390 bfa_fcs_itnim_delete(rport->itnim);
2391 if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
2392 bfa_fcs_rpf_rport_offline(rport);
2393 }
2394
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002395 if (rport->bfa_rport) {
2396 bfa_sm_send_event(rport->bfa_rport, BFA_RPORT_SM_DELETE);
2397 rport->bfa_rport = NULL;
2398 }
2399
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002400 bfa_fcs_lport_del_rport(port, rport);
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002401 fcs->num_rport_logins--;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002402 kfree(rport->rp_drv);
2403}
2404
2405static void
Krishna Gudipati7826f302011-07-20 16:59:13 -07002406bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2407 enum bfa_rport_aen_event event,
2408 struct bfa_rport_aen_data_s *data)
2409{
2410 struct bfa_fcs_lport_s *port = rport->port;
2411 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2412 struct bfa_aen_entry_s *aen_entry;
2413
2414 bfad_get_aen_entry(bfad, aen_entry);
2415 if (!aen_entry)
2416 return;
2417
2418 if (event == BFA_RPORT_AEN_QOS_PRIO)
2419 aen_entry->aen_data.rport.priv.qos = data->priv.qos;
2420 else if (event == BFA_RPORT_AEN_QOS_FLOWID)
2421 aen_entry->aen_data.rport.priv.qos = data->priv.qos;
2422
2423 aen_entry->aen_data.rport.vf_id = rport->port->fabric->vf_id;
2424 aen_entry->aen_data.rport.ppwwn = bfa_fcs_lport_get_pwwn(
2425 bfa_fcs_get_base_port(rport->fcs));
2426 aen_entry->aen_data.rport.lpwwn = bfa_fcs_lport_get_pwwn(rport->port);
2427 aen_entry->aen_data.rport.rpwwn = rport->pwwn;
2428
2429 /* Send the AEN notification */
2430 bfad_im_post_vendor_event(aen_entry, bfad, ++rport->fcs->fcs_aen_seq,
2431 BFA_AEN_CAT_RPORT, event);
2432}
2433
2434static void
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002435bfa_fcs_rport_fcs_online_action(struct bfa_fcs_rport_s *rport)
2436{
2437 if ((!rport->pid) || (!rport->pwwn)) {
2438 bfa_trc(rport->fcs, rport->pid);
2439 bfa_sm_fault(rport->fcs, rport->pid);
2440 }
2441
2442 bfa_sm_send_event(rport->itnim, BFA_FCS_ITNIM_SM_FCS_ONLINE);
2443}
2444
2445static void
2446bfa_fcs_rport_hal_online_action(struct bfa_fcs_rport_s *rport)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002447{
2448 struct bfa_fcs_lport_s *port = rport->port;
2449 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2450 char lpwwn_buf[BFA_STRING_32];
2451 char rpwwn_buf[BFA_STRING_32];
2452
2453 rport->stats.onlines++;
2454
Krishna Gudipatid7be54c2011-06-24 20:24:52 -07002455 if ((!rport->pid) || (!rport->pwwn)) {
2456 bfa_trc(rport->fcs, rport->pid);
2457 bfa_sm_fault(rport->fcs, rport->pid);
2458 }
2459
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002460 if (bfa_fcs_lport_is_initiator(port)) {
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002461 bfa_fcs_itnim_brp_online(rport->itnim);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002462 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2463 bfa_fcs_rpf_rport_online(rport);
2464 };
2465
2466 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2467 wwn2str(rpwwn_buf, rport->pwwn);
Krishna Gudipati7826f302011-07-20 16:59:13 -07002468 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
Jing Huang88166242010-12-09 17:11:53 -08002469 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002470 "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
2471 rpwwn_buf, lpwwn_buf);
Krishna Gudipati7826f302011-07-20 16:59:13 -07002472 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2473 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002474}
2475
2476static void
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002477bfa_fcs_rport_fcs_offline_action(struct bfa_fcs_rport_s *rport)
2478{
2479 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2480 bfa_fcs_rpf_rport_offline(rport);
2481
2482 bfa_fcs_itnim_rport_offline(rport->itnim);
2483}
2484
2485static void
2486bfa_fcs_rport_hal_offline_action(struct bfa_fcs_rport_s *rport)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002487{
2488 struct bfa_fcs_lport_s *port = rport->port;
2489 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2490 char lpwwn_buf[BFA_STRING_32];
2491 char rpwwn_buf[BFA_STRING_32];
2492
Krishna Gudipati61ba4392012-08-22 19:52:58 -07002493 if (!rport->bfa_rport) {
2494 bfa_fcs_rport_fcs_offline_action(rport);
2495 return;
2496 }
2497
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002498 rport->stats.offlines++;
2499
2500 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2501 wwn2str(rpwwn_buf, rport->pwwn);
2502 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
Krishna Gudipati7826f302011-07-20 16:59:13 -07002503 if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE) {
Jing Huang88166242010-12-09 17:11:53 -08002504 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002505 "Remote port (WWN = %s) connectivity lost for "
2506 "logical port (WWN = %s)\n",
2507 rpwwn_buf, lpwwn_buf);
Krishna Gudipati7826f302011-07-20 16:59:13 -07002508 bfa_fcs_rport_aen_post(rport,
2509 BFA_RPORT_AEN_DISCONNECT, NULL);
2510 } else {
Jing Huang88166242010-12-09 17:11:53 -08002511 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002512 "Remote port (WWN = %s) offlined by "
2513 "logical port (WWN = %s)\n",
2514 rpwwn_buf, lpwwn_buf);
Krishna Gudipati7826f302011-07-20 16:59:13 -07002515 bfa_fcs_rport_aen_post(rport,
2516 BFA_RPORT_AEN_OFFLINE, NULL);
2517 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002518 }
2519
2520 if (bfa_fcs_lport_is_initiator(port)) {
2521 bfa_fcs_itnim_rport_offline(rport->itnim);
2522 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2523 bfa_fcs_rpf_rport_offline(rport);
2524 }
2525}
2526
Jing Huang5fbe25c2010-10-18 17:17:23 -07002527/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002528 * Update rport parameters from PLOGI or PLOGI accept.
2529 */
2530static void
2531bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2532{
2533 bfa_fcs_lport_t *port = rport->port;
2534
Jing Huang5fbe25c2010-10-18 17:17:23 -07002535 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002536 * - port name
2537 * - node name
2538 */
2539 rport->pwwn = plogi->port_name;
2540 rport->nwwn = plogi->node_name;
2541
Jing Huang5fbe25c2010-10-18 17:17:23 -07002542 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002543 * - class of service
2544 */
2545 rport->fc_cos = 0;
2546 if (plogi->class3.class_valid)
2547 rport->fc_cos = FC_CLASS_3;
2548
2549 if (plogi->class2.class_valid)
2550 rport->fc_cos |= FC_CLASS_2;
2551
Jing Huang5fbe25c2010-10-18 17:17:23 -07002552 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002553 * - CISC
2554 * - MAX receive frame size
2555 */
2556 rport->cisc = plogi->csp.cisc;
Krishna Gudipatibd5a0262012-03-13 17:41:02 -07002557 if (be16_to_cpu(plogi->class3.rxsz) < be16_to_cpu(plogi->csp.rxsz))
2558 rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz);
2559 else
2560 rport->maxfrsize = be16_to_cpu(plogi->csp.rxsz);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002561
Jing Huangba816ea2010-10-18 17:10:50 -07002562 bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002563 bfa_trc(port->fcs, port->fabric->bb_credit);
Jing Huang5fbe25c2010-10-18 17:17:23 -07002564 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002565 * Direct Attach P2P mode :
2566 * This is to handle a bug (233476) in IBM targets in Direct Attach
2567 * Mode. Basically, in FLOGI Accept the target would have
2568 * erroneously set the BB Credit to the value used in the FLOGI
2569 * sent by the HBA. It uses the correct value (its own BB credit)
2570 * in PLOGI.
2571 */
2572 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
Jing Huangba816ea2010-10-18 17:10:50 -07002573 (be16_to_cpu(plogi->csp.bbcred) < port->fabric->bb_credit)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002574
Jing Huangba816ea2010-10-18 17:10:50 -07002575 bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002576 bfa_trc(port->fcs, port->fabric->bb_credit);
2577
Jing Huangba816ea2010-10-18 17:10:50 -07002578 port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002579 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
Krishna Gudipatibe540a92011-06-13 15:53:04 -07002580 port->fabric->bb_credit, 0);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002581 }
2582
2583}
2584
Jing Huang5fbe25c2010-10-18 17:17:23 -07002585/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002586 * Called to handle LOGO received from an existing remote port.
2587 */
2588static void
2589bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2590{
2591 rport->reply_oxid = fchs->ox_id;
2592 bfa_trc(rport->fcs, rport->reply_oxid);
2593
2594 rport->prlo = BFA_FALSE;
2595 rport->stats.logo_rcvd++;
2596 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2597}
2598
2599
2600
Jing Huang5fbe25c2010-10-18 17:17:23 -07002601/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002602 * fcs_rport_public FCS rport public interfaces
2603 */
2604
Jing Huang5fbe25c2010-10-18 17:17:23 -07002605/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002606 * Called by bport/vport to create a remote port instance for a discovered
2607 * remote device.
2608 *
2609 * @param[in] port - base port or vport
2610 * @param[in] rpid - remote port ID
2611 *
2612 * @return None
2613 */
2614struct bfa_fcs_rport_s *
2615bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
2616{
2617 struct bfa_fcs_rport_s *rport;
2618
2619 bfa_trc(port->fcs, rpid);
2620 rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2621 if (!rport)
2622 return NULL;
2623
2624 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2625 return rport;
2626}
2627
Jing Huang5fbe25c2010-10-18 17:17:23 -07002628/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002629 * Called to create a rport for which only the wwn is known.
2630 *
2631 * @param[in] port - base port
2632 * @param[in] rpwwn - remote port wwn
2633 *
2634 * @return None
2635 */
2636struct bfa_fcs_rport_s *
2637bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
2638{
2639 struct bfa_fcs_rport_s *rport;
2640 bfa_trc(port->fcs, rpwwn);
2641 rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2642 if (!rport)
2643 return NULL;
2644
2645 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2646 return rport;
2647}
Jing Huang5fbe25c2010-10-18 17:17:23 -07002648/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002649 * Called by bport in private loop topology to indicate that a
2650 * rport has been discovered and plogi has been completed.
2651 *
2652 * @param[in] port - base port or vport
2653 * @param[in] rpid - remote port ID
2654 */
2655void
2656bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2657 struct fc_logi_s *plogi)
2658{
2659 struct bfa_fcs_rport_s *rport;
2660
2661 rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2662 if (!rport)
2663 return;
2664
2665 bfa_fcs_rport_update(rport, plogi);
2666
2667 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2668}
2669
Jing Huang5fbe25c2010-10-18 17:17:23 -07002670/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002671 * Called by bport/vport to handle PLOGI received from a new remote port.
2672 * If an existing rport does a plogi, it will be handled separately.
2673 */
2674void
2675bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2676 struct fc_logi_s *plogi)
2677{
2678 struct bfa_fcs_rport_s *rport;
2679
2680 rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2681 if (!rport)
2682 return;
2683
2684 bfa_fcs_rport_update(rport, plogi);
2685
2686 rport->reply_oxid = fchs->ox_id;
2687 bfa_trc(rport->fcs, rport->reply_oxid);
2688
2689 rport->stats.plogi_rcvd++;
2690 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2691}
2692
Jing Huang5fbe25c2010-10-18 17:17:23 -07002693/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002694 * Called by bport/vport to handle PLOGI received from an existing
2695 * remote port.
2696 */
2697void
2698bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2699 struct fc_logi_s *plogi)
2700{
Jing Huang5fbe25c2010-10-18 17:17:23 -07002701 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002702 * @todo Handle P2P and initiator-initiator.
2703 */
2704
2705 bfa_fcs_rport_update(rport, plogi);
2706
2707 rport->reply_oxid = rx_fchs->ox_id;
2708 bfa_trc(rport->fcs, rport->reply_oxid);
2709
Krishna Gudipatid7be54c2011-06-24 20:24:52 -07002710 rport->pid = rx_fchs->s_id;
2711 bfa_trc(rport->fcs, rport->pid);
2712
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002713 rport->stats.plogi_rcvd++;
2714 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2715}
2716
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002717
Jing Huang5fbe25c2010-10-18 17:17:23 -07002718/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002719 * Called by bport/vport to notify SCN for the remote port
2720 */
2721void
2722bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2723{
2724 rport->stats.rscns++;
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07002725 bfa_sm_send_event(rport, RPSM_EVENT_FAB_SCN);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002726}
2727
Jing Huang5fbe25c2010-10-18 17:17:23 -07002728/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002729 * brief
2730 * This routine BFA callback for bfa_rport_online() call.
2731 *
2732 * param[in] cb_arg - rport struct.
2733 *
2734 * return
2735 * void
2736 *
2737 * Special Considerations:
2738 *
2739 * note
2740 */
2741void
2742bfa_cb_rport_online(void *cbarg)
2743{
2744
2745 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2746
2747 bfa_trc(rport->fcs, rport->pwwn);
2748 bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2749}
2750
Jing Huang5fbe25c2010-10-18 17:17:23 -07002751/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002752 * brief
2753 * This routine BFA callback for bfa_rport_offline() call.
2754 *
2755 * param[in] rport -
2756 *
2757 * return
2758 * void
2759 *
2760 * Special Considerations:
2761 *
2762 * note
2763 */
2764void
2765bfa_cb_rport_offline(void *cbarg)
2766{
2767 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
2768
2769 bfa_trc(rport->fcs, rport->pwwn);
2770 bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2771}
2772
Jing Huang5fbe25c2010-10-18 17:17:23 -07002773/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002774 * brief
2775 * This routine is a static BFA callback when there is a QoS flow_id
2776 * change notification
2777 *
2778 * param[in] rport -
2779 *
2780 * return
2781 * void
2782 *
2783 * Special Considerations:
2784 *
2785 * note
2786 */
2787void
2788bfa_cb_rport_qos_scn_flowid(void *cbarg,
2789 struct bfa_rport_qos_attr_s old_qos_attr,
2790 struct bfa_rport_qos_attr_s new_qos_attr)
2791{
2792 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
Krishna Gudipati7826f302011-07-20 16:59:13 -07002793 struct bfa_rport_aen_data_s aen_data;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002794
2795 bfa_trc(rport->fcs, rport->pwwn);
Krishna Gudipati7826f302011-07-20 16:59:13 -07002796 aen_data.priv.qos = new_qos_attr;
2797 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002798}
2799
Krishna Gudipatibc0e2c22012-09-21 17:23:59 -07002800void
2801bfa_cb_rport_scn_online(struct bfa_s *bfa)
2802{
2803 struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
2804 struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
2805 struct bfa_fcs_rport_s *rp;
2806 struct list_head *qe;
2807
2808 list_for_each(qe, &port->rport_q) {
2809 rp = (struct bfa_fcs_rport_s *) qe;
2810 bfa_sm_send_event(rp, RPSM_EVENT_SCN_ONLINE);
2811 rp->scn_online = BFA_TRUE;
2812 }
2813
2814 if (bfa_fcs_lport_is_online(port))
2815 bfa_fcs_lport_lip_scn_online(port);
2816}
2817
2818void
2819bfa_cb_rport_scn_no_dev(void *rport)
2820{
2821 struct bfa_fcs_rport_s *rp = rport;
2822
2823 bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
2824 rp->scn_online = BFA_FALSE;
2825}
2826
2827void
2828bfa_cb_rport_scn_offline(struct bfa_s *bfa)
2829{
2830 struct bfa_fcs_s *fcs = &((struct bfad_s *)bfa->bfad)->bfa_fcs;
2831 struct bfa_fcs_lport_s *port = bfa_fcs_get_base_port(fcs);
2832 struct bfa_fcs_rport_s *rp;
2833 struct list_head *qe;
2834
2835 list_for_each(qe, &port->rport_q) {
2836 rp = (struct bfa_fcs_rport_s *) qe;
2837 bfa_sm_send_event(rp, RPSM_EVENT_SCN_OFFLINE);
2838 rp->scn_online = BFA_FALSE;
2839 }
2840}
2841
Jing Huang5fbe25c2010-10-18 17:17:23 -07002842/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002843 * brief
2844 * This routine is a static BFA callback when there is a QoS priority
2845 * change notification
2846 *
2847 * param[in] rport -
2848 *
2849 * return
2850 * void
2851 *
2852 * Special Considerations:
2853 *
2854 * note
2855 */
2856void
2857bfa_cb_rport_qos_scn_prio(void *cbarg,
2858 struct bfa_rport_qos_attr_s old_qos_attr,
2859 struct bfa_rport_qos_attr_s new_qos_attr)
2860{
2861 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
Krishna Gudipati7826f302011-07-20 16:59:13 -07002862 struct bfa_rport_aen_data_s aen_data;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002863
2864 bfa_trc(rport->fcs, rport->pwwn);
Krishna Gudipati7826f302011-07-20 16:59:13 -07002865 aen_data.priv.qos = new_qos_attr;
2866 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002867}
2868
Jing Huang5fbe25c2010-10-18 17:17:23 -07002869/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002870 * Called to process any unsolicted frames from this remote port
2871 */
2872void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002873bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
2874 struct fchs_s *fchs, u16 len)
2875{
2876 struct bfa_fcs_lport_s *port = rport->port;
2877 struct fc_els_cmd_s *els_cmd;
2878
2879 bfa_trc(rport->fcs, fchs->s_id);
2880 bfa_trc(rport->fcs, fchs->d_id);
2881 bfa_trc(rport->fcs, fchs->type);
2882
2883 if (fchs->type != FC_TYPE_ELS)
2884 return;
2885
2886 els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2887
2888 bfa_trc(rport->fcs, els_cmd->els_code);
2889
2890 switch (els_cmd->els_code) {
2891 case FC_ELS_LOGO:
2892 bfa_stats(port, plogi_rcvd);
2893 bfa_fcs_rport_process_logo(rport, fchs);
2894 break;
2895
2896 case FC_ELS_ADISC:
2897 bfa_stats(port, adisc_rcvd);
2898 bfa_fcs_rport_process_adisc(rport, fchs, len);
2899 break;
2900
2901 case FC_ELS_PRLO:
2902 bfa_stats(port, prlo_rcvd);
2903 if (bfa_fcs_lport_is_initiator(port))
2904 bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2905 break;
2906
2907 case FC_ELS_PRLI:
2908 bfa_stats(port, prli_rcvd);
2909 bfa_fcs_rport_process_prli(rport, fchs, len);
2910 break;
2911
2912 case FC_ELS_RPSC:
2913 bfa_stats(port, rpsc_rcvd);
2914 bfa_fcs_rport_process_rpsc(rport, fchs, len);
2915 break;
2916
2917 default:
2918 bfa_stats(port, un_handled_els_rcvd);
2919 bfa_fcs_rport_send_ls_rjt(rport, fchs,
2920 FC_LS_RJT_RSN_CMD_NOT_SUPP,
2921 FC_LS_RJT_EXP_NO_ADDL_INFO);
2922 break;
2923 }
2924}
2925
2926/* send best case acc to prlo */
2927static void
2928bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2929{
2930 struct bfa_fcs_lport_s *port = rport->port;
2931 struct fchs_s fchs;
2932 struct bfa_fcxp_s *fcxp;
2933 int len;
2934
2935 bfa_trc(rport->fcs, rport->pid);
2936
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002937 fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002938 if (!fcxp)
2939 return;
2940 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2941 rport->pid, bfa_fcs_lport_get_fcid(port),
2942 rport->reply_oxid, 0);
2943
2944 bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
2945 port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
2946 NULL, NULL, FC_MAX_PDUSZ, 0);
2947}
2948
2949/*
2950 * Send a LS reject
2951 */
2952static void
2953bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2954 u8 reason_code, u8 reason_code_expl)
2955{
2956 struct bfa_fcs_lport_s *port = rport->port;
2957 struct fchs_s fchs;
2958 struct bfa_fcxp_s *fcxp;
2959 int len;
2960
2961 bfa_trc(rport->fcs, rx_fchs->s_id);
2962
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07002963 fcxp = bfa_fcs_fcxp_alloc(rport->fcs, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002964 if (!fcxp)
2965 return;
2966
2967 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2968 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2969 rx_fchs->ox_id, reason_code, reason_code_expl);
2970
2971 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2972 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2973 FC_MAX_PDUSZ, 0);
2974}
2975
Jing Huang5fbe25c2010-10-18 17:17:23 -07002976/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002977 * Return state of rport.
2978 */
2979int
2980bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2981{
2982 return bfa_sm_to_state(rport_sm_table, rport->sm);
2983}
2984
Maggie Zhangf7f738122010-12-09 19:08:43 -08002985
Jing Huang5fbe25c2010-10-18 17:17:23 -07002986/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002987 * brief
2988 * Called by the Driver to set rport delete/ageout timeout
2989 *
2990 * param[in] rport timeout value in seconds.
2991 *
2992 * return None
2993 */
2994void
2995bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2996{
2997 /* convert to Millisecs */
2998 if (rport_tmo > 0)
2999 bfa_fcs_rport_del_timeout = rport_tmo * 1000;
3000}
3001void
Maggie50444a32010-11-29 18:26:32 -08003002bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, __be16 ox_id)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003003{
3004 bfa_trc(rport->fcs, rport->pid);
3005
3006 rport->prlo = BFA_TRUE;
3007 rport->reply_oxid = ox_id;
3008 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
3009}
3010
Krishna Gudipati61ba4392012-08-22 19:52:58 -07003011/*
3012 * Called by BFAD to set the max limit on number of bfa_fcs_rport allocation
3013 * which limits number of concurrent logins to remote ports
3014 */
3015void
3016bfa_fcs_rport_set_max_logins(u32 max_logins)
3017{
3018 if (max_logins > 0)
3019 bfa_fcs_rport_max_logins = max_logins;
3020}
3021
Krishna Gudipati60138062011-06-24 20:25:15 -07003022void
3023bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
3024 struct bfa_rport_attr_s *rport_attr)
3025{
3026 struct bfa_rport_qos_attr_s qos_attr;
3027 struct bfa_fcs_lport_s *port = rport->port;
3028 bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
Krishna Gudipati7ace27a2012-09-21 17:26:41 -07003029 struct bfa_port_attr_s port_attr;
3030
3031 bfa_fcport_get_attr(rport->fcs->bfa, &port_attr);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003032
Krishna Gudipati60138062011-06-24 20:25:15 -07003033 memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
3034 memset(&qos_attr, 0, sizeof(struct bfa_rport_qos_attr_s));
3035
3036 rport_attr->pid = rport->pid;
3037 rport_attr->pwwn = rport->pwwn;
3038 rport_attr->nwwn = rport->nwwn;
3039 rport_attr->cos_supported = rport->fc_cos;
3040 rport_attr->df_sz = rport->maxfrsize;
3041 rport_attr->state = bfa_fcs_rport_get_state(rport);
3042 rport_attr->fc_cos = rport->fc_cos;
3043 rport_attr->cisc = rport->cisc;
3044 rport_attr->scsi_function = rport->scsi_function;
3045 rport_attr->curr_speed = rport->rpf.rpsc_speed;
3046 rport_attr->assigned_speed = rport->rpf.assigned_speed;
3047
Krishna Gudipati61ba4392012-08-22 19:52:58 -07003048 if (rport->bfa_rport) {
3049 qos_attr.qos_priority = rport->bfa_rport->qos_attr.qos_priority;
3050 qos_attr.qos_flow_id =
3051 cpu_to_be32(rport->bfa_rport->qos_attr.qos_flow_id);
3052 }
Krishna Gudipati60138062011-06-24 20:25:15 -07003053 rport_attr->qos_attr = qos_attr;
3054
3055 rport_attr->trl_enforced = BFA_FALSE;
3056 if (bfa_fcport_is_ratelim(port->fcs->bfa) &&
3057 (rport->scsi_function == BFA_RPORT_TARGET)) {
3058 if (rport_speed == BFA_PORT_SPEED_UNKNOWN)
3059 rport_speed =
3060 bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
3061
Krishna Gudipati7ace27a2012-09-21 17:26:41 -07003062 if ((bfa_fcs_lport_get_rport_max_speed(port) !=
3063 BFA_PORT_SPEED_UNKNOWN) && (rport_speed < port_attr.speed))
Krishna Gudipati60138062011-06-24 20:25:15 -07003064 rport_attr->trl_enforced = BFA_TRUE;
3065 }
3066}
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003067
Jing Huang5fbe25c2010-10-18 17:17:23 -07003068/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003069 * Remote port implementation.
3070 */
3071
Jing Huang5fbe25c2010-10-18 17:17:23 -07003072/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003073 * fcs_rport_api FCS rport API.
3074 */
3075
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003076struct bfa_fcs_rport_s *
3077bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
3078{
3079 struct bfa_fcs_rport_s *rport;
3080
3081 rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
3082 if (rport == NULL) {
3083 /*
3084 * TBD Error handling
3085 */
3086 }
3087
3088 return rport;
3089}
3090
3091struct bfa_fcs_rport_s *
3092bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
3093{
3094 struct bfa_fcs_rport_s *rport;
3095
3096 rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
3097 if (rport == NULL) {
3098 /*
3099 * TBD Error handling
3100 */
3101 }
3102
3103 return rport;
3104}
3105
3106/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003107 * Remote port features (RPF) implementation.
3108 */
3109
3110#define BFA_FCS_RPF_RETRIES (3)
3111#define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */
3112
3113static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
3114 struct bfa_fcxp_s *fcxp_alloced);
3115static void bfa_fcs_rpf_rpsc2_response(void *fcsarg,
3116 struct bfa_fcxp_s *fcxp,
3117 void *cbarg,
3118 bfa_status_t req_status,
3119 u32 rsp_len,
3120 u32 resid_len,
3121 struct fchs_s *rsp_fchs);
3122
3123static void bfa_fcs_rpf_timeout(void *arg);
3124
Jing Huang5fbe25c2010-10-18 17:17:23 -07003125/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003126 * fcs_rport_ftrs_sm FCS rport state machine events
3127 */
3128
3129enum rpf_event {
3130 RPFSM_EVENT_RPORT_OFFLINE = 1, /* Rport offline */
3131 RPFSM_EVENT_RPORT_ONLINE = 2, /* Rport online */
3132 RPFSM_EVENT_FCXP_SENT = 3, /* Frame from has been sent */
3133 RPFSM_EVENT_TIMEOUT = 4, /* Rport SM timeout event */
3134 RPFSM_EVENT_RPSC_COMP = 5,
3135 RPFSM_EVENT_RPSC_FAIL = 6,
3136 RPFSM_EVENT_RPSC_ERROR = 7,
3137};
3138
3139static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
3140 enum rpf_event event);
3141static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
3142 enum rpf_event event);
3143static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
3144 enum rpf_event event);
3145static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
3146 enum rpf_event event);
3147static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
3148 enum rpf_event event);
3149static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
3150 enum rpf_event event);
3151
3152static void
3153bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3154{
3155 struct bfa_fcs_rport_s *rport = rpf->rport;
3156 struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
3157
3158 bfa_trc(rport->fcs, rport->pwwn);
3159 bfa_trc(rport->fcs, rport->pid);
3160 bfa_trc(rport->fcs, event);
3161
3162 switch (event) {
3163 case RPFSM_EVENT_RPORT_ONLINE:
3164 /* Send RPSC2 to a Brocade fabric only. */
3165 if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
Maggie Zhangf7f738122010-12-09 19:08:43 -08003166 ((rport->port->fabric->lps->brcd_switch) ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003167 (bfa_fcs_fabric_get_switch_oui(fabric) ==
3168 BFA_FCS_BRCD_SWITCH_OUI))) {
3169 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3170 rpf->rpsc_retries = 0;
3171 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3172 }
3173 break;
3174
3175 case RPFSM_EVENT_RPORT_OFFLINE:
3176 break;
3177
3178 default:
3179 bfa_sm_fault(rport->fcs, event);
3180 }
3181}
3182
3183static void
3184bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3185{
3186 struct bfa_fcs_rport_s *rport = rpf->rport;
3187
3188 bfa_trc(rport->fcs, event);
3189
3190 switch (event) {
3191 case RPFSM_EVENT_FCXP_SENT:
3192 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
3193 break;
3194
3195 case RPFSM_EVENT_RPORT_OFFLINE:
3196 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3197 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
3198 rpf->rpsc_retries = 0;
3199 break;
3200
3201 default:
3202 bfa_sm_fault(rport->fcs, event);
3203 }
3204}
3205
3206static void
3207bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3208{
3209 struct bfa_fcs_rport_s *rport = rpf->rport;
3210
3211 bfa_trc(rport->fcs, rport->pid);
3212 bfa_trc(rport->fcs, event);
3213
3214 switch (event) {
3215 case RPFSM_EVENT_RPSC_COMP:
3216 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3217 /* Update speed info in f/w via BFA */
3218 if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
3219 bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
3220 else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
3221 bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
3222 break;
3223
3224 case RPFSM_EVENT_RPSC_FAIL:
3225 /* RPSC not supported by rport */
3226 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3227 break;
3228
3229 case RPFSM_EVENT_RPSC_ERROR:
3230 /* need to retry...delayed a bit. */
3231 if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
3232 bfa_timer_start(rport->fcs->bfa, &rpf->timer,
3233 bfa_fcs_rpf_timeout, rpf,
3234 BFA_FCS_RPF_RETRY_TIMEOUT);
3235 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
3236 } else {
3237 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
3238 }
3239 break;
3240
3241 case RPFSM_EVENT_RPORT_OFFLINE:
3242 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3243 bfa_fcxp_discard(rpf->fcxp);
3244 rpf->rpsc_retries = 0;
3245 break;
3246
3247 default:
3248 bfa_sm_fault(rport->fcs, event);
3249 }
3250}
3251
3252static void
3253bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3254{
3255 struct bfa_fcs_rport_s *rport = rpf->rport;
3256
3257 bfa_trc(rport->fcs, rport->pid);
3258 bfa_trc(rport->fcs, event);
3259
3260 switch (event) {
3261 case RPFSM_EVENT_TIMEOUT:
3262 /* re-send the RPSC */
3263 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3264 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3265 break;
3266
3267 case RPFSM_EVENT_RPORT_OFFLINE:
3268 bfa_timer_stop(&rpf->timer);
3269 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3270 rpf->rpsc_retries = 0;
3271 break;
3272
3273 default:
3274 bfa_sm_fault(rport->fcs, event);
3275 }
3276}
3277
3278static void
3279bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3280{
3281 struct bfa_fcs_rport_s *rport = rpf->rport;
3282
3283 bfa_trc(rport->fcs, rport->pwwn);
3284 bfa_trc(rport->fcs, rport->pid);
3285 bfa_trc(rport->fcs, event);
3286
3287 switch (event) {
3288 case RPFSM_EVENT_RPORT_OFFLINE:
3289 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
3290 rpf->rpsc_retries = 0;
3291 break;
3292
3293 default:
3294 bfa_sm_fault(rport->fcs, event);
3295 }
3296}
3297
3298static void
3299bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
3300{
3301 struct bfa_fcs_rport_s *rport = rpf->rport;
3302
3303 bfa_trc(rport->fcs, rport->pwwn);
3304 bfa_trc(rport->fcs, rport->pid);
3305 bfa_trc(rport->fcs, event);
3306
3307 switch (event) {
3308 case RPFSM_EVENT_RPORT_ONLINE:
3309 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
3310 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
3311 break;
3312
3313 case RPFSM_EVENT_RPORT_OFFLINE:
3314 break;
3315
3316 default:
3317 bfa_sm_fault(rport->fcs, event);
3318 }
3319}
Jing Huang5fbe25c2010-10-18 17:17:23 -07003320/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003321 * Called when Rport is created.
3322 */
3323void
3324bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
3325{
3326 struct bfa_fcs_rpf_s *rpf = &rport->rpf;
3327
3328 bfa_trc(rport->fcs, rport->pid);
3329 rpf->rport = rport;
3330
3331 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
3332}
3333
Jing Huang5fbe25c2010-10-18 17:17:23 -07003334/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003335 * Called when Rport becomes online
3336 */
3337void
3338bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
3339{
3340 bfa_trc(rport->fcs, rport->pid);
3341
3342 if (__fcs_min_cfg(rport->port->fcs))
3343 return;
3344
3345 if (bfa_fcs_fabric_is_switched(rport->port->fabric))
3346 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
3347}
3348
Jing Huang5fbe25c2010-10-18 17:17:23 -07003349/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003350 * Called when Rport becomes offline
3351 */
3352void
3353bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
3354{
3355 bfa_trc(rport->fcs, rport->pid);
3356
3357 if (__fcs_min_cfg(rport->port->fcs))
3358 return;
3359
3360 rport->rpf.rpsc_speed = 0;
3361 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
3362}
3363
3364static void
3365bfa_fcs_rpf_timeout(void *arg)
3366{
3367 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
3368 struct bfa_fcs_rport_s *rport = rpf->rport;
3369
3370 bfa_trc(rport->fcs, rport->pid);
3371 bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
3372}
3373
3374static void
3375bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3376{
3377 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
3378 struct bfa_fcs_rport_s *rport = rpf->rport;
3379 struct bfa_fcs_lport_s *port = rport->port;
3380 struct fchs_s fchs;
3381 int len;
3382 struct bfa_fcxp_s *fcxp;
3383
3384 bfa_trc(rport->fcs, rport->pwwn);
3385
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07003386 fcxp = fcxp_alloced ? fcxp_alloced :
3387 bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003388 if (!fcxp) {
3389 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
Krishna Gudipatic3f1b122012-08-22 19:51:08 -07003390 bfa_fcs_rpf_send_rpsc2, rpf, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003391 return;
3392 }
3393 rpf->fcxp = fcxp;
3394
3395 len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
3396 bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
3397
3398 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3399 FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
3400 rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
3401 rport->stats.rpsc_sent++;
3402 bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
3403
3404}
3405
3406static void
3407bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
3408 bfa_status_t req_status, u32 rsp_len,
3409 u32 resid_len, struct fchs_s *rsp_fchs)
3410{
3411 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
3412 struct bfa_fcs_rport_s *rport = rpf->rport;
3413 struct fc_ls_rjt_s *ls_rjt;
3414 struct fc_rpsc2_acc_s *rpsc2_acc;
3415 u16 num_ents;
3416
3417 bfa_trc(rport->fcs, req_status);
3418
3419 if (req_status != BFA_STATUS_OK) {
3420 bfa_trc(rport->fcs, req_status);
3421 if (req_status == BFA_STATUS_ETIMER)
3422 rport->stats.rpsc_failed++;
3423 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3424 return;
3425 }
3426
3427 rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
3428 if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
3429 rport->stats.rpsc_accs++;
Jing Huangba816ea2010-10-18 17:10:50 -07003430 num_ents = be16_to_cpu(rpsc2_acc->num_pids);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003431 bfa_trc(rport->fcs, num_ents);
3432 if (num_ents > 0) {
Jing Huangd4b671c2010-12-26 21:46:35 -08003433 WARN_ON(rpsc2_acc->port_info[0].pid == rport->pid);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003434 bfa_trc(rport->fcs,
Jing Huangba816ea2010-10-18 17:10:50 -07003435 be16_to_cpu(rpsc2_acc->port_info[0].pid));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003436 bfa_trc(rport->fcs,
Jing Huangba816ea2010-10-18 17:10:50 -07003437 be16_to_cpu(rpsc2_acc->port_info[0].speed));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003438 bfa_trc(rport->fcs,
Jing Huangba816ea2010-10-18 17:10:50 -07003439 be16_to_cpu(rpsc2_acc->port_info[0].index));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003440 bfa_trc(rport->fcs,
3441 rpsc2_acc->port_info[0].type);
3442
3443 if (rpsc2_acc->port_info[0].speed == 0) {
3444 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3445 return;
3446 }
3447
3448 rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
Jing Huangba816ea2010-10-18 17:10:50 -07003449 be16_to_cpu(rpsc2_acc->port_info[0].speed));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07003450
3451 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
3452 }
3453 } else {
3454 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3455 bfa_trc(rport->fcs, ls_rjt->reason_code);
3456 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
3457 rport->stats.rpsc_rejects++;
3458 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
3459 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
3460 else
3461 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3462 }
3463}