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