blob: 4e1fff21a5bcc3435f3aa8a92bc94a7713ff750a [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
18/**
19 * rport.c Remote port implementation.
20 */
21
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/slab.h>
Jing Huang7725ccf2009-09-23 17:46:15 -070023#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>
36
37BFA_TRC_FILE(FCS, RPORT);
38
Jing Huang7725ccf2009-09-23 17:46:15 -070039/* In millisecs */
40static u32 bfa_fcs_rport_del_timeout =
41 BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
42
43/*
44 * forward declarations
45 */
46static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
47 wwn_t pwwn, u32 rpid);
48static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
49static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
50static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
51static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
52static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
53 struct fc_logi_s *plogi);
54static void bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
55static void bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
56static void bfa_fcs_rport_timeout(void *arg);
57static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
58 struct bfa_fcxp_s *fcxp_alloced);
59static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
60 struct bfa_fcxp_s *fcxp_alloced);
61static 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);
68static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
69 struct bfa_fcxp_s *fcxp_alloced);
70static 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);
77static void bfa_fcs_rport_send_gidpn(void *rport_cbarg,
78 struct bfa_fcxp_s *fcxp_alloced);
79static 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);
86static void bfa_fcs_rport_send_logo(void *rport_cbarg,
87 struct bfa_fcxp_s *fcxp_alloced);
88static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
89static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
90 struct fchs_s *rx_fchs, u16 len);
91static 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);
94static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
95 struct fchs_s *rx_fchs, u16 len);
96/**
97 * fcs_rport_sm FCS rport state machine events
98 */
99
100enum rport_event {
101 RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
102 RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
103 RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
104 RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
105 RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
106 RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
107 RPSM_EVENT_DELETE = 7, /* RPORT delete request */
108 RPSM_EVENT_SCN = 8, /* state change notification */
109 RPSM_EVENT_ACCEPTED = 9,/* Good response from remote device */
110 RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
111 RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
112 RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
113 RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */
114 RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */
115 RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */
116 RPSM_EVENT_ADDRESS_DISC = 16 /* Need to Discover rport's PID */
117};
118
119static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
120 enum rport_event event);
121static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
122 enum rport_event event);
123static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
124 enum rport_event event);
125static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
126 enum rport_event event);
127static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
128 enum rport_event event);
129static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
130 enum rport_event event);
131static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
132 enum rport_event event);
133static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
134 enum rport_event event);
135static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
136 enum rport_event event);
137static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
138 enum rport_event event);
139static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
140 enum rport_event event);
141static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
142 enum rport_event event);
143static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
144 enum rport_event event);
145static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
146 enum rport_event event);
147static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
148 enum rport_event event);
149static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
150 enum rport_event event);
151static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
152 enum rport_event event);
153static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
154 enum rport_event event);
155static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
156 enum rport_event event);
157static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
158 enum rport_event event);
159static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
160 enum rport_event event);
161static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
162 enum rport_event event);
163static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
164 enum rport_event event);
165
166static struct bfa_sm_table_s rport_sm_table[] = {
167 {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
168 {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
169 {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
170 {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
171 {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
172 {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
173 {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
174 {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
175 {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
176 {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
177 {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
178 {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
179 {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
180 {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
181 {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
182 {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
183 {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
184 {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
185 {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
186 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
187 {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
188 {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
189};
190
191/**
192 * Beginning state.
193 */
194static void
195bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
196{
197 bfa_trc(rport->fcs, rport->pwwn);
198 bfa_trc(rport->fcs, rport->pid);
199 bfa_trc(rport->fcs, event);
200
201 switch (event) {
202 case RPSM_EVENT_PLOGI_SEND:
203 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
204 rport->plogi_retries = 0;
205 bfa_fcs_rport_send_plogi(rport, NULL);
206 break;
207
208 case RPSM_EVENT_PLOGI_RCVD:
209 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
210 bfa_fcs_rport_send_plogiacc(rport, NULL);
211 break;
212
213 case RPSM_EVENT_PLOGI_COMP:
214 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
215 bfa_fcs_rport_hal_online(rport);
216 break;
217
218 case RPSM_EVENT_ADDRESS_CHANGE:
219 case RPSM_EVENT_ADDRESS_DISC:
220 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
221 rport->ns_retries = 0;
222 bfa_fcs_rport_send_gidpn(rport, NULL);
223 break;
224
225 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800226 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700227 }
228}
229
230/**
231 * PLOGI is being sent.
232 */
233static void
234bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
235 enum rport_event event)
236{
237 bfa_trc(rport->fcs, rport->pwwn);
238 bfa_trc(rport->fcs, rport->pid);
239 bfa_trc(rport->fcs, event);
240
241 switch (event) {
242 case RPSM_EVENT_FCXP_SENT:
243 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
244 break;
245
246 case RPSM_EVENT_DELETE:
247 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
248 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
249 bfa_fcs_rport_free(rport);
250 break;
251
252 case RPSM_EVENT_PLOGI_RCVD:
253 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
254 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
255 bfa_fcs_rport_send_plogiacc(rport, NULL);
256 break;
257
258 case RPSM_EVENT_ADDRESS_CHANGE:
259 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
260 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
261 rport->ns_retries = 0;
262 bfa_fcs_rport_send_gidpn(rport, NULL);
263 break;
264
265 case RPSM_EVENT_LOGO_IMP:
266 rport->pid = 0;
267 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
268 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
269 bfa_timer_start(rport->fcs->bfa, &rport->timer,
270 bfa_fcs_rport_timeout, rport,
271 bfa_fcs_rport_del_timeout);
272 break;
273
274 case RPSM_EVENT_SCN:
275 break;
276
277 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800278 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700279 }
280}
281
282/**
283 * PLOGI is being sent.
284 */
285static void
286bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
287 enum rport_event event)
288{
289 bfa_trc(rport->fcs, rport->pwwn);
290 bfa_trc(rport->fcs, rport->pid);
291 bfa_trc(rport->fcs, event);
292
293 switch (event) {
294 case RPSM_EVENT_FCXP_SENT:
295 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
296 bfa_fcs_rport_hal_online(rport);
297 break;
298
299 case RPSM_EVENT_DELETE:
300 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
301 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
302 bfa_fcs_rport_free(rport);
303 break;
304
305 case RPSM_EVENT_SCN:
306 /**
307 * Ignore, SCN is possibly online notification.
308 */
309 break;
310
311 case RPSM_EVENT_ADDRESS_CHANGE:
312 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
313 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
314 rport->ns_retries = 0;
315 bfa_fcs_rport_send_gidpn(rport, NULL);
316 break;
317
318 case RPSM_EVENT_LOGO_IMP:
319 rport->pid = 0;
320 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
321 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
322 bfa_timer_start(rport->fcs->bfa, &rport->timer,
323 bfa_fcs_rport_timeout, rport,
324 bfa_fcs_rport_del_timeout);
325 break;
326
327 case RPSM_EVENT_HCB_OFFLINE:
328 /**
329 * Ignore BFA callback, on a PLOGI receive we call bfa offline.
330 */
331 break;
332
333 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800334 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700335 }
336}
337
338/**
339 * PLOGI is sent.
340 */
341static void
342bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
343 enum rport_event event)
344{
345 bfa_trc(rport->fcs, rport->pwwn);
346 bfa_trc(rport->fcs, rport->pid);
347 bfa_trc(rport->fcs, event);
348
349 switch (event) {
350 case RPSM_EVENT_SCN:
351 bfa_timer_stop(&rport->timer);
352 /*
353 * !! fall through !!
354 */
355
356 case RPSM_EVENT_TIMEOUT:
Jing Huang7725ccf2009-09-23 17:46:15 -0700357 if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
Jing Huang41188cf2010-07-08 19:52:00 -0700358 rport->plogi_retries++;
Jing Huang7725ccf2009-09-23 17:46:15 -0700359 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
360 bfa_fcs_rport_send_plogi(rport, NULL);
361 } else {
362 rport->pid = 0;
363 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
364 bfa_timer_start(rport->fcs->bfa, &rport->timer,
365 bfa_fcs_rport_timeout, rport,
366 bfa_fcs_rport_del_timeout);
367 }
368 break;
369
370 case RPSM_EVENT_DELETE:
371 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
372 bfa_timer_stop(&rport->timer);
373 bfa_fcs_rport_free(rport);
374 break;
375
376 case RPSM_EVENT_LOGO_RCVD:
377 break;
378
379 case RPSM_EVENT_PLOGI_RCVD:
380 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
381 bfa_timer_stop(&rport->timer);
382 bfa_fcs_rport_send_plogiacc(rport, NULL);
383 break;
384
385 case RPSM_EVENT_ADDRESS_CHANGE:
386 bfa_timer_stop(&rport->timer);
387 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
388 rport->ns_retries = 0;
389 bfa_fcs_rport_send_gidpn(rport, NULL);
390 break;
391
392 case RPSM_EVENT_LOGO_IMP:
393 rport->pid = 0;
394 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
395 bfa_timer_stop(&rport->timer);
396 bfa_timer_start(rport->fcs->bfa, &rport->timer,
397 bfa_fcs_rport_timeout, rport,
398 bfa_fcs_rport_del_timeout);
399 break;
400
401 case RPSM_EVENT_PLOGI_COMP:
402 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
403 bfa_timer_stop(&rport->timer);
404 bfa_fcs_rport_hal_online(rport);
405 break;
406
407 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800408 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700409 }
410}
411
412/**
413 * PLOGI is sent.
414 */
415static void
416bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
417{
418 bfa_trc(rport->fcs, rport->pwwn);
419 bfa_trc(rport->fcs, rport->pid);
420 bfa_trc(rport->fcs, event);
421
422 switch (event) {
423 case RPSM_EVENT_ACCEPTED:
424 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
425 rport->plogi_retries = 0;
426 bfa_fcs_rport_hal_online(rport);
427 break;
428
429 case RPSM_EVENT_LOGO_RCVD:
430 bfa_fcs_rport_send_logo_acc(rport);
431 bfa_fcxp_discard(rport->fcxp);
432 /*
433 * !! fall through !!
434 */
435 case RPSM_EVENT_FAILED:
436 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
437 bfa_timer_start(rport->fcs->bfa, &rport->timer,
438 bfa_fcs_rport_timeout, rport,
439 BFA_FCS_RETRY_TIMEOUT);
440 break;
441
442 case RPSM_EVENT_LOGO_IMP:
443 rport->pid = 0;
444 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
445 bfa_fcxp_discard(rport->fcxp);
446 bfa_timer_start(rport->fcs->bfa, &rport->timer,
447 bfa_fcs_rport_timeout, rport,
448 bfa_fcs_rport_del_timeout);
449 break;
450
451 case RPSM_EVENT_ADDRESS_CHANGE:
452 bfa_fcxp_discard(rport->fcxp);
453 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
454 rport->ns_retries = 0;
455 bfa_fcs_rport_send_gidpn(rport, NULL);
456 break;
457
458 case RPSM_EVENT_PLOGI_RCVD:
459 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
460 bfa_fcxp_discard(rport->fcxp);
461 bfa_fcs_rport_send_plogiacc(rport, NULL);
462 break;
463
464 case RPSM_EVENT_SCN:
465 /**
466 * Ignore SCN - wait for PLOGI response.
467 */
468 break;
469
470 case RPSM_EVENT_DELETE:
471 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
472 bfa_fcxp_discard(rport->fcxp);
473 bfa_fcs_rport_free(rport);
474 break;
475
476 case RPSM_EVENT_PLOGI_COMP:
477 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
478 bfa_fcxp_discard(rport->fcxp);
479 bfa_fcs_rport_hal_online(rport);
480 break;
481
482 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800483 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700484 }
485}
486
487/**
488 * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
489 * are offline.
490 */
491static void
492bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
493 enum rport_event event)
494{
495 bfa_trc(rport->fcs, rport->pwwn);
496 bfa_trc(rport->fcs, rport->pid);
497 bfa_trc(rport->fcs, event);
498
499 switch (event) {
500 case RPSM_EVENT_HCB_ONLINE:
501 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
502 bfa_fcs_rport_online_action(rport);
503 break;
504
505 case RPSM_EVENT_LOGO_RCVD:
506 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
507 bfa_rport_offline(rport->bfa_rport);
508 break;
509
510 case RPSM_EVENT_LOGO_IMP:
511 case RPSM_EVENT_ADDRESS_CHANGE:
512 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
513 bfa_rport_offline(rport->bfa_rport);
514 break;
515
516 case RPSM_EVENT_PLOGI_RCVD:
517 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
518 bfa_rport_offline(rport->bfa_rport);
519 bfa_fcs_rport_send_plogiacc(rport, NULL);
520 break;
521
522 case RPSM_EVENT_DELETE:
523 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
524 bfa_rport_offline(rport->bfa_rport);
525 break;
526
527 case RPSM_EVENT_SCN:
528 /**
529 * @todo
530 * Ignore SCN - PLOGI just completed, FC-4 login should detect
531 * device failures.
532 */
533 break;
534
535 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800536 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700537 }
538}
539
540/**
541 * Rport is ONLINE. FC-4s active.
542 */
543static void
544bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
545{
546 bfa_trc(rport->fcs, rport->pwwn);
547 bfa_trc(rport->fcs, rport->pid);
548 bfa_trc(rport->fcs, event);
549
550 switch (event) {
551 case RPSM_EVENT_SCN:
552 /**
553 * Pause FC-4 activity till rport is authenticated.
554 * In switched fabrics, check presence of device in nameserver
555 * first.
556 */
557 bfa_fcs_rport_fc4_pause(rport);
558
559 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
560 bfa_sm_set_state(rport,
561 bfa_fcs_rport_sm_nsquery_sending);
562 rport->ns_retries = 0;
563 bfa_fcs_rport_send_gidpn(rport, NULL);
564 } else {
565 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
566 bfa_fcs_rport_send_adisc(rport, NULL);
567 }
568 break;
569
570 case RPSM_EVENT_PLOGI_RCVD:
571 case RPSM_EVENT_LOGO_IMP:
572 case RPSM_EVENT_ADDRESS_CHANGE:
573 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
574 bfa_fcs_rport_offline_action(rport);
575 break;
576
577 case RPSM_EVENT_DELETE:
578 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
579 bfa_fcs_rport_offline_action(rport);
580 break;
581
582 case RPSM_EVENT_LOGO_RCVD:
583 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
584 bfa_fcs_rport_offline_action(rport);
585 break;
586
587 case RPSM_EVENT_PLOGI_COMP:
588 break;
589
590 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800591 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700592 }
593}
594
595/**
596 * An SCN event is received in ONLINE state. NS query is being sent
597 * prior to ADISC authentication with rport. FC-4s are paused.
598 */
599static void
600bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
601 enum rport_event event)
602{
603 bfa_trc(rport->fcs, rport->pwwn);
604 bfa_trc(rport->fcs, rport->pid);
605 bfa_trc(rport->fcs, event);
606
607 switch (event) {
608 case RPSM_EVENT_FCXP_SENT:
609 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
610 break;
611
612 case RPSM_EVENT_DELETE:
613 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
614 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
615 bfa_fcs_rport_offline_action(rport);
616 break;
617
618 case RPSM_EVENT_SCN:
619 /**
620 * ignore SCN, wait for response to query itself
621 */
622 break;
623
624 case RPSM_EVENT_LOGO_RCVD:
625 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
626 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
627 bfa_fcs_rport_offline_action(rport);
628 break;
629
630 case RPSM_EVENT_LOGO_IMP:
631 rport->pid = 0;
632 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
633 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
634 bfa_timer_start(rport->fcs->bfa, &rport->timer,
635 bfa_fcs_rport_timeout, rport,
636 bfa_fcs_rport_del_timeout);
637 break;
638
639 case RPSM_EVENT_PLOGI_RCVD:
640 case RPSM_EVENT_ADDRESS_CHANGE:
641 case RPSM_EVENT_PLOGI_COMP:
642 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
643 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
644 bfa_fcs_rport_offline_action(rport);
645 break;
646
647 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800648 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700649 }
650}
651
652/**
653 * An SCN event is received in ONLINE state. NS query is sent to rport.
654 * FC-4s are paused.
655 */
656static void
657bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
658{
659 bfa_trc(rport->fcs, rport->pwwn);
660 bfa_trc(rport->fcs, rport->pid);
661 bfa_trc(rport->fcs, event);
662
663 switch (event) {
664 case RPSM_EVENT_ACCEPTED:
665 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
666 bfa_fcs_rport_send_adisc(rport, NULL);
667 break;
668
669 case RPSM_EVENT_FAILED:
670 rport->ns_retries++;
671 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
672 bfa_sm_set_state(rport,
673 bfa_fcs_rport_sm_nsquery_sending);
674 bfa_fcs_rport_send_gidpn(rport, NULL);
675 } else {
676 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
677 bfa_fcs_rport_offline_action(rport);
678 }
679 break;
680
681 case RPSM_EVENT_DELETE:
682 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
683 bfa_fcxp_discard(rport->fcxp);
684 bfa_fcs_rport_offline_action(rport);
685 break;
686
687 case RPSM_EVENT_SCN:
688 break;
689
690 case RPSM_EVENT_LOGO_RCVD:
691 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
692 bfa_fcxp_discard(rport->fcxp);
693 bfa_fcs_rport_offline_action(rport);
694 break;
695
696 case RPSM_EVENT_PLOGI_COMP:
697 case RPSM_EVENT_ADDRESS_CHANGE:
698 case RPSM_EVENT_PLOGI_RCVD:
699 case RPSM_EVENT_LOGO_IMP:
700 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
701 bfa_fcxp_discard(rport->fcxp);
702 bfa_fcs_rport_offline_action(rport);
703 break;
704
705 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800706 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700707 }
708}
709
710/**
711 * An SCN event is received in ONLINE state. ADISC is being sent for
712 * authenticating with rport. FC-4s are paused.
713 */
714static void
715bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
716 enum rport_event event)
717{
718 bfa_trc(rport->fcs, rport->pwwn);
719 bfa_trc(rport->fcs, rport->pid);
720 bfa_trc(rport->fcs, event);
721
722 switch (event) {
723 case RPSM_EVENT_FCXP_SENT:
724 bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
725 break;
726
727 case RPSM_EVENT_DELETE:
728 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
729 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
730 bfa_fcs_rport_offline_action(rport);
731 break;
732
733 case RPSM_EVENT_LOGO_IMP:
734 case RPSM_EVENT_ADDRESS_CHANGE:
735 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
736 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
737 bfa_fcs_rport_offline_action(rport);
738 break;
739
740 case RPSM_EVENT_LOGO_RCVD:
741 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
742 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
743 bfa_fcs_rport_offline_action(rport);
744 break;
745
746 case RPSM_EVENT_SCN:
747 break;
748
749 case RPSM_EVENT_PLOGI_RCVD:
750 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
751 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
752 bfa_fcs_rport_offline_action(rport);
753 break;
754
755 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800756 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700757 }
758}
759
760/**
761 * An SCN event is received in ONLINE state. ADISC is to rport.
762 * FC-4s are paused.
763 */
764static void
765bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
766{
767 bfa_trc(rport->fcs, rport->pwwn);
768 bfa_trc(rport->fcs, rport->pid);
769 bfa_trc(rport->fcs, event);
770
771 switch (event) {
772 case RPSM_EVENT_ACCEPTED:
773 bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
774 bfa_fcs_rport_fc4_resume(rport);
775 break;
776
777 case RPSM_EVENT_PLOGI_RCVD:
778 /**
779 * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
780 * At least go offline when a PLOGI is received.
781 */
782 bfa_fcxp_discard(rport->fcxp);
783 /*
784 * !!! fall through !!!
785 */
786
787 case RPSM_EVENT_FAILED:
788 case RPSM_EVENT_ADDRESS_CHANGE:
789 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
790 bfa_fcs_rport_offline_action(rport);
791 break;
792
793 case RPSM_EVENT_DELETE:
794 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
795 bfa_fcxp_discard(rport->fcxp);
796 bfa_fcs_rport_offline_action(rport);
797 break;
798
799 case RPSM_EVENT_SCN:
800 /**
801 * already processing RSCN
802 */
803 break;
804
805 case RPSM_EVENT_LOGO_IMP:
806 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
807 bfa_fcxp_discard(rport->fcxp);
808 bfa_fcs_rport_offline_action(rport);
809 break;
810
811 case RPSM_EVENT_LOGO_RCVD:
812 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
813 bfa_fcxp_discard(rport->fcxp);
814 bfa_fcs_rport_offline_action(rport);
815 break;
816
817 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800818 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700819 }
820}
821
822/**
823 * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
824 */
825static void
826bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
827 enum rport_event event)
828{
829 bfa_trc(rport->fcs, rport->pwwn);
830 bfa_trc(rport->fcs, rport->pid);
831 bfa_trc(rport->fcs, event);
832
833 switch (event) {
834 case RPSM_EVENT_FC4_OFFLINE:
835 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
836 bfa_rport_offline(rport->bfa_rport);
837 break;
838
839 case RPSM_EVENT_DELETE:
840 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
841 break;
842
843 case RPSM_EVENT_LOGO_RCVD:
844 case RPSM_EVENT_ADDRESS_CHANGE:
845 break;
846
847 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800848 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700849 }
850}
851
852/**
853 * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
854 * callback.
855 */
856static void
857bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
858 enum rport_event event)
859{
860 bfa_trc(rport->fcs, rport->pwwn);
861 bfa_trc(rport->fcs, rport->pid);
862 bfa_trc(rport->fcs, event);
863
864 switch (event) {
865 case RPSM_EVENT_FC4_OFFLINE:
866 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
867 bfa_rport_offline(rport->bfa_rport);
868 break;
869
870 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800871 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700872 }
873}
874
875/**
876 * Rport is going offline. Awaiting FC-4 offline completion callback.
877 */
878static void
879bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
880 enum rport_event event)
881{
882 bfa_trc(rport->fcs, rport->pwwn);
883 bfa_trc(rport->fcs, rport->pid);
884 bfa_trc(rport->fcs, event);
885
886 switch (event) {
887 case RPSM_EVENT_FC4_OFFLINE:
888 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
889 bfa_rport_offline(rport->bfa_rport);
890 break;
891
892 case RPSM_EVENT_SCN:
893 case RPSM_EVENT_LOGO_IMP:
894 case RPSM_EVENT_LOGO_RCVD:
895 case RPSM_EVENT_ADDRESS_CHANGE:
896 /**
897 * rport is already going offline.
898 * SCN - ignore and wait till transitioning to offline state
899 */
900 break;
901
902 case RPSM_EVENT_DELETE:
903 bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
904 break;
905
906 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800907 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700908 }
909}
910
911/**
912 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
913 * callback.
914 */
915static void
916bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
917 enum rport_event event)
918{
919 bfa_trc(rport->fcs, rport->pwwn);
920 bfa_trc(rport->fcs, rport->pid);
921 bfa_trc(rport->fcs, event);
922
923 switch (event) {
924 case RPSM_EVENT_HCB_OFFLINE:
925 case RPSM_EVENT_ADDRESS_CHANGE:
926 if (bfa_fcs_port_is_online(rport->port)) {
Krishna Gudipati72041ed2010-03-05 19:35:16 -0800927 if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
928 bfa_sm_set_state(rport,
929 bfa_fcs_rport_sm_nsdisc_sending);
930 rport->ns_retries = 0;
931 bfa_fcs_rport_send_gidpn(rport, NULL);
932 } else {
933 bfa_sm_set_state(rport,
934 bfa_fcs_rport_sm_plogi_sending);
935 rport->plogi_retries = 0;
936 bfa_fcs_rport_send_plogi(rport, NULL);
937 }
Jing Huang7725ccf2009-09-23 17:46:15 -0700938 } else {
939 rport->pid = 0;
940 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
941 bfa_timer_start(rport->fcs->bfa, &rport->timer,
942 bfa_fcs_rport_timeout, rport,
943 bfa_fcs_rport_del_timeout);
944 }
945 break;
946
947 case RPSM_EVENT_DELETE:
948 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
949 bfa_fcs_rport_free(rport);
950 break;
951
952 case RPSM_EVENT_SCN:
953 case RPSM_EVENT_LOGO_RCVD:
954 /**
955 * Ignore, already offline.
956 */
957 break;
958
959 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -0800960 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700961 }
962}
963
964/**
965 * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
966 * callback to send LOGO accept.
967 */
968static void
969bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
970 enum rport_event event)
971{
972 bfa_trc(rport->fcs, rport->pwwn);
973 bfa_trc(rport->fcs, rport->pid);
974 bfa_trc(rport->fcs, event);
975
976 switch (event) {
977 case RPSM_EVENT_HCB_OFFLINE:
978 case RPSM_EVENT_ADDRESS_CHANGE:
979 if (rport->pid)
980 bfa_fcs_rport_send_logo_acc(rport);
981 /*
982 * If the lport is online and if the rport is not a well known
983 * address port, we try to re-discover the r-port.
984 */
985 if (bfa_fcs_port_is_online(rport->port)
986 && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
987 bfa_sm_set_state(rport,
988 bfa_fcs_rport_sm_nsdisc_sending);
989 rport->ns_retries = 0;
990 bfa_fcs_rport_send_gidpn(rport, NULL);
991 } else {
992 /*
993 * if it is not a well known address, reset the pid to
994 *
995 */
996 if (!BFA_FCS_PID_IS_WKA(rport->pid))
997 rport->pid = 0;
998 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
999 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1000 bfa_fcs_rport_timeout, rport,
1001 bfa_fcs_rport_del_timeout);
1002 }
1003 break;
1004
1005 case RPSM_EVENT_DELETE:
1006 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
1007 break;
1008
1009 case RPSM_EVENT_LOGO_IMP:
1010 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1011 break;
1012
1013 case RPSM_EVENT_LOGO_RCVD:
1014 /**
1015 * Ignore - already processing a LOGO.
1016 */
1017 break;
1018
1019 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001020 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001021 }
1022}
1023
1024/**
1025 * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
1026 * callback to send LOGO.
1027 */
1028static void
1029bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1030 enum rport_event event)
1031{
1032 bfa_trc(rport->fcs, rport->pwwn);
1033 bfa_trc(rport->fcs, rport->pid);
1034 bfa_trc(rport->fcs, event);
1035
1036 switch (event) {
1037 case RPSM_EVENT_HCB_OFFLINE:
1038 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1039 bfa_fcs_rport_send_logo(rport, NULL);
1040 break;
1041
1042 case RPSM_EVENT_LOGO_RCVD:
1043 case RPSM_EVENT_ADDRESS_CHANGE:
1044 break;
1045
1046 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001047 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001048 }
1049}
1050
1051/**
1052 * Rport is being deleted. FC-4s are offline. LOGO is being sent.
1053 */
1054static void
1055bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1056 enum rport_event event)
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:
1064 /*
1065 * Once LOGO is sent, we donot wait for the response
1066 */
1067 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1068 bfa_fcs_rport_free(rport);
1069 break;
1070
1071 case RPSM_EVENT_SCN:
1072 case RPSM_EVENT_ADDRESS_CHANGE:
1073 break;
1074
1075 case RPSM_EVENT_LOGO_RCVD:
1076 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1077 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1078 bfa_fcs_rport_free(rport);
1079 break;
1080
1081 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001082 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001083 }
1084}
1085
1086/**
1087 * Rport is offline. FC-4s are offline. BFA rport is offline.
1088 * Timer active to delete stale rport.
1089 */
1090static void
1091bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1092{
1093 bfa_trc(rport->fcs, rport->pwwn);
1094 bfa_trc(rport->fcs, rport->pid);
1095 bfa_trc(rport->fcs, event);
1096
1097 switch (event) {
1098 case RPSM_EVENT_TIMEOUT:
1099 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1100 bfa_fcs_rport_free(rport);
1101 break;
1102
1103 case RPSM_EVENT_SCN:
1104 case RPSM_EVENT_ADDRESS_CHANGE:
1105 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1106 bfa_timer_stop(&rport->timer);
1107 rport->ns_retries = 0;
1108 bfa_fcs_rport_send_gidpn(rport, NULL);
1109 break;
1110
1111 case RPSM_EVENT_DELETE:
1112 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1113 bfa_timer_stop(&rport->timer);
1114 bfa_fcs_rport_free(rport);
1115 break;
1116
1117 case RPSM_EVENT_PLOGI_RCVD:
1118 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1119 bfa_timer_stop(&rport->timer);
1120 bfa_fcs_rport_send_plogiacc(rport, NULL);
1121 break;
1122
1123 case RPSM_EVENT_LOGO_RCVD:
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:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001141 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001142 }
1143}
1144
1145/**
1146 * Rport address has changed. Nameserver discovery request is being sent.
1147 */
1148static void
1149bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1150 enum rport_event event)
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:
1175 case RPSM_EVENT_PLOGI_SEND:
1176 break;
1177
1178 case RPSM_EVENT_ADDRESS_CHANGE:
1179 rport->ns_retries = 0; /* reset the retry count */
1180 break;
1181
1182 case RPSM_EVENT_LOGO_IMP:
1183 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1184 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1185 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1186 bfa_fcs_rport_timeout, rport,
1187 bfa_fcs_rport_del_timeout);
1188 break;
1189
1190 case RPSM_EVENT_PLOGI_COMP:
1191 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1192 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1193 bfa_fcs_rport_hal_online(rport);
1194 break;
1195
1196 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001197 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001198 }
1199}
1200
1201/**
1202 * Nameserver discovery failed. Waiting for timeout to retry.
1203 */
1204static void
1205bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1206 enum rport_event event)
1207{
1208 bfa_trc(rport->fcs, rport->pwwn);
1209 bfa_trc(rport->fcs, rport->pid);
1210 bfa_trc(rport->fcs, event);
1211
1212 switch (event) {
1213 case RPSM_EVENT_TIMEOUT:
1214 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1215 bfa_fcs_rport_send_gidpn(rport, NULL);
1216 break;
1217
1218 case RPSM_EVENT_SCN:
1219 case RPSM_EVENT_ADDRESS_CHANGE:
1220 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1221 bfa_timer_stop(&rport->timer);
1222 rport->ns_retries = 0;
1223 bfa_fcs_rport_send_gidpn(rport, NULL);
1224 break;
1225
1226 case RPSM_EVENT_DELETE:
1227 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1228 bfa_timer_stop(&rport->timer);
1229 bfa_fcs_rport_free(rport);
1230 break;
1231
1232 case RPSM_EVENT_PLOGI_RCVD:
1233 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1234 bfa_timer_stop(&rport->timer);
1235 bfa_fcs_rport_send_plogiacc(rport, NULL);
1236 break;
1237
1238 case RPSM_EVENT_LOGO_IMP:
1239 rport->pid = 0;
1240 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1241 bfa_timer_stop(&rport->timer);
1242 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1243 bfa_fcs_rport_timeout, rport,
1244 bfa_fcs_rport_del_timeout);
1245 break;
1246
1247 case RPSM_EVENT_LOGO_RCVD:
1248 bfa_fcs_rport_send_logo_acc(rport);
1249 break;
1250
1251 case RPSM_EVENT_PLOGI_COMP:
1252 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1253 bfa_timer_stop(&rport->timer);
1254 bfa_fcs_rport_hal_online(rport);
1255 break;
1256
1257 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001258 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001259 }
1260}
1261
1262/**
1263 * Rport address has changed. Nameserver discovery request is sent.
1264 */
1265static void
1266bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1267 enum rport_event event)
1268{
1269 bfa_trc(rport->fcs, rport->pwwn);
1270 bfa_trc(rport->fcs, rport->pid);
1271 bfa_trc(rport->fcs, event);
1272
1273 switch (event) {
1274 case RPSM_EVENT_ACCEPTED:
1275 case RPSM_EVENT_ADDRESS_CHANGE:
1276 if (rport->pid) {
1277 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1278 bfa_fcs_rport_send_plogi(rport, NULL);
1279 } else {
1280 bfa_sm_set_state(rport,
1281 bfa_fcs_rport_sm_nsdisc_sending);
1282 rport->ns_retries = 0;
1283 bfa_fcs_rport_send_gidpn(rport, NULL);
1284 }
1285 break;
1286
1287 case RPSM_EVENT_FAILED:
1288 rport->ns_retries++;
1289 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1290 bfa_sm_set_state(rport,
1291 bfa_fcs_rport_sm_nsdisc_sending);
1292 bfa_fcs_rport_send_gidpn(rport, NULL);
1293 } else {
1294 rport->pid = 0;
1295 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1296 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1297 bfa_fcs_rport_timeout, rport,
1298 bfa_fcs_rport_del_timeout);
1299 };
1300 break;
1301
1302 case RPSM_EVENT_DELETE:
1303 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1304 bfa_fcxp_discard(rport->fcxp);
1305 bfa_fcs_rport_free(rport);
1306 break;
1307
1308 case RPSM_EVENT_PLOGI_RCVD:
1309 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1310 bfa_fcxp_discard(rport->fcxp);
1311 bfa_fcs_rport_send_plogiacc(rport, NULL);
1312 break;
1313
1314 case RPSM_EVENT_LOGO_IMP:
1315 rport->pid = 0;
1316 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1317 bfa_fcxp_discard(rport->fcxp);
1318 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1319 bfa_fcs_rport_timeout, rport,
1320 bfa_fcs_rport_del_timeout);
1321 break;
1322
1323 case RPSM_EVENT_SCN:
1324 /**
1325 * ignore, wait for NS query response
1326 */
1327 break;
1328
1329 case RPSM_EVENT_LOGO_RCVD:
1330 /**
1331 * Not logged-in yet. Accept LOGO.
1332 */
1333 bfa_fcs_rport_send_logo_acc(rport);
1334 break;
1335
1336 case RPSM_EVENT_PLOGI_COMP:
1337 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1338 bfa_fcxp_discard(rport->fcxp);
1339 bfa_fcs_rport_hal_online(rport);
1340 break;
1341
1342 default:
Krishna Gudipatie641de32010-03-05 19:35:02 -08001343 bfa_sm_fault(rport->fcs, event);
Jing Huang7725ccf2009-09-23 17:46:15 -07001344 }
1345}
1346
1347
1348
1349/**
1350 * fcs_rport_private FCS RPORT provate functions
1351 */
1352
1353static void
1354bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1355{
1356 struct bfa_fcs_rport_s *rport = rport_cbarg;
1357 struct bfa_fcs_port_s *port = rport->port;
1358 struct fchs_s fchs;
1359 int len;
1360 struct bfa_fcxp_s *fcxp;
1361
1362 bfa_trc(rport->fcs, rport->pwwn);
1363
1364 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1365 if (!fcxp) {
1366 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1367 bfa_fcs_rport_send_plogi, rport);
1368 return;
1369 }
1370 rport->fcxp = fcxp;
1371
1372 len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1373 bfa_fcs_port_get_fcid(port), 0,
1374 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipati1c8a4c32010-03-05 19:37:37 -08001375 bfa_fcport_get_maxfrsize(port->fcs->bfa));
Jing Huang7725ccf2009-09-23 17:46:15 -07001376
1377 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1378 FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
Jing Huang4f1806b2010-07-08 19:50:15 -07001379 (void *)rport, FC_MAX_PDUSZ, FC_ELS_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -07001380
1381 rport->stats.plogis++;
1382 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1383}
1384
1385static void
1386bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1387 bfa_status_t req_status, u32 rsp_len,
1388 u32 resid_len, struct fchs_s *rsp_fchs)
1389{
1390 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1391 struct fc_logi_s *plogi_rsp;
1392 struct fc_ls_rjt_s *ls_rjt;
1393 struct bfa_fcs_rport_s *twin;
1394 struct list_head *qe;
1395
1396 bfa_trc(rport->fcs, rport->pwwn);
1397
1398 /*
1399 * Sanity Checks
1400 */
1401 if (req_status != BFA_STATUS_OK) {
1402 bfa_trc(rport->fcs, req_status);
1403 rport->stats.plogi_failed++;
1404 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1405 return;
1406 }
1407
1408 plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1409
1410 /**
1411 * Check for failure first.
1412 */
1413 if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1414 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1415
1416 bfa_trc(rport->fcs, ls_rjt->reason_code);
1417 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1418
1419 rport->stats.plogi_rejects++;
1420 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1421 return;
1422 }
1423
1424 /**
1425 * PLOGI is complete. Make sure this device is not one of the known
1426 * device with a new FC port address.
1427 */
1428 list_for_each(qe, &rport->port->rport_q) {
1429 twin = (struct bfa_fcs_rport_s *)qe;
1430 if (twin == rport)
1431 continue;
1432 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1433 bfa_trc(rport->fcs, twin->pid);
1434 bfa_trc(rport->fcs, rport->pid);
1435
1436 /*
1437 * Update plogi stats in twin
1438 */
1439 twin->stats.plogis += rport->stats.plogis;
1440 twin->stats.plogi_rejects += rport->stats.plogi_rejects;
1441 twin->stats.plogi_timeouts +=
1442 rport->stats.plogi_timeouts;
1443 twin->stats.plogi_failed += rport->stats.plogi_failed;
1444 twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
1445 twin->stats.plogi_accs++;
1446
1447 bfa_fcs_rport_delete(rport);
1448
1449 bfa_fcs_rport_update(twin, plogi_rsp);
1450 twin->pid = rsp_fchs->s_id;
1451 bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1452 return;
1453 }
1454 }
1455
1456 /**
1457 * Normal login path -- no evil twins.
1458 */
1459 rport->stats.plogi_accs++;
1460 bfa_fcs_rport_update(rport, plogi_rsp);
1461 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1462}
1463
1464static void
1465bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1466{
1467 struct bfa_fcs_rport_s *rport = rport_cbarg;
1468 struct bfa_fcs_port_s *port = rport->port;
1469 struct fchs_s fchs;
1470 int len;
1471 struct bfa_fcxp_s *fcxp;
1472
1473 bfa_trc(rport->fcs, rport->pwwn);
1474 bfa_trc(rport->fcs, rport->reply_oxid);
1475
1476 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1477 if (!fcxp) {
1478 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1479 bfa_fcs_rport_send_plogiacc, rport);
1480 return;
1481 }
1482 rport->fcxp = fcxp;
1483
1484 len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1485 bfa_fcs_port_get_fcid(port), rport->reply_oxid,
1486 port->port_cfg.pwwn, port->port_cfg.nwwn,
Krishna Gudipati1c8a4c32010-03-05 19:37:37 -08001487 bfa_fcport_get_maxfrsize(port->fcs->bfa));
Jing Huang7725ccf2009-09-23 17:46:15 -07001488
1489 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1490 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1491
1492 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1493}
1494
1495static void
1496bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1497{
1498 struct bfa_fcs_rport_s *rport = rport_cbarg;
1499 struct bfa_fcs_port_s *port = rport->port;
1500 struct fchs_s fchs;
1501 int len;
1502 struct bfa_fcxp_s *fcxp;
1503
1504 bfa_trc(rport->fcs, rport->pwwn);
1505
1506 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1507 if (!fcxp) {
1508 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1509 bfa_fcs_rport_send_adisc, rport);
1510 return;
1511 }
1512 rport->fcxp = fcxp;
1513
1514 len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1515 bfa_fcs_port_get_fcid(port), 0,
1516 port->port_cfg.pwwn, port->port_cfg.nwwn);
1517
1518 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1519 FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
Jing Huang4f1806b2010-07-08 19:50:15 -07001520 rport, FC_MAX_PDUSZ, FC_ELS_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -07001521
1522 rport->stats.adisc_sent++;
1523 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1524}
1525
1526static void
1527bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1528 bfa_status_t req_status, u32 rsp_len,
1529 u32 resid_len, struct fchs_s *rsp_fchs)
1530{
1531 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1532 void *pld = bfa_fcxp_get_rspbuf(fcxp);
1533 struct fc_ls_rjt_s *ls_rjt;
1534
1535 if (req_status != BFA_STATUS_OK) {
1536 bfa_trc(rport->fcs, req_status);
1537 rport->stats.adisc_failed++;
1538 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1539 return;
1540 }
1541
1542 if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
1543 rport->nwwn) == FC_PARSE_OK) {
1544 rport->stats.adisc_accs++;
1545 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1546 return;
1547 }
1548
1549 rport->stats.adisc_rejects++;
1550 ls_rjt = pld;
1551 bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1552 bfa_trc(rport->fcs, ls_rjt->reason_code);
1553 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1554 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1555}
1556
1557static void
1558bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1559{
1560 struct bfa_fcs_rport_s *rport = rport_cbarg;
1561 struct bfa_fcs_port_s *port = rport->port;
1562 struct fchs_s fchs;
1563 struct bfa_fcxp_s *fcxp;
1564 int len;
1565
1566 bfa_trc(rport->fcs, rport->pid);
1567
1568 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1569 if (!fcxp) {
1570 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1571 bfa_fcs_rport_send_gidpn, rport);
1572 return;
1573 }
1574 rport->fcxp = fcxp;
1575
1576 len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1577 bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
1578
1579 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1580 FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
Jing Huang4f1806b2010-07-08 19:50:15 -07001581 (void *)rport, FC_MAX_PDUSZ, FC_FCCT_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -07001582
1583 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1584}
1585
1586static void
1587bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1588 bfa_status_t req_status, u32 rsp_len,
1589 u32 resid_len, struct fchs_s *rsp_fchs)
1590{
1591 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1592 struct bfa_fcs_rport_s *twin;
1593 struct list_head *qe;
1594 struct ct_hdr_s *cthdr;
1595 struct fcgs_gidpn_resp_s *gidpn_rsp;
1596
1597 bfa_trc(rport->fcs, rport->pwwn);
1598
1599 cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1600 cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
1601
1602 if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1603 /*
1604 * Check if the pid is the same as before.
1605 */
1606 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1607
1608 if (gidpn_rsp->dap == rport->pid) {
1609 /*
1610 * Device is online
1611 */
1612 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1613 } else {
1614 /*
1615 * Device's PID has changed. We need to cleanup and
1616 * re-login. If there is another device with the the
1617 * newly discovered pid, send an scn notice so that its
1618 * new pid can be discovered.
1619 */
1620 list_for_each(qe, &rport->port->rport_q) {
1621 twin = (struct bfa_fcs_rport_s *)qe;
1622 if (twin == rport)
1623 continue;
1624 if (gidpn_rsp->dap == twin->pid) {
1625 bfa_trc(rport->fcs, twin->pid);
1626 bfa_trc(rport->fcs, rport->pid);
1627
1628 twin->pid = 0;
1629 bfa_sm_send_event(twin,
1630 RPSM_EVENT_ADDRESS_CHANGE);
1631 }
1632 }
1633 rport->pid = gidpn_rsp->dap;
1634 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
1635 }
1636 return;
1637 }
1638
1639 /*
1640 * Reject Response
1641 */
1642 switch (cthdr->reason_code) {
1643 case CT_RSN_LOGICAL_BUSY:
1644 /*
1645 * Need to retry
1646 */
1647 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1648 break;
1649
1650 case CT_RSN_UNABLE_TO_PERF:
1651 /*
1652 * device doesn't exist : Start timer to cleanup this later.
1653 */
1654 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1655 break;
1656
1657 default:
1658 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1659 break;
1660 }
1661}
1662
1663/**
1664 * Called to send a logout to the rport.
1665 */
1666static void
1667bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1668{
1669 struct bfa_fcs_rport_s *rport = rport_cbarg;
1670 struct bfa_fcs_port_s *port;
1671 struct fchs_s fchs;
1672 struct bfa_fcxp_s *fcxp;
1673 u16 len;
1674
1675 bfa_trc(rport->fcs, rport->pid);
1676
1677 port = rport->port;
1678
1679 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1680 if (!fcxp) {
1681 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1682 bfa_fcs_rport_send_logo, rport);
1683 return;
1684 }
1685 rport->fcxp = fcxp;
1686
1687 len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1688 bfa_fcs_port_get_fcid(port), 0,
1689 bfa_fcs_port_get_pwwn(port));
1690
1691 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1692 FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
Jing Huang4f1806b2010-07-08 19:50:15 -07001693 FC_ELS_TOV);
Jing Huang7725ccf2009-09-23 17:46:15 -07001694
1695 rport->stats.logos++;
1696 bfa_fcxp_discard(rport->fcxp);
1697 bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1698}
1699
1700/**
1701 * Send ACC for a LOGO received.
1702 */
1703static void
1704bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
1705{
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;
1711
1712 bfa_trc(rport->fcs, rport->pid);
1713
1714 port = rport->port;
1715
1716 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1717 if (!fcxp)
1718 return;
1719
1720 rport->stats.logo_rcvd++;
1721 len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1722 bfa_fcs_port_get_fcid(port), rport->reply_oxid);
1723
1724 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1725 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1726}
1727
1728/**
1729 * This routine will be called by bfa_timer on timer timeouts.
1730 *
1731 * param[in] rport - pointer to bfa_fcs_port_ns_t.
1732 * param[out] rport_status - pointer to return vport status in
1733 *
1734 * return
1735 * void
1736 *
1737* Special Considerations:
1738 *
1739 * note
1740 */
1741static void
1742bfa_fcs_rport_timeout(void *arg)
1743{
1744 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
1745
1746 rport->stats.plogi_timeouts++;
1747 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1748}
1749
1750static void
1751bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
1752 struct fchs_s *rx_fchs, u16 len)
1753{
1754 struct bfa_fcxp_s *fcxp;
1755 struct fchs_s fchs;
1756 struct bfa_fcs_port_s *port = rport->port;
1757 struct fc_prli_s *prli;
1758
1759 bfa_trc(port->fcs, rx_fchs->s_id);
1760 bfa_trc(port->fcs, rx_fchs->d_id);
1761
1762 rport->stats.prli_rcvd++;
1763
1764 if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1765 /*
1766 * Target Mode : Let the fcptm handle it
1767 */
1768 bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
1769 return;
1770 }
1771
1772 /*
1773 * We are either in Initiator or ipfc Mode
1774 */
1775 prli = (struct fc_prli_s *) (rx_fchs + 1);
1776
1777 if (prli->parampage.servparams.initiator) {
1778 bfa_trc(rport->fcs, prli->parampage.type);
1779 rport->scsi_function = BFA_RPORT_INITIATOR;
1780 bfa_fcs_itnim_is_initiator(rport->itnim);
1781 } else {
1782 /*
1783 * @todo: PRLI from a target ?
1784 */
1785 bfa_trc(port->fcs, rx_fchs->s_id);
1786 rport->scsi_function = BFA_RPORT_TARGET;
1787 }
1788
1789 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1790 if (!fcxp)
1791 return;
1792
1793 len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1794 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1795 port->port_cfg.roles);
1796
1797 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1798 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1799}
1800
1801static void
1802bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
1803 struct fchs_s *rx_fchs, u16 len)
1804{
1805 struct bfa_fcxp_s *fcxp;
1806 struct fchs_s fchs;
1807 struct bfa_fcs_port_s *port = rport->port;
1808 struct fc_rpsc_speed_info_s speeds;
1809 struct bfa_pport_attr_s pport_attr;
1810
1811 bfa_trc(port->fcs, rx_fchs->s_id);
1812 bfa_trc(port->fcs, rx_fchs->d_id);
1813
1814 rport->stats.rpsc_rcvd++;
1815 speeds.port_speed_cap =
1816 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
1817 RPSC_SPEED_CAP_8G;
1818
1819 /*
1820 * get curent speed from pport attributes from BFA
1821 */
Krishna Gudipati1c8a4c32010-03-05 19:37:37 -08001822 bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
Jing Huang7725ccf2009-09-23 17:46:15 -07001823
1824 speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
1825
1826 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1827 if (!fcxp)
1828 return;
1829
1830 len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1831 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1832 &speeds);
1833
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);
1836}
1837
1838static void
1839bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
1840 struct fchs_s *rx_fchs, u16 len)
1841{
1842 struct bfa_fcxp_s *fcxp;
1843 struct fchs_s fchs;
1844 struct bfa_fcs_port_s *port = rport->port;
1845 struct fc_adisc_s *adisc;
1846
1847 bfa_trc(port->fcs, rx_fchs->s_id);
1848 bfa_trc(port->fcs, rx_fchs->d_id);
1849
1850 rport->stats.adisc_rcvd++;
1851
1852 if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1853 /*
1854 * @todo : Target Mode handling
1855 */
1856 bfa_trc(port->fcs, rx_fchs->d_id);
1857 bfa_assert(0);
1858 return;
1859 }
1860
1861 adisc = (struct fc_adisc_s *) (rx_fchs + 1);
1862
1863 /*
1864 * Accept if the itnim for this rport is online. Else reject the ADISC
1865 */
1866 if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
1867
1868 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1869 if (!fcxp)
1870 return;
1871
1872 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1873 rx_fchs->s_id,
1874 bfa_fcs_port_get_fcid(port),
1875 rx_fchs->ox_id, port->port_cfg.pwwn,
1876 port->port_cfg.nwwn);
1877
1878 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
1879 BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
1880 FC_MAX_PDUSZ, 0);
1881 } else {
1882 rport->stats.adisc_rejected++;
1883 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
1884 FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
1885 FC_LS_RJT_EXP_LOGIN_REQUIRED);
1886 }
1887
1888}
1889
1890static void
1891bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
1892{
1893 struct bfa_fcs_port_s *port = rport->port;
1894 struct bfa_rport_info_s rport_info;
1895
1896 rport_info.pid = rport->pid;
1897 rport_info.local_pid = port->pid;
1898 rport_info.lp_tag = port->lp_tag;
1899 rport_info.vf_id = port->fabric->vf_id;
1900 rport_info.vf_en = port->fabric->is_vf;
1901 rport_info.fc_class = rport->fc_cos;
1902 rport_info.cisc = rport->cisc;
1903 rport_info.max_frmsz = rport->maxfrsize;
1904 bfa_rport_online(rport->bfa_rport, &rport_info);
1905}
1906
1907static void
1908bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
1909{
1910 if (bfa_fcs_port_is_initiator(rport->port))
1911 bfa_fcs_itnim_pause(rport->itnim);
1912
1913 if (bfa_fcs_port_is_target(rport->port))
1914 bfa_fcs_tin_pause(rport->tin);
1915}
1916
1917static void
1918bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
1919{
1920 if (bfa_fcs_port_is_initiator(rport->port))
1921 bfa_fcs_itnim_resume(rport->itnim);
1922
1923 if (bfa_fcs_port_is_target(rport->port))
1924 bfa_fcs_tin_resume(rport->tin);
1925}
1926
1927static struct bfa_fcs_rport_s *
1928bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
1929{
1930 struct bfa_fcs_s *fcs = port->fcs;
1931 struct bfa_fcs_rport_s *rport;
1932 struct bfad_rport_s *rport_drv;
1933
1934 /**
1935 * allocate rport
1936 */
1937 if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
1938 != BFA_STATUS_OK) {
1939 bfa_trc(fcs, rpid);
1940 return NULL;
1941 }
1942
1943 /*
1944 * Initialize r-port
1945 */
1946 rport->port = port;
1947 rport->fcs = fcs;
1948 rport->rp_drv = rport_drv;
1949 rport->pid = rpid;
1950 rport->pwwn = pwwn;
1951
1952 /**
1953 * allocate BFA rport
1954 */
1955 rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
1956 if (!rport->bfa_rport) {
1957 bfa_trc(fcs, rpid);
1958 kfree(rport_drv);
1959 return NULL;
1960 }
1961
1962 /**
1963 * allocate FC-4s
1964 */
1965 bfa_assert(bfa_fcs_port_is_initiator(port) ^
1966 bfa_fcs_port_is_target(port));
1967
1968 if (bfa_fcs_port_is_initiator(port)) {
1969 rport->itnim = bfa_fcs_itnim_create(rport);
1970 if (!rport->itnim) {
1971 bfa_trc(fcs, rpid);
1972 bfa_rport_delete(rport->bfa_rport);
1973 kfree(rport_drv);
1974 return NULL;
1975 }
1976 }
1977
1978 if (bfa_fcs_port_is_target(port)) {
1979 rport->tin = bfa_fcs_tin_create(rport);
1980 if (!rport->tin) {
1981 bfa_trc(fcs, rpid);
1982 bfa_rport_delete(rport->bfa_rport);
1983 kfree(rport_drv);
1984 return NULL;
1985 }
1986 }
1987
1988 bfa_fcs_port_add_rport(port, rport);
1989
1990 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1991
1992 /*
1993 * Initialize the Rport Features(RPF) Sub Module
1994 */
1995 if (!BFA_FCS_PID_IS_WKA(rport->pid))
1996 bfa_fcs_rpf_init(rport);
1997
1998 return rport;
1999}
2000
2001
2002static void
2003bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2004{
2005 struct bfa_fcs_port_s *port = rport->port;
2006
2007 /**
2008 * - delete FC-4s
2009 * - delete BFA rport
2010 * - remove from queue of rports
2011 */
2012 if (bfa_fcs_port_is_initiator(port))
2013 bfa_fcs_itnim_delete(rport->itnim);
2014
2015 if (bfa_fcs_port_is_target(port))
2016 bfa_fcs_tin_delete(rport->tin);
2017
2018 bfa_rport_delete(rport->bfa_rport);
2019 bfa_fcs_port_del_rport(port, rport);
2020 kfree(rport->rp_drv);
2021}
2022
2023static void
2024bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2025 enum bfa_rport_aen_event event,
2026 struct bfa_rport_aen_data_s *data)
2027{
2028 union bfa_aen_data_u aen_data;
2029 struct bfa_log_mod_s *logmod = rport->fcs->logm;
2030 wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port);
2031 wwn_t rpwwn = rport->pwwn;
2032 char lpwwn_ptr[BFA_STRING_32];
2033 char rpwwn_ptr[BFA_STRING_32];
2034 char *prio_str[] = { "unknown", "high", "medium", "low" };
2035
2036 wwn2str(lpwwn_ptr, lpwwn);
2037 wwn2str(rpwwn_ptr, rpwwn);
2038
2039 switch (event) {
2040 case BFA_RPORT_AEN_ONLINE:
Jing Huang7725ccf2009-09-23 17:46:15 -07002041 case BFA_RPORT_AEN_OFFLINE:
Jing Huang7725ccf2009-09-23 17:46:15 -07002042 case BFA_RPORT_AEN_DISCONNECT:
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002043 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
2044 rpwwn_ptr, lpwwn_ptr);
Jing Huang7725ccf2009-09-23 17:46:15 -07002045 break;
2046 case BFA_RPORT_AEN_QOS_PRIO:
2047 aen_data.rport.priv.qos = data->priv.qos;
2048 bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
2049 prio_str[aen_data.rport.priv.qos.qos_priority],
2050 rpwwn_ptr, lpwwn_ptr);
2051 break;
2052 case BFA_RPORT_AEN_QOS_FLOWID:
2053 aen_data.rport.priv.qos = data->priv.qos;
2054 bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
2055 aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
2056 lpwwn_ptr);
2057 break;
2058 default:
2059 break;
2060 }
2061
2062 aen_data.rport.vf_id = rport->port->fabric->vf_id;
2063 aen_data.rport.ppwwn =
2064 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
2065 aen_data.rport.lpwwn = lpwwn;
2066 aen_data.rport.rpwwn = rpwwn;
2067}
2068
2069static void
2070bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2071{
2072 struct bfa_fcs_port_s *port = rport->port;
2073
2074 rport->stats.onlines++;
2075
2076 if (bfa_fcs_port_is_initiator(port)) {
2077 bfa_fcs_itnim_rport_online(rport->itnim);
2078 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2079 bfa_fcs_rpf_rport_online(rport);
2080 };
2081
2082 if (bfa_fcs_port_is_target(port))
2083 bfa_fcs_tin_rport_online(rport->tin);
2084
2085 /*
2086 * Don't post events for well known addresses
2087 */
2088 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2089 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2090}
2091
2092static void
2093bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
2094{
2095 struct bfa_fcs_port_s *port = rport->port;
2096
2097 rport->stats.offlines++;
2098
2099 /*
2100 * Don't post events for well known addresses
2101 */
2102 if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2103 if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
2104 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
2105 NULL);
2106 } else {
2107 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
2108 NULL);
2109 }
2110 }
2111
2112 if (bfa_fcs_port_is_initiator(port)) {
2113 bfa_fcs_itnim_rport_offline(rport->itnim);
2114 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2115 bfa_fcs_rpf_rport_offline(rport);
2116 }
2117
2118 if (bfa_fcs_port_is_target(port))
2119 bfa_fcs_tin_rport_offline(rport->tin);
2120}
2121
2122/**
2123 * Update rport parameters from PLOGI or PLOGI accept.
2124 */
2125static void
2126bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2127{
2128 struct bfa_fcs_port_s *port = rport->port;
2129
2130 /**
2131 * - port name
2132 * - node name
2133 */
2134 rport->pwwn = plogi->port_name;
2135 rport->nwwn = plogi->node_name;
2136
2137 /**
2138 * - class of service
2139 */
2140 rport->fc_cos = 0;
2141 if (plogi->class3.class_valid)
2142 rport->fc_cos = FC_CLASS_3;
2143
2144 if (plogi->class2.class_valid)
2145 rport->fc_cos |= FC_CLASS_2;
2146
2147 /**
2148 * - CISC
2149 * - MAX receive frame size
2150 */
2151 rport->cisc = plogi->csp.cisc;
2152 rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
2153
2154 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2155 bfa_trc(port->fcs, port->fabric->bb_credit);
2156 /**
2157 * Direct Attach P2P mode :
2158 * This is to handle a bug (233476) in IBM targets in Direct Attach
2159 * Mode. Basically, in FLOGI Accept the target would have erroneously
2160 * set the BB Credit to the value used in the FLOGI sent by the HBA.
2161 * It uses the correct value (its own BB credit) in PLOGI.
2162 */
2163 if ((!bfa_fcs_fabric_is_switched(port->fabric))
2164 && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
2165
2166 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2167 bfa_trc(port->fcs, port->fabric->bb_credit);
2168
2169 port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
Krishna Gudipati1c8a4c32010-03-05 19:37:37 -08002170 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
Jing Huang7725ccf2009-09-23 17:46:15 -07002171 port->fabric->bb_credit);
2172 }
2173
2174}
2175
2176/**
2177 * Called to handle LOGO received from an existing remote port.
2178 */
2179static void
2180bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2181{
2182 rport->reply_oxid = fchs->ox_id;
2183 bfa_trc(rport->fcs, rport->reply_oxid);
2184
2185 rport->stats.logo_rcvd++;
2186 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2187}
2188
2189
2190
2191/**
2192 * fcs_rport_public FCS rport public interfaces
2193 */
2194
2195/**
2196 * Called by bport/vport to create a remote port instance for a discovered
2197 * remote device.
2198 *
2199 * @param[in] port - base port or vport
2200 * @param[in] rpid - remote port ID
2201 *
2202 * @return None
2203 */
2204struct bfa_fcs_rport_s *
2205bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
2206{
2207 struct bfa_fcs_rport_s *rport;
2208
2209 bfa_trc(port->fcs, rpid);
2210 rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2211 if (!rport)
2212 return NULL;
2213
2214 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2215 return rport;
2216}
2217
2218/**
2219 * Called to create a rport for which only the wwn is known.
2220 *
2221 * @param[in] port - base port
2222 * @param[in] rpwwn - remote port wwn
2223 *
2224 * @return None
2225 */
2226struct bfa_fcs_rport_s *
2227bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
2228{
2229 struct bfa_fcs_rport_s *rport;
2230
2231 bfa_trc(port->fcs, rpwwn);
2232 rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2233 if (!rport)
2234 return NULL;
2235
2236 bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2237 return rport;
2238}
2239
2240/**
2241 * Called by bport in private loop topology to indicate that a
2242 * rport has been discovered and plogi has been completed.
2243 *
2244 * @param[in] port - base port or vport
2245 * @param[in] rpid - remote port ID
2246 */
2247void
2248bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2249 struct fc_logi_s *plogi)
2250{
2251 struct bfa_fcs_rport_s *rport;
2252
2253 rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2254 if (!rport)
2255 return;
2256
2257 bfa_fcs_rport_update(rport, plogi);
2258
2259 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2260}
2261
2262/**
2263 * Called by bport/vport to handle PLOGI received from a new remote port.
2264 * If an existing rport does a plogi, it will be handled separately.
2265 */
2266void
2267bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2268 struct fc_logi_s *plogi)
2269{
2270 struct bfa_fcs_rport_s *rport;
2271
2272 rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2273 if (!rport)
2274 return;
2275
2276 bfa_fcs_rport_update(rport, plogi);
2277
2278 rport->reply_oxid = fchs->ox_id;
2279 bfa_trc(rport->fcs, rport->reply_oxid);
2280
2281 rport->stats.plogi_rcvd++;
2282 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2283}
2284
2285static int
2286wwn_compare(wwn_t wwn1, wwn_t wwn2)
2287{
2288 u8 *b1 = (u8 *) &wwn1;
2289 u8 *b2 = (u8 *) &wwn2;
2290 int i;
2291
2292 for (i = 0; i < sizeof(wwn_t); i++) {
2293 if (b1[i] < b2[i])
2294 return -1;
2295 if (b1[i] > b2[i])
2296 return 1;
2297 }
2298 return 0;
2299}
2300
2301/**
2302 * Called by bport/vport to handle PLOGI received from an existing
2303 * remote port.
2304 */
2305void
2306bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2307 struct fc_logi_s *plogi)
2308{
2309 /**
2310 * @todo Handle P2P and initiator-initiator.
2311 */
2312
2313 bfa_fcs_rport_update(rport, plogi);
2314
2315 rport->reply_oxid = rx_fchs->ox_id;
2316 bfa_trc(rport->fcs, rport->reply_oxid);
2317
2318 /**
2319 * In Switched fabric topology,
2320 * PLOGI to each other. If our pwwn is smaller, ignore it,
2321 * if it is not a well known address.
2322 * If the link topology is N2N,
2323 * this Plogi should be accepted.
2324 */
2325 if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
2326 && (bfa_fcs_fabric_is_switched(rport->port->fabric))
2327 && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
2328 bfa_trc(rport->fcs, rport->pid);
2329 return;
2330 }
2331
2332 rport->stats.plogi_rcvd++;
2333 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2334}
2335
2336/**
2337 * Called by bport/vport to delete a remote port instance.
2338 *
2339* Rport delete is called under the following conditions:
2340 * - vport is deleted
2341 * - vf is deleted
2342 * - explicit request from OS to delete rport (vmware)
2343 */
2344void
2345bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
2346{
2347 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
2348}
2349
2350/**
2351 * Called by bport/vport to when a target goes offline.
2352 *
2353 */
2354void
2355bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
2356{
2357 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2358}
2359
2360/**
2361 * Called by bport in n2n when a target (attached port) becomes online.
2362 *
2363 */
2364void
2365bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
2366{
2367 bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2368}
2369
2370/**
2371 * Called by bport/vport to notify SCN for the remote port
2372 */
2373void
2374bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2375{
2376
2377 rport->stats.rscns++;
2378 bfa_sm_send_event(rport, RPSM_EVENT_SCN);
2379}
2380
2381/**
2382 * Called by fcpim to notify that the ITN cleanup is done.
2383 */
2384void
2385bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
2386{
2387 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2388}
2389
2390/**
2391 * Called by fcptm to notify that the ITN cleanup is done.
2392 */
2393void
2394bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
2395{
2396 bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2397}
2398
2399/**
2400 * This routine BFA callback for bfa_rport_online() call.
2401 *
2402 * param[in] cb_arg - rport struct.
2403 *
2404 * return
2405 * void
2406 *
2407* Special Considerations:
2408 *
2409 * note
2410 */
2411void
2412bfa_cb_rport_online(void *cbarg)
2413{
2414
2415 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2416
2417 bfa_trc(rport->fcs, rport->pwwn);
2418 bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2419}
2420
2421/**
2422 * This routine BFA callback for bfa_rport_offline() call.
2423 *
2424 * param[in] rport -
2425 *
2426 * return
2427 * void
2428 *
2429 * Special Considerations:
2430 *
2431 * note
2432 */
2433void
2434bfa_cb_rport_offline(void *cbarg)
2435{
2436 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2437
2438 bfa_trc(rport->fcs, rport->pwwn);
2439 bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2440}
2441
2442/**
2443 * This routine is a static BFA callback when there is a QoS flow_id
2444 * change notification
2445 *
2446 * @param[in] rport -
2447 *
2448 * @return void
2449 *
2450 * Special Considerations:
2451 *
2452 * @note
2453 */
2454void
2455bfa_cb_rport_qos_scn_flowid(void *cbarg,
2456 struct bfa_rport_qos_attr_s old_qos_attr,
2457 struct bfa_rport_qos_attr_s new_qos_attr)
2458{
2459 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2460 struct bfa_rport_aen_data_s aen_data;
2461
2462 bfa_trc(rport->fcs, rport->pwwn);
2463 aen_data.priv.qos = new_qos_attr;
2464 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
2465}
2466
2467/**
2468 * This routine is a static BFA callback when there is a QoS priority
2469 * change notification
2470 *
2471 * @param[in] rport -
2472 *
2473 * @return void
2474 *
2475 * Special Considerations:
2476 *
2477 * @note
2478 */
2479void
2480bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
2481 struct bfa_rport_qos_attr_s new_qos_attr)
2482{
2483 struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2484 struct bfa_rport_aen_data_s aen_data;
2485
2486 bfa_trc(rport->fcs, rport->pwwn);
2487 aen_data.priv.qos = new_qos_attr;
2488 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
2489}
2490
2491/**
2492 * Called to process any unsolicted frames from this remote port
2493 */
2494void
2495bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
2496{
2497 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2498}
2499
2500/**
2501 * Called to process any unsolicted frames from this remote port
2502 */
2503void
2504bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
2505 u16 len)
2506{
2507 struct bfa_fcs_port_s *port = rport->port;
2508 struct fc_els_cmd_s *els_cmd;
2509
2510 bfa_trc(rport->fcs, fchs->s_id);
2511 bfa_trc(rport->fcs, fchs->d_id);
2512 bfa_trc(rport->fcs, fchs->type);
2513
2514 if (fchs->type != FC_TYPE_ELS)
2515 return;
2516
2517 els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2518
2519 bfa_trc(rport->fcs, els_cmd->els_code);
2520
2521 switch (els_cmd->els_code) {
2522 case FC_ELS_LOGO:
2523 bfa_fcs_rport_process_logo(rport, fchs);
2524 break;
2525
2526 case FC_ELS_ADISC:
2527 bfa_fcs_rport_process_adisc(rport, fchs, len);
2528 break;
2529
2530 case FC_ELS_PRLO:
2531 if (bfa_fcs_port_is_initiator(port))
2532 bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2533
2534 if (bfa_fcs_port_is_target(port))
2535 bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
2536 break;
2537
2538 case FC_ELS_PRLI:
2539 bfa_fcs_rport_process_prli(rport, fchs, len);
2540 break;
2541
2542 case FC_ELS_RPSC:
2543 bfa_fcs_rport_process_rpsc(rport, fchs, len);
2544 break;
2545
2546 default:
2547 bfa_fcs_rport_send_ls_rjt(rport, fchs,
2548 FC_LS_RJT_RSN_CMD_NOT_SUPP,
2549 FC_LS_RJT_EXP_NO_ADDL_INFO);
2550 break;
2551 }
2552}
2553
2554/*
2555 * Send a LS reject
2556 */
2557static void
2558bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2559 u8 reason_code, u8 reason_code_expl)
2560{
2561 struct bfa_fcs_port_s *port = rport->port;
2562 struct fchs_s fchs;
2563 struct bfa_fcxp_s *fcxp;
2564 int len;
2565
2566 bfa_trc(rport->fcs, rx_fchs->s_id);
2567
2568 fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
2569 if (!fcxp)
2570 return;
2571
2572 len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
2573 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
2574 reason_code, reason_code_expl);
2575
2576 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2577 FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2578}
2579
2580/**
Jing Huang7725ccf2009-09-23 17:46:15 -07002581 * Return state of rport.
2582 */
2583int
2584bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2585{
2586 return bfa_sm_to_state(rport_sm_table, rport->sm);
2587}
2588
2589/**
2590 * Called by the Driver to set rport delete/ageout timeout
2591 *
2592 * param[in] rport timeout value in seconds.
2593 *
2594 * return None
2595 */
2596void
2597bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2598{
2599 /*
2600 * convert to Millisecs
2601 */
2602 if (rport_tmo > 0)
2603 bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2604}