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