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