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