8e73dd9a625addab8e7c3f3f0173654bfcbc578f
[linux-flexiantxendom0-natty.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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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_sm_fault(rport->fcs, event);
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                         if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
929                                 bfa_sm_set_state(rport,
930                                         bfa_fcs_rport_sm_nsdisc_sending);
931                                 rport->ns_retries = 0;
932                                 bfa_fcs_rport_send_gidpn(rport, NULL);
933                         } else {
934                                 bfa_sm_set_state(rport,
935                                         bfa_fcs_rport_sm_plogi_sending);
936                                 rport->plogi_retries = 0;
937                                 bfa_fcs_rport_send_plogi(rport, NULL);
938                         }
939                 } else {
940                         rport->pid = 0;
941                         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
942                         bfa_timer_start(rport->fcs->bfa, &rport->timer,
943                                         bfa_fcs_rport_timeout, rport,
944                                         bfa_fcs_rport_del_timeout);
945                 }
946                 break;
947
948         case RPSM_EVENT_DELETE:
949                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
950                 bfa_fcs_rport_free(rport);
951                 break;
952
953         case RPSM_EVENT_SCN:
954         case RPSM_EVENT_LOGO_RCVD:
955                 /**
956                  * Ignore, already offline.
957                  */
958                 break;
959
960         default:
961                 bfa_sm_fault(rport->fcs, event);
962         }
963 }
964
965 /**
966  *              Rport is offline. FC-4s are offline. Awaiting BFA rport offline
967  *              callback to send LOGO accept.
968  */
969 static void
970 bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
971                         enum rport_event event)
972 {
973         bfa_trc(rport->fcs, rport->pwwn);
974         bfa_trc(rport->fcs, rport->pid);
975         bfa_trc(rport->fcs, event);
976
977         switch (event) {
978         case RPSM_EVENT_HCB_OFFLINE:
979         case RPSM_EVENT_ADDRESS_CHANGE:
980                 if (rport->pid)
981                         bfa_fcs_rport_send_logo_acc(rport);
982                 /*
983                  * If the lport is online and if the rport is not a well known
984                  * address port, we try to re-discover the r-port.
985                  */
986                 if (bfa_fcs_port_is_online(rport->port)
987                     && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
988                         bfa_sm_set_state(rport,
989                                          bfa_fcs_rport_sm_nsdisc_sending);
990                         rport->ns_retries = 0;
991                         bfa_fcs_rport_send_gidpn(rport, NULL);
992                 } else {
993                         /*
994                          * if it is not a well known address, reset the pid to
995                          *
996                          */
997                         if (!BFA_FCS_PID_IS_WKA(rport->pid))
998                                 rport->pid = 0;
999                         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1000                         bfa_timer_start(rport->fcs->bfa, &rport->timer,
1001                                         bfa_fcs_rport_timeout, rport,
1002                                         bfa_fcs_rport_del_timeout);
1003                 }
1004                 break;
1005
1006         case RPSM_EVENT_DELETE:
1007                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
1008                 break;
1009
1010         case RPSM_EVENT_LOGO_IMP:
1011                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
1012                 break;
1013
1014         case RPSM_EVENT_LOGO_RCVD:
1015                 /**
1016                  * Ignore - already processing a LOGO.
1017                  */
1018                 break;
1019
1020         default:
1021                 bfa_sm_fault(rport->fcs, event);
1022         }
1023 }
1024
1025 /**
1026  * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
1027  * callback to send LOGO.
1028  */
1029 static void
1030 bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
1031                               enum rport_event event)
1032 {
1033         bfa_trc(rport->fcs, rport->pwwn);
1034         bfa_trc(rport->fcs, rport->pid);
1035         bfa_trc(rport->fcs, event);
1036
1037         switch (event) {
1038         case RPSM_EVENT_HCB_OFFLINE:
1039                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
1040                 bfa_fcs_rport_send_logo(rport, NULL);
1041                 break;
1042
1043         case RPSM_EVENT_LOGO_RCVD:
1044         case RPSM_EVENT_ADDRESS_CHANGE:
1045                 break;
1046
1047         default:
1048                 bfa_sm_fault(rport->fcs, event);
1049         }
1050 }
1051
1052 /**
1053  *              Rport is being deleted. FC-4s are offline. LOGO is being sent.
1054  */
1055 static void
1056 bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
1057                               enum rport_event event)
1058 {
1059         bfa_trc(rport->fcs, rport->pwwn);
1060         bfa_trc(rport->fcs, rport->pid);
1061         bfa_trc(rport->fcs, event);
1062
1063         switch (event) {
1064         case RPSM_EVENT_FCXP_SENT:
1065                 /*
1066                  * Once LOGO is sent, we donot wait for the response
1067                  */
1068                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1069                 bfa_fcs_rport_free(rport);
1070                 break;
1071
1072         case RPSM_EVENT_SCN:
1073         case RPSM_EVENT_ADDRESS_CHANGE:
1074                 break;
1075
1076         case RPSM_EVENT_LOGO_RCVD:
1077                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1078                 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1079                 bfa_fcs_rport_free(rport);
1080                 break;
1081
1082         default:
1083                 bfa_sm_fault(rport->fcs, event);
1084         }
1085 }
1086
1087 /**
1088  *              Rport is offline. FC-4s are offline. BFA rport is offline.
1089  *              Timer active to delete stale rport.
1090  */
1091 static void
1092 bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
1093 {
1094         bfa_trc(rport->fcs, rport->pwwn);
1095         bfa_trc(rport->fcs, rport->pid);
1096         bfa_trc(rport->fcs, event);
1097
1098         switch (event) {
1099         case RPSM_EVENT_TIMEOUT:
1100                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1101                 bfa_fcs_rport_free(rport);
1102                 break;
1103
1104         case RPSM_EVENT_SCN:
1105         case RPSM_EVENT_ADDRESS_CHANGE:
1106                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1107                 bfa_timer_stop(&rport->timer);
1108                 rport->ns_retries = 0;
1109                 bfa_fcs_rport_send_gidpn(rport, NULL);
1110                 break;
1111
1112         case RPSM_EVENT_DELETE:
1113                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1114                 bfa_timer_stop(&rport->timer);
1115                 bfa_fcs_rport_free(rport);
1116                 break;
1117
1118         case RPSM_EVENT_PLOGI_RCVD:
1119                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1120                 bfa_timer_stop(&rport->timer);
1121                 bfa_fcs_rport_send_plogiacc(rport, NULL);
1122                 break;
1123
1124         case RPSM_EVENT_LOGO_RCVD:
1125         case RPSM_EVENT_LOGO_IMP:
1126                 break;
1127
1128         case RPSM_EVENT_PLOGI_COMP:
1129                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1130                 bfa_timer_stop(&rport->timer);
1131                 bfa_fcs_rport_hal_online(rport);
1132                 break;
1133
1134         case RPSM_EVENT_PLOGI_SEND:
1135                 bfa_timer_stop(&rport->timer);
1136                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1137                 rport->plogi_retries = 0;
1138                 bfa_fcs_rport_send_plogi(rport, NULL);
1139                 break;
1140
1141         default:
1142                 bfa_sm_fault(rport->fcs, event);
1143         }
1144 }
1145
1146 /**
1147  *      Rport address has changed. Nameserver discovery request is being sent.
1148  */
1149 static void
1150 bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
1151                                 enum rport_event event)
1152 {
1153         bfa_trc(rport->fcs, rport->pwwn);
1154         bfa_trc(rport->fcs, rport->pid);
1155         bfa_trc(rport->fcs, event);
1156
1157         switch (event) {
1158         case RPSM_EVENT_FCXP_SENT:
1159                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
1160                 break;
1161
1162         case RPSM_EVENT_DELETE:
1163                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1164                 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1165                 bfa_fcs_rport_free(rport);
1166                 break;
1167
1168         case RPSM_EVENT_PLOGI_RCVD:
1169                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1170                 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1171                 bfa_fcs_rport_send_plogiacc(rport, NULL);
1172                 break;
1173
1174         case RPSM_EVENT_SCN:
1175         case RPSM_EVENT_LOGO_RCVD:
1176         case RPSM_EVENT_PLOGI_SEND:
1177                 break;
1178
1179         case RPSM_EVENT_ADDRESS_CHANGE:
1180                 rport->ns_retries = 0;  /* reset the retry count */
1181                 break;
1182
1183         case RPSM_EVENT_LOGO_IMP:
1184                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1185                 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1186                 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1187                                 bfa_fcs_rport_timeout, rport,
1188                                 bfa_fcs_rport_del_timeout);
1189                 break;
1190
1191         case RPSM_EVENT_PLOGI_COMP:
1192                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1193                 bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
1194                 bfa_fcs_rport_hal_online(rport);
1195                 break;
1196
1197         default:
1198                 bfa_sm_fault(rport->fcs, event);
1199         }
1200 }
1201
1202 /**
1203  *              Nameserver discovery failed. Waiting for timeout to retry.
1204  */
1205 static void
1206 bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
1207                               enum rport_event event)
1208 {
1209         bfa_trc(rport->fcs, rport->pwwn);
1210         bfa_trc(rport->fcs, rport->pid);
1211         bfa_trc(rport->fcs, event);
1212
1213         switch (event) {
1214         case RPSM_EVENT_TIMEOUT:
1215                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1216                 bfa_fcs_rport_send_gidpn(rport, NULL);
1217                 break;
1218
1219         case RPSM_EVENT_SCN:
1220         case RPSM_EVENT_ADDRESS_CHANGE:
1221                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
1222                 bfa_timer_stop(&rport->timer);
1223                 rport->ns_retries = 0;
1224                 bfa_fcs_rport_send_gidpn(rport, NULL);
1225                 break;
1226
1227         case RPSM_EVENT_DELETE:
1228                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1229                 bfa_timer_stop(&rport->timer);
1230                 bfa_fcs_rport_free(rport);
1231                 break;
1232
1233         case RPSM_EVENT_PLOGI_RCVD:
1234                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1235                 bfa_timer_stop(&rport->timer);
1236                 bfa_fcs_rport_send_plogiacc(rport, NULL);
1237                 break;
1238
1239         case RPSM_EVENT_LOGO_IMP:
1240                 rport->pid = 0;
1241                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1242                 bfa_timer_stop(&rport->timer);
1243                 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1244                                 bfa_fcs_rport_timeout, rport,
1245                                 bfa_fcs_rport_del_timeout);
1246                 break;
1247
1248         case RPSM_EVENT_LOGO_RCVD:
1249                 bfa_fcs_rport_send_logo_acc(rport);
1250                 break;
1251
1252         case RPSM_EVENT_PLOGI_COMP:
1253                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1254                 bfa_timer_stop(&rport->timer);
1255                 bfa_fcs_rport_hal_online(rport);
1256                 break;
1257
1258         default:
1259                 bfa_sm_fault(rport->fcs, event);
1260         }
1261 }
1262
1263 /**
1264  * Rport address has changed. Nameserver discovery request is sent.
1265  */
1266 static void
1267 bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
1268                         enum rport_event event)
1269 {
1270         bfa_trc(rport->fcs, rport->pwwn);
1271         bfa_trc(rport->fcs, rport->pid);
1272         bfa_trc(rport->fcs, event);
1273
1274         switch (event) {
1275         case RPSM_EVENT_ACCEPTED:
1276         case RPSM_EVENT_ADDRESS_CHANGE:
1277                 if (rport->pid) {
1278                         bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
1279                         bfa_fcs_rport_send_plogi(rport, NULL);
1280                 } else {
1281                         bfa_sm_set_state(rport,
1282                                          bfa_fcs_rport_sm_nsdisc_sending);
1283                         rport->ns_retries = 0;
1284                         bfa_fcs_rport_send_gidpn(rport, NULL);
1285                 }
1286                 break;
1287
1288         case RPSM_EVENT_FAILED:
1289                 rport->ns_retries++;
1290                 if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
1291                         bfa_sm_set_state(rport,
1292                                          bfa_fcs_rport_sm_nsdisc_sending);
1293                         bfa_fcs_rport_send_gidpn(rport, NULL);
1294                 } else {
1295                         rport->pid = 0;
1296                         bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1297                         bfa_timer_start(rport->fcs->bfa, &rport->timer,
1298                                         bfa_fcs_rport_timeout, rport,
1299                                         bfa_fcs_rport_del_timeout);
1300                 };
1301                 break;
1302
1303         case RPSM_EVENT_DELETE:
1304                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1305                 bfa_fcxp_discard(rport->fcxp);
1306                 bfa_fcs_rport_free(rport);
1307                 break;
1308
1309         case RPSM_EVENT_PLOGI_RCVD:
1310                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
1311                 bfa_fcxp_discard(rport->fcxp);
1312                 bfa_fcs_rport_send_plogiacc(rport, NULL);
1313                 break;
1314
1315         case RPSM_EVENT_LOGO_IMP:
1316                 rport->pid = 0;
1317                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
1318                 bfa_fcxp_discard(rport->fcxp);
1319                 bfa_timer_start(rport->fcs->bfa, &rport->timer,
1320                                 bfa_fcs_rport_timeout, rport,
1321                                 bfa_fcs_rport_del_timeout);
1322                 break;
1323
1324         case RPSM_EVENT_SCN:
1325                 /**
1326                  * ignore, wait for NS query response
1327                  */
1328                 break;
1329
1330         case RPSM_EVENT_LOGO_RCVD:
1331                 /**
1332                  * Not logged-in yet. Accept LOGO.
1333                  */
1334                 bfa_fcs_rport_send_logo_acc(rport);
1335                 break;
1336
1337         case RPSM_EVENT_PLOGI_COMP:
1338                 bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
1339                 bfa_fcxp_discard(rport->fcxp);
1340                 bfa_fcs_rport_hal_online(rport);
1341                 break;
1342
1343         default:
1344                 bfa_sm_fault(rport->fcs, event);
1345         }
1346 }
1347
1348
1349
1350 /**
1351  *  fcs_rport_private FCS RPORT provate functions
1352  */
1353
1354 static void
1355 bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1356 {
1357         struct bfa_fcs_rport_s *rport = rport_cbarg;
1358         struct bfa_fcs_port_s *port = rport->port;
1359         struct fchs_s          fchs;
1360         int             len;
1361         struct bfa_fcxp_s *fcxp;
1362
1363         bfa_trc(rport->fcs, rport->pwwn);
1364
1365         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1366         if (!fcxp) {
1367                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1368                                     bfa_fcs_rport_send_plogi, rport);
1369                 return;
1370         }
1371         rport->fcxp = fcxp;
1372
1373         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1374                              bfa_fcs_port_get_fcid(port), 0,
1375                              port->port_cfg.pwwn, port->port_cfg.nwwn,
1376                              bfa_fcport_get_maxfrsize(port->fcs->bfa));
1377
1378         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1379                       FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
1380                       (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV);
1381
1382         rport->stats.plogis++;
1383         bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1384 }
1385
1386 static void
1387 bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1388                              bfa_status_t req_status, u32 rsp_len,
1389                              u32 resid_len, struct fchs_s *rsp_fchs)
1390 {
1391         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1392         struct fc_logi_s        *plogi_rsp;
1393         struct fc_ls_rjt_s      *ls_rjt;
1394         struct bfa_fcs_rport_s *twin;
1395         struct list_head *qe;
1396
1397         bfa_trc(rport->fcs, rport->pwwn);
1398
1399         /*
1400          * Sanity Checks
1401          */
1402         if (req_status != BFA_STATUS_OK) {
1403                 bfa_trc(rport->fcs, req_status);
1404                 rport->stats.plogi_failed++;
1405                 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1406                 return;
1407         }
1408
1409         plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
1410
1411         /**
1412          * Check for failure first.
1413          */
1414         if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
1415                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
1416
1417                 bfa_trc(rport->fcs, ls_rjt->reason_code);
1418                 bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1419
1420                 rport->stats.plogi_rejects++;
1421                 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1422                 return;
1423         }
1424
1425         /**
1426          * PLOGI is complete. Make sure this device is not one of the known
1427          * device with a new FC port address.
1428          */
1429         list_for_each(qe, &rport->port->rport_q) {
1430                 twin = (struct bfa_fcs_rport_s *)qe;
1431                 if (twin == rport)
1432                         continue;
1433                 if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
1434                         bfa_trc(rport->fcs, twin->pid);
1435                         bfa_trc(rport->fcs, rport->pid);
1436
1437                         /*
1438                          * Update plogi stats in twin
1439                          */
1440                         twin->stats.plogis += rport->stats.plogis;
1441                         twin->stats.plogi_rejects += rport->stats.plogi_rejects;
1442                         twin->stats.plogi_timeouts +=
1443                                 rport->stats.plogi_timeouts;
1444                         twin->stats.plogi_failed += rport->stats.plogi_failed;
1445                         twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
1446                         twin->stats.plogi_accs++;
1447
1448                         bfa_fcs_rport_delete(rport);
1449
1450                         bfa_fcs_rport_update(twin, plogi_rsp);
1451                         twin->pid = rsp_fchs->s_id;
1452                         bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
1453                         return;
1454                 }
1455         }
1456
1457         /**
1458          * Normal login path -- no evil twins.
1459          */
1460         rport->stats.plogi_accs++;
1461         bfa_fcs_rport_update(rport, plogi_rsp);
1462         bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1463 }
1464
1465 static void
1466 bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1467 {
1468         struct bfa_fcs_rport_s *rport = rport_cbarg;
1469         struct bfa_fcs_port_s *port = rport->port;
1470         struct fchs_s          fchs;
1471         int             len;
1472         struct bfa_fcxp_s *fcxp;
1473
1474         bfa_trc(rport->fcs, rport->pwwn);
1475         bfa_trc(rport->fcs, rport->reply_oxid);
1476
1477         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1478         if (!fcxp) {
1479                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1480                                     bfa_fcs_rport_send_plogiacc, rport);
1481                 return;
1482         }
1483         rport->fcxp = fcxp;
1484
1485         len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1486                                  bfa_fcs_port_get_fcid(port), rport->reply_oxid,
1487                                  port->port_cfg.pwwn, port->port_cfg.nwwn,
1488                                  bfa_fcport_get_maxfrsize(port->fcs->bfa));
1489
1490         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1491                       FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1492
1493         bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1494 }
1495
1496 static void
1497 bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1498 {
1499         struct bfa_fcs_rport_s *rport = rport_cbarg;
1500         struct bfa_fcs_port_s *port = rport->port;
1501         struct fchs_s          fchs;
1502         int             len;
1503         struct bfa_fcxp_s *fcxp;
1504
1505         bfa_trc(rport->fcs, rport->pwwn);
1506
1507         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1508         if (!fcxp) {
1509                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1510                                     bfa_fcs_rport_send_adisc, rport);
1511                 return;
1512         }
1513         rport->fcxp = fcxp;
1514
1515         len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1516                              bfa_fcs_port_get_fcid(port), 0,
1517                              port->port_cfg.pwwn, port->port_cfg.nwwn);
1518
1519         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1520                       FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
1521                       rport, FC_MAX_PDUSZ, FC_RA_TOV);
1522
1523         rport->stats.adisc_sent++;
1524         bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1525 }
1526
1527 static void
1528 bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1529                              bfa_status_t req_status, u32 rsp_len,
1530                              u32 resid_len, struct fchs_s *rsp_fchs)
1531 {
1532         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1533         void           *pld = bfa_fcxp_get_rspbuf(fcxp);
1534         struct fc_ls_rjt_s    *ls_rjt;
1535
1536         if (req_status != BFA_STATUS_OK) {
1537                 bfa_trc(rport->fcs, req_status);
1538                 rport->stats.adisc_failed++;
1539                 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1540                 return;
1541         }
1542
1543         if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
1544                 rport->nwwn)  == FC_PARSE_OK) {
1545                 rport->stats.adisc_accs++;
1546                 bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1547                 return;
1548         }
1549
1550         rport->stats.adisc_rejects++;
1551         ls_rjt = pld;
1552         bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
1553         bfa_trc(rport->fcs, ls_rjt->reason_code);
1554         bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
1555         bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1556 }
1557
1558 static void
1559 bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1560 {
1561         struct bfa_fcs_rport_s *rport = rport_cbarg;
1562         struct bfa_fcs_port_s *port = rport->port;
1563         struct fchs_s          fchs;
1564         struct bfa_fcxp_s *fcxp;
1565         int             len;
1566
1567         bfa_trc(rport->fcs, rport->pid);
1568
1569         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1570         if (!fcxp) {
1571                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1572                                     bfa_fcs_rport_send_gidpn, rport);
1573                 return;
1574         }
1575         rport->fcxp = fcxp;
1576
1577         len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1578                              bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
1579
1580         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1581                       FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
1582                       (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV);
1583
1584         bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1585 }
1586
1587 static void
1588 bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1589                              bfa_status_t req_status, u32 rsp_len,
1590                              u32 resid_len, struct fchs_s *rsp_fchs)
1591 {
1592         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
1593         struct bfa_fcs_rport_s *twin;
1594         struct list_head *qe;
1595         struct ct_hdr_s         *cthdr;
1596         struct fcgs_gidpn_resp_s        *gidpn_rsp;
1597
1598         bfa_trc(rport->fcs, rport->pwwn);
1599
1600         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1601         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
1602
1603         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1604                 /*
1605                  * Check if the pid is the same as before.
1606                  */
1607                 gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
1608
1609                 if (gidpn_rsp->dap == rport->pid) {
1610                         /*
1611                          * Device is online
1612                          */
1613                         bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
1614                 } else {
1615                         /*
1616                          * Device's PID has changed. We need to cleanup and
1617                          * re-login. If there is another device with the the
1618                          * newly discovered pid, send an scn notice so that its
1619                          * new pid can be discovered.
1620                          */
1621                         list_for_each(qe, &rport->port->rport_q) {
1622                                 twin = (struct bfa_fcs_rport_s *)qe;
1623                                 if (twin == rport)
1624                                         continue;
1625                                 if (gidpn_rsp->dap == twin->pid) {
1626                                         bfa_trc(rport->fcs, twin->pid);
1627                                         bfa_trc(rport->fcs, rport->pid);
1628
1629                                         twin->pid = 0;
1630                                         bfa_sm_send_event(twin,
1631                                                 RPSM_EVENT_ADDRESS_CHANGE);
1632                                 }
1633                         }
1634                         rport->pid = gidpn_rsp->dap;
1635                         bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
1636                 }
1637                 return;
1638         }
1639
1640         /*
1641          * Reject Response
1642          */
1643         switch (cthdr->reason_code) {
1644         case CT_RSN_LOGICAL_BUSY:
1645                 /*
1646                  * Need to retry
1647                  */
1648                 bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1649                 break;
1650
1651         case CT_RSN_UNABLE_TO_PERF:
1652                 /*
1653                  * device doesn't exist : Start timer to cleanup this later.
1654                  */
1655                 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1656                 break;
1657
1658         default:
1659                 bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
1660                 break;
1661         }
1662 }
1663
1664 /**
1665  *    Called to send a logout to the rport.
1666  */
1667 static void
1668 bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1669 {
1670         struct bfa_fcs_rport_s *rport = rport_cbarg;
1671         struct bfa_fcs_port_s *port;
1672         struct fchs_s          fchs;
1673         struct bfa_fcxp_s *fcxp;
1674         u16        len;
1675
1676         bfa_trc(rport->fcs, rport->pid);
1677
1678         port = rport->port;
1679
1680         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1681         if (!fcxp) {
1682                 bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
1683                                     bfa_fcs_rport_send_logo, rport);
1684                 return;
1685         }
1686         rport->fcxp = fcxp;
1687
1688         len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1689                             bfa_fcs_port_get_fcid(port), 0,
1690                             bfa_fcs_port_get_pwwn(port));
1691
1692         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1693                       FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
1694                       FC_ED_TOV);
1695
1696         rport->stats.logos++;
1697         bfa_fcxp_discard(rport->fcxp);
1698         bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
1699 }
1700
1701 /**
1702  *    Send ACC for a LOGO received.
1703  */
1704 static void
1705 bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
1706 {
1707         struct bfa_fcs_rport_s *rport = rport_cbarg;
1708         struct bfa_fcs_port_s *port;
1709         struct fchs_s          fchs;
1710         struct bfa_fcxp_s *fcxp;
1711         u16        len;
1712
1713         bfa_trc(rport->fcs, rport->pid);
1714
1715         port = rport->port;
1716
1717         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1718         if (!fcxp)
1719                 return;
1720
1721         rport->stats.logo_rcvd++;
1722         len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
1723                                 bfa_fcs_port_get_fcid(port), rport->reply_oxid);
1724
1725         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1726                       FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1727 }
1728
1729 /**
1730  *     This routine will be called by bfa_timer on timer timeouts.
1731  *
1732  *      param[in]       rport                   - pointer to bfa_fcs_port_ns_t.
1733  *      param[out]      rport_status    - pointer to return vport status in
1734  *
1735  *      return
1736  *              void
1737  *
1738 *       Special Considerations:
1739  *
1740  *      note
1741  */
1742 static void
1743 bfa_fcs_rport_timeout(void *arg)
1744 {
1745         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
1746
1747         rport->stats.plogi_timeouts++;
1748         bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
1749 }
1750
1751 static void
1752 bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
1753                         struct fchs_s *rx_fchs, u16 len)
1754 {
1755         struct bfa_fcxp_s *fcxp;
1756         struct fchs_s          fchs;
1757         struct bfa_fcs_port_s *port = rport->port;
1758         struct fc_prli_s      *prli;
1759
1760         bfa_trc(port->fcs, rx_fchs->s_id);
1761         bfa_trc(port->fcs, rx_fchs->d_id);
1762
1763         rport->stats.prli_rcvd++;
1764
1765         if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1766                 /*
1767                  * Target Mode : Let the fcptm handle it
1768                  */
1769                 bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
1770                 return;
1771         }
1772
1773         /*
1774          * We are either in Initiator or ipfc Mode
1775          */
1776         prli = (struct fc_prli_s *) (rx_fchs + 1);
1777
1778         if (prli->parampage.servparams.initiator) {
1779                 bfa_trc(rport->fcs, prli->parampage.type);
1780                 rport->scsi_function = BFA_RPORT_INITIATOR;
1781                 bfa_fcs_itnim_is_initiator(rport->itnim);
1782         } else {
1783                 /*
1784                  * @todo: PRLI from a target ?
1785                  */
1786                 bfa_trc(port->fcs, rx_fchs->s_id);
1787                 rport->scsi_function = BFA_RPORT_TARGET;
1788         }
1789
1790         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1791         if (!fcxp)
1792                 return;
1793
1794         len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1795                                 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1796                                 port->port_cfg.roles);
1797
1798         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1799                       FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1800 }
1801
1802 static void
1803 bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
1804                         struct fchs_s *rx_fchs, u16 len)
1805 {
1806         struct bfa_fcxp_s *fcxp;
1807         struct fchs_s          fchs;
1808         struct bfa_fcs_port_s *port = rport->port;
1809         struct fc_rpsc_speed_info_s speeds;
1810         struct bfa_pport_attr_s pport_attr;
1811
1812         bfa_trc(port->fcs, rx_fchs->s_id);
1813         bfa_trc(port->fcs, rx_fchs->d_id);
1814
1815         rport->stats.rpsc_rcvd++;
1816         speeds.port_speed_cap =
1817                 RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
1818                 RPSC_SPEED_CAP_8G;
1819
1820         /*
1821          * get curent speed from pport attributes from BFA
1822          */
1823         bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
1824
1825         speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
1826
1827         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1828         if (!fcxp)
1829                 return;
1830
1831         len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
1832                                 bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
1833                                 &speeds);
1834
1835         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1836                       FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
1837 }
1838
1839 static void
1840 bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
1841                         struct fchs_s *rx_fchs, u16 len)
1842 {
1843         struct bfa_fcxp_s *fcxp;
1844         struct fchs_s          fchs;
1845         struct bfa_fcs_port_s *port = rport->port;
1846         struct fc_adisc_s      *adisc;
1847
1848         bfa_trc(port->fcs, rx_fchs->s_id);
1849         bfa_trc(port->fcs, rx_fchs->d_id);
1850
1851         rport->stats.adisc_rcvd++;
1852
1853         if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
1854                 /*
1855                  * @todo : Target Mode handling
1856                  */
1857                 bfa_trc(port->fcs, rx_fchs->d_id);
1858                 bfa_assert(0);
1859                 return;
1860         }
1861
1862         adisc = (struct fc_adisc_s *) (rx_fchs + 1);
1863
1864         /*
1865          * Accept if the itnim for this rport is online. Else reject the ADISC
1866          */
1867         if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
1868
1869                 fcxp = bfa_fcs_fcxp_alloc(port->fcs);
1870                 if (!fcxp)
1871                         return;
1872
1873                 len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1874                                          rx_fchs->s_id,
1875                                          bfa_fcs_port_get_fcid(port),
1876                                          rx_fchs->ox_id, port->port_cfg.pwwn,
1877                                          port->port_cfg.nwwn);
1878
1879                 bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
1880                               BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
1881                               FC_MAX_PDUSZ, 0);
1882         } else {
1883                 rport->stats.adisc_rejected++;
1884                 bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
1885                                           FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
1886                                           FC_LS_RJT_EXP_LOGIN_REQUIRED);
1887         }
1888
1889 }
1890
1891 static void
1892 bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
1893 {
1894         struct bfa_fcs_port_s *port = rport->port;
1895         struct bfa_rport_info_s rport_info;
1896
1897         rport_info.pid = rport->pid;
1898         rport_info.local_pid = port->pid;
1899         rport_info.lp_tag = port->lp_tag;
1900         rport_info.vf_id = port->fabric->vf_id;
1901         rport_info.vf_en = port->fabric->is_vf;
1902         rport_info.fc_class = rport->fc_cos;
1903         rport_info.cisc = rport->cisc;
1904         rport_info.max_frmsz = rport->maxfrsize;
1905         bfa_rport_online(rport->bfa_rport, &rport_info);
1906 }
1907
1908 static void
1909 bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
1910 {
1911         if (bfa_fcs_port_is_initiator(rport->port))
1912                 bfa_fcs_itnim_pause(rport->itnim);
1913
1914         if (bfa_fcs_port_is_target(rport->port))
1915                 bfa_fcs_tin_pause(rport->tin);
1916 }
1917
1918 static void
1919 bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
1920 {
1921         if (bfa_fcs_port_is_initiator(rport->port))
1922                 bfa_fcs_itnim_resume(rport->itnim);
1923
1924         if (bfa_fcs_port_is_target(rport->port))
1925                 bfa_fcs_tin_resume(rport->tin);
1926 }
1927
1928 static struct bfa_fcs_rport_s *
1929 bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
1930 {
1931         struct bfa_fcs_s *fcs = port->fcs;
1932         struct bfa_fcs_rport_s *rport;
1933         struct bfad_rport_s *rport_drv;
1934
1935         /**
1936          * allocate rport
1937          */
1938         if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
1939             != BFA_STATUS_OK) {
1940                 bfa_trc(fcs, rpid);
1941                 return NULL;
1942         }
1943
1944         /*
1945          * Initialize r-port
1946          */
1947         rport->port = port;
1948         rport->fcs = fcs;
1949         rport->rp_drv = rport_drv;
1950         rport->pid = rpid;
1951         rport->pwwn = pwwn;
1952
1953         /**
1954          * allocate BFA rport
1955          */
1956         rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
1957         if (!rport->bfa_rport) {
1958                 bfa_trc(fcs, rpid);
1959                 kfree(rport_drv);
1960                 return NULL;
1961         }
1962
1963         /**
1964          * allocate FC-4s
1965          */
1966         bfa_assert(bfa_fcs_port_is_initiator(port) ^
1967                    bfa_fcs_port_is_target(port));
1968
1969         if (bfa_fcs_port_is_initiator(port)) {
1970                 rport->itnim = bfa_fcs_itnim_create(rport);
1971                 if (!rport->itnim) {
1972                         bfa_trc(fcs, rpid);
1973                         bfa_rport_delete(rport->bfa_rport);
1974                         kfree(rport_drv);
1975                         return NULL;
1976                 }
1977         }
1978
1979         if (bfa_fcs_port_is_target(port)) {
1980                 rport->tin = bfa_fcs_tin_create(rport);
1981                 if (!rport->tin) {
1982                         bfa_trc(fcs, rpid);
1983                         bfa_rport_delete(rport->bfa_rport);
1984                         kfree(rport_drv);
1985                         return NULL;
1986                 }
1987         }
1988
1989         bfa_fcs_port_add_rport(port, rport);
1990
1991         bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
1992
1993         /*
1994          * Initialize the Rport Features(RPF) Sub Module
1995          */
1996         if (!BFA_FCS_PID_IS_WKA(rport->pid))
1997                 bfa_fcs_rpf_init(rport);
1998
1999         return rport;
2000 }
2001
2002
2003 static void
2004 bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
2005 {
2006         struct bfa_fcs_port_s *port = rport->port;
2007
2008         /**
2009          * - delete FC-4s
2010          * - delete BFA rport
2011          * - remove from queue of rports
2012          */
2013         if (bfa_fcs_port_is_initiator(port))
2014                 bfa_fcs_itnim_delete(rport->itnim);
2015
2016         if (bfa_fcs_port_is_target(port))
2017                 bfa_fcs_tin_delete(rport->tin);
2018
2019         bfa_rport_delete(rport->bfa_rport);
2020         bfa_fcs_port_del_rport(port, rport);
2021         kfree(rport->rp_drv);
2022 }
2023
2024 static void
2025 bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
2026                        enum bfa_rport_aen_event event,
2027                        struct bfa_rport_aen_data_s *data)
2028 {
2029         union bfa_aen_data_u aen_data;
2030         struct bfa_log_mod_s *logmod = rport->fcs->logm;
2031         wwn_t           lpwwn = bfa_fcs_port_get_pwwn(rport->port);
2032         wwn_t           rpwwn = rport->pwwn;
2033         char            lpwwn_ptr[BFA_STRING_32];
2034         char            rpwwn_ptr[BFA_STRING_32];
2035         char           *prio_str[] = { "unknown", "high", "medium", "low" };
2036
2037         wwn2str(lpwwn_ptr, lpwwn);
2038         wwn2str(rpwwn_ptr, rpwwn);
2039
2040         switch (event) {
2041         case BFA_RPORT_AEN_ONLINE:
2042         case BFA_RPORT_AEN_OFFLINE:
2043         case BFA_RPORT_AEN_DISCONNECT:
2044                 bfa_log(logmod, BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, event),
2045                         rpwwn_ptr, lpwwn_ptr);
2046                 break;
2047         case BFA_RPORT_AEN_QOS_PRIO:
2048                 aen_data.rport.priv.qos = data->priv.qos;
2049                 bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
2050                         prio_str[aen_data.rport.priv.qos.qos_priority],
2051                         rpwwn_ptr, lpwwn_ptr);
2052                 break;
2053         case BFA_RPORT_AEN_QOS_FLOWID:
2054                 aen_data.rport.priv.qos = data->priv.qos;
2055                 bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
2056                         aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
2057                         lpwwn_ptr);
2058                 break;
2059         default:
2060                 break;
2061         }
2062
2063         aen_data.rport.vf_id = rport->port->fabric->vf_id;
2064         aen_data.rport.ppwwn =
2065                 bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
2066         aen_data.rport.lpwwn = lpwwn;
2067         aen_data.rport.rpwwn = rpwwn;
2068 }
2069
2070 static void
2071 bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
2072 {
2073         struct bfa_fcs_port_s *port = rport->port;
2074
2075         rport->stats.onlines++;
2076
2077         if (bfa_fcs_port_is_initiator(port)) {
2078                 bfa_fcs_itnim_rport_online(rport->itnim);
2079                 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2080                         bfa_fcs_rpf_rport_online(rport);
2081         };
2082
2083         if (bfa_fcs_port_is_target(port))
2084                 bfa_fcs_tin_rport_online(rport->tin);
2085
2086         /*
2087          * Don't post events for well known addresses
2088          */
2089         if (!BFA_FCS_PID_IS_WKA(rport->pid))
2090                 bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
2091 }
2092
2093 static void
2094 bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
2095 {
2096         struct bfa_fcs_port_s *port = rport->port;
2097
2098         rport->stats.offlines++;
2099
2100         /*
2101          * Don't post events for well known addresses
2102          */
2103         if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
2104                 if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
2105                         bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
2106                                                NULL);
2107                 } else {
2108                         bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
2109                                                NULL);
2110                 }
2111         }
2112
2113         if (bfa_fcs_port_is_initiator(port)) {
2114                 bfa_fcs_itnim_rport_offline(rport->itnim);
2115                 if (!BFA_FCS_PID_IS_WKA(rport->pid))
2116                         bfa_fcs_rpf_rport_offline(rport);
2117         }
2118
2119         if (bfa_fcs_port_is_target(port))
2120                 bfa_fcs_tin_rport_offline(rport->tin);
2121 }
2122
2123 /**
2124  * Update rport parameters from PLOGI or PLOGI accept.
2125  */
2126 static void
2127 bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
2128 {
2129         struct bfa_fcs_port_s *port = rport->port;
2130
2131         /**
2132          * - port name
2133          * - node name
2134          */
2135         rport->pwwn = plogi->port_name;
2136         rport->nwwn = plogi->node_name;
2137
2138         /**
2139          * - class of service
2140          */
2141         rport->fc_cos = 0;
2142         if (plogi->class3.class_valid)
2143                 rport->fc_cos = FC_CLASS_3;
2144
2145         if (plogi->class2.class_valid)
2146                 rport->fc_cos |= FC_CLASS_2;
2147
2148         /**
2149          * - CISC
2150          * - MAX receive frame size
2151          */
2152         rport->cisc = plogi->csp.cisc;
2153         rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
2154
2155         bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2156         bfa_trc(port->fcs, port->fabric->bb_credit);
2157         /**
2158          * Direct Attach P2P mode :
2159          * This is to handle a bug (233476) in IBM targets in Direct Attach
2160          * Mode. Basically, in FLOGI Accept the target would have erroneously
2161          * set the BB Credit to the value used in the FLOGI sent by the HBA.
2162          * It uses the correct value (its own BB credit) in PLOGI.
2163          */
2164         if ((!bfa_fcs_fabric_is_switched(port->fabric))
2165             && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
2166
2167                 bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
2168                 bfa_trc(port->fcs, port->fabric->bb_credit);
2169
2170                 port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
2171                 bfa_fcport_set_tx_bbcredit(port->fcs->bfa,
2172                                           port->fabric->bb_credit);
2173         }
2174
2175 }
2176
2177 /**
2178  *   Called to handle LOGO received from an existing remote port.
2179  */
2180 static void
2181 bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
2182 {
2183         rport->reply_oxid = fchs->ox_id;
2184         bfa_trc(rport->fcs, rport->reply_oxid);
2185
2186         rport->stats.logo_rcvd++;
2187         bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
2188 }
2189
2190
2191
2192 /**
2193  *  fcs_rport_public FCS rport public interfaces
2194  */
2195
2196 /**
2197  *      Called by bport/vport to create a remote port instance for a discovered
2198  *      remote device.
2199  *
2200  * @param[in] port      - base port or vport
2201  * @param[in] rpid      - remote port ID
2202  *
2203  * @return None
2204  */
2205 struct bfa_fcs_rport_s *
2206 bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
2207 {
2208         struct bfa_fcs_rport_s *rport;
2209
2210         bfa_trc(port->fcs, rpid);
2211         rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
2212         if (!rport)
2213                 return NULL;
2214
2215         bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2216         return rport;
2217 }
2218
2219 /**
2220  * Called to create a rport for which only the wwn is known.
2221  *
2222  * @param[in] port      - base port
2223  * @param[in] rpwwn     - remote port wwn
2224  *
2225  * @return None
2226  */
2227 struct bfa_fcs_rport_s *
2228 bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
2229 {
2230         struct bfa_fcs_rport_s *rport;
2231
2232         bfa_trc(port->fcs, rpwwn);
2233         rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
2234         if (!rport)
2235                 return NULL;
2236
2237         bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
2238         return rport;
2239 }
2240
2241 /**
2242  * Called by bport in private loop topology to indicate that a
2243  * rport has been discovered and plogi has been completed.
2244  *
2245  * @param[in] port      - base port or vport
2246  * @param[in] rpid      - remote port ID
2247  */
2248 void
2249 bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2250                         struct fc_logi_s *plogi)
2251 {
2252         struct bfa_fcs_rport_s *rport;
2253
2254         rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
2255         if (!rport)
2256                 return;
2257
2258         bfa_fcs_rport_update(rport, plogi);
2259
2260         bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
2261 }
2262
2263 /**
2264  *   Called by bport/vport to handle PLOGI received from a new remote port.
2265  *   If an existing rport does a plogi, it will be handled separately.
2266  */
2267 void
2268 bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
2269                            struct fc_logi_s *plogi)
2270 {
2271         struct bfa_fcs_rport_s *rport;
2272
2273         rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
2274         if (!rport)
2275                 return;
2276
2277         bfa_fcs_rport_update(rport, plogi);
2278
2279         rport->reply_oxid = fchs->ox_id;
2280         bfa_trc(rport->fcs, rport->reply_oxid);
2281
2282         rport->stats.plogi_rcvd++;
2283         bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2284 }
2285
2286 static int
2287 wwn_compare(wwn_t wwn1, wwn_t wwn2)
2288 {
2289         u8        *b1 = (u8 *) &wwn1;
2290         u8        *b2 = (u8 *) &wwn2;
2291         int             i;
2292
2293         for (i = 0; i < sizeof(wwn_t); i++) {
2294                 if (b1[i] < b2[i])
2295                         return -1;
2296                 if (b1[i] > b2[i])
2297                         return 1;
2298         }
2299         return 0;
2300 }
2301
2302 /**
2303  *   Called by bport/vport to handle PLOGI received from an existing
2304  *       remote port.
2305  */
2306 void
2307 bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2308                     struct fc_logi_s *plogi)
2309 {
2310         /**
2311          * @todo Handle P2P and initiator-initiator.
2312          */
2313
2314         bfa_fcs_rport_update(rport, plogi);
2315
2316         rport->reply_oxid = rx_fchs->ox_id;
2317         bfa_trc(rport->fcs, rport->reply_oxid);
2318
2319         /**
2320          * In Switched fabric topology,
2321          * PLOGI to each other. If our pwwn is smaller, ignore it,
2322          * if it is not a well known address.
2323          * If the link topology is N2N,
2324          * this Plogi should be accepted.
2325          */
2326         if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
2327             && (bfa_fcs_fabric_is_switched(rport->port->fabric))
2328             && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
2329                 bfa_trc(rport->fcs, rport->pid);
2330                 return;
2331         }
2332
2333         rport->stats.plogi_rcvd++;
2334         bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
2335 }
2336
2337 /**
2338  * Called by bport/vport to delete a remote port instance.
2339  *
2340 * Rport delete is called under the following conditions:
2341  *              - vport is deleted
2342  *              - vf is deleted
2343  *              - explicit request from OS to delete rport (vmware)
2344  */
2345 void
2346 bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
2347 {
2348         bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
2349 }
2350
2351 /**
2352  * Called by bport/vport to  when a target goes offline.
2353  *
2354  */
2355 void
2356 bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
2357 {
2358         bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2359 }
2360
2361 /**
2362  * Called by bport in n2n when a target (attached port) becomes online.
2363  *
2364  */
2365 void
2366 bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
2367 {
2368         bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
2369 }
2370
2371 /**
2372  *   Called by bport/vport to notify SCN for the remote port
2373  */
2374 void
2375 bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
2376 {
2377
2378         rport->stats.rscns++;
2379         bfa_sm_send_event(rport, RPSM_EVENT_SCN);
2380 }
2381
2382 /**
2383  *   Called by  fcpim to notify that the ITN cleanup is done.
2384  */
2385 void
2386 bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
2387 {
2388         bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2389 }
2390
2391 /**
2392  *   Called by fcptm to notify that the ITN cleanup is done.
2393  */
2394 void
2395 bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
2396 {
2397         bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
2398 }
2399
2400 /**
2401  *     This routine BFA callback for bfa_rport_online() call.
2402  *
2403  *      param[in]       cb_arg  -  rport struct.
2404  *
2405  *      return
2406  *              void
2407  *
2408 *       Special Considerations:
2409  *
2410  *      note
2411  */
2412 void
2413 bfa_cb_rport_online(void *cbarg)
2414 {
2415
2416         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2417
2418         bfa_trc(rport->fcs, rport->pwwn);
2419         bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
2420 }
2421
2422 /**
2423  *     This routine BFA callback for bfa_rport_offline() call.
2424  *
2425  *      param[in]       rport   -
2426  *
2427  *      return
2428  *              void
2429  *
2430  *      Special Considerations:
2431  *
2432  *      note
2433  */
2434 void
2435 bfa_cb_rport_offline(void *cbarg)
2436 {
2437         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2438
2439         bfa_trc(rport->fcs, rport->pwwn);
2440         bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
2441 }
2442
2443 /**
2444  * This routine is a static BFA callback when there is a QoS flow_id
2445  * change notification
2446  *
2447  * @param[in]   rport   -
2448  *
2449  * @return      void
2450  *
2451  * Special Considerations:
2452  *
2453  * @note
2454  */
2455 void
2456 bfa_cb_rport_qos_scn_flowid(void *cbarg,
2457                             struct bfa_rport_qos_attr_s old_qos_attr,
2458                             struct bfa_rport_qos_attr_s new_qos_attr)
2459 {
2460         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2461         struct bfa_rport_aen_data_s aen_data;
2462
2463         bfa_trc(rport->fcs, rport->pwwn);
2464         aen_data.priv.qos = new_qos_attr;
2465         bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
2466 }
2467
2468 /**
2469  * This routine is a static BFA callback when there is a QoS priority
2470  * change notification
2471  *
2472  * @param[in]   rport   -
2473  *
2474  * @return      void
2475  *
2476  * Special Considerations:
2477  *
2478  * @note
2479  */
2480 void
2481 bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
2482                           struct bfa_rport_qos_attr_s new_qos_attr)
2483 {
2484         struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
2485         struct bfa_rport_aen_data_s aen_data;
2486
2487         bfa_trc(rport->fcs, rport->pwwn);
2488         aen_data.priv.qos = new_qos_attr;
2489         bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
2490 }
2491
2492 /**
2493  *              Called to process any unsolicted frames from this remote port
2494  */
2495 void
2496 bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
2497 {
2498         bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
2499 }
2500
2501 /**
2502  *              Called to process any unsolicted frames from this remote port
2503  */
2504 void
2505 bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
2506                         u16 len)
2507 {
2508         struct bfa_fcs_port_s *port = rport->port;
2509         struct fc_els_cmd_s   *els_cmd;
2510
2511         bfa_trc(rport->fcs, fchs->s_id);
2512         bfa_trc(rport->fcs, fchs->d_id);
2513         bfa_trc(rport->fcs, fchs->type);
2514
2515         if (fchs->type != FC_TYPE_ELS)
2516                 return;
2517
2518         els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
2519
2520         bfa_trc(rport->fcs, els_cmd->els_code);
2521
2522         switch (els_cmd->els_code) {
2523         case FC_ELS_LOGO:
2524                 bfa_fcs_rport_process_logo(rport, fchs);
2525                 break;
2526
2527         case FC_ELS_ADISC:
2528                 bfa_fcs_rport_process_adisc(rport, fchs, len);
2529                 break;
2530
2531         case FC_ELS_PRLO:
2532                 if (bfa_fcs_port_is_initiator(port))
2533                         bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
2534
2535                 if (bfa_fcs_port_is_target(port))
2536                         bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
2537                 break;
2538
2539         case FC_ELS_PRLI:
2540                 bfa_fcs_rport_process_prli(rport, fchs, len);
2541                 break;
2542
2543         case FC_ELS_RPSC:
2544                 bfa_fcs_rport_process_rpsc(rport, fchs, len);
2545                 break;
2546
2547         default:
2548                 bfa_fcs_rport_send_ls_rjt(rport, fchs,
2549                                           FC_LS_RJT_RSN_CMD_NOT_SUPP,
2550                                           FC_LS_RJT_EXP_NO_ADDL_INFO);
2551                 break;
2552         }
2553 }
2554
2555 /*
2556  * Send a LS reject
2557  */
2558 static void
2559 bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
2560                           u8 reason_code, u8 reason_code_expl)
2561 {
2562         struct bfa_fcs_port_s *port = rport->port;
2563         struct fchs_s          fchs;
2564         struct bfa_fcxp_s *fcxp;
2565         int             len;
2566
2567         bfa_trc(rport->fcs, rx_fchs->s_id);
2568
2569         fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
2570         if (!fcxp)
2571                 return;
2572
2573         len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
2574                               bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
2575                               reason_code, reason_code_expl);
2576
2577         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2578                       FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
2579 }
2580
2581 /**
2582  * Return state of rport.
2583  */
2584 int
2585 bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
2586 {
2587         return bfa_sm_to_state(rport_sm_table, rport->sm);
2588 }
2589
2590 /**
2591  *               Called by the Driver to set rport delete/ageout timeout
2592  *
2593  *      param[in]               rport timeout value in seconds.
2594  *
2595  *      return None
2596  */
2597 void
2598 bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
2599 {
2600         /*
2601          * convert to Millisecs
2602          */
2603         if (rport_tmo > 0)
2604                 bfa_fcs_rport_del_timeout = rport_tmo * 1000;
2605 }