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