[SCSI] bfa: fix regular sparse check warnings.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / scsi / bfa / bfa_fcs_rport.c
CommitLineData
7725ccfd 1/*
a36c61f9 2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
7725ccfd
JH
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
5fbe25c7 18/*
7725ccfd
JH
19 * rport.c Remote port implementation.
20 */
21
a36c61f9
KG
22#include "bfa_fcs.h"
23#include "bfa_fcbuild.h"
24#include "bfad_drv.h"
7725ccfd
JH
25
26BFA_TRC_FILE(FCS, RPORT);
27
a36c61f9
KG
28static u32
29bfa_fcs_rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
30 /* In millisecs */
7725ccfd
JH
31/*
32 * forward declarations
33 */
a36c61f9
KG
34static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(
35 struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid);
36static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
37static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
38static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
39static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
40static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
41 struct fc_logi_s *plogi);
42static void bfa_fcs_rport_timeout(void *arg);
43static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
7725ccfd 44 struct bfa_fcxp_s *fcxp_alloced);
a36c61f9
KG
45static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
46 struct bfa_fcxp_s *fcxp_alloced);
47static void bfa_fcs_rport_plogi_response(void *fcsarg,
48 struct bfa_fcxp_s *fcxp, void *cbarg,
49 bfa_status_t req_status, u32 rsp_len,
50 u32 resid_len, struct fchs_s *rsp_fchs);
51static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
7725ccfd 52 struct bfa_fcxp_s *fcxp_alloced);
a36c61f9
KG
53static void bfa_fcs_rport_adisc_response(void *fcsarg,
54 struct bfa_fcxp_s *fcxp, void *cbarg,
55 bfa_status_t req_status, u32 rsp_len,
56 u32 resid_len, struct fchs_s *rsp_fchs);
57static void bfa_fcs_rport_send_nsdisc(void *rport_cbarg,
7725ccfd 58 struct bfa_fcxp_s *fcxp_alloced);
a36c61f9
KG
59static void bfa_fcs_rport_gidpn_response(void *fcsarg,
60 struct bfa_fcxp_s *fcxp, void *cbarg,
61 bfa_status_t req_status, u32 rsp_len,
62 u32 resid_len, struct fchs_s *rsp_fchs);
63static void bfa_fcs_rport_gpnid_response(void *fcsarg,
64 struct bfa_fcxp_s *fcxp, void *cbarg,
65 bfa_status_t req_status, u32 rsp_len,
66 u32 resid_len, struct fchs_s *rsp_fchs);
67static void bfa_fcs_rport_send_logo(void *rport_cbarg,
7725ccfd 68 struct bfa_fcxp_s *fcxp_alloced);
a36c61f9
KG
69static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
70static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
71 struct fchs_s *rx_fchs, u16 len);
72static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
73 struct fchs_s *rx_fchs, u8 reason_code,
74 u8 reason_code_expl);
75static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
76 struct fchs_s *rx_fchs, u16 len);
77static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
5fbe25c7 78/*
7725ccfd
JH
79 * fcs_rport_sm FCS rport state machine events
80 */
81
82enum rport_event {
a36c61f9
KG
83 RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
84 RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
85 RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
86 RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
87 RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
88 RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
89 RPSM_EVENT_DELETE = 7, /* RPORT delete request */
90 RPSM_EVENT_SCN = 8, /* state change notification */
91 RPSM_EVENT_ACCEPTED = 9, /* Good response from remote device */
92 RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
93 RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
94 RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
95 RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */
96 RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */
97 RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */
4b5e759d 98 RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */
a36c61f9
KG
99 RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */
100 RPSM_EVENT_PLOGI_RETRY = 18, /* Retry PLOGI continously */
7725ccfd
JH
101};
102
a36c61f9 103static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
7725ccfd 104 enum rport_event event);
a36c61f9
KG
105static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
106 enum rport_event event);
107static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
7725ccfd 108 enum rport_event event);
a36c61f9
KG
109static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
110 enum rport_event event);
111static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
7725ccfd 112 enum rport_event event);
a36c61f9
KG
113static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
114 enum rport_event event);
115static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
116 enum rport_event event);
117static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
7725ccfd 118 enum rport_event event);
a36c61f9 119static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
7725ccfd 120 enum rport_event event);
a36c61f9
KG
121static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
122 enum rport_event event);
123static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
124 enum rport_event event);
125static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
126 enum rport_event event);
127static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
128 enum rport_event event);
129static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
130 enum rport_event event);
131static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
132 enum rport_event event);
133static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
134 enum rport_event event);
135static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
136 enum rport_event event);
137static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
138 enum rport_event event);
139static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
7725ccfd 140 enum rport_event event);
a36c61f9
KG
141static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
142 enum rport_event event);
143static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
144 enum rport_event event);
145static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
146 enum rport_event event);
147static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
7725ccfd 148 enum rport_event event);
7725ccfd
JH
149
150static struct bfa_sm_table_s rport_sm_table[] = {
151 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
152 {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
153 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
154 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
155 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
156 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
157 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
158 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
159 {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
160 {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
161 {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
162 {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
163 {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
164 {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
165 {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
166 {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
167 {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
168 {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
169 {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
170 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
171 {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
172 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
173};
174
5fbe25c7 175/*
a36c61f9 176 * Beginning state.
7725ccfd
JH
177 */
178static void
179bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
180{
181 bfa_trc(rport->fcs, rport->pwwn);
182 bfa_trc(rport->fcs, rport->pid);
183 bfa_trc(rport->fcs, event);
184
185 switch (event) {
186 case RPSM_EVENT_PLOGI_SEND:
187 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
188 rport->plogi_retries = 0;
189 bfa_fcs_rport_send_plogi(rport, NULL);
190 break;
191
192 case RPSM_EVENT_PLOGI_RCVD:
193 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
194 bfa_fcs_rport_send_plogiacc(rport, NULL);
195 break;
196
197 case RPSM_EVENT_PLOGI_COMP:
198 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
199 bfa_fcs_rport_hal_online(rport);
200 break;
201
202 case RPSM_EVENT_ADDRESS_CHANGE:
203 case RPSM_EVENT_ADDRESS_DISC:
204 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
205 rport->ns_retries = 0;
a36c61f9 206 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd 207 break;
7725ccfd 208 default:
e641de37 209 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
210 }
211}
212
5fbe25c7 213/*
a36c61f9 214 * PLOGI is being sent.
7725ccfd
JH
215 */
216static void
217bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
a36c61f9 218 enum rport_event event)
7725ccfd
JH
219{
220 bfa_trc(rport->fcs, rport->pwwn);
221 bfa_trc(rport->fcs, rport->pid);
222 bfa_trc(rport->fcs, event);
223
224 switch (event) {
225 case RPSM_EVENT_FCXP_SENT:
226 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
227 break;
228
229 case RPSM_EVENT_DELETE:
230 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
231 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
232 bfa_fcs_rport_free(rport);
233 break;
234
235 case RPSM_EVENT_PLOGI_RCVD:
236 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
237 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
238 bfa_fcs_rport_send_plogiacc(rport, NULL);
239 break;
240
241 case RPSM_EVENT_ADDRESS_CHANGE:
a36c61f9
KG
242 case RPSM_EVENT_SCN:
243 /* query the NS */
7725ccfd
JH
244 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
245 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
246 rport->ns_retries = 0;
a36c61f9 247 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
248 break;
249
250 case RPSM_EVENT_LOGO_IMP:
251 rport->pid = 0;
252 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
253 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
254 bfa_timer_start(rport->fcs->bfa, &rport->timer,
255 bfa_fcs_rport_timeout, rport,
256 bfa_fcs_rport_del_timeout);
257 break;
258
7725ccfd
JH
259
260 default:
e641de37 261 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
262 }
263}
264
5fbe25c7 265/*
a36c61f9 266 * PLOGI is being sent.
7725ccfd
JH
267 */
268static void
269bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
a36c61f9 270 enum rport_event event)
7725ccfd
JH
271{
272 bfa_trc(rport->fcs, rport->pwwn);
273 bfa_trc(rport->fcs, rport->pid);
274 bfa_trc(rport->fcs, event);
275
276 switch (event) {
277 case RPSM_EVENT_FCXP_SENT:
278 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
279 bfa_fcs_rport_hal_online(rport);
280 break;
281
282 case RPSM_EVENT_DELETE:
283 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
284 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
285 bfa_fcs_rport_free(rport);
286 break;
287
a36c61f9 288 case RPSM_EVENT_PLOGI_RCVD:
7725ccfd 289 case RPSM_EVENT_SCN:
5fbe25c7 290 /*
7725ccfd
JH
291 * Ignore, SCN is possibly online notification.
292 */
293 break;
294
295 case RPSM_EVENT_ADDRESS_CHANGE:
296 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
297 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
298 rport->ns_retries = 0;
a36c61f9 299 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
300 break;
301
302 case RPSM_EVENT_LOGO_IMP:
303 rport->pid = 0;
304 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
305 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
306 bfa_timer_start(rport->fcs->bfa, &rport->timer,
307 bfa_fcs_rport_timeout, rport,
308 bfa_fcs_rport_del_timeout);
309 break;
310
311 case RPSM_EVENT_HCB_OFFLINE:
5fbe25c7 312 /*
7725ccfd
JH
313 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
314 */
315 break;
316
317 default:
e641de37 318 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
319 }
320}
321
5fbe25c7 322/*
a36c61f9 323 * PLOGI is sent.
7725ccfd
JH
324 */
325static void
326bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
327 enum rport_event event)
328{
329 bfa_trc(rport->fcs, rport->pwwn);
330 bfa_trc(rport->fcs, rport->pid);
331 bfa_trc(rport->fcs, event);
332
333 switch (event) {
7725ccfd 334 case RPSM_EVENT_TIMEOUT:
a36c61f9
KG
335 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
336 bfa_fcs_rport_send_plogi(rport, NULL);
7725ccfd
JH
337 break;
338
339 case RPSM_EVENT_DELETE:
340 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
341 bfa_timer_stop(&rport->timer);
342 bfa_fcs_rport_free(rport);
343 break;
344
4b5e759d 345 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
346 case RPSM_EVENT_LOGO_RCVD:
347 break;
348
349 case RPSM_EVENT_PLOGI_RCVD:
350 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
351 bfa_timer_stop(&rport->timer);
352 bfa_fcs_rport_send_plogiacc(rport, NULL);
353 break;
354
355 case RPSM_EVENT_ADDRESS_CHANGE:
a36c61f9 356 case RPSM_EVENT_SCN:
7725ccfd
JH
357 bfa_timer_stop(&rport->timer);
358 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
359 rport->ns_retries = 0;
a36c61f9 360 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
361 break;
362
363 case RPSM_EVENT_LOGO_IMP:
364 rport->pid = 0;
365 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
366 bfa_timer_stop(&rport->timer);
367 bfa_timer_start(rport->fcs->bfa, &rport->timer,
368 bfa_fcs_rport_timeout, rport,
369 bfa_fcs_rport_del_timeout);
370 break;
371
372 case RPSM_EVENT_PLOGI_COMP:
373 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
374 bfa_timer_stop(&rport->timer);
375 bfa_fcs_rport_hal_online(rport);
376 break;
377
378 default:
e641de37 379 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
380 }
381}
382
5fbe25c7 383/*
a36c61f9 384 * PLOGI is sent.
7725ccfd
JH
385 */
386static void
387bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
388{
389 bfa_trc(rport->fcs, rport->pwwn);
390 bfa_trc(rport->fcs, rport->pid);
391 bfa_trc(rport->fcs, event);
392
393 switch (event) {
394 case RPSM_EVENT_ACCEPTED:
395 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
396 rport->plogi_retries = 0;
397 bfa_fcs_rport_hal_online(rport);
398 break;
399
400 case RPSM_EVENT_LOGO_RCVD:
401 bfa_fcs_rport_send_logo_acc(rport);
4b5e759d
JH
402 /*
403 * !! fall through !!
404 */
405 case RPSM_EVENT_PRLO_RCVD:
406 if (rport->prlo == BFA_TRUE)
407 bfa_fcs_rport_send_prlo_acc(rport);
408
7725ccfd
JH
409 bfa_fcxp_discard(rport->fcxp);
410 /*
411 * !! fall through !!
412 */
413 case RPSM_EVENT_FAILED:
a36c61f9
KG
414 if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
415 rport->plogi_retries++;
416 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
417 bfa_timer_start(rport->fcs->bfa, &rport->timer,
418 bfa_fcs_rport_timeout, rport,
419 BFA_FCS_RETRY_TIMEOUT);
420 } else {
421 bfa_stats(rport->port, rport_del_max_plogi_retry);
422 rport->pid = 0;
423 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
424 bfa_timer_start(rport->fcs->bfa, &rport->timer,
425 bfa_fcs_rport_timeout, rport,
426 bfa_fcs_rport_del_timeout);
427 }
428 break;
429
430 case RPSM_EVENT_PLOGI_RETRY:
431 rport->plogi_retries = 0;
7725ccfd
JH
432 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
433 bfa_timer_start(rport->fcs->bfa, &rport->timer,
434 bfa_fcs_rport_timeout, rport,
a36c61f9 435 (FC_RA_TOV * 1000));
7725ccfd
JH
436 break;
437
438 case RPSM_EVENT_LOGO_IMP:
439 rport->pid = 0;
440 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
441 bfa_fcxp_discard(rport->fcxp);
442 bfa_timer_start(rport->fcs->bfa, &rport->timer,
443 bfa_fcs_rport_timeout, rport,
444 bfa_fcs_rport_del_timeout);
445 break;
446
447 case RPSM_EVENT_ADDRESS_CHANGE:
a36c61f9 448 case RPSM_EVENT_SCN:
7725ccfd
JH
449 bfa_fcxp_discard(rport->fcxp);
450 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
451 rport->ns_retries = 0;
a36c61f9 452 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
453 break;
454
455 case RPSM_EVENT_PLOGI_RCVD:
456 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
457 bfa_fcxp_discard(rport->fcxp);
458 bfa_fcs_rport_send_plogiacc(rport, NULL);
459 break;
460
7725ccfd
JH
461 case RPSM_EVENT_DELETE:
462 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
463 bfa_fcxp_discard(rport->fcxp);
464 bfa_fcs_rport_free(rport);
465 break;
466
467 case RPSM_EVENT_PLOGI_COMP:
468 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
469 bfa_fcxp_discard(rport->fcxp);
470 bfa_fcs_rport_hal_online(rport);
471 break;
472
473 default:
e641de37 474 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
475 }
476}
477
5fbe25c7 478/*
a36c61f9
KG
479 * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
480 * are offline.
7725ccfd
JH
481 */
482static void
483bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
484 enum rport_event event)
485{
486 bfa_trc(rport->fcs, rport->pwwn);
487 bfa_trc(rport->fcs, rport->pid);
488 bfa_trc(rport->fcs, event);
489
490 switch (event) {
491 case RPSM_EVENT_HCB_ONLINE:
492 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
493 bfa_fcs_rport_online_action(rport);
494 break;
495
4b5e759d
JH
496 case RPSM_EVENT_PRLO_RCVD:
497 break;
498
7725ccfd
JH
499 case RPSM_EVENT_LOGO_RCVD:
500 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
501 bfa_rport_offline(rport->bfa_rport);
502 break;
503
504 case RPSM_EVENT_LOGO_IMP:
505 case RPSM_EVENT_ADDRESS_CHANGE:
506 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
507 bfa_rport_offline(rport->bfa_rport);
508 break;
509
510 case RPSM_EVENT_PLOGI_RCVD:
511 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
512 bfa_rport_offline(rport->bfa_rport);
513 bfa_fcs_rport_send_plogiacc(rport, NULL);
514 break;
515
516 case RPSM_EVENT_DELETE:
517 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
518 bfa_rport_offline(rport->bfa_rport);
519 break;
520
521 case RPSM_EVENT_SCN:
5fbe25c7 522 /*
7725ccfd
JH
523 * @todo
524 * Ignore SCN - PLOGI just completed, FC-4 login should detect
525 * device failures.
526 */
527 break;
528
529 default:
e641de37 530 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
531 }
532}
533
5fbe25c7 534/*
a36c61f9 535 * Rport is ONLINE. FC-4s active.
7725ccfd
JH
536 */
537static void
538bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
539{
540 bfa_trc(rport->fcs, rport->pwwn);
541 bfa_trc(rport->fcs, rport->pid);
542 bfa_trc(rport->fcs, event);
543
544 switch (event) {
545 case RPSM_EVENT_SCN:
7725ccfd
JH
546 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
547 bfa_sm_set_state(rport,
548 bfa_fcs_rport_sm_nsquery_sending);
549 rport->ns_retries = 0;
a36c61f9 550 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
551 } else {
552 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
553 bfa_fcs_rport_send_adisc(rport, NULL);
554 }
555 break;
556
557 case RPSM_EVENT_PLOGI_RCVD:
558 case RPSM_EVENT_LOGO_IMP:
559 case RPSM_EVENT_ADDRESS_CHANGE:
560 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
561 bfa_fcs_rport_offline_action(rport);
562 break;
563
564 case RPSM_EVENT_DELETE:
565 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
566 bfa_fcs_rport_offline_action(rport);
567 break;
568
569 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 570 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
571 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
572 bfa_fcs_rport_offline_action(rport);
573 break;
574
575 case RPSM_EVENT_PLOGI_COMP:
576 break;
577
578 default:
e641de37 579 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
580 }
581}
582
5fbe25c7 583/*
a36c61f9
KG
584 * An SCN event is received in ONLINE state. NS query is being sent
585 * prior to ADISC authentication with rport. FC-4s are paused.
7725ccfd
JH
586 */
587static void
588bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
a36c61f9 589 enum rport_event event)
7725ccfd
JH
590{
591 bfa_trc(rport->fcs, rport->pwwn);
592 bfa_trc(rport->fcs, rport->pid);
593 bfa_trc(rport->fcs, event);
594
595 switch (event) {
596 case RPSM_EVENT_FCXP_SENT:
597 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
598 break;
599
600 case RPSM_EVENT_DELETE:
601 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
602 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
603 bfa_fcs_rport_offline_action(rport);
604 break;
605
606 case RPSM_EVENT_SCN:
5fbe25c7 607 /*
7725ccfd
JH
608 * ignore SCN, wait for response to query itself
609 */
610 break;
611
612 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 613 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
614 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
615 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
616 bfa_fcs_rport_offline_action(rport);
617 break;
618
619 case RPSM_EVENT_LOGO_IMP:
620 rport->pid = 0;
621 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
622 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
623 bfa_timer_start(rport->fcs->bfa, &rport->timer,
624 bfa_fcs_rport_timeout, rport,
625 bfa_fcs_rport_del_timeout);
626 break;
627
628 case RPSM_EVENT_PLOGI_RCVD:
629 case RPSM_EVENT_ADDRESS_CHANGE:
630 case RPSM_EVENT_PLOGI_COMP:
631 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
632 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
633 bfa_fcs_rport_offline_action(rport);
634 break;
635
636 default:
e641de37 637 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
638 }
639}
640
5fbe25c7 641/*
a36c61f9
KG
642 * An SCN event is received in ONLINE state. NS query is sent to rport.
643 * FC-4s are paused.
7725ccfd
JH
644 */
645static void
646bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
647{
648 bfa_trc(rport->fcs, rport->pwwn);
649 bfa_trc(rport->fcs, rport->pid);
650 bfa_trc(rport->fcs, event);
651
652 switch (event) {
653 case RPSM_EVENT_ACCEPTED:
654 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
655 bfa_fcs_rport_send_adisc(rport, NULL);
656 break;
657
658 case RPSM_EVENT_FAILED:
659 rport->ns_retries++;
660 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
661 bfa_sm_set_state(rport,
662 bfa_fcs_rport_sm_nsquery_sending);
a36c61f9 663 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
664 } else {
665 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
666 bfa_fcs_rport_offline_action(rport);
667 }
668 break;
669
670 case RPSM_EVENT_DELETE:
671 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
672 bfa_fcxp_discard(rport->fcxp);
673 bfa_fcs_rport_offline_action(rport);
674 break;
675
676 case RPSM_EVENT_SCN:
677 break;
678
679 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 680 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
681 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
682 bfa_fcxp_discard(rport->fcxp);
683 bfa_fcs_rport_offline_action(rport);
684 break;
685
686 case RPSM_EVENT_PLOGI_COMP:
687 case RPSM_EVENT_ADDRESS_CHANGE:
688 case RPSM_EVENT_PLOGI_RCVD:
689 case RPSM_EVENT_LOGO_IMP:
690 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
691 bfa_fcxp_discard(rport->fcxp);
692 bfa_fcs_rport_offline_action(rport);
693 break;
694
695 default:
e641de37 696 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
697 }
698}
699
5fbe25c7 700/*
a36c61f9
KG
701 * An SCN event is received in ONLINE state. ADISC is being sent for
702 * authenticating with rport. FC-4s are paused.
7725ccfd
JH
703 */
704static void
705bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
a36c61f9 706 enum rport_event event)
7725ccfd
JH
707{
708 bfa_trc(rport->fcs, rport->pwwn);
709 bfa_trc(rport->fcs, rport->pid);
710 bfa_trc(rport->fcs, event);
711
712 switch (event) {
713 case RPSM_EVENT_FCXP_SENT:
714 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
715 break;
716
717 case RPSM_EVENT_DELETE:
718 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
719 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
720 bfa_fcs_rport_offline_action(rport);
721 break;
722
723 case RPSM_EVENT_LOGO_IMP:
724 case RPSM_EVENT_ADDRESS_CHANGE:
725 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
726 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
727 bfa_fcs_rport_offline_action(rport);
728 break;
729
730 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 731 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
732 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
733 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
734 bfa_fcs_rport_offline_action(rport);
735 break;
736
737 case RPSM_EVENT_SCN:
738 break;
739
740 case RPSM_EVENT_PLOGI_RCVD:
741 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
742 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
743 bfa_fcs_rport_offline_action(rport);
744 break;
745
746 default:
e641de37 747 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
748 }
749}
750
5fbe25c7 751/*
a36c61f9
KG
752 * An SCN event is received in ONLINE state. ADISC is to rport.
753 * FC-4s are paused.
7725ccfd
JH
754 */
755static void
756bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
757{
758 bfa_trc(rport->fcs, rport->pwwn);
759 bfa_trc(rport->fcs, rport->pid);
760 bfa_trc(rport->fcs, event);
761
762 switch (event) {
763 case RPSM_EVENT_ACCEPTED:
764 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
7725ccfd
JH
765 break;
766
767 case RPSM_EVENT_PLOGI_RCVD:
5fbe25c7 768 /*
7725ccfd
JH
769 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
770 * At least go offline when a PLOGI is received.
771 */
772 bfa_fcxp_discard(rport->fcxp);
773 /*
774 * !!! fall through !!!
775 */
776
777 case RPSM_EVENT_FAILED:
778 case RPSM_EVENT_ADDRESS_CHANGE:
779 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
780 bfa_fcs_rport_offline_action(rport);
781 break;
782
783 case RPSM_EVENT_DELETE:
784 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
785 bfa_fcxp_discard(rport->fcxp);
786 bfa_fcs_rport_offline_action(rport);
787 break;
788
789 case RPSM_EVENT_SCN:
5fbe25c7 790 /*
7725ccfd
JH
791 * already processing RSCN
792 */
793 break;
794
795 case RPSM_EVENT_LOGO_IMP:
796 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
797 bfa_fcxp_discard(rport->fcxp);
798 bfa_fcs_rport_offline_action(rport);
799 break;
800
801 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 802 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
803 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
804 bfa_fcxp_discard(rport->fcxp);
805 bfa_fcs_rport_offline_action(rport);
806 break;
807
808 default:
e641de37 809 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
810 }
811}
812
5fbe25c7 813/*
a36c61f9 814 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
7725ccfd
JH
815 */
816static void
817bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
818 enum rport_event event)
819{
820 bfa_trc(rport->fcs, rport->pwwn);
821 bfa_trc(rport->fcs, rport->pid);
822 bfa_trc(rport->fcs, event);
823
824 switch (event) {
825 case RPSM_EVENT_FC4_OFFLINE:
826 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
827 bfa_rport_offline(rport->bfa_rport);
828 break;
829
830 case RPSM_EVENT_DELETE:
831 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
832 break;
833
834 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 835 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
836 case RPSM_EVENT_ADDRESS_CHANGE:
837 break;
838
839 default:
e641de37 840 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
841 }
842}
843
5fbe25c7 844/*
a36c61f9
KG
845 * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
846 * callback.
7725ccfd
JH
847 */
848static void
849bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
a36c61f9 850 enum rport_event event)
7725ccfd
JH
851{
852 bfa_trc(rport->fcs, rport->pwwn);
853 bfa_trc(rport->fcs, rport->pid);
854 bfa_trc(rport->fcs, event);
855
856 switch (event) {
857 case RPSM_EVENT_FC4_OFFLINE:
858 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
859 bfa_rport_offline(rport->bfa_rport);
860 break;
861
862 default:
e641de37 863 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
864 }
865}
866
5fbe25c7 867/*
a36c61f9 868 * Rport is going offline. Awaiting FC-4 offline completion callback.
7725ccfd
JH
869 */
870static void
871bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
872 enum rport_event event)
873{
874 bfa_trc(rport->fcs, rport->pwwn);
875 bfa_trc(rport->fcs, rport->pid);
876 bfa_trc(rport->fcs, event);
877
878 switch (event) {
879 case RPSM_EVENT_FC4_OFFLINE:
880 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
881 bfa_rport_offline(rport->bfa_rport);
882 break;
883
884 case RPSM_EVENT_SCN:
885 case RPSM_EVENT_LOGO_IMP:
886 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 887 case RPSM_EVENT_PRLO_RCVD:
7725ccfd 888 case RPSM_EVENT_ADDRESS_CHANGE:
5fbe25c7 889 /*
7725ccfd
JH
890 * rport is already going offline.
891 * SCN - ignore and wait till transitioning to offline state
892 */
893 break;
894
895 case RPSM_EVENT_DELETE:
896 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
897 break;
898
899 default:
e641de37 900 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
901 }
902}
903
5fbe25c7 904/*
a36c61f9
KG
905 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
906 * callback.
7725ccfd
JH
907 */
908static void
909bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
a36c61f9 910 enum rport_event event)
7725ccfd
JH
911{
912 bfa_trc(rport->fcs, rport->pwwn);
913 bfa_trc(rport->fcs, rport->pid);
914 bfa_trc(rport->fcs, event);
915
916 switch (event) {
917 case RPSM_EVENT_HCB_OFFLINE:
918 case RPSM_EVENT_ADDRESS_CHANGE:
a36c61f9 919 if (bfa_fcs_lport_is_online(rport->port)) {
72041ed8
KG
920 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
921 bfa_sm_set_state(rport,
922 bfa_fcs_rport_sm_nsdisc_sending);
923 rport->ns_retries = 0;
a36c61f9 924 bfa_fcs_rport_send_nsdisc(rport, NULL);
72041ed8
KG
925 } else {
926 bfa_sm_set_state(rport,
927 bfa_fcs_rport_sm_plogi_sending);
928 rport->plogi_retries = 0;
929 bfa_fcs_rport_send_plogi(rport, NULL);
930 }
7725ccfd
JH
931 } else {
932 rport->pid = 0;
933 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
934 bfa_timer_start(rport->fcs->bfa, &rport->timer,
935 bfa_fcs_rport_timeout, rport,
936 bfa_fcs_rport_del_timeout);
937 }
938 break;
939
940 case RPSM_EVENT_DELETE:
941 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
942 bfa_fcs_rport_free(rport);
943 break;
944
945 case RPSM_EVENT_SCN:
946 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 947 case RPSM_EVENT_PRLO_RCVD:
5fbe25c7 948 /*
7725ccfd
JH
949 * Ignore, already offline.
950 */
951 break;
952
953 default:
e641de37 954 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
955 }
956}
957
5fbe25c7 958/*
a36c61f9
KG
959 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
960 * callback to send LOGO accept.
7725ccfd
JH
961 */
962static void
963bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
964 enum rport_event event)
965{
966 bfa_trc(rport->fcs, rport->pwwn);
967 bfa_trc(rport->fcs, rport->pid);
968 bfa_trc(rport->fcs, event);
969
970 switch (event) {
971 case RPSM_EVENT_HCB_OFFLINE:
972 case RPSM_EVENT_ADDRESS_CHANGE:
4b5e759d
JH
973 if (rport->pid && (rport->prlo == BFA_TRUE))
974 bfa_fcs_rport_send_prlo_acc(rport);
975 if (rport->pid && (rport->prlo == BFA_FALSE))
7725ccfd
JH
976 bfa_fcs_rport_send_logo_acc(rport);
977 /*
a36c61f9
KG
978 * If the lport is online and if the rport is not a well
979 * known address port,
980 * we try to re-discover the r-port.
7725ccfd 981 */
a36c61f9
KG
982 if (bfa_fcs_lport_is_online(rport->port) &&
983 (!BFA_FCS_PID_IS_WKA(rport->pid))) {
7725ccfd 984 bfa_sm_set_state(rport,
a36c61f9 985 bfa_fcs_rport_sm_nsdisc_sending);
7725ccfd 986 rport->ns_retries = 0;
a36c61f9 987 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
988 } else {
989 /*
a36c61f9
KG
990 * if it is not a well known address, reset the
991 * pid to 0.
7725ccfd
JH
992 */
993 if (!BFA_FCS_PID_IS_WKA(rport->pid))
994 rport->pid = 0;
995 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
996 bfa_timer_start(rport->fcs->bfa, &rport->timer,
997 bfa_fcs_rport_timeout, rport,
998 bfa_fcs_rport_del_timeout);
999 }
1000 break;
1001
1002 case RPSM_EVENT_DELETE:
1003 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
1004 break;
1005
1006 case RPSM_EVENT_LOGO_IMP:
1007 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1008 break;
1009
1010 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 1011 case RPSM_EVENT_PRLO_RCVD:
5fbe25c7 1012 /*
7725ccfd
JH
1013 * Ignore - already processing a LOGO.
1014 */
1015 break;
1016
1017 default:
e641de37 1018 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1019 }
1020}
1021
5fbe25c7 1022/*
a36c61f9
KG
1023 * Rport is being deleted. FC-4s are offline.
1024 * Awaiting BFA rport offline
1025 * callback to send LOGO.
7725ccfd
JH
1026 */
1027static void
1028bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
a36c61f9 1029 enum rport_event event)
7725ccfd
JH
1030{
1031 bfa_trc(rport->fcs, rport->pwwn);
1032 bfa_trc(rport->fcs, rport->pid);
1033 bfa_trc(rport->fcs, event);
1034
1035 switch (event) {
1036 case RPSM_EVENT_HCB_OFFLINE:
1037 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1038 bfa_fcs_rport_send_logo(rport, NULL);
1039 break;
1040
1041 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 1042 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
1043 case RPSM_EVENT_ADDRESS_CHANGE:
1044 break;
1045
1046 default:
e641de37 1047 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1048 }
1049}
1050
5fbe25c7 1051/*
a36c61f9 1052 * Rport is being deleted. FC-4s are offline. LOGO is being sent.
7725ccfd
JH
1053 */
1054static void
1055bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
a36c61f9 1056 enum rport_event event)
7725ccfd
JH
1057{
1058 bfa_trc(rport->fcs, rport->pwwn);
1059 bfa_trc(rport->fcs, rport->pid);
1060 bfa_trc(rport->fcs, event);
1061
1062 switch (event) {
1063 case RPSM_EVENT_FCXP_SENT:
a36c61f9 1064 /* Once LOGO is sent, we donot wait for the response */
7725ccfd
JH
1065 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1066 bfa_fcs_rport_free(rport);
1067 break;
1068
1069 case RPSM_EVENT_SCN:
1070 case RPSM_EVENT_ADDRESS_CHANGE:
1071 break;
1072
1073 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 1074 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
1075 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1076 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1077 bfa_fcs_rport_free(rport);
1078 break;
1079
1080 default:
e641de37 1081 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1082 }
1083}
1084
5fbe25c7 1085/*
a36c61f9
KG
1086 * Rport is offline. FC-4s are offline. BFA rport is offline.
1087 * Timer active to delete stale rport.
7725ccfd
JH
1088 */
1089static void
1090bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1091{
1092 bfa_trc(rport->fcs, rport->pwwn);
1093 bfa_trc(rport->fcs, rport->pid);
1094 bfa_trc(rport->fcs, event);
1095
1096 switch (event) {
1097 case RPSM_EVENT_TIMEOUT:
1098 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1099 bfa_fcs_rport_free(rport);
1100 break;
1101
1102 case RPSM_EVENT_SCN:
1103 case RPSM_EVENT_ADDRESS_CHANGE:
1104 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1105 bfa_timer_stop(&rport->timer);
1106 rport->ns_retries = 0;
a36c61f9 1107 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
1108 break;
1109
1110 case RPSM_EVENT_DELETE:
1111 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1112 bfa_timer_stop(&rport->timer);
1113 bfa_fcs_rport_free(rport);
1114 break;
1115
1116 case RPSM_EVENT_PLOGI_RCVD:
1117 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1118 bfa_timer_stop(&rport->timer);
1119 bfa_fcs_rport_send_plogiacc(rport, NULL);
1120 break;
1121
1122 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 1123 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
1124 case RPSM_EVENT_LOGO_IMP:
1125 break;
1126
1127 case RPSM_EVENT_PLOGI_COMP:
1128 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1129 bfa_timer_stop(&rport->timer);
1130 bfa_fcs_rport_hal_online(rport);
1131 break;
1132
1133 case RPSM_EVENT_PLOGI_SEND:
1134 bfa_timer_stop(&rport->timer);
1135 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1136 rport->plogi_retries = 0;
1137 bfa_fcs_rport_send_plogi(rport, NULL);
1138 break;
1139
1140 default:
e641de37 1141 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1142 }
1143}
1144
5fbe25c7 1145/*
a36c61f9 1146 * Rport address has changed. Nameserver discovery request is being sent.
7725ccfd
JH
1147 */
1148static void
1149bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
a36c61f9 1150 enum rport_event event)
7725ccfd
JH
1151{
1152 bfa_trc(rport->fcs, rport->pwwn);
1153 bfa_trc(rport->fcs, rport->pid);
1154 bfa_trc(rport->fcs, event);
1155
1156 switch (event) {
1157 case RPSM_EVENT_FCXP_SENT:
1158 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
1159 break;
1160
1161 case RPSM_EVENT_DELETE:
1162 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1163 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1164 bfa_fcs_rport_free(rport);
1165 break;
1166
1167 case RPSM_EVENT_PLOGI_RCVD:
1168 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1169 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1170 bfa_fcs_rport_send_plogiacc(rport, NULL);
1171 break;
1172
1173 case RPSM_EVENT_SCN:
1174 case RPSM_EVENT_LOGO_RCVD:
4b5e759d 1175 case RPSM_EVENT_PRLO_RCVD:
7725ccfd
JH
1176 case RPSM_EVENT_PLOGI_SEND:
1177 break;
1178
1179 case RPSM_EVENT_ADDRESS_CHANGE:
a36c61f9 1180 rport->ns_retries = 0; /* reset the retry count */
7725ccfd
JH
1181 break;
1182
1183 case RPSM_EVENT_LOGO_IMP:
1184 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1185 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1186 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1187 bfa_fcs_rport_timeout, rport,
1188 bfa_fcs_rport_del_timeout);
1189 break;
1190
1191 case RPSM_EVENT_PLOGI_COMP:
1192 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1193 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1194 bfa_fcs_rport_hal_online(rport);
1195 break;
1196
1197 default:
e641de37 1198 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1199 }
1200}
1201
5fbe25c7 1202/*
a36c61f9 1203 * Nameserver discovery failed. Waiting for timeout to retry.
7725ccfd
JH
1204 */
1205static void
1206bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
a36c61f9 1207 enum rport_event event)
7725ccfd
JH
1208{
1209 bfa_trc(rport->fcs, rport->pwwn);
1210 bfa_trc(rport->fcs, rport->pid);
1211 bfa_trc(rport->fcs, event);
1212
1213 switch (event) {
1214 case RPSM_EVENT_TIMEOUT:
1215 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
a36c61f9 1216 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
1217 break;
1218
1219 case RPSM_EVENT_SCN:
1220 case RPSM_EVENT_ADDRESS_CHANGE:
1221 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1222 bfa_timer_stop(&rport->timer);
1223 rport->ns_retries = 0;
a36c61f9 1224 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
1225 break;
1226
1227 case RPSM_EVENT_DELETE:
1228 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1229 bfa_timer_stop(&rport->timer);
1230 bfa_fcs_rport_free(rport);
1231 break;
1232
1233 case RPSM_EVENT_PLOGI_RCVD:
1234 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1235 bfa_timer_stop(&rport->timer);
1236 bfa_fcs_rport_send_plogiacc(rport, NULL);
1237 break;
1238
1239 case RPSM_EVENT_LOGO_IMP:
1240 rport->pid = 0;
1241 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1242 bfa_timer_stop(&rport->timer);
1243 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1244 bfa_fcs_rport_timeout, rport,
1245 bfa_fcs_rport_del_timeout);
1246 break;
1247
1248 case RPSM_EVENT_LOGO_RCVD:
1249 bfa_fcs_rport_send_logo_acc(rport);
1250 break;
4b5e759d
JH
1251 case RPSM_EVENT_PRLO_RCVD:
1252 bfa_fcs_rport_send_prlo_acc(rport);
1253 break;
1254
7725ccfd
JH
1255 case RPSM_EVENT_PLOGI_COMP:
1256 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1257 bfa_timer_stop(&rport->timer);
1258 bfa_fcs_rport_hal_online(rport);
1259 break;
1260
1261 default:
e641de37 1262 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1263 }
1264}
1265
5fbe25c7 1266/*
a36c61f9 1267 * Rport address has changed. Nameserver discovery request is sent.
7725ccfd
JH
1268 */
1269static void
1270bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1271 enum rport_event event)
1272{
1273 bfa_trc(rport->fcs, rport->pwwn);
1274 bfa_trc(rport->fcs, rport->pid);
1275 bfa_trc(rport->fcs, event);
1276
1277 switch (event) {
1278 case RPSM_EVENT_ACCEPTED:
1279 case RPSM_EVENT_ADDRESS_CHANGE:
1280 if (rport->pid) {
1281 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1282 bfa_fcs_rport_send_plogi(rport, NULL);
1283 } else {
1284 bfa_sm_set_state(rport,
a36c61f9 1285 bfa_fcs_rport_sm_nsdisc_sending);
7725ccfd 1286 rport->ns_retries = 0;
a36c61f9 1287 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
1288 }
1289 break;
1290
1291 case RPSM_EVENT_FAILED:
1292 rport->ns_retries++;
1293 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1294 bfa_sm_set_state(rport,
a36c61f9
KG
1295 bfa_fcs_rport_sm_nsdisc_sending);
1296 bfa_fcs_rport_send_nsdisc(rport, NULL);
7725ccfd
JH
1297 } else {
1298 rport->pid = 0;
1299 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1300 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1301 bfa_fcs_rport_timeout, rport,
1302 bfa_fcs_rport_del_timeout);
1303 };
1304 break;
1305
1306 case RPSM_EVENT_DELETE:
1307 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1308 bfa_fcxp_discard(rport->fcxp);
1309 bfa_fcs_rport_free(rport);
1310 break;
1311
1312 case RPSM_EVENT_PLOGI_RCVD:
1313 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1314 bfa_fcxp_discard(rport->fcxp);
1315 bfa_fcs_rport_send_plogiacc(rport, NULL);
1316 break;
1317
1318 case RPSM_EVENT_LOGO_IMP:
1319 rport->pid = 0;
1320 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1321 bfa_fcxp_discard(rport->fcxp);
1322 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1323 bfa_fcs_rport_timeout, rport,
1324 bfa_fcs_rport_del_timeout);
1325 break;
1326
a36c61f9 1327
4b5e759d
JH
1328 case RPSM_EVENT_PRLO_RCVD:
1329 bfa_fcs_rport_send_prlo_acc(rport);
1330 break;
7725ccfd 1331 case RPSM_EVENT_SCN:
5fbe25c7 1332 /*
7725ccfd
JH
1333 * ignore, wait for NS query response
1334 */
1335 break;
1336
1337 case RPSM_EVENT_LOGO_RCVD:
5fbe25c7 1338 /*
7725ccfd
JH
1339 * Not logged-in yet. Accept LOGO.
1340 */
1341 bfa_fcs_rport_send_logo_acc(rport);
1342 break;
1343
1344 case RPSM_EVENT_PLOGI_COMP:
1345 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1346 bfa_fcxp_discard(rport->fcxp);
1347 bfa_fcs_rport_hal_online(rport);
1348 break;
1349
1350 default:
e641de37 1351 bfa_sm_fault(rport->fcs, event);
7725ccfd
JH
1352 }
1353}
1354
1355
1356
5fbe25c7 1357/*
7725ccfd
JH
1358 * fcs_rport_private FCS RPORT provate functions
1359 */
1360
1361static void
1362bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1363{
1364 struct bfa_fcs_rport_s *rport = rport_cbarg;
a36c61f9
KG
1365 struct bfa_fcs_lport_s *port = rport->port;
1366 struct fchs_s fchs;
1367 int len;
7725ccfd
JH
1368 struct bfa_fcxp_s *fcxp;
1369
1370 bfa_trc(rport->fcs, rport->pwwn);
1371
1372 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1373 if (!fcxp) {
a36c61f9
KG
1374 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1375 bfa_fcs_rport_send_plogi, rport);
7725ccfd
JH
1376 return;
1377 }
1378 rport->fcxp = fcxp;
1379
1380 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
a36c61f9
KG
1381 bfa_fcs_lport_get_fcid(port), 0,
1382 port->port_cfg.pwwn, port->port_cfg.nwwn,
1383 bfa_fcport_get_maxfrsize(port->fcs->bfa));
7725ccfd
JH
1384
1385 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9
KG
1386 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
1387 (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
7725ccfd
JH
1388
1389 rport->stats.plogis++;
1390 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1391}
1392
1393static void
1394bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
a36c61f9
KG
1395 bfa_status_t req_status, u32 rsp_len,
1396 u32 resid_len, struct fchs_s *rsp_fchs)
7725ccfd 1397{
a36c61f9 1398 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
7725ccfd
JH
1399 struct fc_logi_s *plogi_rsp;
1400 struct fc_ls_rjt_s *ls_rjt;
1401 struct bfa_fcs_rport_s *twin;
a36c61f9 1402 struct list_head *qe;
7725ccfd
JH
1403
1404 bfa_trc(rport->fcs, rport->pwwn);
1405
1406 /*
1407 * Sanity Checks
1408 */
1409 if (req_status != BFA_STATUS_OK) {
1410 bfa_trc(rport->fcs, req_status);
1411 rport->stats.plogi_failed++;
1412 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1413 return;
1414 }
1415
1416 plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1417
5fbe25c7 1418 /*
7725ccfd
JH
1419 * Check for failure first.
1420 */
1421 if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1422 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1423
1424 bfa_trc(rport->fcs, ls_rjt->reason_code);
1425 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1426
a36c61f9
KG
1427 if ((ls_rjt->reason_code == FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD) &&
1428 (ls_rjt->reason_code_expl == FC_LS_RJT_EXP_INSUFF_RES)) {
1429 rport->stats.rjt_insuff_res++;
1430 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RETRY);
1431 return;
1432 }
1433
7725ccfd
JH
1434 rport->stats.plogi_rejects++;
1435 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1436 return;
1437 }
1438
5fbe25c7 1439 /*
7725ccfd
JH
1440 * PLOGI is complete. Make sure this device is not one of the known
1441 * device with a new FC port address.
1442 */
1443 list_for_each(qe, &rport->port->rport_q) {
a36c61f9 1444 twin = (struct bfa_fcs_rport_s *) qe;
7725ccfd
JH
1445 if (twin == rport)
1446 continue;
1447 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1448 bfa_trc(rport->fcs, twin->pid);
1449 bfa_trc(rport->fcs, rport->pid);
1450
a36c61f9
KG
1451 /* Update plogi stats in twin */
1452 twin->stats.plogis += rport->stats.plogis;
1453 twin->stats.plogi_rejects +=
1454 rport->stats.plogi_rejects;
1455 twin->stats.plogi_timeouts +=
1456 rport->stats.plogi_timeouts;
1457 twin->stats.plogi_failed +=
1458 rport->stats.plogi_failed;
1459 twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
7725ccfd
JH
1460 twin->stats.plogi_accs++;
1461
1462 bfa_fcs_rport_delete(rport);
1463
1464 bfa_fcs_rport_update(twin, plogi_rsp);
1465 twin->pid = rsp_fchs->s_id;
1466 bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1467 return;
1468 }
1469 }
1470
5fbe25c7 1471 /*
7725ccfd
JH
1472 * Normal login path -- no evil twins.
1473 */
1474 rport->stats.plogi_accs++;
1475 bfa_fcs_rport_update(rport, plogi_rsp);
1476 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1477}
1478
1479static void
1480bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1481{
1482 struct bfa_fcs_rport_s *rport = rport_cbarg;
a36c61f9
KG
1483 struct bfa_fcs_lport_s *port = rport->port;
1484 struct fchs_s fchs;
1485 int len;
7725ccfd
JH
1486 struct bfa_fcxp_s *fcxp;
1487
1488 bfa_trc(rport->fcs, rport->pwwn);
1489 bfa_trc(rport->fcs, rport->reply_oxid);
1490
1491 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1492 if (!fcxp) {
a36c61f9
KG
1493 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1494 bfa_fcs_rport_send_plogiacc, rport);
7725ccfd
JH
1495 return;
1496 }
1497 rport->fcxp = fcxp;
1498
a36c61f9
KG
1499 len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1500 rport->pid, bfa_fcs_lport_get_fcid(port),
1501 rport->reply_oxid, port->port_cfg.pwwn,
1502 port->port_cfg.nwwn,
1c8a4c37 1503 bfa_fcport_get_maxfrsize(port->fcs->bfa));
7725ccfd
JH
1504
1505 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9 1506 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
7725ccfd
JH
1507
1508 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1509}
1510
1511static void
1512bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1513{
1514 struct bfa_fcs_rport_s *rport = rport_cbarg;
a36c61f9
KG
1515 struct bfa_fcs_lport_s *port = rport->port;
1516 struct fchs_s fchs;
1517 int len;
7725ccfd
JH
1518 struct bfa_fcxp_s *fcxp;
1519
1520 bfa_trc(rport->fcs, rport->pwwn);
1521
1522 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1523 if (!fcxp) {
a36c61f9
KG
1524 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1525 bfa_fcs_rport_send_adisc, rport);
7725ccfd
JH
1526 return;
1527 }
1528 rport->fcxp = fcxp;
1529
1530 len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
a36c61f9
KG
1531 bfa_fcs_lport_get_fcid(port), 0,
1532 port->port_cfg.pwwn, port->port_cfg.nwwn);
7725ccfd
JH
1533
1534 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9
KG
1535 FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
1536 rport, FC_MAX_PDUSZ, FC_ELS_TOV);
7725ccfd
JH
1537
1538 rport->stats.adisc_sent++;
1539 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1540}
1541
1542static void
1543bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
a36c61f9
KG
1544 bfa_status_t req_status, u32 rsp_len,
1545 u32 resid_len, struct fchs_s *rsp_fchs)
7725ccfd 1546{
a36c61f9
KG
1547 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1548 void *pld = bfa_fcxp_get_rspbuf(fcxp);
1549 struct fc_ls_rjt_s *ls_rjt;
7725ccfd
JH
1550
1551 if (req_status != BFA_STATUS_OK) {
1552 bfa_trc(rport->fcs, req_status);
1553 rport->stats.adisc_failed++;
1554 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1555 return;
1556 }
1557
1558 if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
a36c61f9 1559 rport->nwwn) == FC_PARSE_OK) {
7725ccfd
JH
1560 rport->stats.adisc_accs++;
1561 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1562 return;
1563 }
1564
1565 rport->stats.adisc_rejects++;
1566 ls_rjt = pld;
1567 bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1568 bfa_trc(rport->fcs, ls_rjt->reason_code);
1569 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1570 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1571}
1572
1573static void
a36c61f9 1574bfa_fcs_rport_send_nsdisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
7725ccfd
JH
1575{
1576 struct bfa_fcs_rport_s *rport = rport_cbarg;
a36c61f9
KG
1577 struct bfa_fcs_lport_s *port = rport->port;
1578 struct fchs_s fchs;
7725ccfd 1579 struct bfa_fcxp_s *fcxp;
a36c61f9
KG
1580 int len;
1581 bfa_cb_fcxp_send_t cbfn;
7725ccfd
JH
1582
1583 bfa_trc(rport->fcs, rport->pid);
1584
1585 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1586 if (!fcxp) {
a36c61f9
KG
1587 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1588 bfa_fcs_rport_send_nsdisc, rport);
7725ccfd
JH
1589 return;
1590 }
1591 rport->fcxp = fcxp;
1592
a36c61f9
KG
1593 if (rport->pwwn) {
1594 len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1595 bfa_fcs_lport_get_fcid(port), 0, rport->pwwn);
1596 cbfn = bfa_fcs_rport_gidpn_response;
1597 } else {
1598 len = fc_gpnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1599 bfa_fcs_lport_get_fcid(port), 0, rport->pid);
1600 cbfn = bfa_fcs_rport_gpnid_response;
1601 }
7725ccfd
JH
1602
1603 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9
KG
1604 FC_CLASS_3, len, &fchs, cbfn,
1605 (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
7725ccfd
JH
1606
1607 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1608}
1609
1610static void
1611bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
a36c61f9
KG
1612 bfa_status_t req_status, u32 rsp_len,
1613 u32 resid_len, struct fchs_s *rsp_fchs)
7725ccfd 1614{
a36c61f9
KG
1615 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1616 struct ct_hdr_s *cthdr;
7725ccfd 1617 struct fcgs_gidpn_resp_s *gidpn_rsp;
a36c61f9
KG
1618 struct bfa_fcs_rport_s *twin;
1619 struct list_head *qe;
7725ccfd
JH
1620
1621 bfa_trc(rport->fcs, rport->pwwn);
1622
1623 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
ba816ea8 1624 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
7725ccfd
JH
1625
1626 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
a36c61f9 1627 /* Check if the pid is the same as before. */
7725ccfd
JH
1628 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1629
1630 if (gidpn_rsp->dap == rport->pid) {
a36c61f9 1631 /* Device is online */
7725ccfd
JH
1632 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1633 } else {
1634 /*
a36c61f9
KG
1635 * Device's PID has changed. We need to cleanup
1636 * and re-login. If there is another device with
1637 * the the newly discovered pid, send an scn notice
1638 * so that its new pid can be discovered.
7725ccfd
JH
1639 */
1640 list_for_each(qe, &rport->port->rport_q) {
a36c61f9 1641 twin = (struct bfa_fcs_rport_s *) qe;
7725ccfd
JH
1642 if (twin == rport)
1643 continue;
1644 if (gidpn_rsp->dap == twin->pid) {
1645 bfa_trc(rport->fcs, twin->pid);
1646 bfa_trc(rport->fcs, rport->pid);
1647
1648 twin->pid = 0;
1649 bfa_sm_send_event(twin,
a36c61f9 1650 RPSM_EVENT_ADDRESS_CHANGE);
7725ccfd
JH
1651 }
1652 }
1653 rport->pid = gidpn_rsp->dap;
1654 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
1655 }
1656 return;
1657 }
1658
1659 /*
1660 * Reject Response
1661 */
1662 switch (cthdr->reason_code) {
1663 case CT_RSN_LOGICAL_BUSY:
1664 /*
1665 * Need to retry
1666 */
1667 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1668 break;
1669
1670 case CT_RSN_UNABLE_TO_PERF:
1671 /*
1672 * device doesn't exist : Start timer to cleanup this later.
1673 */
1674 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1675 break;
1676
1677 default:
1678 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1679 break;
1680 }
1681}
1682
a36c61f9
KG
1683static void
1684bfa_fcs_rport_gpnid_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1685 bfa_status_t req_status, u32 rsp_len,
1686 u32 resid_len, struct fchs_s *rsp_fchs)
1687{
1688 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
1689 struct ct_hdr_s *cthdr;
1690
1691 bfa_trc(rport->fcs, rport->pwwn);
1692
1693 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
ba816ea8 1694 cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
a36c61f9
KG
1695
1696 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1697 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1698 return;
1699 }
1700
1701 /*
1702 * Reject Response
1703 */
1704 switch (cthdr->reason_code) {
1705 case CT_RSN_LOGICAL_BUSY:
1706 /*
1707 * Need to retry
1708 */
1709 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1710 break;
1711
1712 case CT_RSN_UNABLE_TO_PERF:
1713 /*
1714 * device doesn't exist : Start timer to cleanup this later.
1715 */
1716 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1717 break;
1718
1719 default:
1720 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1721 break;
1722 }
1723}
1724
5fbe25c7 1725/*
a36c61f9 1726 * Called to send a logout to the rport.
7725ccfd
JH
1727 */
1728static void
1729bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1730{
1731 struct bfa_fcs_rport_s *rport = rport_cbarg;
a36c61f9
KG
1732 struct bfa_fcs_lport_s *port;
1733 struct fchs_s fchs;
7725ccfd 1734 struct bfa_fcxp_s *fcxp;
a36c61f9 1735 u16 len;
7725ccfd
JH
1736
1737 bfa_trc(rport->fcs, rport->pid);
1738
1739 port = rport->port;
1740
1741 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1742 if (!fcxp) {
a36c61f9
KG
1743 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1744 bfa_fcs_rport_send_logo, rport);
7725ccfd
JH
1745 return;
1746 }
1747 rport->fcxp = fcxp;
1748
1749 len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
a36c61f9
KG
1750 bfa_fcs_lport_get_fcid(port), 0,
1751 bfa_fcs_lport_get_pwwn(port));
7725ccfd
JH
1752
1753 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9
KG
1754 FC_CLASS_3, len, &fchs, NULL,
1755 rport, FC_MAX_PDUSZ, FC_ELS_TOV);
7725ccfd
JH
1756
1757 rport->stats.logos++;
1758 bfa_fcxp_discard(rport->fcxp);
1759 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1760}
1761
5fbe25c7 1762/*
a36c61f9 1763 * Send ACC for a LOGO received.
7725ccfd
JH
1764 */
1765static void
1766bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
1767{
1768 struct bfa_fcs_rport_s *rport = rport_cbarg;
a36c61f9
KG
1769 struct bfa_fcs_lport_s *port;
1770 struct fchs_s fchs;
7725ccfd 1771 struct bfa_fcxp_s *fcxp;
a36c61f9 1772 u16 len;
7725ccfd
JH
1773
1774 bfa_trc(rport->fcs, rport->pid);
1775
1776 port = rport->port;
1777
1778 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1779 if (!fcxp)
1780 return;
1781
1782 rport->stats.logo_rcvd++;
a36c61f9
KG
1783 len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1784 rport->pid, bfa_fcs_lport_get_fcid(port),
1785 rport->reply_oxid);
7725ccfd
JH
1786
1787 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9 1788 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
7725ccfd
JH
1789}
1790
5fbe25c7 1791/*
a36c61f9
KG
1792 * brief
1793 * This routine will be called by bfa_timer on timer timeouts.
7725ccfd 1794 *
a36c61f9
KG
1795 * param[in] rport - pointer to bfa_fcs_lport_ns_t.
1796 * param[out] rport_status - pointer to return vport status in
7725ccfd 1797 *
a36c61f9
KG
1798 * return
1799 * void
7725ccfd 1800 *
a36c61f9 1801 * Special Considerations:
7725ccfd 1802 *
a36c61f9 1803 * note
7725ccfd
JH
1804 */
1805static void
1806bfa_fcs_rport_timeout(void *arg)
1807{
a36c61f9 1808 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) arg;
7725ccfd
JH
1809
1810 rport->stats.plogi_timeouts++;
a36c61f9 1811 bfa_stats(rport->port, rport_plogi_timeouts);
7725ccfd
JH
1812 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1813}
1814
1815static void
1816bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
1817 struct fchs_s *rx_fchs, u16 len)
1818{
1819 struct bfa_fcxp_s *fcxp;
a36c61f9
KG
1820 struct fchs_s fchs;
1821 struct bfa_fcs_lport_s *port = rport->port;
1822 struct fc_prli_s *prli;
7725ccfd
JH
1823
1824 bfa_trc(port->fcs, rx_fchs->s_id);
1825 bfa_trc(port->fcs, rx_fchs->d_id);
1826
1827 rport->stats.prli_rcvd++;
1828
7725ccfd 1829 /*
a36c61f9 1830 * We are in Initiator Mode
7725ccfd
JH
1831 */
1832 prli = (struct fc_prli_s *) (rx_fchs + 1);
1833
a36c61f9 1834 if (prli->parampage.servparams.target) {
7725ccfd 1835 /*
a36c61f9
KG
1836 * PRLI from a target ?
1837 * Send the Acc.
1838 * PRLI sent by us will be used to transition the IT nexus,
1839 * once the response is received from the target.
7725ccfd
JH
1840 */
1841 bfa_trc(port->fcs, rx_fchs->s_id);
1842 rport->scsi_function = BFA_RPORT_TARGET;
a36c61f9
KG
1843 } else {
1844 bfa_trc(rport->fcs, prli->parampage.type);
1845 rport->scsi_function = BFA_RPORT_INITIATOR;
1846 bfa_fcs_itnim_is_initiator(rport->itnim);
7725ccfd
JH
1847 }
1848
1849 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1850 if (!fcxp)
1851 return;
1852
a36c61f9
KG
1853 len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1854 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
1855 rx_fchs->ox_id, port->port_cfg.roles);
7725ccfd
JH
1856
1857 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9 1858 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
7725ccfd
JH
1859}
1860
1861static void
1862bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
1863 struct fchs_s *rx_fchs, u16 len)
1864{
1865 struct bfa_fcxp_s *fcxp;
a36c61f9
KG
1866 struct fchs_s fchs;
1867 struct bfa_fcs_lport_s *port = rport->port;
7725ccfd 1868 struct fc_rpsc_speed_info_s speeds;
a36c61f9 1869 struct bfa_port_attr_s pport_attr;
7725ccfd
JH
1870
1871 bfa_trc(port->fcs, rx_fchs->s_id);
1872 bfa_trc(port->fcs, rx_fchs->d_id);
1873
1874 rport->stats.rpsc_rcvd++;
1875 speeds.port_speed_cap =
1876 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
1877 RPSC_SPEED_CAP_8G;
1878
1879 /*
1880 * get curent speed from pport attributes from BFA
1881 */
1c8a4c37 1882 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
7725ccfd
JH
1883
1884 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
1885
1886 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1887 if (!fcxp)
1888 return;
1889
a36c61f9
KG
1890 len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1891 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
1892 rx_fchs->ox_id, &speeds);
7725ccfd
JH
1893
1894 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
a36c61f9 1895 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
7725ccfd
JH
1896}
1897
1898static void
1899bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
1900 struct fchs_s *rx_fchs, u16 len)
1901{
1902 struct bfa_fcxp_s *fcxp;
a36c61f9
KG
1903 struct fchs_s fchs;
1904 struct bfa_fcs_lport_s *port = rport->port;
1905 struct fc_adisc_s *adisc;
7725ccfd
JH
1906
1907 bfa_trc(port->fcs, rx_fchs->s_id);
1908 bfa_trc(port->fcs, rx_fchs->d_id);
1909
1910 rport->stats.adisc_rcvd++;
1911
7725ccfd
JH
1912 adisc = (struct fc_adisc_s *) (rx_fchs + 1);
1913
1914 /*
a36c61f9
KG
1915 * Accept if the itnim for this rport is online.
1916 * Else reject the ADISC.
7725ccfd
JH
1917 */
1918 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
1919
1920 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1921 if (!fcxp)
1922 return;
1923
1924 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
a36c61f9
KG
1925 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
1926 rx_fchs->ox_id, port->port_cfg.pwwn,
1927 port->port_cfg.nwwn);
7725ccfd
JH
1928
1929 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
a36c61f9
KG
1930 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
1931 FC_MAX_PDUSZ, 0);
7725ccfd
JH
1932 } else {
1933 rport->stats.adisc_rejected++;
1934 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
1935 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
1936 FC_LS_RJT_EXP_LOGIN_REQUIRED);
1937 }
7725ccfd
JH
1938}
1939
1940static void
1941bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
1942{
a36c61f9 1943 struct bfa_fcs_lport_s *port = rport->port;
7725ccfd
JH
1944 struct bfa_rport_info_s rport_info;
1945
1946 rport_info.pid = rport->pid;
1947 rport_info.local_pid = port->pid;
1948 rport_info.lp_tag = port->lp_tag;
1949 rport_info.vf_id = port->fabric->vf_id;
1950 rport_info.vf_en = port->fabric->is_vf;
1951 rport_info.fc_class = rport->fc_cos;
1952 rport_info.cisc = rport->cisc;
1953 rport_info.max_frmsz = rport->maxfrsize;
1954 bfa_rport_online(rport->bfa_rport, &rport_info);
1955}
1956
7725ccfd 1957static struct bfa_fcs_rport_s *
a36c61f9 1958bfa_fcs_rport_alloc(struct bfa_fcs_lport_s *port, wwn_t pwwn, u32 rpid)
7725ccfd 1959{
a36c61f9 1960 struct bfa_fcs_s *fcs = port->fcs;
7725ccfd 1961 struct bfa_fcs_rport_s *rport;
a36c61f9 1962 struct bfad_rport_s *rport_drv;
7725ccfd 1963
5fbe25c7 1964 /*
7725ccfd
JH
1965 * allocate rport
1966 */
1967 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
a36c61f9 1968 != BFA_STATUS_OK) {
7725ccfd
JH
1969 bfa_trc(fcs, rpid);
1970 return NULL;
1971 }
1972
1973 /*
1974 * Initialize r-port
1975 */
1976 rport->port = port;
1977 rport->fcs = fcs;
1978 rport->rp_drv = rport_drv;
1979 rport->pid = rpid;
1980 rport->pwwn = pwwn;
1981
5fbe25c7 1982 /*
7725ccfd
JH
1983 * allocate BFA rport
1984 */
1985 rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
1986 if (!rport->bfa_rport) {
1987 bfa_trc(fcs, rpid);
1988 kfree(rport_drv);
1989 return NULL;
1990 }
1991
5fbe25c7 1992 /*
7725ccfd
JH
1993 * allocate FC-4s
1994 */
a36c61f9 1995 bfa_assert(bfa_fcs_lport_is_initiator(port));
7725ccfd 1996
a36c61f9 1997 if (bfa_fcs_lport_is_initiator(port)) {
7725ccfd
JH
1998 rport->itnim = bfa_fcs_itnim_create(rport);
1999 if (!rport->itnim) {
2000 bfa_trc(fcs, rpid);
2001 bfa_rport_delete(rport->bfa_rport);
2002 kfree(rport_drv);
2003 return NULL;
2004 }
2005 }
2006
a36c61f9 2007 bfa_fcs_lport_add_rport(port, rport);
7725ccfd
JH
2008
2009 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2010
a36c61f9 2011 /* Initialize the Rport Features(RPF) Sub Module */
7725ccfd
JH
2012 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2013 bfa_fcs_rpf_init(rport);
2014
2015 return rport;
2016}
2017
2018
2019static void
2020bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2021{
a36c61f9 2022 struct bfa_fcs_lport_s *port = rport->port;
7725ccfd 2023
5fbe25c7 2024 /*
7725ccfd
JH
2025 * - delete FC-4s
2026 * - delete BFA rport
2027 * - remove from queue of rports
2028 */
a36c61f9 2029 if (bfa_fcs_lport_is_initiator(port)) {
7725ccfd 2030 bfa_fcs_itnim_delete(rport->itnim);
a36c61f9
KG
2031 if (rport->pid != 0 && !BFA_FCS_PID_IS_WKA(rport->pid))
2032 bfa_fcs_rpf_rport_offline(rport);
2033 }
7725ccfd
JH
2034
2035 bfa_rport_delete(rport->bfa_rport);
a36c61f9 2036 bfa_fcs_lport_del_rport(port, rport);
7725ccfd
JH
2037 kfree(rport->rp_drv);
2038}
2039
7725ccfd
JH
2040static void
2041bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2042{
a36c61f9
KG
2043 struct bfa_fcs_lport_s *port = rport->port;
2044 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2045 char lpwwn_buf[BFA_STRING_32];
2046 char rpwwn_buf[BFA_STRING_32];
7725ccfd
JH
2047
2048 rport->stats.onlines++;
2049
a36c61f9 2050 if (bfa_fcs_lport_is_initiator(port)) {
7725ccfd
JH
2051 bfa_fcs_itnim_rport_online(rport->itnim);
2052 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2053 bfa_fcs_rpf_rport_online(rport);
2054 };
2055
a36c61f9
KG
2056 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2057 wwn2str(rpwwn_buf, rport->pwwn);
7725ccfd 2058 if (!BFA_FCS_PID_IS_WKA(rport->pid))
88166242 2059 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
a36c61f9
KG
2060 "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
2061 rpwwn_buf, lpwwn_buf);
7725ccfd
JH
2062}
2063
2064static void
2065bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
2066{
a36c61f9
KG
2067 struct bfa_fcs_lport_s *port = rport->port;
2068 struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
2069 char lpwwn_buf[BFA_STRING_32];
2070 char rpwwn_buf[BFA_STRING_32];
7725ccfd
JH
2071
2072 rport->stats.offlines++;
2073
a36c61f9
KG
2074 wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
2075 wwn2str(rpwwn_buf, rport->pwwn);
7725ccfd 2076 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
a36c61f9 2077 if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE)
88166242 2078 BFA_LOG(KERN_ERR, bfad, bfa_log_level,
a36c61f9
KG
2079 "Remote port (WWN = %s) connectivity lost for "
2080 "logical port (WWN = %s)\n",
2081 rpwwn_buf, lpwwn_buf);
2082 else
88166242 2083 BFA_LOG(KERN_INFO, bfad, bfa_log_level,
a36c61f9
KG
2084 "Remote port (WWN = %s) offlined by "
2085 "logical port (WWN = %s)\n",
2086 rpwwn_buf, lpwwn_buf);
7725ccfd
JH
2087 }
2088
a36c61f9 2089 if (bfa_fcs_lport_is_initiator(port)) {
7725ccfd
JH
2090 bfa_fcs_itnim_rport_offline(rport->itnim);
2091 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2092 bfa_fcs_rpf_rport_offline(rport);
2093 }
7725ccfd
JH
2094}
2095
5fbe25c7 2096/*
7725ccfd
JH
2097 * Update rport parameters from PLOGI or PLOGI accept.
2098 */
2099static void
2100bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2101{
a36c61f9 2102 bfa_fcs_lport_t *port = rport->port;
7725ccfd 2103
5fbe25c7 2104 /*
7725ccfd
JH
2105 * - port name
2106 * - node name
2107 */
2108 rport->pwwn = plogi->port_name;
2109 rport->nwwn = plogi->node_name;
2110
5fbe25c7 2111 /*
7725ccfd
JH
2112 * - class of service
2113 */
2114 rport->fc_cos = 0;
2115 if (plogi->class3.class_valid)
2116 rport->fc_cos = FC_CLASS_3;
2117
2118 if (plogi->class2.class_valid)
2119 rport->fc_cos |= FC_CLASS_2;
2120
5fbe25c7 2121 /*
7725ccfd
JH
2122 * - CISC
2123 * - MAX receive frame size
2124 */
2125 rport->cisc = plogi->csp.cisc;
ba816ea8 2126 rport->maxfrsize = be16_to_cpu(plogi->class3.rxsz);
7725ccfd 2127
ba816ea8 2128 bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
7725ccfd 2129 bfa_trc(port->fcs, port->fabric->bb_credit);
5fbe25c7 2130 /*
7725ccfd
JH
2131 * Direct Attach P2P mode :
2132 * This is to handle a bug (233476) in IBM targets in Direct Attach
a36c61f9
KG
2133 * Mode. Basically, in FLOGI Accept the target would have
2134 * erroneously set the BB Credit to the value used in the FLOGI
2135 * sent by the HBA. It uses the correct value (its own BB credit)
2136 * in PLOGI.
7725ccfd 2137 */
a36c61f9 2138 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
ba816ea8 2139 (be16_to_cpu(plogi->csp.bbcred) < port->fabric->bb_credit)) {
7725ccfd 2140
ba816ea8 2141 bfa_trc(port->fcs, be16_to_cpu(plogi->csp.bbcred));
7725ccfd
JH
2142 bfa_trc(port->fcs, port->fabric->bb_credit);
2143
ba816ea8 2144 port->fabric->bb_credit = be16_to_cpu(plogi->csp.bbcred);
1c8a4c37 2145 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
7725ccfd
JH
2146 port->fabric->bb_credit);
2147 }
2148
2149}
2150
5fbe25c7 2151/*
a36c61f9 2152 * Called to handle LOGO received from an existing remote port.
7725ccfd
JH
2153 */
2154static void
2155bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2156{
2157 rport->reply_oxid = fchs->ox_id;
2158 bfa_trc(rport->fcs, rport->reply_oxid);
2159
4b5e759d 2160 rport->prlo = BFA_FALSE;
7725ccfd
JH
2161 rport->stats.logo_rcvd++;
2162 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2163}
2164
2165
2166
5fbe25c7 2167/*
7725ccfd
JH
2168 * fcs_rport_public FCS rport public interfaces
2169 */
2170
5fbe25c7 2171/*
a36c61f9
KG
2172 * Called by bport/vport to create a remote port instance for a discovered
2173 * remote device.
7725ccfd
JH
2174 *
2175 * @param[in] port - base port or vport
2176 * @param[in] rpid - remote port ID
2177 *
2178 * @return None
2179 */
2180struct bfa_fcs_rport_s *
a36c61f9 2181bfa_fcs_rport_create(struct bfa_fcs_lport_s *port, u32 rpid)
7725ccfd
JH
2182{
2183 struct bfa_fcs_rport_s *rport;
2184
2185 bfa_trc(port->fcs, rpid);
2186 rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2187 if (!rport)
2188 return NULL;
2189
2190 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2191 return rport;
2192}
2193
5fbe25c7 2194/*
7725ccfd
JH
2195 * Called to create a rport for which only the wwn is known.
2196 *
2197 * @param[in] port - base port
2198 * @param[in] rpwwn - remote port wwn
2199 *
2200 * @return None
2201 */
2202struct bfa_fcs_rport_s *
a36c61f9 2203bfa_fcs_rport_create_by_wwn(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
7725ccfd
JH
2204{
2205 struct bfa_fcs_rport_s *rport;
7725ccfd
JH
2206 bfa_trc(port->fcs, rpwwn);
2207 rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2208 if (!rport)
2209 return NULL;
2210
2211 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2212 return rport;
2213}
5fbe25c7 2214/*
7725ccfd
JH
2215 * Called by bport in private loop topology to indicate that a
2216 * rport has been discovered and plogi has been completed.
2217 *
2218 * @param[in] port - base port or vport
2219 * @param[in] rpid - remote port ID
2220 */
2221void
a36c61f9
KG
2222bfa_fcs_rport_start(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2223 struct fc_logi_s *plogi)
7725ccfd
JH
2224{
2225 struct bfa_fcs_rport_s *rport;
2226
2227 rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2228 if (!rport)
2229 return;
2230
2231 bfa_fcs_rport_update(rport, plogi);
2232
2233 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2234}
2235
5fbe25c7 2236/*
a36c61f9
KG
2237 * Called by bport/vport to handle PLOGI received from a new remote port.
2238 * If an existing rport does a plogi, it will be handled separately.
7725ccfd
JH
2239 */
2240void
a36c61f9
KG
2241bfa_fcs_rport_plogi_create(struct bfa_fcs_lport_s *port, struct fchs_s *fchs,
2242 struct fc_logi_s *plogi)
7725ccfd
JH
2243{
2244 struct bfa_fcs_rport_s *rport;
2245
2246 rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2247 if (!rport)
2248 return;
2249
2250 bfa_fcs_rport_update(rport, plogi);
2251
2252 rport->reply_oxid = fchs->ox_id;
2253 bfa_trc(rport->fcs, rport->reply_oxid);
2254
2255 rport->stats.plogi_rcvd++;
2256 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2257}
2258
2259static int
2260wwn_compare(wwn_t wwn1, wwn_t wwn2)
2261{
a36c61f9
KG
2262 u8 *b1 = (u8 *) &wwn1;
2263 u8 *b2 = (u8 *) &wwn2;
2264 int i;
7725ccfd
JH
2265
2266 for (i = 0; i < sizeof(wwn_t); i++) {
2267 if (b1[i] < b2[i])
2268 return -1;
2269 if (b1[i] > b2[i])
2270 return 1;
2271 }
2272 return 0;
2273}
2274
5fbe25c7 2275/*
a36c61f9
KG
2276 * Called by bport/vport to handle PLOGI received from an existing
2277 * remote port.
7725ccfd
JH
2278 */
2279void
2280bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
a36c61f9 2281 struct fc_logi_s *plogi)
7725ccfd 2282{
5fbe25c7 2283 /*
7725ccfd
JH
2284 * @todo Handle P2P and initiator-initiator.
2285 */
2286
2287 bfa_fcs_rport_update(rport, plogi);
2288
2289 rport->reply_oxid = rx_fchs->ox_id;
2290 bfa_trc(rport->fcs, rport->reply_oxid);
2291
5fbe25c7 2292 /*
7725ccfd
JH
2293 * In Switched fabric topology,
2294 * PLOGI to each other. If our pwwn is smaller, ignore it,
2295 * if it is not a well known address.
2296 * If the link topology is N2N,
2297 * this Plogi should be accepted.
2298 */
a36c61f9
KG
2299 if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) &&
2300 (bfa_fcs_fabric_is_switched(rport->port->fabric)) &&
2301 (!BFA_FCS_PID_IS_WKA(rport->pid))) {
7725ccfd
JH
2302 bfa_trc(rport->fcs, rport->pid);
2303 return;
2304 }
2305
2306 rport->stats.plogi_rcvd++;
2307 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2308}
2309
5fbe25c7 2310/*
7725ccfd
JH
2311 * Called by bport/vport to delete a remote port instance.
2312 *
a36c61f9
KG
2313 * Rport delete is called under the following conditions:
2314 * - vport is deleted
2315 * - vf is deleted
2316 * - explicit request from OS to delete rport
7725ccfd
JH
2317 */
2318void
2319bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
2320{
2321 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
2322}
2323
5fbe25c7 2324/*
7725ccfd
JH
2325 * Called by bport/vport to when a target goes offline.
2326 *
2327 */
2328void
2329bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
2330{
2331 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2332}
2333
5fbe25c7 2334/*
7725ccfd
JH
2335 * Called by bport in n2n when a target (attached port) becomes online.
2336 *
2337 */
2338void
2339bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
2340{
2341 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2342}
5fbe25c7 2343/*
a36c61f9 2344 * Called by bport/vport to notify SCN for the remote port
7725ccfd
JH
2345 */
2346void
2347bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2348{
7725ccfd
JH
2349 rport->stats.rscns++;
2350 bfa_sm_send_event(rport, RPSM_EVENT_SCN);
2351}
2352
5fbe25c7 2353/*
a36c61f9 2354 * Called by fcpim to notify that the ITN cleanup is done.
7725ccfd
JH
2355 */
2356void
2357bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
2358{
2359 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2360}
2361
7725ccfd 2362
5fbe25c7 2363/*
a36c61f9
KG
2364 * brief
2365 * This routine BFA callback for bfa_rport_online() call.
7725ccfd 2366 *
a36c61f9 2367 * param[in] cb_arg - rport struct.
7725ccfd 2368 *
a36c61f9
KG
2369 * return
2370 * void
7725ccfd 2371 *
a36c61f9 2372 * Special Considerations:
7725ccfd 2373 *
a36c61f9 2374 * note
7725ccfd
JH
2375 */
2376void
2377bfa_cb_rport_online(void *cbarg)
2378{
2379
a36c61f9 2380 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
7725ccfd
JH
2381
2382 bfa_trc(rport->fcs, rport->pwwn);
2383 bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2384}
2385
5fbe25c7 2386/*
a36c61f9
KG
2387 * brief
2388 * This routine BFA callback for bfa_rport_offline() call.
7725ccfd 2389 *
a36c61f9 2390 * param[in] rport -
7725ccfd 2391 *
a36c61f9
KG
2392 * return
2393 * void
7725ccfd 2394 *
a36c61f9 2395 * Special Considerations:
7725ccfd 2396 *
a36c61f9 2397 * note
7725ccfd
JH
2398 */
2399void
2400bfa_cb_rport_offline(void *cbarg)
2401{
a36c61f9 2402 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
7725ccfd
JH
2403
2404 bfa_trc(rport->fcs, rport->pwwn);
2405 bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2406}
2407
5fbe25c7 2408/*
a36c61f9
KG
2409 * brief
2410 * This routine is a static BFA callback when there is a QoS flow_id
2411 * change notification
7725ccfd 2412 *
a36c61f9 2413 * param[in] rport -
7725ccfd 2414 *
a36c61f9
KG
2415 * return
2416 * void
7725ccfd 2417 *
a36c61f9 2418 * Special Considerations:
7725ccfd 2419 *
a36c61f9 2420 * note
7725ccfd
JH
2421 */
2422void
2423bfa_cb_rport_qos_scn_flowid(void *cbarg,
a36c61f9
KG
2424 struct bfa_rport_qos_attr_s old_qos_attr,
2425 struct bfa_rport_qos_attr_s new_qos_attr)
7725ccfd 2426{
a36c61f9 2427 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
7725ccfd
JH
2428
2429 bfa_trc(rport->fcs, rport->pwwn);
7725ccfd
JH
2430}
2431
5fbe25c7 2432/*
a36c61f9
KG
2433 * brief
2434 * This routine is a static BFA callback when there is a QoS priority
2435 * change notification
7725ccfd 2436 *
a36c61f9 2437 * param[in] rport -
7725ccfd 2438 *
a36c61f9
KG
2439 * return
2440 * void
7725ccfd 2441 *
a36c61f9 2442 * Special Considerations:
7725ccfd 2443 *
a36c61f9 2444 * note
7725ccfd
JH
2445 */
2446void
a36c61f9
KG
2447bfa_cb_rport_qos_scn_prio(void *cbarg,
2448 struct bfa_rport_qos_attr_s old_qos_attr,
2449 struct bfa_rport_qos_attr_s new_qos_attr)
7725ccfd 2450{
a36c61f9 2451 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *) cbarg;
7725ccfd
JH
2452
2453 bfa_trc(rport->fcs, rport->pwwn);
7725ccfd
JH
2454}
2455
5fbe25c7 2456/*
a36c61f9 2457 * Called to process any unsolicted frames from this remote port
7725ccfd
JH
2458 */
2459void
2460bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
2461{
2462 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2463}
2464
5fbe25c7 2465/*
a36c61f9 2466 * Called to process any unsolicted frames from this remote port
7725ccfd
JH
2467 */
2468void
a36c61f9
KG
2469bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport,
2470 struct fchs_s *fchs, u16 len)
7725ccfd 2471{
a36c61f9
KG
2472 struct bfa_fcs_lport_s *port = rport->port;
2473 struct fc_els_cmd_s *els_cmd;
7725ccfd
JH
2474
2475 bfa_trc(rport->fcs, fchs->s_id);
2476 bfa_trc(rport->fcs, fchs->d_id);
2477 bfa_trc(rport->fcs, fchs->type);
2478
2479 if (fchs->type != FC_TYPE_ELS)
2480 return;
2481
2482 els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2483
2484 bfa_trc(rport->fcs, els_cmd->els_code);
2485
2486 switch (els_cmd->els_code) {
2487 case FC_ELS_LOGO:
a36c61f9 2488 bfa_stats(port, plogi_rcvd);
7725ccfd
JH
2489 bfa_fcs_rport_process_logo(rport, fchs);
2490 break;
2491
2492 case FC_ELS_ADISC:
a36c61f9 2493 bfa_stats(port, adisc_rcvd);
7725ccfd
JH
2494 bfa_fcs_rport_process_adisc(rport, fchs, len);
2495 break;
2496
2497 case FC_ELS_PRLO:
a36c61f9
KG
2498 bfa_stats(port, prlo_rcvd);
2499 if (bfa_fcs_lport_is_initiator(port))
7725ccfd 2500 bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
7725ccfd
JH
2501 break;
2502
2503 case FC_ELS_PRLI:
a36c61f9 2504 bfa_stats(port, prli_rcvd);
7725ccfd
JH
2505 bfa_fcs_rport_process_prli(rport, fchs, len);
2506 break;
2507
2508 case FC_ELS_RPSC:
a36c61f9 2509 bfa_stats(port, rpsc_rcvd);
7725ccfd
JH
2510 bfa_fcs_rport_process_rpsc(rport, fchs, len);
2511 break;
2512
2513 default:
a36c61f9 2514 bfa_stats(port, un_handled_els_rcvd);
7725ccfd
JH
2515 bfa_fcs_rport_send_ls_rjt(rport, fchs,
2516 FC_LS_RJT_RSN_CMD_NOT_SUPP,
2517 FC_LS_RJT_EXP_NO_ADDL_INFO);
2518 break;
2519 }
2520}
2521
a36c61f9 2522/* send best case acc to prlo */
4b5e759d
JH
2523static void
2524bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2525{
a36c61f9
KG
2526 struct bfa_fcs_lport_s *port = rport->port;
2527 struct fchs_s fchs;
4b5e759d 2528 struct bfa_fcxp_s *fcxp;
a36c61f9 2529 int len;
4b5e759d
JH
2530
2531 bfa_trc(rport->fcs, rport->pid);
2532
2533 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
2534 if (!fcxp)
2535 return;
4b5e759d 2536 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
a36c61f9 2537 rport->pid, bfa_fcs_lport_get_fcid(port),
4b5e759d
JH
2538 rport->reply_oxid, 0);
2539
2540 bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
a36c61f9
KG
2541 port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
2542 NULL, NULL, FC_MAX_PDUSZ, 0);
4b5e759d
JH
2543}
2544
7725ccfd
JH
2545/*
2546 * Send a LS reject
2547 */
2548static void
2549bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2550 u8 reason_code, u8 reason_code_expl)
2551{
a36c61f9
KG
2552 struct bfa_fcs_lport_s *port = rport->port;
2553 struct fchs_s fchs;
7725ccfd 2554 struct bfa_fcxp_s *fcxp;
a36c61f9 2555 int len;
7725ccfd
JH
2556
2557 bfa_trc(rport->fcs, rx_fchs->s_id);
2558
2559 fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
2560 if (!fcxp)
2561 return;
2562
a36c61f9
KG
2563 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2564 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
2565 rx_fchs->ox_id, reason_code, reason_code_expl);
7725ccfd 2566
a36c61f9
KG
2567 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
2568 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
2569 FC_MAX_PDUSZ, 0);
7725ccfd
JH
2570}
2571
5fbe25c7 2572/*
7725ccfd
JH
2573 * Return state of rport.
2574 */
2575int
2576bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2577{
2578 return bfa_sm_to_state(rport_sm_table, rport->sm);
2579}
2580
5fbe25c7 2581/*
a36c61f9
KG
2582 * brief
2583 * Called by the Driver to set rport delete/ageout timeout
7725ccfd 2584 *
a36c61f9 2585 * param[in] rport timeout value in seconds.
7725ccfd 2586 *
a36c61f9 2587 * return None
7725ccfd
JH
2588 */
2589void
2590bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2591{
a36c61f9 2592 /* convert to Millisecs */
7725ccfd
JH
2593 if (rport_tmo > 0)
2594 bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2595}
4b5e759d 2596void
a36c61f9 2597bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, u16 ox_id)
4b5e759d
JH
2598{
2599 bfa_trc(rport->fcs, rport->pid);
2600
2601 rport->prlo = BFA_TRUE;
2602 rport->reply_oxid = ox_id;
2603 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);
2604}
a36c61f9
KG
2605
2606
2607
5fbe25c7 2608/*
a36c61f9
KG
2609 * Remote port implementation.
2610 */
2611
5fbe25c7 2612/*
a36c61f9
KG
2613 * fcs_rport_api FCS rport API.
2614 */
2615
5fbe25c7 2616/*
a36c61f9
KG
2617 * Direct API to add a target by port wwn. This interface is used, for
2618 * example, by bios when target pwwn is known from boot lun configuration.
2619 */
2620bfa_status_t
2621bfa_fcs_rport_add(struct bfa_fcs_lport_s *port, wwn_t *pwwn,
2622 struct bfa_fcs_rport_s *rport, struct bfad_rport_s *rport_drv)
2623{
2624 bfa_trc(port->fcs, *pwwn);
2625
2626 return BFA_STATUS_OK;
2627}
2628
5fbe25c7 2629/*
a36c61f9
KG
2630 * Direct API to remove a target and its associated resources. This
2631 * interface is used, for example, by driver to remove target
2632 * ports from the target list for a VM.
2633 */
2634bfa_status_t
2635bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in)
2636{
2637
2638 struct bfa_fcs_rport_s *rport;
2639
2640 bfa_trc(rport_in->fcs, rport_in->pwwn);
2641
2642 rport = bfa_fcs_lport_get_rport_by_pwwn(rport_in->port, rport_in->pwwn);
2643 if (rport == NULL) {
2644 /*
2645 * TBD Error handling
2646 */
2647 bfa_trc(rport_in->fcs, rport_in->pid);
2648 return BFA_STATUS_UNKNOWN_RWWN;
2649 }
2650
2651 /*
2652 * TBD if this remote port is online, send a logo
2653 */
2654 return BFA_STATUS_OK;
2655
2656}
2657
5fbe25c7 2658/*
a36c61f9
KG
2659 * Remote device status for display/debug.
2660 */
2661void
2662bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport,
2663 struct bfa_rport_attr_s *rport_attr)
2664{
2665 struct bfa_rport_qos_attr_s qos_attr;
2666 bfa_fcs_lport_t *port = rport->port;
2667 bfa_port_speed_t rport_speed = rport->rpf.rpsc_speed;
2668
6a18b167 2669 memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s));
a36c61f9
KG
2670
2671 rport_attr->pid = rport->pid;
2672 rport_attr->pwwn = rport->pwwn;
2673 rport_attr->nwwn = rport->nwwn;
2674 rport_attr->cos_supported = rport->fc_cos;
2675 rport_attr->df_sz = rport->maxfrsize;
2676 rport_attr->state = bfa_fcs_rport_get_state(rport);
2677 rport_attr->fc_cos = rport->fc_cos;
2678 rport_attr->cisc = rport->cisc;
2679 rport_attr->scsi_function = rport->scsi_function;
2680 rport_attr->curr_speed = rport->rpf.rpsc_speed;
2681 rport_attr->assigned_speed = rport->rpf.assigned_speed;
2682
2683 bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr);
2684 rport_attr->qos_attr = qos_attr;
2685
2686 rport_attr->trl_enforced = BFA_FALSE;
2687 if (bfa_fcport_is_ratelim(port->fcs->bfa)) {
2688 if (rport_speed == BFA_PORT_SPEED_UNKNOWN) {
2689 /* Use default ratelim speed setting */
2690 rport_speed =
2691 bfa_fcport_get_ratelim_speed(rport->fcs->bfa);
2692 }
2693
2694 if (rport_speed < bfa_fcs_lport_get_rport_max_speed(port))
2695 rport_attr->trl_enforced = BFA_TRUE;
2696 }
2697}
2698
5fbe25c7 2699/*
a36c61f9
KG
2700 * Per remote device statistics.
2701 */
2702void
2703bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport,
2704 struct bfa_rport_stats_s *stats)
2705{
2706 *stats = rport->stats;
2707}
2708
2709void
2710bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport)
2711{
6a18b167 2712 memset((char *)&rport->stats, 0,
a36c61f9
KG
2713 sizeof(struct bfa_rport_stats_s));
2714}
2715
2716struct bfa_fcs_rport_s *
2717bfa_fcs_rport_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
2718{
2719 struct bfa_fcs_rport_s *rport;
2720
2721 rport = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
2722 if (rport == NULL) {
2723 /*
2724 * TBD Error handling
2725 */
2726 }
2727
2728 return rport;
2729}
2730
2731struct bfa_fcs_rport_s *
2732bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t rnwwn)
2733{
2734 struct bfa_fcs_rport_s *rport;
2735
2736 rport = bfa_fcs_lport_get_rport_by_nwwn(port, rnwwn);
2737 if (rport == NULL) {
2738 /*
2739 * TBD Error handling
2740 */
2741 }
2742
2743 return rport;
2744}
2745
2746/*
2747 * This API is to set the Rport's speed. Should be used when RPSC is not
2748 * supported by the rport.
2749 */
2750void
2751bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, bfa_port_speed_t speed)
2752{
2753 rport->rpf.assigned_speed = speed;
2754
2755 /* Set this speed in f/w only if the RPSC speed is not available */
2756 if (rport->rpf.rpsc_speed == BFA_PORT_SPEED_UNKNOWN)
2757 bfa_rport_speed(rport->bfa_rport, speed);
2758}
2759
2760
2761
5fbe25c7 2762/*
a36c61f9
KG
2763 * Remote port features (RPF) implementation.
2764 */
2765
2766#define BFA_FCS_RPF_RETRIES (3)
2767#define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */
2768
2769static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg,
2770 struct bfa_fcxp_s *fcxp_alloced);
2771static void bfa_fcs_rpf_rpsc2_response(void *fcsarg,
2772 struct bfa_fcxp_s *fcxp,
2773 void *cbarg,
2774 bfa_status_t req_status,
2775 u32 rsp_len,
2776 u32 resid_len,
2777 struct fchs_s *rsp_fchs);
2778
2779static void bfa_fcs_rpf_timeout(void *arg);
2780
5fbe25c7 2781/*
a36c61f9
KG
2782 * fcs_rport_ftrs_sm FCS rport state machine events
2783 */
2784
2785enum rpf_event {
2786 RPFSM_EVENT_RPORT_OFFLINE = 1, /* Rport offline */
2787 RPFSM_EVENT_RPORT_ONLINE = 2, /* Rport online */
2788 RPFSM_EVENT_FCXP_SENT = 3, /* Frame from has been sent */
2789 RPFSM_EVENT_TIMEOUT = 4, /* Rport SM timeout event */
2790 RPFSM_EVENT_RPSC_COMP = 5,
2791 RPFSM_EVENT_RPSC_FAIL = 6,
2792 RPFSM_EVENT_RPSC_ERROR = 7,
2793};
2794
2795static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf,
2796 enum rpf_event event);
2797static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf,
2798 enum rpf_event event);
2799static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf,
2800 enum rpf_event event);
2801static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf,
2802 enum rpf_event event);
2803static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf,
2804 enum rpf_event event);
2805static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf,
2806 enum rpf_event event);
2807
2808static void
2809bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
2810{
2811 struct bfa_fcs_rport_s *rport = rpf->rport;
2812 struct bfa_fcs_fabric_s *fabric = &rport->fcs->fabric;
2813
2814 bfa_trc(rport->fcs, rport->pwwn);
2815 bfa_trc(rport->fcs, rport->pid);
2816 bfa_trc(rport->fcs, event);
2817
2818 switch (event) {
2819 case RPFSM_EVENT_RPORT_ONLINE:
2820 /* Send RPSC2 to a Brocade fabric only. */
2821 if ((!BFA_FCS_PID_IS_WKA(rport->pid)) &&
2822 ((bfa_lps_is_brcd_fabric(rport->port->fabric->lps)) ||
2823 (bfa_fcs_fabric_get_switch_oui(fabric) ==
2824 BFA_FCS_BRCD_SWITCH_OUI))) {
2825 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
2826 rpf->rpsc_retries = 0;
2827 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
2828 }
2829 break;
2830
2831 case RPFSM_EVENT_RPORT_OFFLINE:
2832 break;
2833
2834 default:
2835 bfa_sm_fault(rport->fcs, event);
2836 }
2837}
2838
2839static void
2840bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
2841{
2842 struct bfa_fcs_rport_s *rport = rpf->rport;
2843
2844 bfa_trc(rport->fcs, event);
2845
2846 switch (event) {
2847 case RPFSM_EVENT_FCXP_SENT:
2848 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc);
2849 break;
2850
2851 case RPFSM_EVENT_RPORT_OFFLINE:
2852 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
2853 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe);
2854 rpf->rpsc_retries = 0;
2855 break;
2856
2857 default:
2858 bfa_sm_fault(rport->fcs, event);
2859 }
2860}
2861
2862static void
2863bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
2864{
2865 struct bfa_fcs_rport_s *rport = rpf->rport;
2866
2867 bfa_trc(rport->fcs, rport->pid);
2868 bfa_trc(rport->fcs, event);
2869
2870 switch (event) {
2871 case RPFSM_EVENT_RPSC_COMP:
2872 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
2873 /* Update speed info in f/w via BFA */
2874 if (rpf->rpsc_speed != BFA_PORT_SPEED_UNKNOWN)
2875 bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed);
2876 else if (rpf->assigned_speed != BFA_PORT_SPEED_UNKNOWN)
2877 bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed);
2878 break;
2879
2880 case RPFSM_EVENT_RPSC_FAIL:
2881 /* RPSC not supported by rport */
2882 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
2883 break;
2884
2885 case RPFSM_EVENT_RPSC_ERROR:
2886 /* need to retry...delayed a bit. */
2887 if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) {
2888 bfa_timer_start(rport->fcs->bfa, &rpf->timer,
2889 bfa_fcs_rpf_timeout, rpf,
2890 BFA_FCS_RPF_RETRY_TIMEOUT);
2891 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry);
2892 } else {
2893 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online);
2894 }
2895 break;
2896
2897 case RPFSM_EVENT_RPORT_OFFLINE:
2898 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
2899 bfa_fcxp_discard(rpf->fcxp);
2900 rpf->rpsc_retries = 0;
2901 break;
2902
2903 default:
2904 bfa_sm_fault(rport->fcs, event);
2905 }
2906}
2907
2908static void
2909bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
2910{
2911 struct bfa_fcs_rport_s *rport = rpf->rport;
2912
2913 bfa_trc(rport->fcs, rport->pid);
2914 bfa_trc(rport->fcs, event);
2915
2916 switch (event) {
2917 case RPFSM_EVENT_TIMEOUT:
2918 /* re-send the RPSC */
2919 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
2920 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
2921 break;
2922
2923 case RPFSM_EVENT_RPORT_OFFLINE:
2924 bfa_timer_stop(&rpf->timer);
2925 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
2926 rpf->rpsc_retries = 0;
2927 break;
2928
2929 default:
2930 bfa_sm_fault(rport->fcs, event);
2931 }
2932}
2933
2934static void
2935bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
2936{
2937 struct bfa_fcs_rport_s *rport = rpf->rport;
2938
2939 bfa_trc(rport->fcs, rport->pwwn);
2940 bfa_trc(rport->fcs, rport->pid);
2941 bfa_trc(rport->fcs, event);
2942
2943 switch (event) {
2944 case RPFSM_EVENT_RPORT_OFFLINE:
2945 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline);
2946 rpf->rpsc_retries = 0;
2947 break;
2948
2949 default:
2950 bfa_sm_fault(rport->fcs, event);
2951 }
2952}
2953
2954static void
2955bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event)
2956{
2957 struct bfa_fcs_rport_s *rport = rpf->rport;
2958
2959 bfa_trc(rport->fcs, rport->pwwn);
2960 bfa_trc(rport->fcs, rport->pid);
2961 bfa_trc(rport->fcs, event);
2962
2963 switch (event) {
2964 case RPFSM_EVENT_RPORT_ONLINE:
2965 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending);
2966 bfa_fcs_rpf_send_rpsc2(rpf, NULL);
2967 break;
2968
2969 case RPFSM_EVENT_RPORT_OFFLINE:
2970 break;
2971
2972 default:
2973 bfa_sm_fault(rport->fcs, event);
2974 }
2975}
5fbe25c7 2976/*
a36c61f9
KG
2977 * Called when Rport is created.
2978 */
2979void
2980bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport)
2981{
2982 struct bfa_fcs_rpf_s *rpf = &rport->rpf;
2983
2984 bfa_trc(rport->fcs, rport->pid);
2985 rpf->rport = rport;
2986
2987 bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit);
2988}
2989
5fbe25c7 2990/*
a36c61f9
KG
2991 * Called when Rport becomes online
2992 */
2993void
2994bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport)
2995{
2996 bfa_trc(rport->fcs, rport->pid);
2997
2998 if (__fcs_min_cfg(rport->port->fcs))
2999 return;
3000
3001 if (bfa_fcs_fabric_is_switched(rport->port->fabric))
3002 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE);
3003}
3004
5fbe25c7 3005/*
a36c61f9
KG
3006 * Called when Rport becomes offline
3007 */
3008void
3009bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport)
3010{
3011 bfa_trc(rport->fcs, rport->pid);
3012
3013 if (__fcs_min_cfg(rport->port->fcs))
3014 return;
3015
3016 rport->rpf.rpsc_speed = 0;
3017 bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE);
3018}
3019
3020static void
3021bfa_fcs_rpf_timeout(void *arg)
3022{
3023 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg;
3024 struct bfa_fcs_rport_s *rport = rpf->rport;
3025
3026 bfa_trc(rport->fcs, rport->pid);
3027 bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT);
3028}
3029
3030static void
3031bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3032{
3033 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg;
3034 struct bfa_fcs_rport_s *rport = rpf->rport;
3035 struct bfa_fcs_lport_s *port = rport->port;
3036 struct fchs_s fchs;
3037 int len;
3038 struct bfa_fcxp_s *fcxp;
3039
3040 bfa_trc(rport->fcs, rport->pwwn);
3041
3042 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3043 if (!fcxp) {
3044 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe,
3045 bfa_fcs_rpf_send_rpsc2, rpf);
3046 return;
3047 }
3048 rpf->fcxp = fcxp;
3049
3050 len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
3051 bfa_fcs_lport_get_fcid(port), &rport->pid, 1);
3052
3053 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3054 FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response,
3055 rpf, FC_MAX_PDUSZ, FC_ELS_TOV);
3056 rport->stats.rpsc_sent++;
3057 bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT);
3058
3059}
3060
3061static void
3062bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
3063 bfa_status_t req_status, u32 rsp_len,
3064 u32 resid_len, struct fchs_s *rsp_fchs)
3065{
3066 struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg;
3067 struct bfa_fcs_rport_s *rport = rpf->rport;
3068 struct fc_ls_rjt_s *ls_rjt;
3069 struct fc_rpsc2_acc_s *rpsc2_acc;
3070 u16 num_ents;
3071
3072 bfa_trc(rport->fcs, req_status);
3073
3074 if (req_status != BFA_STATUS_OK) {
3075 bfa_trc(rport->fcs, req_status);
3076 if (req_status == BFA_STATUS_ETIMER)
3077 rport->stats.rpsc_failed++;
3078 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3079 return;
3080 }
3081
3082 rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp);
3083 if (rpsc2_acc->els_cmd == FC_ELS_ACC) {
3084 rport->stats.rpsc_accs++;
ba816ea8 3085 num_ents = be16_to_cpu(rpsc2_acc->num_pids);
a36c61f9
KG
3086 bfa_trc(rport->fcs, num_ents);
3087 if (num_ents > 0) {
3088 bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid);
3089 bfa_trc(rport->fcs,
ba816ea8 3090 be16_to_cpu(rpsc2_acc->port_info[0].pid));
a36c61f9 3091 bfa_trc(rport->fcs,
ba816ea8 3092 be16_to_cpu(rpsc2_acc->port_info[0].speed));
a36c61f9 3093 bfa_trc(rport->fcs,
ba816ea8 3094 be16_to_cpu(rpsc2_acc->port_info[0].index));
a36c61f9
KG
3095 bfa_trc(rport->fcs,
3096 rpsc2_acc->port_info[0].type);
3097
3098 if (rpsc2_acc->port_info[0].speed == 0) {
3099 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3100 return;
3101 }
3102
3103 rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed(
ba816ea8 3104 be16_to_cpu(rpsc2_acc->port_info[0].speed));
a36c61f9
KG
3105
3106 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP);
3107 }
3108 } else {
3109 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3110 bfa_trc(rport->fcs, ls_rjt->reason_code);
3111 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
3112 rport->stats.rpsc_rejects++;
3113 if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP)
3114 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL);
3115 else
3116 bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR);
3117 }
3118}