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