GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / scsi / bfa / rport.c
blob9b4c2c9a644b328d611d8849498d261224ceb054
1 /*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
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
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.
18 /**
19 * rport.c Remote port implementation.
22 #include <linux/slab.h>
23 #include <bfa.h>
24 #include <bfa_svc.h>
25 #include "fcbuild.h"
26 #include "fcs_vport.h"
27 #include "fcs_lport.h"
28 #include "fcs_rport.h"
29 #include "fcs_fcpim.h"
30 #include "fcs_fcptm.h"
31 #include "fcs_trcmod.h"
32 #include "fcs_fcxp.h"
33 #include "fcs.h"
34 #include <fcb/bfa_fcb_rport.h>
35 #include <aen/bfa_aen_rport.h>
37 BFA_TRC_FILE(FCS, RPORT);
39 /* In millisecs */
40 static u32 bfa_fcs_rport_del_timeout =
41 BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
44 * forward declarations
46 static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
47 wwn_t pwwn, u32 rpid);
48 static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
49 static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
50 static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
51 static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
52 static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
53 struct fc_logi_s *plogi);
54 static void bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
55 static void bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
56 static void bfa_fcs_rport_timeout(void *arg);
57 static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
58 struct bfa_fcxp_s *fcxp_alloced);
59 static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
60 struct bfa_fcxp_s *fcxp_alloced);
61 static void bfa_fcs_rport_plogi_response(void *fcsarg,
62 struct bfa_fcxp_s *fcxp,
63 void *cbarg,
64 bfa_status_t req_status,
65 u32 rsp_len,
66 u32 resid_len,
67 struct fchs_s *rsp_fchs);
68 static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
69 struct bfa_fcxp_s *fcxp_alloced);
70 static void bfa_fcs_rport_adisc_response(void *fcsarg,
71 struct bfa_fcxp_s *fcxp,
72 void *cbarg,
73 bfa_status_t req_status,
74 u32 rsp_len,
75 u32 resid_len,
76 struct fchs_s *rsp_fchs);
77 static void bfa_fcs_rport_send_gidpn(void *rport_cbarg,
78 struct bfa_fcxp_s *fcxp_alloced);
79 static void bfa_fcs_rport_gidpn_response(void *fcsarg,
80 struct bfa_fcxp_s *fcxp,
81 void *cbarg,
82 bfa_status_t req_status,
83 u32 rsp_len,
84 u32 resid_len,
85 struct fchs_s *rsp_fchs);
86 static void bfa_fcs_rport_send_logo(void *rport_cbarg,
87 struct bfa_fcxp_s *fcxp_alloced);
88 static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
89 static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
90 struct fchs_s *rx_fchs, u16 len);
91 static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
92 struct fchs_s *rx_fchs, u8 reason_code,
93 u8 reason_code_expl);
94 static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
95 struct fchs_s *rx_fchs, u16 len);
96 static void bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport);
97 /**
98 * fcs_rport_sm FCS rport state machine events
101 enum rport_event {
102 RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
103 RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
104 RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
105 RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
106 RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
107 RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
108 RPSM_EVENT_DELETE = 7, /* RPORT delete request */
109 RPSM_EVENT_SCN = 8, /* state change notification */
110 RPSM_EVENT_ACCEPTED = 9,/* Good response from remote device */
111 RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
112 RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
113 RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
114 RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */
115 RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */
116 RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */
117 RPSM_EVENT_ADDRESS_DISC = 16, /* Need to Discover rport's PID */
118 RPSM_EVENT_PRLO_RCVD = 17, /* PRLO from remote device */
121 static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
122 enum rport_event event);
123 static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
124 enum rport_event event);
125 static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
126 enum rport_event event);
127 static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
128 enum rport_event event);
129 static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
130 enum rport_event event);
131 static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
132 enum rport_event event);
133 static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
134 enum rport_event event);
135 static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
136 enum rport_event event);
137 static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
138 enum rport_event event);
139 static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
140 enum rport_event event);
141 static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
142 enum rport_event event);
143 static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
144 enum rport_event event);
145 static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
146 enum rport_event event);
147 static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
148 enum rport_event event);
149 static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
150 enum rport_event event);
151 static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
152 enum rport_event event);
153 static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
154 enum rport_event event);
155 static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
156 enum rport_event event);
157 static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
158 enum rport_event event);
159 static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
160 enum rport_event event);
161 static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
162 enum rport_event event);
163 static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
164 enum rport_event event);
165 static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
166 enum rport_event event);
168 static struct bfa_sm_table_s rport_sm_table[] = {
169 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
170 {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
171 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
172 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
173 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
174 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
175 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
176 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
177 {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
178 {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
179 {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
180 {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
181 {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
182 {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
183 {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
184 {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
185 {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
186 {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
187 {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
188 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
189 {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
190 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
194 * Beginning state.
196 static void
197 bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
199 bfa_trc(rport->fcs, rport->pwwn);
200 bfa_trc(rport->fcs, rport->pid);
201 bfa_trc(rport->fcs, event);
203 switch (event) {
204 case RPSM_EVENT_PLOGI_SEND:
205 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
206 rport->plogi_retries = 0;
207 bfa_fcs_rport_send_plogi(rport, NULL);
208 break;
210 case RPSM_EVENT_PLOGI_RCVD:
211 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
212 bfa_fcs_rport_send_plogiacc(rport, NULL);
213 break;
215 case RPSM_EVENT_PLOGI_COMP:
216 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
217 bfa_fcs_rport_hal_online(rport);
218 break;
220 case RPSM_EVENT_ADDRESS_CHANGE:
221 case RPSM_EVENT_ADDRESS_DISC:
222 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
223 rport->ns_retries = 0;
224 bfa_fcs_rport_send_gidpn(rport, NULL);
225 break;
227 default:
228 bfa_sm_fault(rport->fcs, event);
233 * PLOGI is being sent.
235 static void
236 bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
237 enum rport_event event)
239 bfa_trc(rport->fcs, rport->pwwn);
240 bfa_trc(rport->fcs, rport->pid);
241 bfa_trc(rport->fcs, event);
243 switch (event) {
244 case RPSM_EVENT_FCXP_SENT:
245 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
246 break;
248 case RPSM_EVENT_DELETE:
249 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
250 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
251 bfa_fcs_rport_free(rport);
252 break;
254 case RPSM_EVENT_PLOGI_RCVD:
255 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
256 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
257 bfa_fcs_rport_send_plogiacc(rport, NULL);
258 break;
260 case RPSM_EVENT_ADDRESS_CHANGE:
261 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
262 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
263 rport->ns_retries = 0;
264 bfa_fcs_rport_send_gidpn(rport, NULL);
265 break;
267 case RPSM_EVENT_LOGO_IMP:
268 rport->pid = 0;
269 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
270 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
271 bfa_timer_start(rport->fcs->bfa, &rport->timer,
272 bfa_fcs_rport_timeout, rport,
273 bfa_fcs_rport_del_timeout);
274 break;
276 case RPSM_EVENT_SCN:
277 break;
279 default:
280 bfa_sm_fault(rport->fcs, event);
285 * PLOGI is being sent.
287 static void
288 bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
289 enum rport_event event)
291 bfa_trc(rport->fcs, rport->pwwn);
292 bfa_trc(rport->fcs, rport->pid);
293 bfa_trc(rport->fcs, event);
295 switch (event) {
296 case RPSM_EVENT_FCXP_SENT:
297 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
298 bfa_fcs_rport_hal_online(rport);
299 break;
301 case RPSM_EVENT_DELETE:
302 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
303 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
304 bfa_fcs_rport_free(rport);
305 break;
307 case RPSM_EVENT_SCN:
309 * Ignore, SCN is possibly online notification.
311 break;
313 case RPSM_EVENT_ADDRESS_CHANGE:
314 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
315 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
316 rport->ns_retries = 0;
317 bfa_fcs_rport_send_gidpn(rport, NULL);
318 break;
320 case RPSM_EVENT_LOGO_IMP:
321 rport->pid = 0;
322 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
323 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
324 bfa_timer_start(rport->fcs->bfa, &rport->timer,
325 bfa_fcs_rport_timeout, rport,
326 bfa_fcs_rport_del_timeout);
327 break;
329 case RPSM_EVENT_HCB_OFFLINE:
331 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
333 break;
335 default:
336 bfa_sm_fault(rport->fcs, event);
341 * PLOGI is sent.
343 static void
344 bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
345 enum rport_event event)
347 bfa_trc(rport->fcs, rport->pwwn);
348 bfa_trc(rport->fcs, rport->pid);
349 bfa_trc(rport->fcs, event);
351 switch (event) {
352 case RPSM_EVENT_SCN:
353 bfa_timer_stop(&rport->timer);
355 * !! fall through !!
358 case RPSM_EVENT_TIMEOUT:
359 if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
360 rport->plogi_retries++;
361 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
362 bfa_fcs_rport_send_plogi(rport, NULL);
363 } else {
364 rport->pid = 0;
365 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
366 bfa_timer_start(rport->fcs->bfa, &rport->timer,
367 bfa_fcs_rport_timeout, rport,
368 bfa_fcs_rport_del_timeout);
370 break;
372 case RPSM_EVENT_DELETE:
373 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
374 bfa_timer_stop(&rport->timer);
375 bfa_fcs_rport_free(rport);
376 break;
378 case RPSM_EVENT_PRLO_RCVD:
379 case RPSM_EVENT_LOGO_RCVD:
380 break;
382 case RPSM_EVENT_PLOGI_RCVD:
383 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
384 bfa_timer_stop(&rport->timer);
385 bfa_fcs_rport_send_plogiacc(rport, NULL);
386 break;
388 case RPSM_EVENT_ADDRESS_CHANGE:
389 bfa_timer_stop(&rport->timer);
390 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
391 rport->ns_retries = 0;
392 bfa_fcs_rport_send_gidpn(rport, NULL);
393 break;
395 case RPSM_EVENT_LOGO_IMP:
396 rport->pid = 0;
397 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
398 bfa_timer_stop(&rport->timer);
399 bfa_timer_start(rport->fcs->bfa, &rport->timer,
400 bfa_fcs_rport_timeout, rport,
401 bfa_fcs_rport_del_timeout);
402 break;
404 case RPSM_EVENT_PLOGI_COMP:
405 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
406 bfa_timer_stop(&rport->timer);
407 bfa_fcs_rport_hal_online(rport);
408 break;
410 default:
411 bfa_sm_fault(rport->fcs, event);
416 * PLOGI is sent.
418 static void
419 bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
421 bfa_trc(rport->fcs, rport->pwwn);
422 bfa_trc(rport->fcs, rport->pid);
423 bfa_trc(rport->fcs, event);
425 switch (event) {
426 case RPSM_EVENT_ACCEPTED:
427 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
428 rport->plogi_retries = 0;
429 bfa_fcs_rport_hal_online(rport);
430 break;
432 case RPSM_EVENT_LOGO_RCVD:
433 bfa_fcs_rport_send_logo_acc(rport);
435 * !! fall through !!
437 case RPSM_EVENT_PRLO_RCVD:
438 if (rport->prlo == BFA_TRUE)
439 bfa_fcs_rport_send_prlo_acc(rport);
441 bfa_fcxp_discard(rport->fcxp);
443 * !! fall through !!
445 case RPSM_EVENT_FAILED:
446 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
447 bfa_timer_start(rport->fcs->bfa, &rport->timer,
448 bfa_fcs_rport_timeout, rport,
449 BFA_FCS_RETRY_TIMEOUT);
450 break;
452 case RPSM_EVENT_LOGO_IMP:
453 rport->pid = 0;
454 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
455 bfa_fcxp_discard(rport->fcxp);
456 bfa_timer_start(rport->fcs->bfa, &rport->timer,
457 bfa_fcs_rport_timeout, rport,
458 bfa_fcs_rport_del_timeout);
459 break;
461 case RPSM_EVENT_ADDRESS_CHANGE:
462 bfa_fcxp_discard(rport->fcxp);
463 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
464 rport->ns_retries = 0;
465 bfa_fcs_rport_send_gidpn(rport, NULL);
466 break;
468 case RPSM_EVENT_PLOGI_RCVD:
469 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
470 bfa_fcxp_discard(rport->fcxp);
471 bfa_fcs_rport_send_plogiacc(rport, NULL);
472 break;
474 case RPSM_EVENT_SCN:
476 * Ignore SCN - wait for PLOGI response.
478 break;
480 case RPSM_EVENT_DELETE:
481 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
482 bfa_fcxp_discard(rport->fcxp);
483 bfa_fcs_rport_free(rport);
484 break;
486 case RPSM_EVENT_PLOGI_COMP:
487 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
488 bfa_fcxp_discard(rport->fcxp);
489 bfa_fcs_rport_hal_online(rport);
490 break;
492 default:
493 bfa_sm_fault(rport->fcs, event);
498 * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
499 * are offline.
501 static void
502 bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
503 enum rport_event event)
505 bfa_trc(rport->fcs, rport->pwwn);
506 bfa_trc(rport->fcs, rport->pid);
507 bfa_trc(rport->fcs, event);
509 switch (event) {
510 case RPSM_EVENT_HCB_ONLINE:
511 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
512 bfa_fcs_rport_online_action(rport);
513 break;
515 case RPSM_EVENT_PRLO_RCVD:
516 break;
518 case RPSM_EVENT_LOGO_RCVD:
519 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
520 bfa_rport_offline(rport->bfa_rport);
521 break;
523 case RPSM_EVENT_LOGO_IMP:
524 case RPSM_EVENT_ADDRESS_CHANGE:
525 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
526 bfa_rport_offline(rport->bfa_rport);
527 break;
529 case RPSM_EVENT_PLOGI_RCVD:
530 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
531 bfa_rport_offline(rport->bfa_rport);
532 bfa_fcs_rport_send_plogiacc(rport, NULL);
533 break;
535 case RPSM_EVENT_DELETE:
536 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
537 bfa_rport_offline(rport->bfa_rport);
538 break;
540 case RPSM_EVENT_SCN:
542 * @todo
543 * Ignore SCN - PLOGI just completed, FC-4 login should detect
544 * device failures.
546 break;
548 default:
549 bfa_sm_fault(rport->fcs, event);
554 * Rport is ONLINE. FC-4s active.
556 static void
557 bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
559 bfa_trc(rport->fcs, rport->pwwn);
560 bfa_trc(rport->fcs, rport->pid);
561 bfa_trc(rport->fcs, event);
563 switch (event) {
564 case RPSM_EVENT_SCN:
566 * Pause FC-4 activity till rport is authenticated.
567 * In switched fabrics, check presence of device in nameserver
568 * first.
570 bfa_fcs_rport_fc4_pause(rport);
572 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
573 bfa_sm_set_state(rport,
574 bfa_fcs_rport_sm_nsquery_sending);
575 rport->ns_retries = 0;
576 bfa_fcs_rport_send_gidpn(rport, NULL);
577 } else {
578 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
579 bfa_fcs_rport_send_adisc(rport, NULL);
581 break;
583 case RPSM_EVENT_PLOGI_RCVD:
584 case RPSM_EVENT_LOGO_IMP:
585 case RPSM_EVENT_ADDRESS_CHANGE:
586 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
587 bfa_fcs_rport_offline_action(rport);
588 break;
590 case RPSM_EVENT_DELETE:
591 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
592 bfa_fcs_rport_offline_action(rport);
593 break;
595 case RPSM_EVENT_LOGO_RCVD:
596 case RPSM_EVENT_PRLO_RCVD:
597 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
598 bfa_fcs_rport_offline_action(rport);
599 break;
601 case RPSM_EVENT_PLOGI_COMP:
602 break;
604 default:
605 bfa_sm_fault(rport->fcs, event);
610 * An SCN event is received in ONLINE state. NS query is being sent
611 * prior to ADISC authentication with rport. FC-4s are paused.
613 static void
614 bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
615 enum rport_event event)
617 bfa_trc(rport->fcs, rport->pwwn);
618 bfa_trc(rport->fcs, rport->pid);
619 bfa_trc(rport->fcs, event);
621 switch (event) {
622 case RPSM_EVENT_FCXP_SENT:
623 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
624 break;
626 case RPSM_EVENT_DELETE:
627 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
628 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
629 bfa_fcs_rport_offline_action(rport);
630 break;
632 case RPSM_EVENT_SCN:
634 * ignore SCN, wait for response to query itself
636 break;
638 case RPSM_EVENT_LOGO_RCVD:
639 case RPSM_EVENT_PRLO_RCVD:
640 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
641 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
642 bfa_fcs_rport_offline_action(rport);
643 break;
645 case RPSM_EVENT_LOGO_IMP:
646 rport->pid = 0;
647 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
648 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
649 bfa_timer_start(rport->fcs->bfa, &rport->timer,
650 bfa_fcs_rport_timeout, rport,
651 bfa_fcs_rport_del_timeout);
652 break;
654 case RPSM_EVENT_PLOGI_RCVD:
655 case RPSM_EVENT_ADDRESS_CHANGE:
656 case RPSM_EVENT_PLOGI_COMP:
657 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
658 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
659 bfa_fcs_rport_offline_action(rport);
660 break;
662 default:
663 bfa_sm_fault(rport->fcs, event);
668 * An SCN event is received in ONLINE state. NS query is sent to rport.
669 * FC-4s are paused.
671 static void
672 bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
674 bfa_trc(rport->fcs, rport->pwwn);
675 bfa_trc(rport->fcs, rport->pid);
676 bfa_trc(rport->fcs, event);
678 switch (event) {
679 case RPSM_EVENT_ACCEPTED:
680 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
681 bfa_fcs_rport_send_adisc(rport, NULL);
682 break;
684 case RPSM_EVENT_FAILED:
685 rport->ns_retries++;
686 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
687 bfa_sm_set_state(rport,
688 bfa_fcs_rport_sm_nsquery_sending);
689 bfa_fcs_rport_send_gidpn(rport, NULL);
690 } else {
691 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
692 bfa_fcs_rport_offline_action(rport);
694 break;
696 case RPSM_EVENT_DELETE:
697 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
698 bfa_fcxp_discard(rport->fcxp);
699 bfa_fcs_rport_offline_action(rport);
700 break;
702 case RPSM_EVENT_SCN:
703 break;
705 case RPSM_EVENT_LOGO_RCVD:
706 case RPSM_EVENT_PRLO_RCVD:
707 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
708 bfa_fcxp_discard(rport->fcxp);
709 bfa_fcs_rport_offline_action(rport);
710 break;
712 case RPSM_EVENT_PLOGI_COMP:
713 case RPSM_EVENT_ADDRESS_CHANGE:
714 case RPSM_EVENT_PLOGI_RCVD:
715 case RPSM_EVENT_LOGO_IMP:
716 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
717 bfa_fcxp_discard(rport->fcxp);
718 bfa_fcs_rport_offline_action(rport);
719 break;
721 default:
722 bfa_sm_fault(rport->fcs, event);
727 * An SCN event is received in ONLINE state. ADISC is being sent for
728 * authenticating with rport. FC-4s are paused.
730 static void
731 bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
732 enum rport_event event)
734 bfa_trc(rport->fcs, rport->pwwn);
735 bfa_trc(rport->fcs, rport->pid);
736 bfa_trc(rport->fcs, event);
738 switch (event) {
739 case RPSM_EVENT_FCXP_SENT:
740 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
741 break;
743 case RPSM_EVENT_DELETE:
744 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
745 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
746 bfa_fcs_rport_offline_action(rport);
747 break;
749 case RPSM_EVENT_LOGO_IMP:
750 case RPSM_EVENT_ADDRESS_CHANGE:
751 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
752 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
753 bfa_fcs_rport_offline_action(rport);
754 break;
756 case RPSM_EVENT_LOGO_RCVD:
757 case RPSM_EVENT_PRLO_RCVD:
758 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
759 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
760 bfa_fcs_rport_offline_action(rport);
761 break;
763 case RPSM_EVENT_SCN:
764 break;
766 case RPSM_EVENT_PLOGI_RCVD:
767 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
768 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
769 bfa_fcs_rport_offline_action(rport);
770 break;
772 default:
773 bfa_sm_fault(rport->fcs, event);
778 * An SCN event is received in ONLINE state. ADISC is to rport.
779 * FC-4s are paused.
781 static void
782 bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
784 bfa_trc(rport->fcs, rport->pwwn);
785 bfa_trc(rport->fcs, rport->pid);
786 bfa_trc(rport->fcs, event);
788 switch (event) {
789 case RPSM_EVENT_ACCEPTED:
790 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
791 bfa_fcs_rport_fc4_resume(rport);
792 break;
794 case RPSM_EVENT_PLOGI_RCVD:
796 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
797 * At least go offline when a PLOGI is received.
799 bfa_fcxp_discard(rport->fcxp);
801 * !!! fall through !!!
804 case RPSM_EVENT_FAILED:
805 case RPSM_EVENT_ADDRESS_CHANGE:
806 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
807 bfa_fcs_rport_offline_action(rport);
808 break;
810 case RPSM_EVENT_DELETE:
811 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
812 bfa_fcxp_discard(rport->fcxp);
813 bfa_fcs_rport_offline_action(rport);
814 break;
816 case RPSM_EVENT_SCN:
818 * already processing RSCN
820 break;
822 case RPSM_EVENT_LOGO_IMP:
823 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
824 bfa_fcxp_discard(rport->fcxp);
825 bfa_fcs_rport_offline_action(rport);
826 break;
828 case RPSM_EVENT_LOGO_RCVD:
829 case RPSM_EVENT_PRLO_RCVD:
830 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
831 bfa_fcxp_discard(rport->fcxp);
832 bfa_fcs_rport_offline_action(rport);
833 break;
835 default:
836 bfa_sm_fault(rport->fcs, event);
841 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
843 static void
844 bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
845 enum rport_event event)
847 bfa_trc(rport->fcs, rport->pwwn);
848 bfa_trc(rport->fcs, rport->pid);
849 bfa_trc(rport->fcs, event);
851 switch (event) {
852 case RPSM_EVENT_FC4_OFFLINE:
853 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
854 bfa_rport_offline(rport->bfa_rport);
855 break;
857 case RPSM_EVENT_DELETE:
858 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
859 break;
861 case RPSM_EVENT_LOGO_RCVD:
862 case RPSM_EVENT_PRLO_RCVD:
863 case RPSM_EVENT_ADDRESS_CHANGE:
864 break;
866 default:
867 bfa_sm_fault(rport->fcs, event);
872 * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
873 * callback.
875 static void
876 bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
877 enum rport_event event)
879 bfa_trc(rport->fcs, rport->pwwn);
880 bfa_trc(rport->fcs, rport->pid);
881 bfa_trc(rport->fcs, event);
883 switch (event) {
884 case RPSM_EVENT_FC4_OFFLINE:
885 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
886 bfa_rport_offline(rport->bfa_rport);
887 break;
889 default:
890 bfa_sm_fault(rport->fcs, event);
895 * Rport is going offline. Awaiting FC-4 offline completion callback.
897 static void
898 bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
899 enum rport_event event)
901 bfa_trc(rport->fcs, rport->pwwn);
902 bfa_trc(rport->fcs, rport->pid);
903 bfa_trc(rport->fcs, event);
905 switch (event) {
906 case RPSM_EVENT_FC4_OFFLINE:
907 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
908 bfa_rport_offline(rport->bfa_rport);
909 break;
911 case RPSM_EVENT_SCN:
912 case RPSM_EVENT_LOGO_IMP:
913 case RPSM_EVENT_LOGO_RCVD:
914 case RPSM_EVENT_PRLO_RCVD:
915 case RPSM_EVENT_ADDRESS_CHANGE:
917 * rport is already going offline.
918 * SCN - ignore and wait till transitioning to offline state
920 break;
922 case RPSM_EVENT_DELETE:
923 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
924 break;
926 default:
927 bfa_sm_fault(rport->fcs, event);
932 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
933 * callback.
935 static void
936 bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
937 enum rport_event event)
939 bfa_trc(rport->fcs, rport->pwwn);
940 bfa_trc(rport->fcs, rport->pid);
941 bfa_trc(rport->fcs, event);
943 switch (event) {
944 case RPSM_EVENT_HCB_OFFLINE:
945 case RPSM_EVENT_ADDRESS_CHANGE:
946 if (bfa_fcs_port_is_online(rport->port)) {
947 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
948 bfa_sm_set_state(rport,
949 bfa_fcs_rport_sm_nsdisc_sending);
950 rport->ns_retries = 0;
951 bfa_fcs_rport_send_gidpn(rport, NULL);
952 } else {
953 bfa_sm_set_state(rport,
954 bfa_fcs_rport_sm_plogi_sending);
955 rport->plogi_retries = 0;
956 bfa_fcs_rport_send_plogi(rport, NULL);
958 } else {
959 rport->pid = 0;
960 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
961 bfa_timer_start(rport->fcs->bfa, &rport->timer,
962 bfa_fcs_rport_timeout, rport,
963 bfa_fcs_rport_del_timeout);
965 break;
967 case RPSM_EVENT_DELETE:
968 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
969 bfa_fcs_rport_free(rport);
970 break;
972 case RPSM_EVENT_SCN:
973 case RPSM_EVENT_LOGO_RCVD:
974 case RPSM_EVENT_PRLO_RCVD:
976 * Ignore, already offline.
978 break;
980 default:
981 bfa_sm_fault(rport->fcs, event);
986 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
987 * callback to send LOGO accept.
989 static void
990 bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
991 enum rport_event event)
993 bfa_trc(rport->fcs, rport->pwwn);
994 bfa_trc(rport->fcs, rport->pid);
995 bfa_trc(rport->fcs, event);
997 switch (event) {
998 case RPSM_EVENT_HCB_OFFLINE:
999 case RPSM_EVENT_ADDRESS_CHANGE:
1000 if (rport->pid && (rport->prlo == BFA_TRUE))
1001 bfa_fcs_rport_send_prlo_acc(rport);
1002 if (rport->pid && (rport->prlo == BFA_FALSE))
1003 bfa_fcs_rport_send_logo_acc(rport);
1006 * If the lport is online and if the rport is not a well known
1007 * address port, we try to re-discover the r-port.
1009 if (bfa_fcs_port_is_online(rport->port)
1010 && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
1011 bfa_sm_set_state(rport,
1012 bfa_fcs_rport_sm_nsdisc_sending);
1013 rport->ns_retries = 0;
1014 bfa_fcs_rport_send_gidpn(rport, NULL);
1015 } else {
1017 * if it is not a well known address, reset the pid to
1020 if (!BFA_FCS_PID_IS_WKA(rport->pid))
1021 rport->pid = 0;
1022 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1023 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1024 bfa_fcs_rport_timeout, rport,
1025 bfa_fcs_rport_del_timeout);
1027 break;
1029 case RPSM_EVENT_DELETE:
1030 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
1031 break;
1033 case RPSM_EVENT_LOGO_IMP:
1034 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1035 break;
1037 case RPSM_EVENT_LOGO_RCVD:
1038 case RPSM_EVENT_PRLO_RCVD:
1040 * Ignore - already processing a LOGO.
1042 break;
1044 default:
1045 bfa_sm_fault(rport->fcs, event);
1050 * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
1051 * callback to send LOGO.
1053 static void
1054 bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1055 enum rport_event event)
1057 bfa_trc(rport->fcs, rport->pwwn);
1058 bfa_trc(rport->fcs, rport->pid);
1059 bfa_trc(rport->fcs, event);
1061 switch (event) {
1062 case RPSM_EVENT_HCB_OFFLINE:
1063 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1064 bfa_fcs_rport_send_logo(rport, NULL);
1065 break;
1067 case RPSM_EVENT_LOGO_RCVD:
1068 case RPSM_EVENT_PRLO_RCVD:
1069 case RPSM_EVENT_ADDRESS_CHANGE:
1070 break;
1072 default:
1073 bfa_sm_fault(rport->fcs, event);
1078 * Rport is being deleted. FC-4s are offline. LOGO is being sent.
1080 static void
1081 bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1082 enum rport_event event)
1084 bfa_trc(rport->fcs, rport->pwwn);
1085 bfa_trc(rport->fcs, rport->pid);
1086 bfa_trc(rport->fcs, event);
1088 switch (event) {
1089 case RPSM_EVENT_FCXP_SENT:
1091 * Once LOGO is sent, we donot wait for the response
1093 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1094 bfa_fcs_rport_free(rport);
1095 break;
1097 case RPSM_EVENT_SCN:
1098 case RPSM_EVENT_ADDRESS_CHANGE:
1099 break;
1101 case RPSM_EVENT_LOGO_RCVD:
1102 case RPSM_EVENT_PRLO_RCVD:
1103 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1104 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1105 bfa_fcs_rport_free(rport);
1106 break;
1108 default:
1109 bfa_sm_fault(rport->fcs, event);
1114 * Rport is offline. FC-4s are offline. BFA rport is offline.
1115 * Timer active to delete stale rport.
1117 static void
1118 bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1120 bfa_trc(rport->fcs, rport->pwwn);
1121 bfa_trc(rport->fcs, rport->pid);
1122 bfa_trc(rport->fcs, event);
1124 switch (event) {
1125 case RPSM_EVENT_TIMEOUT:
1126 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1127 bfa_fcs_rport_free(rport);
1128 break;
1130 case RPSM_EVENT_SCN:
1131 case RPSM_EVENT_ADDRESS_CHANGE:
1132 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1133 bfa_timer_stop(&rport->timer);
1134 rport->ns_retries = 0;
1135 bfa_fcs_rport_send_gidpn(rport, NULL);
1136 break;
1138 case RPSM_EVENT_DELETE:
1139 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1140 bfa_timer_stop(&rport->timer);
1141 bfa_fcs_rport_free(rport);
1142 break;
1144 case RPSM_EVENT_PLOGI_RCVD:
1145 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1146 bfa_timer_stop(&rport->timer);
1147 bfa_fcs_rport_send_plogiacc(rport, NULL);
1148 break;
1150 case RPSM_EVENT_LOGO_RCVD:
1151 case RPSM_EVENT_PRLO_RCVD:
1152 case RPSM_EVENT_LOGO_IMP:
1153 break;
1155 case RPSM_EVENT_PLOGI_COMP:
1156 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1157 bfa_timer_stop(&rport->timer);
1158 bfa_fcs_rport_hal_online(rport);
1159 break;
1161 case RPSM_EVENT_PLOGI_SEND:
1162 bfa_timer_stop(&rport->timer);
1163 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1164 rport->plogi_retries = 0;
1165 bfa_fcs_rport_send_plogi(rport, NULL);
1166 break;
1168 default:
1169 bfa_sm_fault(rport->fcs, event);
1174 * Rport address has changed. Nameserver discovery request is being sent.
1176 static void
1177 bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1178 enum rport_event event)
1180 bfa_trc(rport->fcs, rport->pwwn);
1181 bfa_trc(rport->fcs, rport->pid);
1182 bfa_trc(rport->fcs, event);
1184 switch (event) {
1185 case RPSM_EVENT_FCXP_SENT:
1186 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
1187 break;
1189 case RPSM_EVENT_DELETE:
1190 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1191 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1192 bfa_fcs_rport_free(rport);
1193 break;
1195 case RPSM_EVENT_PLOGI_RCVD:
1196 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1197 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1198 bfa_fcs_rport_send_plogiacc(rport, NULL);
1199 break;
1201 case RPSM_EVENT_SCN:
1202 case RPSM_EVENT_LOGO_RCVD:
1203 case RPSM_EVENT_PRLO_RCVD:
1204 case RPSM_EVENT_PLOGI_SEND:
1205 break;
1207 case RPSM_EVENT_ADDRESS_CHANGE:
1208 rport->ns_retries = 0; /* reset the retry count */
1209 break;
1211 case RPSM_EVENT_LOGO_IMP:
1212 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1213 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1214 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1215 bfa_fcs_rport_timeout, rport,
1216 bfa_fcs_rport_del_timeout);
1217 break;
1219 case RPSM_EVENT_PLOGI_COMP:
1220 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1221 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1222 bfa_fcs_rport_hal_online(rport);
1223 break;
1225 default:
1226 bfa_sm_fault(rport->fcs, event);
1231 * Nameserver discovery failed. Waiting for timeout to retry.
1233 static void
1234 bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1235 enum rport_event event)
1237 bfa_trc(rport->fcs, rport->pwwn);
1238 bfa_trc(rport->fcs, rport->pid);
1239 bfa_trc(rport->fcs, event);
1241 switch (event) {
1242 case RPSM_EVENT_TIMEOUT:
1243 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1244 bfa_fcs_rport_send_gidpn(rport, NULL);
1245 break;
1247 case RPSM_EVENT_SCN:
1248 case RPSM_EVENT_ADDRESS_CHANGE:
1249 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1250 bfa_timer_stop(&rport->timer);
1251 rport->ns_retries = 0;
1252 bfa_fcs_rport_send_gidpn(rport, NULL);
1253 break;
1255 case RPSM_EVENT_DELETE:
1256 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1257 bfa_timer_stop(&rport->timer);
1258 bfa_fcs_rport_free(rport);
1259 break;
1261 case RPSM_EVENT_PLOGI_RCVD:
1262 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1263 bfa_timer_stop(&rport->timer);
1264 bfa_fcs_rport_send_plogiacc(rport, NULL);
1265 break;
1267 case RPSM_EVENT_LOGO_IMP:
1268 rport->pid = 0;
1269 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1270 bfa_timer_stop(&rport->timer);
1271 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1272 bfa_fcs_rport_timeout, rport,
1273 bfa_fcs_rport_del_timeout);
1274 break;
1276 case RPSM_EVENT_LOGO_RCVD:
1277 bfa_fcs_rport_send_logo_acc(rport);
1278 break;
1280 case RPSM_EVENT_PRLO_RCVD:
1281 bfa_fcs_rport_send_prlo_acc(rport);
1282 break;
1284 case RPSM_EVENT_PLOGI_COMP:
1285 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1286 bfa_timer_stop(&rport->timer);
1287 bfa_fcs_rport_hal_online(rport);
1288 break;
1290 default:
1291 bfa_sm_fault(rport->fcs, event);
1296 * Rport address has changed. Nameserver discovery request is sent.
1298 static void
1299 bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1300 enum rport_event event)
1302 bfa_trc(rport->fcs, rport->pwwn);
1303 bfa_trc(rport->fcs, rport->pid);
1304 bfa_trc(rport->fcs, event);
1306 switch (event) {
1307 case RPSM_EVENT_ACCEPTED:
1308 case RPSM_EVENT_ADDRESS_CHANGE:
1309 if (rport->pid) {
1310 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1311 bfa_fcs_rport_send_plogi(rport, NULL);
1312 } else {
1313 bfa_sm_set_state(rport,
1314 bfa_fcs_rport_sm_nsdisc_sending);
1315 rport->ns_retries = 0;
1316 bfa_fcs_rport_send_gidpn(rport, NULL);
1318 break;
1320 case RPSM_EVENT_FAILED:
1321 rport->ns_retries++;
1322 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1323 bfa_sm_set_state(rport,
1324 bfa_fcs_rport_sm_nsdisc_sending);
1325 bfa_fcs_rport_send_gidpn(rport, NULL);
1326 } else {
1327 rport->pid = 0;
1328 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1329 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1330 bfa_fcs_rport_timeout, rport,
1331 bfa_fcs_rport_del_timeout);
1333 break;
1335 case RPSM_EVENT_DELETE:
1336 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1337 bfa_fcxp_discard(rport->fcxp);
1338 bfa_fcs_rport_free(rport);
1339 break;
1341 case RPSM_EVENT_PLOGI_RCVD:
1342 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1343 bfa_fcxp_discard(rport->fcxp);
1344 bfa_fcs_rport_send_plogiacc(rport, NULL);
1345 break;
1347 case RPSM_EVENT_LOGO_IMP:
1348 rport->pid = 0;
1349 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1350 bfa_fcxp_discard(rport->fcxp);
1351 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1352 bfa_fcs_rport_timeout, rport,
1353 bfa_fcs_rport_del_timeout);
1354 break;
1356 case RPSM_EVENT_PRLO_RCVD:
1357 bfa_fcs_rport_send_prlo_acc(rport);
1358 break;
1360 case RPSM_EVENT_SCN:
1362 * ignore, wait for NS query response
1364 break;
1366 case RPSM_EVENT_LOGO_RCVD:
1368 * Not logged-in yet. Accept LOGO.
1370 bfa_fcs_rport_send_logo_acc(rport);
1371 break;
1373 case RPSM_EVENT_PLOGI_COMP:
1374 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1375 bfa_fcxp_discard(rport->fcxp);
1376 bfa_fcs_rport_hal_online(rport);
1377 break;
1379 default:
1380 bfa_sm_fault(rport->fcs, event);
1387 * fcs_rport_private FCS RPORT provate functions
1390 static void
1391 bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1393 struct bfa_fcs_rport_s *rport = rport_cbarg;
1394 struct bfa_fcs_port_s *port = rport->port;
1395 struct fchs_s fchs;
1396 int len;
1397 struct bfa_fcxp_s *fcxp;
1399 bfa_trc(rport->fcs, rport->pwwn);
1401 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1402 if (!fcxp) {
1403 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1404 bfa_fcs_rport_send_plogi, rport);
1405 return;
1407 rport->fcxp = fcxp;
1409 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1410 bfa_fcs_port_get_fcid(port), 0,
1411 port->port_cfg.pwwn, port->port_cfg.nwwn,
1412 bfa_fcport_get_maxfrsize(port->fcs->bfa));
1414 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1415 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
1416 (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1418 rport->stats.plogis++;
1419 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1422 static void
1423 bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1424 bfa_status_t req_status, u32 rsp_len,
1425 u32 resid_len, struct fchs_s *rsp_fchs)
1427 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1428 struct fc_logi_s *plogi_rsp;
1429 struct fc_ls_rjt_s *ls_rjt;
1430 struct bfa_fcs_rport_s *twin;
1431 struct list_head *qe;
1433 bfa_trc(rport->fcs, rport->pwwn);
1436 * Sanity Checks
1438 if (req_status != BFA_STATUS_OK) {
1439 bfa_trc(rport->fcs, req_status);
1440 rport->stats.plogi_failed++;
1441 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1442 return;
1445 plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1448 * Check for failure first.
1450 if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1451 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1453 bfa_trc(rport->fcs, ls_rjt->reason_code);
1454 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1456 rport->stats.plogi_rejects++;
1457 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1458 return;
1462 * PLOGI is complete. Make sure this device is not one of the known
1463 * device with a new FC port address.
1465 list_for_each(qe, &rport->port->rport_q) {
1466 twin = (struct bfa_fcs_rport_s *)qe;
1467 if (twin == rport)
1468 continue;
1469 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1470 bfa_trc(rport->fcs, twin->pid);
1471 bfa_trc(rport->fcs, rport->pid);
1474 * Update plogi stats in twin
1476 twin->stats.plogis += rport->stats.plogis;
1477 twin->stats.plogi_rejects += rport->stats.plogi_rejects;
1478 twin->stats.plogi_timeouts +=
1479 rport->stats.plogi_timeouts;
1480 twin->stats.plogi_failed += rport->stats.plogi_failed;
1481 twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
1482 twin->stats.plogi_accs++;
1484 bfa_fcs_rport_delete(rport);
1486 bfa_fcs_rport_update(twin, plogi_rsp);
1487 twin->pid = rsp_fchs->s_id;
1488 bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1489 return;
1494 * Normal login path -- no evil twins.
1496 rport->stats.plogi_accs++;
1497 bfa_fcs_rport_update(rport, plogi_rsp);
1498 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1501 static void
1502 bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1504 struct bfa_fcs_rport_s *rport = rport_cbarg;
1505 struct bfa_fcs_port_s *port = rport->port;
1506 struct fchs_s fchs;
1507 int len;
1508 struct bfa_fcxp_s *fcxp;
1510 bfa_trc(rport->fcs, rport->pwwn);
1511 bfa_trc(rport->fcs, rport->reply_oxid);
1513 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1514 if (!fcxp) {
1515 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1516 bfa_fcs_rport_send_plogiacc, rport);
1517 return;
1519 rport->fcxp = fcxp;
1521 len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1522 bfa_fcs_port_get_fcid(port), rport->reply_oxid,
1523 port->port_cfg.pwwn, port->port_cfg.nwwn,
1524 bfa_fcport_get_maxfrsize(port->fcs->bfa));
1526 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1527 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1529 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1532 static void
1533 bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1535 struct bfa_fcs_rport_s *rport = rport_cbarg;
1536 struct bfa_fcs_port_s *port = rport->port;
1537 struct fchs_s fchs;
1538 int len;
1539 struct bfa_fcxp_s *fcxp;
1541 bfa_trc(rport->fcs, rport->pwwn);
1543 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1544 if (!fcxp) {
1545 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1546 bfa_fcs_rport_send_adisc, rport);
1547 return;
1549 rport->fcxp = fcxp;
1551 len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1552 bfa_fcs_port_get_fcid(port), 0,
1553 port->port_cfg.pwwn, port->port_cfg.nwwn);
1555 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1556 FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
1557 rport, FC_MAX_PDUSZ, FC_ELS_TOV);
1559 rport->stats.adisc_sent++;
1560 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1563 static void
1564 bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1565 bfa_status_t req_status, u32 rsp_len,
1566 u32 resid_len, struct fchs_s *rsp_fchs)
1568 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1569 void *pld = bfa_fcxp_get_rspbuf(fcxp);
1570 struct fc_ls_rjt_s *ls_rjt;
1572 if (req_status != BFA_STATUS_OK) {
1573 bfa_trc(rport->fcs, req_status);
1574 rport->stats.adisc_failed++;
1575 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1576 return;
1579 if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
1580 rport->nwwn) == FC_PARSE_OK) {
1581 rport->stats.adisc_accs++;
1582 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1583 return;
1586 rport->stats.adisc_rejects++;
1587 ls_rjt = pld;
1588 bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1589 bfa_trc(rport->fcs, ls_rjt->reason_code);
1590 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1591 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1594 static void
1595 bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1597 struct bfa_fcs_rport_s *rport = rport_cbarg;
1598 struct bfa_fcs_port_s *port = rport->port;
1599 struct fchs_s fchs;
1600 struct bfa_fcxp_s *fcxp;
1601 int len;
1603 bfa_trc(rport->fcs, rport->pid);
1605 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1606 if (!fcxp) {
1607 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1608 bfa_fcs_rport_send_gidpn, rport);
1609 return;
1611 rport->fcxp = fcxp;
1613 len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1614 bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
1616 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1617 FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
1618 (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
1620 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1623 static void
1624 bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1625 bfa_status_t req_status, u32 rsp_len,
1626 u32 resid_len, struct fchs_s *rsp_fchs)
1628 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1629 struct bfa_fcs_rport_s *twin;
1630 struct list_head *qe;
1631 struct ct_hdr_s *cthdr;
1632 struct fcgs_gidpn_resp_s *gidpn_rsp;
1634 bfa_trc(rport->fcs, rport->pwwn);
1636 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1637 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
1639 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1641 * Check if the pid is the same as before.
1643 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1645 if (gidpn_rsp->dap == rport->pid) {
1647 * Device is online
1649 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1650 } else {
1652 * Device's PID has changed. We need to cleanup and
1653 * re-login. If there is another device with the the
1654 * newly discovered pid, send an scn notice so that its
1655 * new pid can be discovered.
1657 list_for_each(qe, &rport->port->rport_q) {
1658 twin = (struct bfa_fcs_rport_s *)qe;
1659 if (twin == rport)
1660 continue;
1661 if (gidpn_rsp->dap == twin->pid) {
1662 bfa_trc(rport->fcs, twin->pid);
1663 bfa_trc(rport->fcs, rport->pid);
1665 twin->pid = 0;
1666 bfa_sm_send_event(twin,
1667 RPSM_EVENT_ADDRESS_CHANGE);
1670 rport->pid = gidpn_rsp->dap;
1671 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
1673 return;
1677 * Reject Response
1679 switch (cthdr->reason_code) {
1680 case CT_RSN_LOGICAL_BUSY:
1682 * Need to retry
1684 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1685 break;
1687 case CT_RSN_UNABLE_TO_PERF:
1689 * device doesn't exist : Start timer to cleanup this later.
1691 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1692 break;
1694 default:
1695 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1696 break;
1701 * Called to send a logout to the rport.
1703 static void
1704 bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1706 struct bfa_fcs_rport_s *rport = rport_cbarg;
1707 struct bfa_fcs_port_s *port;
1708 struct fchs_s fchs;
1709 struct bfa_fcxp_s *fcxp;
1710 u16 len;
1712 bfa_trc(rport->fcs, rport->pid);
1714 port = rport->port;
1716 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1717 if (!fcxp) {
1718 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1719 bfa_fcs_rport_send_logo, rport);
1720 return;
1722 rport->fcxp = fcxp;
1724 len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1725 bfa_fcs_port_get_fcid(port), 0,
1726 bfa_fcs_port_get_pwwn(port));
1728 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1729 FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
1730 FC_ELS_TOV);
1732 rport->stats.logos++;
1733 bfa_fcxp_discard(rport->fcxp);
1734 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1738 * Send ACC for a LOGO received.
1740 static void
1741 bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
1743 struct bfa_fcs_rport_s *rport = rport_cbarg;
1744 struct bfa_fcs_port_s *port;
1745 struct fchs_s fchs;
1746 struct bfa_fcxp_s *fcxp;
1747 u16 len;
1749 bfa_trc(rport->fcs, rport->pid);
1751 port = rport->port;
1753 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1754 if (!fcxp)
1755 return;
1757 rport->stats.logo_rcvd++;
1758 len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1759 bfa_fcs_port_get_fcid(port), rport->reply_oxid);
1761 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1762 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1766 * This routine will be called by bfa_timer on timer timeouts.
1768 * param[in] rport - pointer to bfa_fcs_port_ns_t.
1769 * param[out] rport_status - pointer to return vport status in
1771 * return
1772 * void
1774 * Special Considerations:
1776 * note
1778 static void
1779 bfa_fcs_rport_timeout(void *arg)
1781 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
1783 rport->stats.plogi_timeouts++;
1784 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1787 static void
1788 bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
1789 struct fchs_s *rx_fchs, u16 len)
1791 struct bfa_fcxp_s *fcxp;
1792 struct fchs_s fchs;
1793 struct bfa_fcs_port_s *port = rport->port;
1794 struct fc_prli_s *prli;
1796 bfa_trc(port->fcs, rx_fchs->s_id);
1797 bfa_trc(port->fcs, rx_fchs->d_id);
1799 rport->stats.prli_rcvd++;
1801 if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1803 * Target Mode : Let the fcptm handle it
1805 bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
1806 return;
1810 * We are either in Initiator or ipfc Mode
1812 prli = (struct fc_prli_s *) (rx_fchs + 1);
1814 if (prli->parampage.servparams.initiator) {
1815 bfa_trc(rport->fcs, prli->parampage.type);
1816 rport->scsi_function = BFA_RPORT_INITIATOR;
1817 bfa_fcs_itnim_is_initiator(rport->itnim);
1818 } else {
1820 * @todo: PRLI from a target ?
1822 bfa_trc(port->fcs, rx_fchs->s_id);
1823 rport->scsi_function = BFA_RPORT_TARGET;
1826 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1827 if (!fcxp)
1828 return;
1830 len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1831 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1832 port->port_cfg.roles);
1834 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1835 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1838 static void
1839 bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
1840 struct fchs_s *rx_fchs, u16 len)
1842 struct bfa_fcxp_s *fcxp;
1843 struct fchs_s fchs;
1844 struct bfa_fcs_port_s *port = rport->port;
1845 struct fc_rpsc_speed_info_s speeds;
1846 struct bfa_pport_attr_s pport_attr;
1848 bfa_trc(port->fcs, rx_fchs->s_id);
1849 bfa_trc(port->fcs, rx_fchs->d_id);
1851 rport->stats.rpsc_rcvd++;
1852 speeds.port_speed_cap =
1853 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
1854 RPSC_SPEED_CAP_8G;
1857 * get curent speed from pport attributes from BFA
1859 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
1861 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
1863 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1864 if (!fcxp)
1865 return;
1867 len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1868 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1869 &speeds);
1871 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1872 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1875 static void
1876 bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
1877 struct fchs_s *rx_fchs, u16 len)
1879 struct bfa_fcxp_s *fcxp;
1880 struct fchs_s fchs;
1881 struct bfa_fcs_port_s *port = rport->port;
1882 struct fc_adisc_s *adisc;
1884 bfa_trc(port->fcs, rx_fchs->s_id);
1885 bfa_trc(port->fcs, rx_fchs->d_id);
1887 rport->stats.adisc_rcvd++;
1889 if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1891 * @todo : Target Mode handling
1893 bfa_trc(port->fcs, rx_fchs->d_id);
1894 bfa_assert(0);
1895 return;
1898 adisc = (struct fc_adisc_s *) (rx_fchs + 1);
1901 * Accept if the itnim for this rport is online. Else reject the ADISC
1903 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
1905 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1906 if (!fcxp)
1907 return;
1909 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1910 rx_fchs->s_id,
1911 bfa_fcs_port_get_fcid(port),
1912 rx_fchs->ox_id, port->port_cfg.pwwn,
1913 port->port_cfg.nwwn);
1915 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
1916 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
1917 FC_MAX_PDUSZ, 0);
1918 } else {
1919 rport->stats.adisc_rejected++;
1920 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
1921 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
1922 FC_LS_RJT_EXP_LOGIN_REQUIRED);
1927 static void
1928 bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
1930 struct bfa_fcs_port_s *port = rport->port;
1931 struct bfa_rport_info_s rport_info;
1933 rport_info.pid = rport->pid;
1934 rport_info.local_pid = port->pid;
1935 rport_info.lp_tag = port->lp_tag;
1936 rport_info.vf_id = port->fabric->vf_id;
1937 rport_info.vf_en = port->fabric->is_vf;
1938 rport_info.fc_class = rport->fc_cos;
1939 rport_info.cisc = rport->cisc;
1940 rport_info.max_frmsz = rport->maxfrsize;
1941 bfa_rport_online(rport->bfa_rport, &rport_info);
1944 static void
1945 bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
1947 if (bfa_fcs_port_is_initiator(rport->port))
1948 bfa_fcs_itnim_pause(rport->itnim);
1950 if (bfa_fcs_port_is_target(rport->port))
1951 bfa_fcs_tin_pause(rport->tin);
1954 static void
1955 bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
1957 if (bfa_fcs_port_is_initiator(rport->port))
1958 bfa_fcs_itnim_resume(rport->itnim);
1960 if (bfa_fcs_port_is_target(rport->port))
1961 bfa_fcs_tin_resume(rport->tin);
1964 static struct bfa_fcs_rport_s *
1965 bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
1967 struct bfa_fcs_s *fcs = port->fcs;
1968 struct bfa_fcs_rport_s *rport;
1969 struct bfad_rport_s *rport_drv;
1972 * allocate rport
1974 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
1975 != BFA_STATUS_OK) {
1976 bfa_trc(fcs, rpid);
1977 return NULL;
1981 * Initialize r-port
1983 rport->port = port;
1984 rport->fcs = fcs;
1985 rport->rp_drv = rport_drv;
1986 rport->pid = rpid;
1987 rport->pwwn = pwwn;
1990 * allocate BFA rport
1992 rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
1993 if (!rport->bfa_rport) {
1994 bfa_trc(fcs, rpid);
1995 kfree(rport_drv);
1996 return NULL;
2000 * allocate FC-4s
2002 bfa_assert(bfa_fcs_port_is_initiator(port) ^
2003 bfa_fcs_port_is_target(port));
2005 if (bfa_fcs_port_is_initiator(port)) {
2006 rport->itnim = bfa_fcs_itnim_create(rport);
2007 if (!rport->itnim) {
2008 bfa_trc(fcs, rpid);
2009 bfa_rport_delete(rport->bfa_rport);
2010 kfree(rport_drv);
2011 return NULL;
2015 if (bfa_fcs_port_is_target(port)) {
2016 rport->tin = bfa_fcs_tin_create(rport);
2017 if (!rport->tin) {
2018 bfa_trc(fcs, rpid);
2019 bfa_rport_delete(rport->bfa_rport);
2020 kfree(rport_drv);
2021 return NULL;
2025 bfa_fcs_port_add_rport(port, rport);
2027 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
2030 * Initialize the Rport Features(RPF) Sub Module
2032 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2033 bfa_fcs_rpf_init(rport);
2035 return rport;
2039 static void
2040 bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2042 struct bfa_fcs_port_s *port = rport->port;
2045 * - delete FC-4s
2046 * - delete BFA rport
2047 * - remove from queue of rports
2049 if (bfa_fcs_port_is_initiator(port))
2050 bfa_fcs_itnim_delete(rport->itnim);
2052 if (bfa_fcs_port_is_target(port))
2053 bfa_fcs_tin_delete(rport->tin);
2055 bfa_rport_delete(rport->bfa_rport);
2056 bfa_fcs_port_del_rport(port, rport);
2057 kfree(rport->rp_drv);
2060 static void
2061 bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2062 enum bfa_rport_aen_event event,
2063 struct bfa_rport_aen_data_s *data)
2065 union bfa_aen_data_u aen_data;
2066 struct bfa_log_mod_s *logmod = rport->fcs->logm;
2067 wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port);
2068 wwn_t rpwwn = rport->pwwn;
2069 char lpwwn_ptr[BFA_STRING_32];
2070 char rpwwn_ptr[BFA_STRING_32];
2071 char *prio_str[] = { "unknown", "high", "medium", "low" };
2073 wwn2str(lpwwn_ptr, lpwwn);
2074 wwn2str(rpwwn_ptr, rpwwn);
2076 switch (event) {
2077 case BFA_RPORT_AEN_ONLINE:
2078 case BFA_RPORT_AEN_OFFLINE:
2079 case BFA_RPORT_AEN_DISCONNECT:
2080 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
2081 rpwwn_ptr, lpwwn_ptr);
2082 break;
2083 case BFA_RPORT_AEN_QOS_PRIO:
2084 aen_data.rport.priv.qos = data->priv.qos;
2085 bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
2086 prio_str[aen_data.rport.priv.qos.qos_priority],
2087 rpwwn_ptr, lpwwn_ptr);
2088 break;
2089 case BFA_RPORT_AEN_QOS_FLOWID:
2090 aen_data.rport.priv.qos = data->priv.qos;
2091 bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
2092 aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
2093 lpwwn_ptr);
2094 break;
2095 default:
2096 break;
2099 aen_data.rport.vf_id = rport->port->fabric->vf_id;
2100 aen_data.rport.ppwwn =
2101 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
2102 aen_data.rport.lpwwn = lpwwn;
2103 aen_data.rport.rpwwn = rpwwn;
2106 static void
2107 bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2109 struct bfa_fcs_port_s *port = rport->port;
2111 rport->stats.onlines++;
2113 if (bfa_fcs_port_is_initiator(port)) {
2114 bfa_fcs_itnim_rport_online(rport->itnim);
2115 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2116 bfa_fcs_rpf_rport_online(rport);
2119 if (bfa_fcs_port_is_target(port))
2120 bfa_fcs_tin_rport_online(rport->tin);
2123 * Don't post events for well known addresses
2125 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2126 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2129 static void
2130 bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
2132 struct bfa_fcs_port_s *port = rport->port;
2134 rport->stats.offlines++;
2137 * Don't post events for well known addresses
2139 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2140 if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
2141 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
2142 NULL);
2143 } else {
2144 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
2145 NULL);
2149 if (bfa_fcs_port_is_initiator(port)) {
2150 bfa_fcs_itnim_rport_offline(rport->itnim);
2151 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2152 bfa_fcs_rpf_rport_offline(rport);
2155 if (bfa_fcs_port_is_target(port))
2156 bfa_fcs_tin_rport_offline(rport->tin);
2160 * Update rport parameters from PLOGI or PLOGI accept.
2162 static void
2163 bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2165 struct bfa_fcs_port_s *port = rport->port;
2168 * - port name
2169 * - node name
2171 rport->pwwn = plogi->port_name;
2172 rport->nwwn = plogi->node_name;
2175 * - class of service
2177 rport->fc_cos = 0;
2178 if (plogi->class3.class_valid)
2179 rport->fc_cos = FC_CLASS_3;
2181 if (plogi->class2.class_valid)
2182 rport->fc_cos |= FC_CLASS_2;
2185 * - CISC
2186 * - MAX receive frame size
2188 rport->cisc = plogi->csp.cisc;
2189 rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
2191 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2192 bfa_trc(port->fcs, port->fabric->bb_credit);
2194 * Direct Attach P2P mode :
2195 * This is to handle a bug (233476) in IBM targets in Direct Attach
2196 * Mode. Basically, in FLOGI Accept the target would have erroneously
2197 * set the BB Credit to the value used in the FLOGI sent by the HBA.
2198 * It uses the correct value (its own BB credit) in PLOGI.
2200 if ((!bfa_fcs_fabric_is_switched(port->fabric))
2201 && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
2203 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2204 bfa_trc(port->fcs, port->fabric->bb_credit);
2206 port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
2207 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
2208 port->fabric->bb_credit);
2214 * Called to handle LOGO received from an existing remote port.
2216 static void
2217 bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2219 rport->reply_oxid = fchs->ox_id;
2220 bfa_trc(rport->fcs, rport->reply_oxid);
2222 rport->prlo = BFA_FALSE;
2223 rport->stats.logo_rcvd++;
2224 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2230 * fcs_rport_public FCS rport public interfaces
2234 * Called by bport/vport to create a remote port instance for a discovered
2235 * remote device.
2237 * @param[in] port - base port or vport
2238 * @param[in] rpid - remote port ID
2240 * @return None
2242 struct bfa_fcs_rport_s *
2243 bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
2245 struct bfa_fcs_rport_s *rport;
2247 bfa_trc(port->fcs, rpid);
2248 rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2249 if (!rport)
2250 return NULL;
2252 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2253 return rport;
2257 * Called to create a rport for which only the wwn is known.
2259 * @param[in] port - base port
2260 * @param[in] rpwwn - remote port wwn
2262 * @return None
2264 struct bfa_fcs_rport_s *
2265 bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
2267 struct bfa_fcs_rport_s *rport;
2269 bfa_trc(port->fcs, rpwwn);
2270 rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2271 if (!rport)
2272 return NULL;
2274 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2275 return rport;
2279 * Called by bport in private loop topology to indicate that a
2280 * rport has been discovered and plogi has been completed.
2282 * @param[in] port - base port or vport
2283 * @param[in] rpid - remote port ID
2285 void
2286 bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2287 struct fc_logi_s *plogi)
2289 struct bfa_fcs_rport_s *rport;
2291 rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2292 if (!rport)
2293 return;
2295 bfa_fcs_rport_update(rport, plogi);
2297 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2301 * Called by bport/vport to handle PLOGI received from a new remote port.
2302 * If an existing rport does a plogi, it will be handled separately.
2304 void
2305 bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2306 struct fc_logi_s *plogi)
2308 struct bfa_fcs_rport_s *rport;
2310 rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2311 if (!rport)
2312 return;
2314 bfa_fcs_rport_update(rport, plogi);
2316 rport->reply_oxid = fchs->ox_id;
2317 bfa_trc(rport->fcs, rport->reply_oxid);
2319 rport->stats.plogi_rcvd++;
2320 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2323 static int
2324 wwn_compare(wwn_t wwn1, wwn_t wwn2)
2326 u8 *b1 = (u8 *) &wwn1;
2327 u8 *b2 = (u8 *) &wwn2;
2328 int i;
2330 for (i = 0; i < sizeof(wwn_t); i++) {
2331 if (b1[i] < b2[i])
2332 return -1;
2333 if (b1[i] > b2[i])
2334 return 1;
2336 return 0;
2340 * Called by bport/vport to handle PLOGI received from an existing
2341 * remote port.
2343 void
2344 bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2345 struct fc_logi_s *plogi)
2348 * @todo Handle P2P and initiator-initiator.
2351 bfa_fcs_rport_update(rport, plogi);
2353 rport->reply_oxid = rx_fchs->ox_id;
2354 bfa_trc(rport->fcs, rport->reply_oxid);
2357 * In Switched fabric topology,
2358 * PLOGI to each other. If our pwwn is smaller, ignore it,
2359 * if it is not a well known address.
2360 * If the link topology is N2N,
2361 * this Plogi should be accepted.
2363 if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
2364 && (bfa_fcs_fabric_is_switched(rport->port->fabric))
2365 && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
2366 bfa_trc(rport->fcs, rport->pid);
2367 return;
2370 rport->stats.plogi_rcvd++;
2371 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2375 * Called by bport/vport to delete a remote port instance.
2377 * Rport delete is called under the following conditions:
2378 * - vport is deleted
2379 * - vf is deleted
2380 * - explicit request from OS to delete rport (vmware)
2382 void
2383 bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
2385 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
2389 * Called by bport/vport to when a target goes offline.
2392 void
2393 bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
2395 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2399 * Called by bport in n2n when a target (attached port) becomes online.
2402 void
2403 bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
2405 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2409 * Called by bport/vport to notify SCN for the remote port
2411 void
2412 bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2415 rport->stats.rscns++;
2416 bfa_sm_send_event(rport, RPSM_EVENT_SCN);
2420 * Called by fcpim to notify that the ITN cleanup is done.
2422 void
2423 bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
2425 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2429 * Called by fcptm to notify that the ITN cleanup is done.
2431 void
2432 bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
2434 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2438 * This routine BFA callback for bfa_rport_online() call.
2440 * param[in] cb_arg - rport struct.
2442 * return
2443 * void
2445 * Special Considerations:
2447 * note
2449 void
2450 bfa_cb_rport_online(void *cbarg)
2453 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2455 bfa_trc(rport->fcs, rport->pwwn);
2456 bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2460 * This routine BFA callback for bfa_rport_offline() call.
2462 * param[in] rport -
2464 * return
2465 * void
2467 * Special Considerations:
2469 * note
2471 void
2472 bfa_cb_rport_offline(void *cbarg)
2474 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2476 bfa_trc(rport->fcs, rport->pwwn);
2477 bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2481 * This routine is a static BFA callback when there is a QoS flow_id
2482 * change notification
2484 * @param[in] rport -
2486 * @return void
2488 * Special Considerations:
2490 * @note
2492 void
2493 bfa_cb_rport_qos_scn_flowid(void *cbarg,
2494 struct bfa_rport_qos_attr_s old_qos_attr,
2495 struct bfa_rport_qos_attr_s new_qos_attr)
2497 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2498 struct bfa_rport_aen_data_s aen_data;
2500 bfa_trc(rport->fcs, rport->pwwn);
2501 aen_data.priv.qos = new_qos_attr;
2502 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
2506 * This routine is a static BFA callback when there is a QoS priority
2507 * change notification
2509 * @param[in] rport -
2511 * @return void
2513 * Special Considerations:
2515 * @note
2517 void
2518 bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
2519 struct bfa_rport_qos_attr_s new_qos_attr)
2521 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2522 struct bfa_rport_aen_data_s aen_data;
2524 bfa_trc(rport->fcs, rport->pwwn);
2525 aen_data.priv.qos = new_qos_attr;
2526 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
2530 * Called to process any unsolicted frames from this remote port
2532 void
2533 bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
2535 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2539 * Called to process any unsolicted frames from this remote port
2541 void
2542 bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
2543 u16 len)
2545 struct bfa_fcs_port_s *port = rport->port;
2546 struct fc_els_cmd_s *els_cmd;
2548 bfa_trc(rport->fcs, fchs->s_id);
2549 bfa_trc(rport->fcs, fchs->d_id);
2550 bfa_trc(rport->fcs, fchs->type);
2552 if (fchs->type != FC_TYPE_ELS)
2553 return;
2555 els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2557 bfa_trc(rport->fcs, els_cmd->els_code);
2559 switch (els_cmd->els_code) {
2560 case FC_ELS_LOGO:
2561 bfa_fcs_rport_process_logo(rport, fchs);
2562 break;
2564 case FC_ELS_ADISC:
2565 bfa_fcs_rport_process_adisc(rport, fchs, len);
2566 break;
2568 case FC_ELS_PRLO:
2569 if (bfa_fcs_port_is_initiator(port))
2570 bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2572 if (bfa_fcs_port_is_target(port))
2573 bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
2574 break;
2576 case FC_ELS_PRLI:
2577 bfa_fcs_rport_process_prli(rport, fchs, len);
2578 break;
2580 case FC_ELS_RPSC:
2581 bfa_fcs_rport_process_rpsc(rport, fchs, len);
2582 break;
2584 default:
2585 bfa_fcs_rport_send_ls_rjt(rport, fchs,
2586 FC_LS_RJT_RSN_CMD_NOT_SUPP,
2587 FC_LS_RJT_EXP_NO_ADDL_INFO);
2588 break;
2592 /* Send best case acc to prlo */
2593 static void
2594 bfa_fcs_rport_send_prlo_acc(struct bfa_fcs_rport_s *rport)
2596 struct bfa_fcs_port_s *port = rport->port;
2597 struct fchs_s fchs;
2598 struct bfa_fcxp_s *fcxp;
2599 int len;
2601 bfa_trc(rport->fcs, rport->pid);
2603 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
2604 if (!fcxp)
2605 return;
2607 len = fc_prlo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2608 rport->pid, bfa_fcs_port_get_fcid(port),
2609 rport->reply_oxid, 0);
2611 bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id,
2612 port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs,
2613 NULL, NULL, FC_MAX_PDUSZ, 0);
2617 * Send a LS reject
2619 static void
2620 bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2621 u8 reason_code, u8 reason_code_expl)
2623 struct bfa_fcs_port_s *port = rport->port;
2624 struct fchs_s fchs;
2625 struct bfa_fcxp_s *fcxp;
2626 int len;
2628 bfa_trc(rport->fcs, rx_fchs->s_id);
2630 fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
2631 if (!fcxp)
2632 return;
2634 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
2635 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
2636 reason_code, reason_code_expl);
2638 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2639 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2643 * Return state of rport.
2646 bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2648 return bfa_sm_to_state(rport_sm_table, rport->sm);
2652 * Called by the Driver to set rport delete/ageout timeout
2654 * param[in] rport timeout value in seconds.
2656 * return None
2658 void
2659 bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2662 * convert to Millisecs
2664 if (rport_tmo > 0)
2665 bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2668 void
2669 bfa_fcs_rport_prlo(struct bfa_fcs_rport_s *rport, uint16_t ox_id)
2671 bfa_trc(rport->fcs, rport->pid);
2673 rport->prlo = BFA_TRUE;
2674 rport->reply_oxid = ox_id;
2675 bfa_sm_send_event(rport, RPSM_EVENT_PRLO_RCVD);