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