]> Pileus Git - ~andy/linux/blob - drivers/scsi/bfa/bfa_fcs_lport.c
Merge tag 'mfd-3.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
[~andy/linux] / drivers / scsi / bfa / bfa_fcs_lport.c
1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 #include "bfad_drv.h"
19 #include "bfad_im.h"
20 #include "bfa_fcs.h"
21 #include "bfa_fcbuild.h"
22 #include "bfa_fc.h"
23
24 BFA_TRC_FILE(FCS, PORT);
25
26 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
27                                          struct fchs_s *rx_fchs, u8 reason_code,
28                                          u8 reason_code_expl);
29 static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
30                         struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
31 static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
32 static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
33 static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
34 static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
35 static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
36 static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
37 static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
38                         struct fchs_s *rx_fchs,
39                         struct fc_echo_s *echo, u16 len);
40 static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
41                         struct fchs_s *rx_fchs,
42                         struct fc_rnid_cmd_s *rnid, u16 len);
43 static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
44                         struct fc_rnid_general_topology_data_s *gen_topo_data);
45
46 static void     bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
47 static void     bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
48 static void     bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
49
50 static void     bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
51 static void     bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
52 static void     bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
53
54 static struct {
55         void            (*init) (struct bfa_fcs_lport_s *port);
56         void            (*online) (struct bfa_fcs_lport_s *port);
57         void            (*offline) (struct bfa_fcs_lport_s *port);
58 } __port_action[] = {
59         {
60         bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
61                         bfa_fcs_lport_unknown_offline}, {
62         bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
63                         bfa_fcs_lport_fab_offline}, {
64         bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
65                         bfa_fcs_lport_n2n_offline},
66         };
67
68 /*
69  *  fcs_port_sm FCS logical port state machine
70  */
71
72 enum bfa_fcs_lport_event {
73         BFA_FCS_PORT_SM_CREATE = 1,
74         BFA_FCS_PORT_SM_ONLINE = 2,
75         BFA_FCS_PORT_SM_OFFLINE = 3,
76         BFA_FCS_PORT_SM_DELETE = 4,
77         BFA_FCS_PORT_SM_DELRPORT = 5,
78         BFA_FCS_PORT_SM_STOP = 6,
79 };
80
81 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
82                                         enum bfa_fcs_lport_event event);
83 static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
84                                         enum bfa_fcs_lport_event event);
85 static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
86                                         enum bfa_fcs_lport_event event);
87 static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
88                                         enum bfa_fcs_lport_event event);
89 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
90                                         enum bfa_fcs_lport_event event);
91 static void     bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
92                                         enum bfa_fcs_lport_event event);
93
94 static void
95 bfa_fcs_lport_sm_uninit(
96         struct bfa_fcs_lport_s *port,
97         enum bfa_fcs_lport_event event)
98 {
99         bfa_trc(port->fcs, port->port_cfg.pwwn);
100         bfa_trc(port->fcs, event);
101
102         switch (event) {
103         case BFA_FCS_PORT_SM_CREATE:
104                 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
105                 break;
106
107         default:
108                 bfa_sm_fault(port->fcs, event);
109         }
110 }
111
112 static void
113 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
114                         enum bfa_fcs_lport_event event)
115 {
116         bfa_trc(port->fcs, port->port_cfg.pwwn);
117         bfa_trc(port->fcs, event);
118
119         switch (event) {
120         case BFA_FCS_PORT_SM_ONLINE:
121                 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
122                 bfa_fcs_lport_online_actions(port);
123                 break;
124
125         case BFA_FCS_PORT_SM_DELETE:
126                 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
127                 bfa_fcs_lport_deleted(port);
128                 break;
129
130         case BFA_FCS_PORT_SM_STOP:
131                 /* If vport - send completion call back */
132                 if (port->vport)
133                         bfa_fcs_vport_stop_comp(port->vport);
134                 else
135                         bfa_wc_down(&(port->fabric->stop_wc));
136                 break;
137
138         case BFA_FCS_PORT_SM_OFFLINE:
139                 break;
140
141         default:
142                 bfa_sm_fault(port->fcs, event);
143         }
144 }
145
146 static void
147 bfa_fcs_lport_sm_online(
148         struct bfa_fcs_lport_s *port,
149         enum bfa_fcs_lport_event event)
150 {
151         struct bfa_fcs_rport_s *rport;
152         struct list_head                *qe, *qen;
153
154         bfa_trc(port->fcs, port->port_cfg.pwwn);
155         bfa_trc(port->fcs, event);
156
157         switch (event) {
158         case BFA_FCS_PORT_SM_OFFLINE:
159                 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
160                 bfa_fcs_lport_offline_actions(port);
161                 break;
162
163         case BFA_FCS_PORT_SM_STOP:
164                 __port_action[port->fabric->fab_type].offline(port);
165
166                 if (port->num_rports == 0) {
167                         bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
168                         /* If vport - send completion call back */
169                         if (port->vport)
170                                 bfa_fcs_vport_stop_comp(port->vport);
171                         else
172                                 bfa_wc_down(&(port->fabric->stop_wc));
173                 } else {
174                         bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
175                         list_for_each_safe(qe, qen, &port->rport_q) {
176                                 rport = (struct bfa_fcs_rport_s *) qe;
177                                 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
178                         }
179                 }
180                 break;
181
182         case BFA_FCS_PORT_SM_DELETE:
183
184                 __port_action[port->fabric->fab_type].offline(port);
185
186                 if (port->num_rports == 0) {
187                         bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
188                         bfa_fcs_lport_deleted(port);
189                 } else {
190                         bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
191                         list_for_each_safe(qe, qen, &port->rport_q) {
192                                 rport = (struct bfa_fcs_rport_s *) qe;
193                                 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
194                         }
195                 }
196                 break;
197
198         case BFA_FCS_PORT_SM_DELRPORT:
199                 break;
200
201         default:
202                 bfa_sm_fault(port->fcs, event);
203         }
204 }
205
206 static void
207 bfa_fcs_lport_sm_offline(
208         struct bfa_fcs_lport_s *port,
209         enum bfa_fcs_lport_event event)
210 {
211         struct bfa_fcs_rport_s *rport;
212         struct list_head                *qe, *qen;
213
214         bfa_trc(port->fcs, port->port_cfg.pwwn);
215         bfa_trc(port->fcs, event);
216
217         switch (event) {
218         case BFA_FCS_PORT_SM_ONLINE:
219                 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
220                 bfa_fcs_lport_online_actions(port);
221                 break;
222
223         case BFA_FCS_PORT_SM_STOP:
224                 if (port->num_rports == 0) {
225                         bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
226                         /* If vport - send completion call back */
227                         if (port->vport)
228                                 bfa_fcs_vport_stop_comp(port->vport);
229                         else
230                                 bfa_wc_down(&(port->fabric->stop_wc));
231                 } else {
232                         bfa_sm_set_state(port, bfa_fcs_lport_sm_stopping);
233                         list_for_each_safe(qe, qen, &port->rport_q) {
234                                 rport = (struct bfa_fcs_rport_s *) qe;
235                                 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
236                         }
237                 }
238                 break;
239
240         case BFA_FCS_PORT_SM_DELETE:
241                 if (port->num_rports == 0) {
242                         bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
243                         bfa_fcs_lport_deleted(port);
244                 } else {
245                         bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
246                         list_for_each_safe(qe, qen, &port->rport_q) {
247                                 rport = (struct bfa_fcs_rport_s *) qe;
248                                 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
249                         }
250                 }
251                 break;
252
253         case BFA_FCS_PORT_SM_DELRPORT:
254         case BFA_FCS_PORT_SM_OFFLINE:
255                 break;
256
257         default:
258                 bfa_sm_fault(port->fcs, event);
259         }
260 }
261
262 static void
263 bfa_fcs_lport_sm_stopping(struct bfa_fcs_lport_s *port,
264                           enum bfa_fcs_lport_event event)
265 {
266         bfa_trc(port->fcs, port->port_cfg.pwwn);
267         bfa_trc(port->fcs, event);
268
269         switch (event) {
270         case BFA_FCS_PORT_SM_DELRPORT:
271                 if (port->num_rports == 0) {
272                         bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
273                         /* If vport - send completion call back */
274                         if (port->vport)
275                                 bfa_fcs_vport_stop_comp(port->vport);
276                         else
277                                 bfa_wc_down(&(port->fabric->stop_wc));
278                 }
279                 break;
280
281         default:
282                 bfa_sm_fault(port->fcs, event);
283         }
284 }
285
286 static void
287 bfa_fcs_lport_sm_deleting(
288         struct bfa_fcs_lport_s *port,
289         enum bfa_fcs_lport_event event)
290 {
291         bfa_trc(port->fcs, port->port_cfg.pwwn);
292         bfa_trc(port->fcs, event);
293
294         switch (event) {
295         case BFA_FCS_PORT_SM_DELRPORT:
296                 if (port->num_rports == 0) {
297                         bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
298                         bfa_fcs_lport_deleted(port);
299                 }
300                 break;
301
302         default:
303                 bfa_sm_fault(port->fcs, event);
304         }
305 }
306
307 /*
308  *  fcs_port_pvt
309  */
310
311 /*
312  * Send AEN notification
313  */
314 static void
315 bfa_fcs_lport_aen_post(struct bfa_fcs_lport_s *port,
316                         enum bfa_lport_aen_event event)
317 {
318         struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
319         struct bfa_aen_entry_s  *aen_entry;
320
321         bfad_get_aen_entry(bfad, aen_entry);
322         if (!aen_entry)
323                 return;
324
325         aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
326         aen_entry->aen_data.lport.roles = port->port_cfg.roles;
327         aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
328                                         bfa_fcs_get_base_port(port->fcs));
329         aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
330
331         /* Send the AEN notification */
332         bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
333                                   BFA_AEN_CAT_LPORT, event);
334 }
335
336 /*
337  * Send a LS reject
338  */
339 static void
340 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
341                          u8 reason_code, u8 reason_code_expl)
342 {
343         struct fchs_s   fchs;
344         struct bfa_fcxp_s *fcxp;
345         struct bfa_rport_s *bfa_rport = NULL;
346         int             len;
347
348         bfa_trc(port->fcs, rx_fchs->d_id);
349         bfa_trc(port->fcs, rx_fchs->s_id);
350
351         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
352         if (!fcxp)
353                 return;
354
355         len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
356                               rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
357                               rx_fchs->ox_id, reason_code, reason_code_expl);
358
359         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
360                           BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
361                           FC_MAX_PDUSZ, 0);
362 }
363
364 /*
365  * Send a FCCT Reject
366  */
367 static void
368 bfa_fcs_lport_send_fcgs_rjt(struct bfa_fcs_lport_s *port,
369         struct fchs_s *rx_fchs, u8 reason_code, u8 reason_code_expl)
370 {
371         struct fchs_s   fchs;
372         struct bfa_fcxp_s *fcxp;
373         struct bfa_rport_s *bfa_rport = NULL;
374         int             len;
375         struct ct_hdr_s *rx_cthdr = (struct ct_hdr_s *)(rx_fchs + 1);
376         struct ct_hdr_s *ct_hdr;
377
378         bfa_trc(port->fcs, rx_fchs->d_id);
379         bfa_trc(port->fcs, rx_fchs->s_id);
380
381         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
382         if (!fcxp)
383                 return;
384
385         ct_hdr = bfa_fcxp_get_reqbuf(fcxp);
386         ct_hdr->gs_type = rx_cthdr->gs_type;
387         ct_hdr->gs_sub_type = rx_cthdr->gs_sub_type;
388
389         len = fc_gs_rjt_build(&fchs, ct_hdr, rx_fchs->s_id,
390                         bfa_fcs_lport_get_fcid(port),
391                         rx_fchs->ox_id, reason_code, reason_code_expl);
392
393         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
394                         BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
395                         FC_MAX_PDUSZ, 0);
396 }
397
398 /*
399  * Process incoming plogi from a remote port.
400  */
401 static void
402 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
403                 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
404 {
405         struct bfa_fcs_rport_s *rport;
406
407         bfa_trc(port->fcs, rx_fchs->d_id);
408         bfa_trc(port->fcs, rx_fchs->s_id);
409
410         /*
411          * If min cfg mode is enabled, drop any incoming PLOGIs
412          */
413         if (__fcs_min_cfg(port->fcs)) {
414                 bfa_trc(port->fcs, rx_fchs->s_id);
415                 return;
416         }
417
418         if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
419                 bfa_trc(port->fcs, rx_fchs->s_id);
420                 /*
421                  * send a LS reject
422                  */
423                 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
424                                         FC_LS_RJT_RSN_PROTOCOL_ERROR,
425                                         FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
426                 return;
427         }
428
429         /*
430          * Direct Attach P2P mode : verify address assigned by the r-port.
431          */
432         if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
433                 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
434                            (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
435                 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
436                         /* Address assigned to us cannot be a WKA */
437                         bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
438                                         FC_LS_RJT_RSN_PROTOCOL_ERROR,
439                                         FC_LS_RJT_EXP_INVALID_NPORT_ID);
440                         return;
441                 }
442                 port->pid  = rx_fchs->d_id;
443                 bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
444         }
445
446         /*
447          * First, check if we know the device by pwwn.
448          */
449         rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
450         if (rport) {
451                 /*
452                  * Direct Attach P2P mode : handle address assigned by r-port.
453                  */
454                 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
455                         (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
456                         (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
457                         port->pid  = rx_fchs->d_id;
458                         bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
459                         rport->pid = rx_fchs->s_id;
460                 }
461                 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
462                 return;
463         }
464
465         /*
466          * Next, lookup rport by PID.
467          */
468         rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
469         if (!rport) {
470                 /*
471                  * Inbound PLOGI from a new device.
472                  */
473                 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
474                 return;
475         }
476
477         /*
478          * Rport is known only by PID.
479          */
480         if (rport->pwwn) {
481                 /*
482                  * This is a different device with the same pid. Old device
483                  * disappeared. Send implicit LOGO to old device.
484                  */
485                 WARN_ON(rport->pwwn == plogi->port_name);
486                 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
487
488                 /*
489                  * Inbound PLOGI from a new device (with old PID).
490                  */
491                 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
492                 return;
493         }
494
495         /*
496          * PLOGI crossing each other.
497          */
498         WARN_ON(rport->pwwn != WWN_NULL);
499         bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
500 }
501
502 /*
503  * Process incoming ECHO.
504  * Since it does not require a login, it is processed here.
505  */
506 static void
507 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
508                 struct fc_echo_s *echo, u16 rx_len)
509 {
510         struct fchs_s           fchs;
511         struct bfa_fcxp_s       *fcxp;
512         struct bfa_rport_s      *bfa_rport = NULL;
513         int                     len, pyld_len;
514
515         bfa_trc(port->fcs, rx_fchs->s_id);
516         bfa_trc(port->fcs, rx_fchs->d_id);
517
518         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
519         if (!fcxp)
520                 return;
521
522         len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
523                                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
524                                 rx_fchs->ox_id);
525
526         /*
527          * Copy the payload (if any) from the echo frame
528          */
529         pyld_len = rx_len - sizeof(struct fchs_s);
530         bfa_trc(port->fcs, rx_len);
531         bfa_trc(port->fcs, pyld_len);
532
533         if (pyld_len > len)
534                 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
535                         sizeof(struct fc_echo_s), (echo + 1),
536                         (pyld_len - sizeof(struct fc_echo_s)));
537
538         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
539                         BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
540                         FC_MAX_PDUSZ, 0);
541 }
542
543 /*
544  * Process incoming RNID.
545  * Since it does not require a login, it is processed here.
546  */
547 static void
548 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
549                 struct fc_rnid_cmd_s *rnid, u16 rx_len)
550 {
551         struct fc_rnid_common_id_data_s common_id_data;
552         struct fc_rnid_general_topology_data_s gen_topo_data;
553         struct fchs_s   fchs;
554         struct bfa_fcxp_s *fcxp;
555         struct bfa_rport_s *bfa_rport = NULL;
556         u16     len;
557         u32     data_format;
558
559         bfa_trc(port->fcs, rx_fchs->s_id);
560         bfa_trc(port->fcs, rx_fchs->d_id);
561         bfa_trc(port->fcs, rx_len);
562
563         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
564         if (!fcxp)
565                 return;
566
567         /*
568          * Check Node Indentification Data Format
569          * We only support General Topology Discovery Format.
570          * For any other requested Data Formats, we return Common Node Id Data
571          * only, as per FC-LS.
572          */
573         bfa_trc(port->fcs, rnid->node_id_data_format);
574         if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
575                 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
576                 /*
577                  * Get General topology data for this port
578                  */
579                 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
580         } else {
581                 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
582         }
583
584         /*
585          * Copy the Node Id Info
586          */
587         common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
588         common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
589
590         len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
591                                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
592                                 rx_fchs->ox_id, data_format, &common_id_data,
593                                 &gen_topo_data);
594
595         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
596                         BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
597                         FC_MAX_PDUSZ, 0);
598 }
599
600 /*
601  *  Fill out General Topolpgy Discovery Data for RNID ELS.
602  */
603 static void
604 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
605                         struct fc_rnid_general_topology_data_s *gen_topo_data)
606 {
607         memset(gen_topo_data, 0,
608                       sizeof(struct fc_rnid_general_topology_data_s));
609
610         gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
611         gen_topo_data->phy_port_num = 0;        /* @todo */
612         gen_topo_data->num_attached_nodes = cpu_to_be32(1);
613 }
614
615 static void
616 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
617 {
618         struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
619         char    lpwwn_buf[BFA_STRING_32];
620
621         bfa_trc(port->fcs, port->fabric->oper_type);
622
623         __port_action[port->fabric->fab_type].init(port);
624         __port_action[port->fabric->fab_type].online(port);
625
626         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
627         BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
628                 "Logical port online: WWN = %s Role = %s\n",
629                 lpwwn_buf, "Initiator");
630         bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_ONLINE);
631
632         bfad->bfad_flags |= BFAD_PORT_ONLINE;
633 }
634
635 static void
636 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
637 {
638         struct list_head        *qe, *qen;
639         struct bfa_fcs_rport_s *rport;
640         struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
641         char    lpwwn_buf[BFA_STRING_32];
642
643         bfa_trc(port->fcs, port->fabric->oper_type);
644
645         __port_action[port->fabric->fab_type].offline(port);
646
647         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
648         if (bfa_sm_cmp_state(port->fabric,
649                         bfa_fcs_fabric_sm_online) == BFA_TRUE) {
650                 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
651                 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
652                 lpwwn_buf, "Initiator");
653                 bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DISCONNECT);
654         } else {
655                 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
656                 "Logical port taken offline: WWN = %s Role = %s\n",
657                 lpwwn_buf, "Initiator");
658                 bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_OFFLINE);
659         }
660
661         list_for_each_safe(qe, qen, &port->rport_q) {
662                 rport = (struct bfa_fcs_rport_s *) qe;
663                 bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
664         }
665 }
666
667 static void
668 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
669 {
670         WARN_ON(1);
671 }
672
673 static void
674 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
675 {
676         WARN_ON(1);
677 }
678
679 static void
680 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
681 {
682         WARN_ON(1);
683 }
684
685 static void
686 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
687 {
688         struct fchs_s fchs;
689         struct bfa_fcxp_s *fcxp;
690         int             len;
691
692         bfa_trc(port->fcs, rx_fchs->d_id);
693         bfa_trc(port->fcs, rx_fchs->s_id);
694
695         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
696         if (!fcxp)
697                 return;
698
699         len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
700                         rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
701                         rx_fchs->ox_id, 0);
702
703         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
704                           BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
705                           FC_MAX_PDUSZ, 0);
706 }
707 static void
708 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
709 {
710         struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
711         char    lpwwn_buf[BFA_STRING_32];
712
713         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
714         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
715                 "Logical port deleted: WWN = %s Role = %s\n",
716                 lpwwn_buf, "Initiator");
717         bfa_fcs_lport_aen_post(port, BFA_LPORT_AEN_DELETE);
718
719         /* Base port will be deleted by the OS driver */
720         if (port->vport)
721                 bfa_fcs_vport_delete_comp(port->vport);
722         else
723                 bfa_wc_down(&port->fabric->wc);
724 }
725
726
727 /*
728  * Unsolicited frame receive handling.
729  */
730 void
731 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
732                         struct fchs_s *fchs, u16 len)
733 {
734         u32     pid = fchs->s_id;
735         struct bfa_fcs_rport_s *rport = NULL;
736         struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
737
738         bfa_stats(lport, uf_recvs);
739         bfa_trc(lport->fcs, fchs->type);
740
741         if (!bfa_fcs_lport_is_online(lport)) {
742                 bfa_stats(lport, uf_recv_drops);
743                 return;
744         }
745
746         /*
747          * First, handle ELSs that donot require a login.
748          */
749         /*
750          * Handle PLOGI first
751          */
752         if ((fchs->type == FC_TYPE_ELS) &&
753                 (els_cmd->els_code == FC_ELS_PLOGI)) {
754                 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
755                 return;
756         }
757
758         /*
759          * Handle ECHO separately.
760          */
761         if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
762                 bfa_fcs_lport_echo(lport, fchs,
763                                 (struct fc_echo_s *)els_cmd, len);
764                 return;
765         }
766
767         /*
768          * Handle RNID separately.
769          */
770         if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
771                 bfa_fcs_lport_rnid(lport, fchs,
772                         (struct fc_rnid_cmd_s *) els_cmd, len);
773                 return;
774         }
775
776         if (fchs->type == FC_TYPE_BLS) {
777                 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
778                                 (fchs->cat_info == FC_CAT_ABTS))
779                         bfa_fcs_lport_abts_acc(lport, fchs);
780                 return;
781         }
782
783         if (fchs->type == FC_TYPE_SERVICES) {
784                 /*
785                  * Unhandled FC-GS frames. Send a FC-CT Reject
786                  */
787                 bfa_fcs_lport_send_fcgs_rjt(lport, fchs, CT_RSN_NOT_SUPP,
788                                 CT_NS_EXP_NOADDITIONAL);
789                 return;
790         }
791
792         /*
793          * look for a matching remote port ID
794          */
795         rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
796         if (rport) {
797                 bfa_trc(rport->fcs, fchs->s_id);
798                 bfa_trc(rport->fcs, fchs->d_id);
799                 bfa_trc(rport->fcs, fchs->type);
800
801                 bfa_fcs_rport_uf_recv(rport, fchs, len);
802                 return;
803         }
804
805         /*
806          * Only handles ELS frames for now.
807          */
808         if (fchs->type != FC_TYPE_ELS) {
809                 bfa_trc(lport->fcs, fchs->s_id);
810                 bfa_trc(lport->fcs, fchs->d_id);
811                 /* ignore type FC_TYPE_FC_FSS */
812                 if (fchs->type != FC_TYPE_FC_FSS)
813                         bfa_sm_fault(lport->fcs, fchs->type);
814                 return;
815         }
816
817         bfa_trc(lport->fcs, els_cmd->els_code);
818         if (els_cmd->els_code == FC_ELS_RSCN) {
819                 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
820                 return;
821         }
822
823         if (els_cmd->els_code == FC_ELS_LOGO) {
824                 /*
825                  * @todo Handle LOGO frames received.
826                  */
827                 return;
828         }
829
830         if (els_cmd->els_code == FC_ELS_PRLI) {
831                 /*
832                  * @todo Handle PRLI frames received.
833                  */
834                 return;
835         }
836
837         /*
838          * Unhandled ELS frames. Send a LS_RJT.
839          */
840         bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
841                                  FC_LS_RJT_EXP_NO_ADDL_INFO);
842
843 }
844
845 /*
846  *   PID based Lookup for a R-Port in the Port R-Port Queue
847  */
848 struct bfa_fcs_rport_s *
849 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
850 {
851         struct bfa_fcs_rport_s *rport;
852         struct list_head        *qe;
853
854         list_for_each(qe, &port->rport_q) {
855                 rport = (struct bfa_fcs_rport_s *) qe;
856                 if (rport->pid == pid)
857                         return rport;
858         }
859
860         bfa_trc(port->fcs, pid);
861         return NULL;
862 }
863
864 /*
865  * OLD_PID based Lookup for a R-Port in the Port R-Port Queue
866  */
867 struct bfa_fcs_rport_s *
868 bfa_fcs_lport_get_rport_by_old_pid(struct bfa_fcs_lport_s *port, u32 pid)
869 {
870         struct bfa_fcs_rport_s *rport;
871         struct list_head        *qe;
872
873         list_for_each(qe, &port->rport_q) {
874                 rport = (struct bfa_fcs_rport_s *) qe;
875                 if (rport->old_pid == pid)
876                         return rport;
877         }
878
879         bfa_trc(port->fcs, pid);
880         return NULL;
881 }
882
883 /*
884  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
885  */
886 struct bfa_fcs_rport_s *
887 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
888 {
889         struct bfa_fcs_rport_s *rport;
890         struct list_head        *qe;
891
892         list_for_each(qe, &port->rport_q) {
893                 rport = (struct bfa_fcs_rport_s *) qe;
894                 if (wwn_is_equal(rport->pwwn, pwwn))
895                         return rport;
896         }
897
898         bfa_trc(port->fcs, pwwn);
899         return NULL;
900 }
901
902 /*
903  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
904  */
905 struct bfa_fcs_rport_s *
906 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
907 {
908         struct bfa_fcs_rport_s *rport;
909         struct list_head        *qe;
910
911         list_for_each(qe, &port->rport_q) {
912                 rport = (struct bfa_fcs_rport_s *) qe;
913                 if (wwn_is_equal(rport->nwwn, nwwn))
914                         return rport;
915         }
916
917         bfa_trc(port->fcs, nwwn);
918         return NULL;
919 }
920
921 /*
922  * PWWN & PID based Lookup for a R-Port in the Port R-Port Queue
923  */
924 struct bfa_fcs_rport_s *
925 bfa_fcs_lport_get_rport_by_qualifier(struct bfa_fcs_lport_s *port,
926                                      wwn_t pwwn, u32 pid)
927 {
928         struct bfa_fcs_rport_s *rport;
929         struct list_head        *qe;
930
931         list_for_each(qe, &port->rport_q) {
932                 rport = (struct bfa_fcs_rport_s *) qe;
933                 if (wwn_is_equal(rport->pwwn, pwwn) && rport->pid == pid)
934                         return rport;
935         }
936
937         bfa_trc(port->fcs, pwwn);
938         return NULL;
939 }
940
941 /*
942  * Called by rport module when new rports are discovered.
943  */
944 void
945 bfa_fcs_lport_add_rport(
946         struct bfa_fcs_lport_s *port,
947         struct bfa_fcs_rport_s *rport)
948 {
949         list_add_tail(&rport->qe, &port->rport_q);
950         port->num_rports++;
951 }
952
953 /*
954  * Called by rport module to when rports are deleted.
955  */
956 void
957 bfa_fcs_lport_del_rport(
958         struct bfa_fcs_lport_s *port,
959         struct bfa_fcs_rport_s *rport)
960 {
961         WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
962         list_del(&rport->qe);
963         port->num_rports--;
964
965         bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
966 }
967
968 /*
969  * Called by fabric for base port when fabric login is complete.
970  * Called by vport for virtual ports when FDISC is complete.
971  */
972 void
973 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
974 {
975         bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
976 }
977
978 /*
979  * Called by fabric for base port when fabric goes offline.
980  * Called by vport for virtual ports when virtual port becomes offline.
981  */
982 void
983 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
984 {
985         bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
986 }
987
988 /*
989  * Called by fabric for base port and by vport for virtual ports
990  * when target mode driver is unloaded.
991  */
992 void
993 bfa_fcs_lport_stop(struct bfa_fcs_lport_s *port)
994 {
995         bfa_sm_send_event(port, BFA_FCS_PORT_SM_STOP);
996 }
997
998 /*
999  * Called by fabric to delete base lport and associated resources.
1000  *
1001  * Called by vport to delete lport and associated resources. Should call
1002  * bfa_fcs_vport_delete_comp() for vports on completion.
1003  */
1004 void
1005 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
1006 {
1007         bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
1008 }
1009
1010 /*
1011  * Return TRUE if port is online, else return FALSE
1012  */
1013 bfa_boolean_t
1014 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
1015 {
1016         return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
1017 }
1018
1019 /*
1020   * Attach time initialization of logical ports.
1021  */
1022 void
1023 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
1024                    u16 vf_id, struct bfa_fcs_vport_s *vport)
1025 {
1026         lport->fcs = fcs;
1027         lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
1028         lport->vport = vport;
1029         lport->lp_tag = (vport) ? vport->lps->bfa_tag :
1030                                   lport->fabric->lps->bfa_tag;
1031
1032         INIT_LIST_HEAD(&lport->rport_q);
1033         lport->num_rports = 0;
1034 }
1035
1036 /*
1037  * Logical port initialization of base or virtual port.
1038  * Called by fabric for base port or by vport for virtual ports.
1039  */
1040
1041 void
1042 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
1043         struct bfa_lport_cfg_s *port_cfg)
1044 {
1045         struct bfa_fcs_vport_s *vport = lport->vport;
1046         struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
1047         char    lpwwn_buf[BFA_STRING_32];
1048
1049         lport->port_cfg = *port_cfg;
1050
1051         lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
1052                                         lport->port_cfg.roles,
1053                                         lport->fabric->vf_drv,
1054                                         vport ? vport->vport_drv : NULL);
1055
1056         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
1057         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
1058                 "New logical port created: WWN = %s Role = %s\n",
1059                 lpwwn_buf, "Initiator");
1060         bfa_fcs_lport_aen_post(lport, BFA_LPORT_AEN_NEW);
1061
1062         bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
1063         bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
1064 }
1065
1066 /*
1067  *  fcs_lport_api
1068  */
1069
1070 void
1071 bfa_fcs_lport_get_attr(
1072         struct bfa_fcs_lport_s *port,
1073         struct bfa_lport_attr_s *port_attr)
1074 {
1075         if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
1076                 port_attr->pid = port->pid;
1077         else
1078                 port_attr->pid = 0;
1079
1080         port_attr->port_cfg = port->port_cfg;
1081
1082         if (port->fabric) {
1083                 port_attr->port_type = port->fabric->oper_type;
1084                 port_attr->loopback = bfa_sm_cmp_state(port->fabric,
1085                                 bfa_fcs_fabric_sm_loopback);
1086                 port_attr->authfail =
1087                         bfa_sm_cmp_state(port->fabric,
1088                                 bfa_fcs_fabric_sm_auth_failed);
1089                 port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
1090                 memcpy(port_attr->fabric_ip_addr,
1091                         bfa_fcs_lport_get_fabric_ipaddr(port),
1092                         BFA_FCS_FABRIC_IPADDR_SZ);
1093
1094                 if (port->vport != NULL) {
1095                         port_attr->port_type = BFA_PORT_TYPE_VPORT;
1096                         port_attr->fpma_mac =
1097                                 port->vport->lps->lp_mac;
1098                 } else {
1099                         port_attr->fpma_mac =
1100                                 port->fabric->lps->lp_mac;
1101                 }
1102         } else {
1103                 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
1104                 port_attr->state = BFA_LPORT_UNINIT;
1105         }
1106 }
1107
1108 /*
1109  *  bfa_fcs_lport_fab port fab functions
1110  */
1111
1112 /*
1113  *   Called by port to initialize fabric services of the base port.
1114  */
1115 static void
1116 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
1117 {
1118         bfa_fcs_lport_ns_init(port);
1119         bfa_fcs_lport_scn_init(port);
1120         bfa_fcs_lport_ms_init(port);
1121 }
1122
1123 /*
1124  *   Called by port to notify transition to online state.
1125  */
1126 static void
1127 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
1128 {
1129         bfa_fcs_lport_ns_online(port);
1130         bfa_fcs_lport_scn_online(port);
1131 }
1132
1133 /*
1134  *   Called by port to notify transition to offline state.
1135  */
1136 static void
1137 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
1138 {
1139         bfa_fcs_lport_ns_offline(port);
1140         bfa_fcs_lport_scn_offline(port);
1141         bfa_fcs_lport_ms_offline(port);
1142 }
1143
1144 /*
1145  *  bfa_fcs_lport_n2n  functions
1146  */
1147
1148 /*
1149  *   Called by fcs/port to initialize N2N topology.
1150  */
1151 static void
1152 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
1153 {
1154 }
1155
1156 /*
1157  *   Called by fcs/port to notify transition to online state.
1158  */
1159 static void
1160 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
1161 {
1162         struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1163         struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
1164         struct bfa_fcs_rport_s *rport;
1165
1166         bfa_trc(port->fcs, pcfg->pwwn);
1167
1168         /*
1169          * If our PWWN is > than that of the r-port, we have to initiate PLOGI
1170          * and assign an Address. if not, we need to wait for its PLOGI.
1171          *
1172          * If our PWWN is < than that of the remote port, it will send a PLOGI
1173          * with the PIDs assigned. The rport state machine take care of this
1174          * incoming PLOGI.
1175          */
1176         if (memcmp
1177             ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1178              sizeof(wwn_t)) > 0) {
1179                 port->pid = N2N_LOCAL_PID;
1180                 bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
1181                 /*
1182                  * First, check if we know the device by pwwn.
1183                  */
1184                 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
1185                                                         n2n_port->rem_port_wwn);
1186                 if (rport) {
1187                         bfa_trc(port->fcs, rport->pid);
1188                         bfa_trc(port->fcs, rport->pwwn);
1189                         rport->pid = N2N_REMOTE_PID;
1190                         bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
1191                         return;
1192                 }
1193
1194                 /*
1195                  * In n2n there can be only one rport. Delete the old one
1196                  * whose pid should be zero, because it is offline.
1197                  */
1198                 if (port->num_rports > 0) {
1199                         rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1200                         WARN_ON(rport == NULL);
1201                         if (rport) {
1202                                 bfa_trc(port->fcs, rport->pwwn);
1203                                 bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1204                         }
1205                 }
1206                 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1207         }
1208 }
1209
1210 /*
1211  *   Called by fcs/port to notify transition to offline state.
1212  */
1213 static void
1214 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1215 {
1216         struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1217
1218         bfa_trc(port->fcs, port->pid);
1219         port->pid = 0;
1220         n2n_port->rem_port_wwn = 0;
1221         n2n_port->reply_oxid = 0;
1222 }
1223
1224 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1225
1226 /*
1227  * forward declarations
1228  */
1229 static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1230                                             struct bfa_fcxp_s *fcxp_alloced);
1231 static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1232                                             struct bfa_fcxp_s *fcxp_alloced);
1233 static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1234                                            struct bfa_fcxp_s *fcxp_alloced);
1235 static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1236                                                 struct bfa_fcxp_s *fcxp,
1237                                                 void *cbarg,
1238                                                 bfa_status_t req_status,
1239                                                 u32 rsp_len,
1240                                                 u32 resid_len,
1241                                                 struct fchs_s *rsp_fchs);
1242 static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1243                                                 struct bfa_fcxp_s *fcxp,
1244                                                 void *cbarg,
1245                                                 bfa_status_t req_status,
1246                                                 u32 rsp_len,
1247                                                 u32 resid_len,
1248                                                 struct fchs_s *rsp_fchs);
1249 static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1250                                                struct bfa_fcxp_s *fcxp,
1251                                                void *cbarg,
1252                                                bfa_status_t req_status,
1253                                                u32 rsp_len,
1254                                                u32 resid_len,
1255                                                struct fchs_s *rsp_fchs);
1256 static void     bfa_fcs_lport_fdmi_timeout(void *arg);
1257 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1258                                                   u8 *pyld);
1259 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1260                                                   u8 *pyld);
1261 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1262                                                  u8 *pyld);
1263 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1264                                                        fdmi, u8 *pyld);
1265 static void     bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1266                                  struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1267 static void     bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1268                                   struct bfa_fcs_fdmi_port_attr_s *port_attr);
1269 u32     bfa_fcs_fdmi_convert_speed(enum bfa_port_speed pport_speed);
1270
1271 /*
1272  *  fcs_fdmi_sm FCS FDMI state machine
1273  */
1274
1275 /*
1276  *  FDMI State Machine events
1277  */
1278 enum port_fdmi_event {
1279         FDMISM_EVENT_PORT_ONLINE = 1,
1280         FDMISM_EVENT_PORT_OFFLINE = 2,
1281         FDMISM_EVENT_RSP_OK = 4,
1282         FDMISM_EVENT_RSP_ERROR = 5,
1283         FDMISM_EVENT_TIMEOUT = 6,
1284         FDMISM_EVENT_RHBA_SENT = 7,
1285         FDMISM_EVENT_RPRT_SENT = 8,
1286         FDMISM_EVENT_RPA_SENT = 9,
1287 };
1288
1289 static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1290                                              enum port_fdmi_event event);
1291 static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
1292                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1293                                 enum port_fdmi_event event);
1294 static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1295                                           enum port_fdmi_event event);
1296 static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
1297                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1298                                 enum port_fdmi_event event);
1299 static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
1300                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1301                                 enum port_fdmi_event event);
1302 static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1303                                           enum port_fdmi_event event);
1304 static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
1305                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1306                                 enum port_fdmi_event event);
1307 static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
1308                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1309                                 enum port_fdmi_event event);
1310 static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1311                                          enum port_fdmi_event event);
1312 static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
1313                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1314                                 enum port_fdmi_event event);
1315 static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1316                                             enum port_fdmi_event event);
1317 static void     bfa_fcs_lport_fdmi_sm_disabled(
1318                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1319                                 enum port_fdmi_event event);
1320 /*
1321  *      Start in offline state - awaiting MS to send start.
1322  */
1323 static void
1324 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1325                              enum port_fdmi_event event)
1326 {
1327         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1328
1329         bfa_trc(port->fcs, port->port_cfg.pwwn);
1330         bfa_trc(port->fcs, event);
1331
1332         fdmi->retry_cnt = 0;
1333
1334         switch (event) {
1335         case FDMISM_EVENT_PORT_ONLINE:
1336                 if (port->vport) {
1337                         /*
1338                          * For Vports, register a new port.
1339                          */
1340                         bfa_sm_set_state(fdmi,
1341                                          bfa_fcs_lport_fdmi_sm_sending_rprt);
1342                         bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1343                 } else {
1344                         /*
1345                          * For a base port, we should first register the HBA
1346                          * attribute. The HBA attribute also contains the base
1347                          *  port registration.
1348                          */
1349                         bfa_sm_set_state(fdmi,
1350                                          bfa_fcs_lport_fdmi_sm_sending_rhba);
1351                         bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1352                 }
1353                 break;
1354
1355         case FDMISM_EVENT_PORT_OFFLINE:
1356                 break;
1357
1358         default:
1359                 bfa_sm_fault(port->fcs, event);
1360         }
1361 }
1362
1363 static void
1364 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1365                                   enum port_fdmi_event event)
1366 {
1367         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1368
1369         bfa_trc(port->fcs, port->port_cfg.pwwn);
1370         bfa_trc(port->fcs, event);
1371
1372         switch (event) {
1373         case FDMISM_EVENT_RHBA_SENT:
1374                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1375                 break;
1376
1377         case FDMISM_EVENT_PORT_OFFLINE:
1378                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1379                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1380                                            &fdmi->fcxp_wqe);
1381                 break;
1382
1383         default:
1384                 bfa_sm_fault(port->fcs, event);
1385         }
1386 }
1387
1388 static void
1389 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1390                         enum port_fdmi_event event)
1391 {
1392         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1393
1394         bfa_trc(port->fcs, port->port_cfg.pwwn);
1395         bfa_trc(port->fcs, event);
1396
1397         switch (event) {
1398         case FDMISM_EVENT_RSP_ERROR:
1399                 /*
1400                  * if max retries have not been reached, start timer for a
1401                  * delayed retry
1402                  */
1403                 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1404                         bfa_sm_set_state(fdmi,
1405                                         bfa_fcs_lport_fdmi_sm_rhba_retry);
1406                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1407                                             &fdmi->timer,
1408                                             bfa_fcs_lport_fdmi_timeout, fdmi,
1409                                             BFA_FCS_RETRY_TIMEOUT);
1410                 } else {
1411                         /*
1412                          * set state to offline
1413                          */
1414                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1415                 }
1416                 break;
1417
1418         case FDMISM_EVENT_RSP_OK:
1419                 /*
1420                  * Initiate Register Port Attributes
1421                  */
1422                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1423                 fdmi->retry_cnt = 0;
1424                 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1425                 break;
1426
1427         case FDMISM_EVENT_PORT_OFFLINE:
1428                 bfa_fcxp_discard(fdmi->fcxp);
1429                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1430                 break;
1431
1432         default:
1433                 bfa_sm_fault(port->fcs, event);
1434         }
1435 }
1436
1437 static void
1438 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1439                                 enum port_fdmi_event event)
1440 {
1441         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1442
1443         bfa_trc(port->fcs, port->port_cfg.pwwn);
1444         bfa_trc(port->fcs, event);
1445
1446         switch (event) {
1447         case FDMISM_EVENT_TIMEOUT:
1448                 /*
1449                  * Retry Timer Expired. Re-send
1450                  */
1451                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1452                 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1453                 break;
1454
1455         case FDMISM_EVENT_PORT_OFFLINE:
1456                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1457                 bfa_timer_stop(&fdmi->timer);
1458                 break;
1459
1460         default:
1461                 bfa_sm_fault(port->fcs, event);
1462         }
1463 }
1464
1465 /*
1466 * RPRT : Register Port
1467  */
1468 static void
1469 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1470                                   enum port_fdmi_event event)
1471 {
1472         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1473
1474         bfa_trc(port->fcs, port->port_cfg.pwwn);
1475         bfa_trc(port->fcs, event);
1476
1477         switch (event) {
1478         case FDMISM_EVENT_RPRT_SENT:
1479                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1480                 break;
1481
1482         case FDMISM_EVENT_PORT_OFFLINE:
1483                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1484                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1485                                            &fdmi->fcxp_wqe);
1486                 break;
1487
1488         default:
1489                 bfa_sm_fault(port->fcs, event);
1490         }
1491 }
1492
1493 static void
1494 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1495                         enum port_fdmi_event event)
1496 {
1497         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1498
1499         bfa_trc(port->fcs, port->port_cfg.pwwn);
1500         bfa_trc(port->fcs, event);
1501
1502         switch (event) {
1503         case FDMISM_EVENT_RSP_ERROR:
1504                 /*
1505                  * if max retries have not been reached, start timer for a
1506                  * delayed retry
1507                  */
1508                 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1509                         bfa_sm_set_state(fdmi,
1510                                         bfa_fcs_lport_fdmi_sm_rprt_retry);
1511                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1512                                             &fdmi->timer,
1513                                             bfa_fcs_lport_fdmi_timeout, fdmi,
1514                                             BFA_FCS_RETRY_TIMEOUT);
1515
1516                 } else {
1517                         /*
1518                          * set state to offline
1519                          */
1520                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1521                         fdmi->retry_cnt = 0;
1522                 }
1523                 break;
1524
1525         case FDMISM_EVENT_RSP_OK:
1526                 fdmi->retry_cnt = 0;
1527                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1528                 break;
1529
1530         case FDMISM_EVENT_PORT_OFFLINE:
1531                 bfa_fcxp_discard(fdmi->fcxp);
1532                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1533                 break;
1534
1535         default:
1536                 bfa_sm_fault(port->fcs, event);
1537         }
1538 }
1539
1540 static void
1541 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1542                                 enum port_fdmi_event event)
1543 {
1544         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1545
1546         bfa_trc(port->fcs, port->port_cfg.pwwn);
1547         bfa_trc(port->fcs, event);
1548
1549         switch (event) {
1550         case FDMISM_EVENT_TIMEOUT:
1551                 /*
1552                  * Retry Timer Expired. Re-send
1553                  */
1554                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1555                 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1556                 break;
1557
1558         case FDMISM_EVENT_PORT_OFFLINE:
1559                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1560                 bfa_timer_stop(&fdmi->timer);
1561                 break;
1562
1563         default:
1564                 bfa_sm_fault(port->fcs, event);
1565         }
1566 }
1567
1568 /*
1569  * Register Port Attributes
1570  */
1571 static void
1572 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1573                                  enum port_fdmi_event event)
1574 {
1575         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1576
1577         bfa_trc(port->fcs, port->port_cfg.pwwn);
1578         bfa_trc(port->fcs, event);
1579
1580         switch (event) {
1581         case FDMISM_EVENT_RPA_SENT:
1582                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1583                 break;
1584
1585         case FDMISM_EVENT_PORT_OFFLINE:
1586                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1587                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1588                                            &fdmi->fcxp_wqe);
1589                 break;
1590
1591         default:
1592                 bfa_sm_fault(port->fcs, event);
1593         }
1594 }
1595
1596 static void
1597 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1598                         enum port_fdmi_event event)
1599 {
1600         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1601
1602         bfa_trc(port->fcs, port->port_cfg.pwwn);
1603         bfa_trc(port->fcs, event);
1604
1605         switch (event) {
1606         case FDMISM_EVENT_RSP_ERROR:
1607                 /*
1608                  * if max retries have not been reached, start timer for a
1609                  * delayed retry
1610                  */
1611                 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1612                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1613                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1614                                             &fdmi->timer,
1615                                             bfa_fcs_lport_fdmi_timeout, fdmi,
1616                                             BFA_FCS_RETRY_TIMEOUT);
1617                 } else {
1618                         /*
1619                          * set state to offline
1620                          */
1621                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1622                         fdmi->retry_cnt = 0;
1623                 }
1624                 break;
1625
1626         case FDMISM_EVENT_RSP_OK:
1627                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1628                 fdmi->retry_cnt = 0;
1629                 break;
1630
1631         case FDMISM_EVENT_PORT_OFFLINE:
1632                 bfa_fcxp_discard(fdmi->fcxp);
1633                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1634                 break;
1635
1636         default:
1637                 bfa_sm_fault(port->fcs, event);
1638         }
1639 }
1640
1641 static void
1642 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1643                                enum port_fdmi_event event)
1644 {
1645         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1646
1647         bfa_trc(port->fcs, port->port_cfg.pwwn);
1648         bfa_trc(port->fcs, event);
1649
1650         switch (event) {
1651         case FDMISM_EVENT_TIMEOUT:
1652                 /*
1653                  * Retry Timer Expired. Re-send
1654                  */
1655                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1656                 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1657                 break;
1658
1659         case FDMISM_EVENT_PORT_OFFLINE:
1660                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1661                 bfa_timer_stop(&fdmi->timer);
1662                 break;
1663
1664         default:
1665                 bfa_sm_fault(port->fcs, event);
1666         }
1667 }
1668
1669 static void
1670 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1671                                 enum port_fdmi_event event)
1672 {
1673         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1674
1675         bfa_trc(port->fcs, port->port_cfg.pwwn);
1676         bfa_trc(port->fcs, event);
1677
1678         switch (event) {
1679         case FDMISM_EVENT_PORT_OFFLINE:
1680                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1681                 break;
1682
1683         default:
1684                 bfa_sm_fault(port->fcs, event);
1685         }
1686 }
1687 /*
1688  *  FDMI is disabled state.
1689  */
1690 static void
1691 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1692                              enum port_fdmi_event event)
1693 {
1694         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1695
1696         bfa_trc(port->fcs, port->port_cfg.pwwn);
1697         bfa_trc(port->fcs, event);
1698
1699         /* No op State. It can only be enabled at Driver Init. */
1700 }
1701
1702 /*
1703 *  RHBA : Register HBA Attributes.
1704  */
1705 static void
1706 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1707 {
1708         struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1709         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1710         struct fchs_s fchs;
1711         int             len, attr_len;
1712         struct bfa_fcxp_s *fcxp;
1713         u8        *pyld;
1714
1715         bfa_trc(port->fcs, port->port_cfg.pwwn);
1716
1717         fcxp = fcxp_alloced ? fcxp_alloced :
1718                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1719         if (!fcxp) {
1720                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1721                                 bfa_fcs_lport_fdmi_send_rhba, fdmi, BFA_TRUE);
1722                 return;
1723         }
1724         fdmi->fcxp = fcxp;
1725
1726         pyld = bfa_fcxp_get_reqbuf(fcxp);
1727         memset(pyld, 0, FC_MAX_PDUSZ);
1728
1729         len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1730                                    FDMI_RHBA);
1731
1732         attr_len =
1733                 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1734                                           (u8 *) ((struct ct_hdr_s *) pyld
1735                                                        + 1));
1736
1737         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1738                           FC_CLASS_3, (len + attr_len), &fchs,
1739                           bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1740                           FC_MAX_PDUSZ, FC_FCCT_TOV);
1741
1742         bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1743 }
1744
1745 static          u16
1746 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1747 {
1748         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1749         struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1750         struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1751         struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1752         struct fdmi_attr_s *attr;
1753         u8        *curr_ptr;
1754         u16        len, count;
1755         u16     templen;
1756
1757         /*
1758          * get hba attributes
1759          */
1760         bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1761
1762         rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1763         rhba->port_list.num_ports = cpu_to_be32(1);
1764         rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1765
1766         len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1767
1768         count = 0;
1769         len += sizeof(rhba->hba_attr_blk.attr_count);
1770
1771         /*
1772          * fill out the invididual entries of the HBA attrib Block
1773          */
1774         curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1775
1776         /*
1777          * Node Name
1778          */
1779         attr = (struct fdmi_attr_s *) curr_ptr;
1780         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1781         templen = sizeof(wwn_t);
1782         memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1783         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1784         len += templen;
1785         count++;
1786         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1787                              sizeof(templen));
1788
1789         /*
1790          * Manufacturer
1791          */
1792         attr = (struct fdmi_attr_s *) curr_ptr;
1793         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1794         templen = (u16) strlen(fcs_hba_attr->manufacturer);
1795         memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1796         templen = fc_roundup(templen, sizeof(u32));
1797         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1798         len += templen;
1799         count++;
1800         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1801                              sizeof(templen));
1802
1803         /*
1804          * Serial Number
1805          */
1806         attr = (struct fdmi_attr_s *) curr_ptr;
1807         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1808         templen = (u16) strlen(fcs_hba_attr->serial_num);
1809         memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1810         templen = fc_roundup(templen, sizeof(u32));
1811         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1812         len += templen;
1813         count++;
1814         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1815                              sizeof(templen));
1816
1817         /*
1818          * Model
1819          */
1820         attr = (struct fdmi_attr_s *) curr_ptr;
1821         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1822         templen = (u16) strlen(fcs_hba_attr->model);
1823         memcpy(attr->value, fcs_hba_attr->model, templen);
1824         templen = fc_roundup(templen, sizeof(u32));
1825         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1826         len += templen;
1827         count++;
1828         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1829                              sizeof(templen));
1830
1831         /*
1832          * Model Desc
1833          */
1834         attr = (struct fdmi_attr_s *) curr_ptr;
1835         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1836         templen = (u16) strlen(fcs_hba_attr->model_desc);
1837         memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1838         templen = fc_roundup(templen, sizeof(u32));
1839         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1840         len += templen;
1841         count++;
1842         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1843                              sizeof(templen));
1844
1845         /*
1846          * H/W Version
1847          */
1848         if (fcs_hba_attr->hw_version[0] != '\0') {
1849                 attr = (struct fdmi_attr_s *) curr_ptr;
1850                 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
1851                 templen = (u16) strlen(fcs_hba_attr->hw_version);
1852                 memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1853                 templen = fc_roundup(templen, sizeof(u32));
1854                 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1855                 len += templen;
1856                 count++;
1857                 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1858                                          sizeof(templen));
1859         }
1860
1861         /*
1862          * Driver Version
1863          */
1864         attr = (struct fdmi_attr_s *) curr_ptr;
1865         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1866         templen = (u16) strlen(fcs_hba_attr->driver_version);
1867         memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1868         templen = fc_roundup(templen, sizeof(u32));
1869         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1870         len += templen;
1871         count++;
1872         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1873                              sizeof(templen));
1874
1875         /*
1876          * Option Rom Version
1877          */
1878         if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1879                 attr = (struct fdmi_attr_s *) curr_ptr;
1880                 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
1881                 templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1882                 memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1883                 templen = fc_roundup(templen, sizeof(u32));
1884                 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1885                 len += templen;
1886                 count++;
1887                 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1888                                          sizeof(templen));
1889         }
1890
1891         /*
1892          * f/w Version = driver version
1893          */
1894         attr = (struct fdmi_attr_s *) curr_ptr;
1895         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
1896         templen = (u16) strlen(fcs_hba_attr->driver_version);
1897         memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1898         templen = fc_roundup(templen, sizeof(u32));
1899         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1900         len += templen;
1901         count++;
1902         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1903                              sizeof(templen));
1904
1905         /*
1906          * OS Name
1907          */
1908         if (fcs_hba_attr->os_name[0] != '\0') {
1909                 attr = (struct fdmi_attr_s *) curr_ptr;
1910                 attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
1911                 templen = (u16) strlen(fcs_hba_attr->os_name);
1912                 memcpy(attr->value, fcs_hba_attr->os_name, templen);
1913                 templen = fc_roundup(templen, sizeof(u32));
1914                 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1915                 len += templen;
1916                 count++;
1917                 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1918                                         sizeof(templen));
1919         }
1920
1921         /*
1922          * MAX_CT_PAYLOAD
1923          */
1924         attr = (struct fdmi_attr_s *) curr_ptr;
1925         attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
1926         templen = sizeof(fcs_hba_attr->max_ct_pyld);
1927         memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1928         len += templen;
1929         count++;
1930         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1931                              sizeof(templen));
1932
1933         /*
1934          * Update size of payload
1935          */
1936         len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1937
1938         rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1939         return len;
1940 }
1941
1942 static void
1943 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1944                                 void *cbarg, bfa_status_t req_status,
1945                                 u32 rsp_len, u32 resid_len,
1946                                 struct fchs_s *rsp_fchs)
1947 {
1948         struct bfa_fcs_lport_fdmi_s *fdmi =
1949                                 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1950         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1951         struct ct_hdr_s *cthdr = NULL;
1952
1953         bfa_trc(port->fcs, port->port_cfg.pwwn);
1954
1955         /*
1956          * Sanity Checks
1957          */
1958         if (req_status != BFA_STATUS_OK) {
1959                 bfa_trc(port->fcs, req_status);
1960                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1961                 return;
1962         }
1963
1964         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1965         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1966
1967         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1968                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1969                 return;
1970         }
1971
1972         bfa_trc(port->fcs, cthdr->reason_code);
1973         bfa_trc(port->fcs, cthdr->exp_code);
1974         bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1975 }
1976
1977 /*
1978 *  RPRT : Register Port
1979  */
1980 static void
1981 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1982 {
1983         struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1984         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1985         struct fchs_s fchs;
1986         u16        len, attr_len;
1987         struct bfa_fcxp_s *fcxp;
1988         u8        *pyld;
1989
1990         bfa_trc(port->fcs, port->port_cfg.pwwn);
1991
1992         fcxp = fcxp_alloced ? fcxp_alloced :
1993                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
1994         if (!fcxp) {
1995                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1996                                 bfa_fcs_lport_fdmi_send_rprt, fdmi, BFA_TRUE);
1997                 return;
1998         }
1999         fdmi->fcxp = fcxp;
2000
2001         pyld = bfa_fcxp_get_reqbuf(fcxp);
2002         memset(pyld, 0, FC_MAX_PDUSZ);
2003
2004         len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2005                                    FDMI_RPRT);
2006
2007         attr_len =
2008                 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
2009                                           (u8 *) ((struct ct_hdr_s *) pyld
2010                                                        + 1));
2011
2012         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2013                           FC_CLASS_3, len + attr_len, &fchs,
2014                           bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
2015                           FC_MAX_PDUSZ, FC_FCCT_TOV);
2016
2017         bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
2018 }
2019
2020 /*
2021  * This routine builds Port Attribute Block that used in RPA, RPRT commands.
2022  */
2023 static          u16
2024 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
2025                                        u8 *pyld)
2026 {
2027         struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
2028         struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
2029         struct fdmi_attr_s *attr;
2030         u8        *curr_ptr;
2031         u16        len;
2032         u8      count = 0;
2033         u16     templen;
2034
2035         /*
2036          * get port attributes
2037          */
2038         bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
2039
2040         len = sizeof(port_attrib->attr_count);
2041
2042         /*
2043          * fill out the invididual entries
2044          */
2045         curr_ptr = (u8 *) &port_attrib->port_attr;
2046
2047         /*
2048          * FC4 Types
2049          */
2050         attr = (struct fdmi_attr_s *) curr_ptr;
2051         attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
2052         templen = sizeof(fcs_port_attr.supp_fc4_types);
2053         memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
2054         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2055         len += templen;
2056         ++count;
2057         attr->len =
2058                 cpu_to_be16(templen + sizeof(attr->type) +
2059                              sizeof(templen));
2060
2061         /*
2062          * Supported Speed
2063          */
2064         attr = (struct fdmi_attr_s *) curr_ptr;
2065         attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
2066         templen = sizeof(fcs_port_attr.supp_speed);
2067         memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
2068         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2069         len += templen;
2070         ++count;
2071         attr->len =
2072                 cpu_to_be16(templen + sizeof(attr->type) +
2073                              sizeof(templen));
2074
2075         /*
2076          * current Port Speed
2077          */
2078         attr = (struct fdmi_attr_s *) curr_ptr;
2079         attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
2080         templen = sizeof(fcs_port_attr.curr_speed);
2081         memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
2082         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2083         len += templen;
2084         ++count;
2085         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2086                              sizeof(templen));
2087
2088         /*
2089          * max frame size
2090          */
2091         attr = (struct fdmi_attr_s *) curr_ptr;
2092         attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
2093         templen = sizeof(fcs_port_attr.max_frm_size);
2094         memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
2095         curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2096         len += templen;
2097         ++count;
2098         attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2099                              sizeof(templen));
2100
2101         /*
2102          * OS Device Name
2103          */
2104         if (fcs_port_attr.os_device_name[0] != '\0') {
2105                 attr = (struct fdmi_attr_s *) curr_ptr;
2106                 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
2107                 templen = (u16) strlen(fcs_port_attr.os_device_name);
2108                 memcpy(attr->value, fcs_port_attr.os_device_name, templen);
2109                 templen = fc_roundup(templen, sizeof(u32));
2110                 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2111                 len += templen;
2112                 ++count;
2113                 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2114                                         sizeof(templen));
2115         }
2116         /*
2117          * Host Name
2118          */
2119         if (fcs_port_attr.host_name[0] != '\0') {
2120                 attr = (struct fdmi_attr_s *) curr_ptr;
2121                 attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
2122                 templen = (u16) strlen(fcs_port_attr.host_name);
2123                 memcpy(attr->value, fcs_port_attr.host_name, templen);
2124                 templen = fc_roundup(templen, sizeof(u32));
2125                 curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
2126                 len += templen;
2127                 ++count;
2128                 attr->len = cpu_to_be16(templen + sizeof(attr->type) +
2129                                 sizeof(templen));
2130         }
2131
2132         /*
2133          * Update size of payload
2134          */
2135         port_attrib->attr_count = cpu_to_be32(count);
2136         len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
2137         return len;
2138 }
2139
2140 static          u16
2141 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2142 {
2143         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2144         struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2145         u16        len;
2146
2147         rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2148         rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2149
2150         len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2151                                 (u8 *) &rprt->port_attr_blk);
2152
2153         len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2154
2155         return len;
2156 }
2157
2158 static void
2159 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2160                                 void *cbarg, bfa_status_t req_status,
2161                                 u32 rsp_len, u32 resid_len,
2162                                 struct fchs_s *rsp_fchs)
2163 {
2164         struct bfa_fcs_lport_fdmi_s *fdmi =
2165                         (struct bfa_fcs_lport_fdmi_s *) cbarg;
2166         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2167         struct ct_hdr_s *cthdr = NULL;
2168
2169         bfa_trc(port->fcs, port->port_cfg.pwwn);
2170
2171         /*
2172          * Sanity Checks
2173          */
2174         if (req_status != BFA_STATUS_OK) {
2175                 bfa_trc(port->fcs, req_status);
2176                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2177                 return;
2178         }
2179
2180         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2181         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2182
2183         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2184                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2185                 return;
2186         }
2187
2188         bfa_trc(port->fcs, cthdr->reason_code);
2189         bfa_trc(port->fcs, cthdr->exp_code);
2190         bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2191 }
2192
2193 /*
2194 *  RPA : Register Port Attributes.
2195  */
2196 static void
2197 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2198 {
2199         struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2200         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2201         struct fchs_s fchs;
2202         u16        len, attr_len;
2203         struct bfa_fcxp_s *fcxp;
2204         u8        *pyld;
2205
2206         bfa_trc(port->fcs, port->port_cfg.pwwn);
2207
2208         fcxp = fcxp_alloced ? fcxp_alloced :
2209                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2210         if (!fcxp) {
2211                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2212                                 bfa_fcs_lport_fdmi_send_rpa, fdmi, BFA_TRUE);
2213                 return;
2214         }
2215         fdmi->fcxp = fcxp;
2216
2217         pyld = bfa_fcxp_get_reqbuf(fcxp);
2218         memset(pyld, 0, FC_MAX_PDUSZ);
2219
2220         len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2221                                    FDMI_RPA);
2222
2223         attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2224                                 (u8 *) ((struct ct_hdr_s *) pyld + 1));
2225
2226         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2227                           FC_CLASS_3, len + attr_len, &fchs,
2228                           bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2229                           FC_MAX_PDUSZ, FC_FCCT_TOV);
2230
2231         bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2232 }
2233
2234 static          u16
2235 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2236 {
2237         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2238         struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2239         u16        len;
2240
2241         rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2242
2243         len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2244                                 (u8 *) &rpa->port_attr_blk);
2245
2246         len += sizeof(rpa->port_name);
2247
2248         return len;
2249 }
2250
2251 static void
2252 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2253                         void *cbarg, bfa_status_t req_status, u32 rsp_len,
2254                         u32 resid_len, struct fchs_s *rsp_fchs)
2255 {
2256         struct bfa_fcs_lport_fdmi_s *fdmi =
2257                                 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2258         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2259         struct ct_hdr_s *cthdr = NULL;
2260
2261         bfa_trc(port->fcs, port->port_cfg.pwwn);
2262
2263         /*
2264          * Sanity Checks
2265          */
2266         if (req_status != BFA_STATUS_OK) {
2267                 bfa_trc(port->fcs, req_status);
2268                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2269                 return;
2270         }
2271
2272         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2273         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2274
2275         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2276                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2277                 return;
2278         }
2279
2280         bfa_trc(port->fcs, cthdr->reason_code);
2281         bfa_trc(port->fcs, cthdr->exp_code);
2282         bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2283 }
2284
2285 static void
2286 bfa_fcs_lport_fdmi_timeout(void *arg)
2287 {
2288         struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2289
2290         bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2291 }
2292
2293 static void
2294 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2295                          struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2296 {
2297         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2298         struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2299
2300         memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2301
2302         bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2303                                         hba_attr->manufacturer);
2304         bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2305                                         hba_attr->serial_num);
2306         bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2307                                         hba_attr->model);
2308         bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2309                                         hba_attr->model_desc);
2310         bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2311                                         hba_attr->hw_version);
2312         bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2313                                         hba_attr->option_rom_ver);
2314         bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2315                                         hba_attr->fw_version);
2316
2317         strncpy(hba_attr->driver_version, (char *)driver_info->version,
2318                 sizeof(hba_attr->driver_version));
2319
2320         strncpy(hba_attr->os_name, driver_info->host_os_name,
2321                 sizeof(hba_attr->os_name));
2322
2323         /*
2324          * If there is a patch level, append it
2325          * to the os name along with a separator
2326          */
2327         if (driver_info->host_os_patch[0] != '\0') {
2328                 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2329                         sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2330                 strncat(hba_attr->os_name, driver_info->host_os_patch,
2331                                 sizeof(driver_info->host_os_patch));
2332         }
2333
2334         hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2335 }
2336
2337 static void
2338 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2339                           struct bfa_fcs_fdmi_port_attr_s *port_attr)
2340 {
2341         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2342         struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2343         struct bfa_port_attr_s pport_attr;
2344
2345         memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2346
2347         /*
2348          * get pport attributes from hal
2349          */
2350         bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2351
2352         /*
2353          * get FC4 type Bitmask
2354          */
2355         fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2356
2357         /*
2358          * Supported Speeds
2359          */
2360         switch (pport_attr.speed_supported) {
2361         case BFA_PORT_SPEED_16GBPS:
2362                 port_attr->supp_speed =
2363                         cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_16G);
2364                 break;
2365
2366         case BFA_PORT_SPEED_10GBPS:
2367                 port_attr->supp_speed =
2368                         cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_10G);
2369                 break;
2370
2371         case BFA_PORT_SPEED_8GBPS:
2372                 port_attr->supp_speed =
2373                         cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_8G);
2374                 break;
2375
2376         case BFA_PORT_SPEED_4GBPS:
2377                 port_attr->supp_speed =
2378                         cpu_to_be32(BFA_FCS_FDMI_SUPP_SPEEDS_4G);
2379                 break;
2380
2381         default:
2382                 bfa_sm_fault(port->fcs, pport_attr.speed_supported);
2383         }
2384
2385         /*
2386          * Current Speed
2387          */
2388         port_attr->curr_speed = cpu_to_be32(
2389                                 bfa_fcs_fdmi_convert_speed(pport_attr.speed));
2390
2391         /*
2392          * Max PDU Size.
2393          */
2394         port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2395
2396         /*
2397          * OS device Name
2398          */
2399         strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2400                 sizeof(port_attr->os_device_name));
2401
2402         /*
2403          * Host name
2404          */
2405         strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2406                 sizeof(port_attr->host_name));
2407
2408 }
2409
2410 /*
2411  * Convert BFA speed to FDMI format.
2412  */
2413 u32
2414 bfa_fcs_fdmi_convert_speed(bfa_port_speed_t pport_speed)
2415 {
2416         u32     ret;
2417
2418         switch (pport_speed) {
2419         case BFA_PORT_SPEED_1GBPS:
2420         case BFA_PORT_SPEED_2GBPS:
2421                 ret = pport_speed;
2422                 break;
2423
2424         case BFA_PORT_SPEED_4GBPS:
2425                 ret = FDMI_TRANS_SPEED_4G;
2426                 break;
2427
2428         case BFA_PORT_SPEED_8GBPS:
2429                 ret = FDMI_TRANS_SPEED_8G;
2430                 break;
2431
2432         case BFA_PORT_SPEED_10GBPS:
2433                 ret = FDMI_TRANS_SPEED_10G;
2434                 break;
2435
2436         case BFA_PORT_SPEED_16GBPS:
2437                 ret = FDMI_TRANS_SPEED_16G;
2438                 break;
2439
2440         default:
2441                 ret = FDMI_TRANS_SPEED_UNKNOWN;
2442         }
2443         return ret;
2444 }
2445
2446 void
2447 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2448 {
2449         struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2450
2451         fdmi->ms = ms;
2452         if (ms->port->fcs->fdmi_enabled)
2453                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2454         else
2455                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2456 }
2457
2458 void
2459 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2460 {
2461         struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2462
2463         fdmi->ms = ms;
2464         bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2465 }
2466
2467 void
2468 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2469 {
2470         struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2471
2472         fdmi->ms = ms;
2473         bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2474 }
2475
2476 #define BFA_FCS_MS_CMD_MAX_RETRIES  2
2477
2478 /*
2479  * forward declarations
2480  */
2481 static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2482                                            struct bfa_fcxp_s *fcxp_alloced);
2483 static void     bfa_fcs_lport_ms_timeout(void *arg);
2484 static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2485                                                struct bfa_fcxp_s *fcxp,
2486                                                void *cbarg,
2487                                                bfa_status_t req_status,
2488                                                u32 rsp_len,
2489                                                u32 resid_len,
2490                                                struct fchs_s *rsp_fchs);
2491
2492 static void     bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2493                                         struct bfa_fcxp_s *fcxp_alloced);
2494 static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2495                                                struct bfa_fcxp_s *fcxp,
2496                                                void *cbarg,
2497                                                bfa_status_t req_status,
2498                                                u32 rsp_len,
2499                                                u32 resid_len,
2500                                                struct fchs_s *rsp_fchs);
2501 static void     bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2502                                         struct bfa_fcxp_s *fcxp_alloced);
2503 static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2504                                                struct bfa_fcxp_s *fcxp,
2505                                                void *cbarg,
2506                                                bfa_status_t req_status,
2507                                                u32 rsp_len,
2508                                                u32 resid_len,
2509                                                struct fchs_s *rsp_fchs);
2510 /*
2511  *  fcs_ms_sm FCS MS state machine
2512  */
2513
2514 /*
2515  *  MS State Machine events
2516  */
2517 enum port_ms_event {
2518         MSSM_EVENT_PORT_ONLINE = 1,
2519         MSSM_EVENT_PORT_OFFLINE = 2,
2520         MSSM_EVENT_RSP_OK = 3,
2521         MSSM_EVENT_RSP_ERROR = 4,
2522         MSSM_EVENT_TIMEOUT = 5,
2523         MSSM_EVENT_FCXP_SENT = 6,
2524         MSSM_EVENT_PORT_FABRIC_RSCN = 7
2525 };
2526
2527 static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2528                                            enum port_ms_event event);
2529 static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2530                                                  enum port_ms_event event);
2531 static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2532                                          enum port_ms_event event);
2533 static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2534                                                enum port_ms_event event);
2535 static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2536                                                  enum port_ms_event event);
2537 static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2538                                          enum port_ms_event event);
2539 static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2540                                                enum port_ms_event event);
2541 static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2542                                                  enum port_ms_event event);
2543 static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2544                                          enum port_ms_event event);
2545 static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2546                                                enum port_ms_event event);
2547 static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2548                                           enum port_ms_event event);
2549 /*
2550  *      Start in offline state - awaiting NS to send start.
2551  */
2552 static void
2553 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2554                                 enum port_ms_event event)
2555 {
2556         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2557         bfa_trc(ms->port->fcs, event);
2558
2559         switch (event) {
2560         case MSSM_EVENT_PORT_ONLINE:
2561                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2562                 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2563                 break;
2564
2565         case MSSM_EVENT_PORT_OFFLINE:
2566                 break;
2567
2568         default:
2569                 bfa_sm_fault(ms->port->fcs, event);
2570         }
2571 }
2572
2573 static void
2574 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2575                                 enum port_ms_event event)
2576 {
2577         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2578         bfa_trc(ms->port->fcs, event);
2579
2580         switch (event) {
2581         case MSSM_EVENT_FCXP_SENT:
2582                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2583                 break;
2584
2585         case MSSM_EVENT_PORT_OFFLINE:
2586                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2587                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2588                                            &ms->fcxp_wqe);
2589                 break;
2590
2591         default:
2592                 bfa_sm_fault(ms->port->fcs, event);
2593         }
2594 }
2595
2596 static void
2597 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2598                         enum port_ms_event event)
2599 {
2600         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2601         bfa_trc(ms->port->fcs, event);
2602
2603         switch (event) {
2604         case MSSM_EVENT_RSP_ERROR:
2605                 /*
2606                  * Start timer for a delayed retry
2607                  */
2608                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2609                 ms->port->stats.ms_retries++;
2610                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2611                                     &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2612                                     BFA_FCS_RETRY_TIMEOUT);
2613                 break;
2614
2615         case MSSM_EVENT_RSP_OK:
2616                 /*
2617                  * since plogi is done, now invoke MS related sub-modules
2618                  */
2619                 bfa_fcs_lport_fdmi_online(ms);
2620
2621                 /*
2622                  * if this is a Vport, go to online state.
2623                  */
2624                 if (ms->port->vport) {
2625                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2626                         break;
2627                 }
2628
2629                 /*
2630                  * For a base port we need to get the
2631                  * switch's IP address.
2632                  */
2633                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2634                 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2635                 break;
2636
2637         case MSSM_EVENT_PORT_OFFLINE:
2638                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2639                 bfa_fcxp_discard(ms->fcxp);
2640                 break;
2641
2642         default:
2643                 bfa_sm_fault(ms->port->fcs, event);
2644         }
2645 }
2646
2647 static void
2648 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2649                         enum port_ms_event event)
2650 {
2651         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2652         bfa_trc(ms->port->fcs, event);
2653
2654         switch (event) {
2655         case MSSM_EVENT_TIMEOUT:
2656                 /*
2657                  * Retry Timer Expired. Re-send
2658                  */
2659                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2660                 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2661                 break;
2662
2663         case MSSM_EVENT_PORT_OFFLINE:
2664                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2665                 bfa_timer_stop(&ms->timer);
2666                 break;
2667
2668         default:
2669                 bfa_sm_fault(ms->port->fcs, event);
2670         }
2671 }
2672
2673 static void
2674 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2675                         enum port_ms_event event)
2676 {
2677         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2678         bfa_trc(ms->port->fcs, event);
2679
2680         switch (event) {
2681         case MSSM_EVENT_PORT_OFFLINE:
2682                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2683                 break;
2684
2685         case MSSM_EVENT_PORT_FABRIC_RSCN:
2686                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2687                 ms->retry_cnt = 0;
2688                 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2689                 break;
2690
2691         default:
2692                 bfa_sm_fault(ms->port->fcs, event);
2693         }
2694 }
2695
2696 static void
2697 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2698                                 enum port_ms_event event)
2699 {
2700         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2701         bfa_trc(ms->port->fcs, event);
2702
2703         switch (event) {
2704         case MSSM_EVENT_FCXP_SENT:
2705                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2706                 break;
2707
2708         case MSSM_EVENT_PORT_OFFLINE:
2709                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2710                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2711                                            &ms->fcxp_wqe);
2712                 break;
2713
2714         default:
2715                 bfa_sm_fault(ms->port->fcs, event);
2716         }
2717 }
2718
2719 static void
2720 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2721                                 enum port_ms_event event)
2722 {
2723         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2724         bfa_trc(ms->port->fcs, event);
2725
2726         switch (event) {
2727         case MSSM_EVENT_RSP_ERROR:
2728                 /*
2729                  * Start timer for a delayed retry
2730                  */
2731                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2732                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2733                         ms->port->stats.ms_retries++;
2734                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2735                                 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2736                                 BFA_FCS_RETRY_TIMEOUT);
2737                 } else {
2738                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2739                         bfa_fcs_lport_ms_send_gfn(ms, NULL);
2740                         ms->retry_cnt = 0;
2741                 }
2742                 break;
2743
2744         case MSSM_EVENT_RSP_OK:
2745                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2746                 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2747                 break;
2748
2749         case MSSM_EVENT_PORT_OFFLINE:
2750                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2751                 bfa_fcxp_discard(ms->fcxp);
2752                 break;
2753
2754         default:
2755                 bfa_sm_fault(ms->port->fcs, event);
2756         }
2757 }
2758
2759 static void
2760 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2761                                 enum port_ms_event event)
2762 {
2763         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2764         bfa_trc(ms->port->fcs, event);
2765
2766         switch (event) {
2767         case MSSM_EVENT_TIMEOUT:
2768                 /*
2769                  * Retry Timer Expired. Re-send
2770                  */
2771                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2772                 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2773                 break;
2774
2775         case MSSM_EVENT_PORT_OFFLINE:
2776                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2777                 bfa_timer_stop(&ms->timer);
2778                 break;
2779
2780         default:
2781                 bfa_sm_fault(ms->port->fcs, event);
2782         }
2783 }
2784 /*
2785  *  ms_pvt MS local functions
2786  */
2787
2788 static void
2789 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2790 {
2791         struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2792         bfa_fcs_lport_t *port = ms->port;
2793         struct fchs_s   fchs;
2794         int             len;
2795         struct bfa_fcxp_s *fcxp;
2796
2797         bfa_trc(port->fcs, port->pid);
2798
2799         fcxp = fcxp_alloced ? fcxp_alloced :
2800                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
2801         if (!fcxp) {
2802                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2803                                 bfa_fcs_lport_ms_send_gmal, ms, BFA_TRUE);
2804                 return;
2805         }
2806         ms->fcxp = fcxp;
2807
2808         len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2809                              bfa_fcs_lport_get_fcid(port),
2810                                  port->fabric->lps->pr_nwwn);
2811
2812         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2813                           FC_CLASS_3, len, &fchs,
2814                           bfa_fcs_lport_ms_gmal_response, (void *)ms,
2815                           FC_MAX_PDUSZ, FC_FCCT_TOV);
2816
2817         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2818 }
2819
2820 static void
2821 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2822                                 void *cbarg, bfa_status_t req_status,
2823                                 u32 rsp_len, u32 resid_len,
2824                                 struct fchs_s *rsp_fchs)
2825 {
2826         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2827         bfa_fcs_lport_t *port = ms->port;
2828         struct ct_hdr_s         *cthdr = NULL;
2829         struct fcgs_gmal_resp_s *gmal_resp;
2830         struct fcgs_gmal_entry_s *gmal_entry;
2831         u32             num_entries;
2832         u8                      *rsp_str;
2833
2834         bfa_trc(port->fcs, req_status);
2835         bfa_trc(port->fcs, port->port_cfg.pwwn);
2836
2837         /*
2838          * Sanity Checks
2839          */
2840         if (req_status != BFA_STATUS_OK) {
2841                 bfa_trc(port->fcs, req_status);
2842                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2843                 return;
2844         }
2845
2846         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2847         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2848
2849         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2850                 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2851
2852                 num_entries = be32_to_cpu(gmal_resp->ms_len);
2853                 if (num_entries == 0) {
2854                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2855                         return;
2856                 }
2857                 /*
2858                 * The response could contain multiple Entries.
2859                 * Entries for SNMP interface, etc.
2860                 * We look for the entry with a telnet prefix.
2861                 * First "http://" entry refers to IP addr
2862                 */
2863
2864                 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2865                 while (num_entries > 0) {
2866                         if (strncmp(gmal_entry->prefix,
2867                                 CT_GMAL_RESP_PREFIX_HTTP,
2868                                 sizeof(gmal_entry->prefix)) == 0) {
2869
2870                                 /*
2871                                 * if the IP address is terminating with a '/',
2872                                 * remove it.
2873                                 * Byte 0 consists of the length of the string.
2874                                 */
2875                                 rsp_str = &(gmal_entry->prefix[0]);
2876                                 if (rsp_str[gmal_entry->len-1] == '/')
2877                                         rsp_str[gmal_entry->len-1] = 0;
2878
2879                                 /* copy IP Address to fabric */
2880                                 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2881                                         gmal_entry->ip_addr,
2882                                         BFA_FCS_FABRIC_IPADDR_SZ);
2883                                 break;
2884                         } else {
2885                                 --num_entries;
2886                                 ++gmal_entry;
2887                         }
2888                 }
2889
2890                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2891                 return;
2892         }
2893
2894         bfa_trc(port->fcs, cthdr->reason_code);
2895         bfa_trc(port->fcs, cthdr->exp_code);
2896         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2897 }
2898
2899 static void
2900 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2901                         enum port_ms_event event)
2902 {
2903         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2904         bfa_trc(ms->port->fcs, event);
2905
2906         switch (event) {
2907         case MSSM_EVENT_FCXP_SENT:
2908                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2909                 break;
2910
2911         case MSSM_EVENT_PORT_OFFLINE:
2912                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2913                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2914                                            &ms->fcxp_wqe);
2915                 break;
2916
2917         default:
2918                 bfa_sm_fault(ms->port->fcs, event);
2919         }
2920 }
2921
2922 static void
2923 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2924                         enum port_ms_event event)
2925 {
2926         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2927         bfa_trc(ms->port->fcs, event);
2928
2929         switch (event) {
2930         case MSSM_EVENT_RSP_ERROR:
2931                 /*
2932                  * Start timer for a delayed retry
2933                  */
2934                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2935                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2936                         ms->port->stats.ms_retries++;
2937                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2938                                 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2939                                 BFA_FCS_RETRY_TIMEOUT);
2940                 } else {
2941                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2942                         ms->retry_cnt = 0;
2943                 }
2944                 break;
2945
2946         case MSSM_EVENT_RSP_OK:
2947                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2948                 break;
2949
2950         case MSSM_EVENT_PORT_OFFLINE:
2951                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2952                 bfa_fcxp_discard(ms->fcxp);
2953                 break;
2954
2955         default:
2956                 bfa_sm_fault(ms->port->fcs, event);
2957         }
2958 }
2959
2960 static void
2961 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2962                                 enum port_ms_event event)
2963 {
2964         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2965         bfa_trc(ms->port->fcs, event);
2966
2967         switch (event) {
2968         case MSSM_EVENT_TIMEOUT:
2969                 /*
2970                  * Retry Timer Expired. Re-send
2971                  */
2972                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2973                 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2974                 break;
2975
2976         case MSSM_EVENT_PORT_OFFLINE:
2977                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2978                 bfa_timer_stop(&ms->timer);
2979                 break;
2980
2981         default:
2982                 bfa_sm_fault(ms->port->fcs, event);
2983         }
2984 }
2985 /*
2986  *  ms_pvt MS local functions
2987  */
2988
2989 static void
2990 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2991 {
2992         struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2993         bfa_fcs_lport_t *port = ms->port;
2994         struct fchs_s           fchs;
2995         int                     len;
2996         struct bfa_fcxp_s *fcxp;
2997
2998         bfa_trc(port->fcs, port->pid);
2999
3000         fcxp = fcxp_alloced ? fcxp_alloced :
3001                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3002         if (!fcxp) {
3003                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3004                                 bfa_fcs_lport_ms_send_gfn, ms, BFA_TRUE);
3005                 return;
3006         }
3007         ms->fcxp = fcxp;
3008
3009         len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3010                              bfa_fcs_lport_get_fcid(port),
3011                                  port->fabric->lps->pr_nwwn);
3012
3013         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3014                           FC_CLASS_3, len, &fchs,
3015                           bfa_fcs_lport_ms_gfn_response, (void *)ms,
3016                           FC_MAX_PDUSZ, FC_FCCT_TOV);
3017
3018         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3019 }
3020
3021 static void
3022 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3023                         void *cbarg, bfa_status_t req_status, u32 rsp_len,
3024                         u32 resid_len, struct fchs_s *rsp_fchs)
3025 {
3026         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3027         bfa_fcs_lport_t *port = ms->port;
3028         struct ct_hdr_s *cthdr = NULL;
3029         wwn_t          *gfn_resp;
3030
3031         bfa_trc(port->fcs, req_status);
3032         bfa_trc(port->fcs, port->port_cfg.pwwn);
3033
3034         /*
3035          * Sanity Checks
3036          */
3037         if (req_status != BFA_STATUS_OK) {
3038                 bfa_trc(port->fcs, req_status);
3039                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3040                 return;
3041         }
3042
3043         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3044         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3045
3046         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3047                 gfn_resp = (wwn_t *)(cthdr + 1);
3048                 /* check if it has actually changed */
3049                 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
3050                                 gfn_resp, sizeof(wwn_t)) != 0)) {
3051                         bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
3052                 }
3053                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3054                 return;
3055         }
3056
3057         bfa_trc(port->fcs, cthdr->reason_code);
3058         bfa_trc(port->fcs, cthdr->exp_code);
3059         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3060 }
3061
3062 /*
3063  *  ms_pvt MS local functions
3064  */
3065
3066 static void
3067 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3068 {
3069         struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
3070         struct bfa_fcs_lport_s *port = ms->port;
3071         struct fchs_s   fchs;
3072         int     len;
3073         struct bfa_fcxp_s *fcxp;
3074
3075         bfa_trc(port->fcs, port->pid);
3076
3077         fcxp = fcxp_alloced ? fcxp_alloced :
3078                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
3079         if (!fcxp) {
3080                 port->stats.ms_plogi_alloc_wait++;
3081                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
3082                                 bfa_fcs_lport_ms_send_plogi, ms, BFA_TRUE);
3083                 return;
3084         }
3085         ms->fcxp = fcxp;
3086
3087         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3088                              bfa_hton3b(FC_MGMT_SERVER),
3089                              bfa_fcs_lport_get_fcid(port), 0,
3090                              port->port_cfg.pwwn, port->port_cfg.nwwn,
3091                              bfa_fcport_get_maxfrsize(port->fcs->bfa),
3092                              bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
3093
3094         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3095                           FC_CLASS_3, len, &fchs,
3096                           bfa_fcs_lport_ms_plogi_response, (void *)ms,
3097                           FC_MAX_PDUSZ, FC_ELS_TOV);
3098
3099         port->stats.ms_plogi_sent++;
3100         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
3101 }
3102
3103 static void
3104 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3105                         void *cbarg, bfa_status_t req_status,
3106                         u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
3107 {
3108         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
3109         struct bfa_fcs_lport_s *port = ms->port;
3110         struct fc_els_cmd_s *els_cmd;
3111         struct fc_ls_rjt_s *ls_rjt;
3112
3113         bfa_trc(port->fcs, req_status);
3114         bfa_trc(port->fcs, port->port_cfg.pwwn);
3115
3116         /*
3117          * Sanity Checks
3118          */
3119         if (req_status != BFA_STATUS_OK) {
3120                 port->stats.ms_plogi_rsp_err++;
3121                 bfa_trc(port->fcs, req_status);
3122                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3123                 return;
3124         }
3125
3126         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3127
3128         switch (els_cmd->els_code) {
3129
3130         case FC_ELS_ACC:
3131                 if (rsp_len < sizeof(struct fc_logi_s)) {
3132                         bfa_trc(port->fcs, rsp_len);
3133                         port->stats.ms_plogi_acc_err++;
3134                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3135                         break;
3136                 }
3137                 port->stats.ms_plogi_accepts++;
3138                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
3139                 break;
3140
3141         case FC_ELS_LS_RJT:
3142                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3143
3144                 bfa_trc(port->fcs, ls_rjt->reason_code);
3145                 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3146
3147                 port->stats.ms_rejects++;
3148                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3149                 break;
3150
3151         default:
3152                 port->stats.ms_plogi_unknown_rsp++;
3153                 bfa_trc(port->fcs, els_cmd->els_code);
3154                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
3155         }
3156 }
3157
3158 static void
3159 bfa_fcs_lport_ms_timeout(void *arg)
3160 {
3161         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
3162
3163         ms->port->stats.ms_timeouts++;
3164         bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
3165 }
3166
3167
3168 void
3169 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
3170 {
3171         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3172
3173         ms->port = port;
3174         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
3175
3176         /*
3177          * Invoke init routines of sub modules.
3178          */
3179         bfa_fcs_lport_fdmi_init(ms);
3180 }
3181
3182 void
3183 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
3184 {
3185         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3186
3187         ms->port = port;
3188         bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
3189         bfa_fcs_lport_fdmi_offline(ms);
3190 }
3191
3192 void
3193 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3194 {
3195         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3196
3197         ms->port = port;
3198         bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3199 }
3200 void
3201 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3202 {
3203         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3204
3205         /* todo.  Handle this only  when in Online state */
3206         if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3207                 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3208 }
3209
3210 /*
3211  * @page ns_sm_info VPORT NS State Machine
3212  *
3213  * @section ns_sm_interactions VPORT NS State Machine Interactions
3214  *
3215  * @section ns_sm VPORT NS State Machine
3216  * img ns_sm.jpg
3217  */
3218
3219 /*
3220  * forward declarations
3221  */
3222 static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3223                                            struct bfa_fcxp_s *fcxp_alloced);
3224 static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3225                                              struct bfa_fcxp_s *fcxp_alloced);
3226 static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3227                                             struct bfa_fcxp_s *fcxp_alloced);
3228 static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3229                                             struct bfa_fcxp_s *fcxp_alloced);
3230 static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3231                                             struct bfa_fcxp_s *fcxp_alloced);
3232 static void     bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg,
3233                                         struct bfa_fcxp_s *fcxp_alloced);
3234 static void     bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg,
3235                                         struct bfa_fcxp_s *fcxp_alloced);
3236 static void     bfa_fcs_lport_ns_timeout(void *arg);
3237 static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3238                                                struct bfa_fcxp_s *fcxp,
3239                                                void *cbarg,
3240                                                bfa_status_t req_status,
3241                                                u32 rsp_len,
3242                                                u32 resid_len,
3243                                                struct fchs_s *rsp_fchs);
3244 static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3245                                                  struct bfa_fcxp_s *fcxp,
3246                                                  void *cbarg,
3247                                                  bfa_status_t req_status,
3248                                                  u32 rsp_len,
3249                                                  u32 resid_len,
3250                                                  struct fchs_s *rsp_fchs);
3251 static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
3252                                                 struct bfa_fcxp_s *fcxp,
3253                                                 void *cbarg,
3254                                                 bfa_status_t req_status,
3255                                                 u32 rsp_len,
3256                                                 u32 resid_len,
3257                                                 struct fchs_s *rsp_fchs);
3258 static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
3259                                                 struct bfa_fcxp_s *fcxp,
3260                                                 void *cbarg,
3261                                                 bfa_status_t req_status,
3262                                                 u32 rsp_len,
3263                                                 u32 resid_len,
3264                                                 struct fchs_s *rsp_fchs);
3265 static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3266                                                 struct bfa_fcxp_s *fcxp,
3267                                                 void *cbarg,
3268                                                 bfa_status_t req_status,
3269                                                 u32 rsp_len,
3270                                                 u32 resid_len,
3271                                                 struct fchs_s *rsp_fchs);
3272 static void     bfa_fcs_lport_ns_rnn_id_response(void *fcsarg,
3273                                                 struct bfa_fcxp_s *fcxp,
3274                                                 void *cbarg,
3275                                                 bfa_status_t req_status,
3276                                                 u32 rsp_len,
3277                                                 u32 resid_len,
3278                                                 struct fchs_s *rsp_fchs);
3279 static void     bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg,
3280                                                 struct bfa_fcxp_s *fcxp,
3281                                                 void *cbarg,
3282                                                 bfa_status_t req_status,
3283                                                 u32 rsp_len,
3284                                                 u32 resid_len,
3285                                                 struct fchs_s *rsp_fchs);
3286 static void     bfa_fcs_lport_ns_process_gidft_pids(
3287                                 struct bfa_fcs_lport_s *port,
3288                                 u32 *pid_buf, u32 n_pids);
3289
3290 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3291 /*
3292  *  fcs_ns_sm FCS nameserver interface state machine
3293  */
3294
3295 /*
3296  * VPort NS State Machine events
3297  */
3298 enum vport_ns_event {
3299         NSSM_EVENT_PORT_ONLINE = 1,
3300         NSSM_EVENT_PORT_OFFLINE = 2,
3301         NSSM_EVENT_PLOGI_SENT = 3,
3302         NSSM_EVENT_RSP_OK = 4,
3303         NSSM_EVENT_RSP_ERROR = 5,
3304         NSSM_EVENT_TIMEOUT = 6,
3305         NSSM_EVENT_NS_QUERY = 7,
3306         NSSM_EVENT_RSPNID_SENT = 8,
3307         NSSM_EVENT_RFTID_SENT = 9,
3308         NSSM_EVENT_RFFID_SENT = 10,
3309         NSSM_EVENT_GIDFT_SENT = 11,
3310         NSSM_EVENT_RNNID_SENT = 12,
3311         NSSM_EVENT_RSNN_NN_SENT = 13,
3312 };
3313
3314 static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3315                                            enum vport_ns_event event);
3316 static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3317                                                  enum vport_ns_event event);
3318 static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3319                                          enum vport_ns_event event);
3320 static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3321                                                enum vport_ns_event event);
3322 static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
3323                                         struct bfa_fcs_lport_ns_s *ns,
3324                                         enum vport_ns_event event);
3325 static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3326                                            enum vport_ns_event event);
3327 static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3328                                                  enum vport_ns_event event);
3329 static void     bfa_fcs_lport_ns_sm_sending_rft_id(
3330                                         struct bfa_fcs_lport_ns_s *ns,
3331                                         enum vport_ns_event event);
3332 static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3333                                                 enum vport_ns_event event);
3334 static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3335                                           enum vport_ns_event event);
3336 static void     bfa_fcs_lport_ns_sm_sending_rff_id(
3337                                         struct bfa_fcs_lport_ns_s *ns,
3338                                         enum vport_ns_event event);
3339 static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3340                                                 enum vport_ns_event event);
3341 static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3342                                           enum vport_ns_event event);
3343 static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
3344                                         struct bfa_fcs_lport_ns_s *ns,
3345                                         enum vport_ns_event event);
3346 static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3347                                           enum vport_ns_event event);
3348 static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3349                                                 enum vport_ns_event event);
3350 static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3351                                           enum vport_ns_event event);
3352 static void     bfa_fcs_lport_ns_sm_sending_rnn_id(
3353                                         struct bfa_fcs_lport_ns_s *ns,
3354                                         enum vport_ns_event event);
3355 static void     bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3356                                         enum vport_ns_event event);
3357 static void     bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3358                                                 enum vport_ns_event event);
3359 static void     bfa_fcs_lport_ns_sm_sending_rsnn_nn(
3360                                         struct bfa_fcs_lport_ns_s *ns,
3361                                         enum vport_ns_event event);
3362 static void     bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3363                                                 enum vport_ns_event event);
3364 static void     bfa_fcs_lport_ns_sm_rsnn_nn_retry(
3365                                         struct bfa_fcs_lport_ns_s *ns,
3366                                         enum vport_ns_event event);
3367 /*
3368  *      Start in offline state - awaiting linkup
3369  */
3370 static void
3371 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3372                         enum vport_ns_event event)
3373 {
3374         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3375         bfa_trc(ns->port->fcs, event);
3376
3377         switch (event) {
3378         case NSSM_EVENT_PORT_ONLINE:
3379                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3380                 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3381                 break;
3382
3383         case NSSM_EVENT_PORT_OFFLINE:
3384                 break;
3385
3386         default:
3387                 bfa_sm_fault(ns->port->fcs, event);
3388         }
3389 }
3390
3391 static void
3392 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3393                         enum vport_ns_event event)
3394 {
3395         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3396         bfa_trc(ns->port->fcs, event);
3397
3398         switch (event) {
3399         case NSSM_EVENT_PLOGI_SENT:
3400                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3401                 break;
3402
3403         case NSSM_EVENT_PORT_OFFLINE:
3404                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3405                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3406                                            &ns->fcxp_wqe);
3407                 break;
3408
3409         default:
3410                 bfa_sm_fault(ns->port->fcs, event);
3411         }
3412 }
3413
3414 static void
3415 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3416                         enum vport_ns_event event)
3417 {
3418         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3419         bfa_trc(ns->port->fcs, event);
3420
3421         switch (event) {
3422         case NSSM_EVENT_RSP_ERROR:
3423                 /*
3424                  * Start timer for a delayed retry
3425                  */
3426                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3427                 ns->port->stats.ns_retries++;
3428                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3429                                     &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3430                                     BFA_FCS_RETRY_TIMEOUT);
3431                 break;
3432
3433         case NSSM_EVENT_RSP_OK:
3434                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3435                 ns->num_rnnid_retries = 0;
3436                 bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3437                 break;
3438
3439         case NSSM_EVENT_PORT_OFFLINE:
3440                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3441                 bfa_fcxp_discard(ns->fcxp);
3442                 break;
3443
3444         default:
3445                 bfa_sm_fault(ns->port->fcs, event);
3446         }
3447 }
3448
3449 static void
3450 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3451                                 enum vport_ns_event event)
3452 {
3453         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3454         bfa_trc(ns->port->fcs, event);
3455
3456         switch (event) {
3457         case NSSM_EVENT_TIMEOUT:
3458                 /*
3459                  * Retry Timer Expired. Re-send
3460                  */
3461                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3462                 bfa_fcs_lport_ns_send_plogi(ns, NULL);
3463                 break;
3464
3465         case NSSM_EVENT_PORT_OFFLINE:
3466                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3467                 bfa_timer_stop(&ns->timer);
3468                 break;
3469
3470         default:
3471                 bfa_sm_fault(ns->port->fcs, event);
3472         }
3473 }
3474
3475 static void
3476 bfa_fcs_lport_ns_sm_sending_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3477                                         enum vport_ns_event event)
3478 {
3479         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3480         bfa_trc(ns->port->fcs, event);
3481
3482         switch (event) {
3483         case NSSM_EVENT_RNNID_SENT:
3484                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id);
3485                 break;
3486
3487         case NSSM_EVENT_PORT_OFFLINE:
3488                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3489                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3490                                                 &ns->fcxp_wqe);
3491                 break;
3492         default:
3493                 bfa_sm_fault(ns->port->fcs, event);
3494         }
3495 }
3496
3497 static void
3498 bfa_fcs_lport_ns_sm_rnn_id(struct bfa_fcs_lport_ns_s *ns,
3499                                 enum vport_ns_event event)
3500 {
3501         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3502         bfa_trc(ns->port->fcs, event);
3503
3504         switch (event) {
3505         case NSSM_EVENT_RSP_OK:
3506                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3507                 ns->num_rnnid_retries = 0;
3508                 ns->num_rsnn_nn_retries = 0;
3509                 bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3510                 break;
3511
3512         case NSSM_EVENT_RSP_ERROR:
3513                 if (ns->num_rnnid_retries < BFA_FCS_MAX_NS_RETRIES) {
3514                         bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rnn_id_retry);
3515                         ns->port->stats.ns_retries++;
3516                         ns->num_rnnid_retries++;
3517                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3518                                 &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3519                                 BFA_FCS_RETRY_TIMEOUT);
3520                 } else {
3521                         bfa_sm_set_state(ns,
3522                                 bfa_fcs_lport_ns_sm_sending_rspn_id);
3523                         bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3524                 }
3525                 break;
3526
3527         case NSSM_EVENT_PORT_OFFLINE:
3528                 bfa_fcxp_discard(ns->fcxp);
3529                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3530                 break;
3531
3532         default:
3533                 bfa_sm_fault(ns->port->fcs, event);
3534         }
3535 }
3536
3537 static void
3538 bfa_fcs_lport_ns_sm_rnn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3539                                 enum vport_ns_event event)
3540 {
3541         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3542         bfa_trc(ns->port->fcs, event);
3543
3544         switch (event) {
3545         case NSSM_EVENT_TIMEOUT:
3546                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rnn_id);
3547                 bfa_fcs_lport_ns_send_rnn_id(ns, NULL);
3548                 break;
3549
3550         case NSSM_EVENT_PORT_OFFLINE:
3551                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3552                 bfa_timer_stop(&ns->timer);
3553                 break;
3554
3555         default:
3556                 bfa_sm_fault(ns->port->fcs, event);
3557         }
3558 }
3559
3560 static void
3561 bfa_fcs_lport_ns_sm_sending_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3562                                         enum vport_ns_event event)
3563 {
3564         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3565         bfa_trc(ns->port->fcs, event);
3566
3567         switch (event) {
3568         case NSSM_EVENT_RSNN_NN_SENT:
3569                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn);
3570                 break;
3571
3572         case NSSM_EVENT_PORT_OFFLINE:
3573                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3574                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3575                         &ns->fcxp_wqe);
3576                 break;
3577
3578         default:
3579                 bfa_sm_fault(ns->port->fcs, event);
3580         }
3581 }
3582
3583 static void
3584 bfa_fcs_lport_ns_sm_rsnn_nn(struct bfa_fcs_lport_ns_s *ns,
3585                                 enum vport_ns_event event)
3586 {
3587         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3588         bfa_trc(ns->port->fcs, event);
3589
3590         switch (event) {
3591         case NSSM_EVENT_RSP_OK:
3592                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3593                 ns->num_rsnn_nn_retries = 0;
3594                 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3595                 break;
3596
3597         case NSSM_EVENT_RSP_ERROR:
3598                 if (ns->num_rsnn_nn_retries < BFA_FCS_MAX_NS_RETRIES) {
3599                         bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rsnn_nn_retry);
3600                         ns->port->stats.ns_retries++;
3601                         ns->num_rsnn_nn_retries++;
3602                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3603                                         &ns->timer, bfa_fcs_lport_ns_timeout,
3604                                         ns, BFA_FCS_RETRY_TIMEOUT);
3605                 } else {
3606                         bfa_sm_set_state(ns,
3607                                 bfa_fcs_lport_ns_sm_sending_rspn_id);
3608                         bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3609                 }
3610                 break;
3611
3612         case NSSM_EVENT_PORT_OFFLINE:
3613                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3614                 bfa_fcxp_discard(ns->fcxp);
3615                 break;
3616
3617         default:
3618                 bfa_sm_fault(ns->port->fcs, event);
3619         }
3620 }
3621
3622 static void
3623 bfa_fcs_lport_ns_sm_rsnn_nn_retry(struct bfa_fcs_lport_ns_s *ns,
3624                                         enum vport_ns_event event)
3625 {
3626         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3627         bfa_trc(ns->port->fcs, event);
3628
3629         switch (event) {
3630         case NSSM_EVENT_TIMEOUT:
3631                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rsnn_nn);
3632                 bfa_fcs_lport_ns_send_rsnn_nn(ns, NULL);
3633                 break;
3634
3635         case NSSM_EVENT_PORT_OFFLINE:
3636                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3637                 bfa_timer_stop(&ns->timer);
3638                 break;
3639
3640         default:
3641                 bfa_sm_fault(ns->port->fcs, event);
3642         }
3643 }
3644
3645 static void
3646 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3647                                    enum vport_ns_event event)
3648 {
3649         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3650         bfa_trc(ns->port->fcs, event);
3651
3652         switch (event) {
3653         case NSSM_EVENT_RSPNID_SENT:
3654                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3655                 break;
3656
3657         case NSSM_EVENT_PORT_OFFLINE:
3658                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3659                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3660                                            &ns->fcxp_wqe);
3661                 break;
3662
3663         default:
3664                 bfa_sm_fault(ns->port->fcs, event);
3665         }
3666 }
3667
3668 static void
3669 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3670                         enum vport_ns_event event)
3671 {
3672         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3673         bfa_trc(ns->port->fcs, event);
3674
3675         switch (event) {
3676         case NSSM_EVENT_RSP_ERROR:
3677                 /*
3678                  * Start timer for a delayed retry
3679                  */
3680                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3681                 ns->port->stats.ns_retries++;
3682                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3683                                     &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3684                                     BFA_FCS_RETRY_TIMEOUT);
3685                 break;
3686
3687         case NSSM_EVENT_RSP_OK:
3688                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3689                 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3690                 break;
3691
3692         case NSSM_EVENT_PORT_OFFLINE:
3693                 bfa_fcxp_discard(ns->fcxp);
3694                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3695                 break;
3696
3697         default:
3698                 bfa_sm_fault(ns->port->fcs, event);
3699         }
3700 }
3701
3702 static void
3703 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3704                                 enum vport_ns_event event)
3705 {
3706         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3707         bfa_trc(ns->port->fcs, event);
3708
3709         switch (event) {
3710         case NSSM_EVENT_TIMEOUT:
3711                 /*
3712                  * Retry Timer Expired. Re-send
3713                  */
3714                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3715                 bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3716                 break;
3717
3718         case NSSM_EVENT_PORT_OFFLINE:
3719                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3720                 bfa_timer_stop(&ns->timer);
3721                 break;
3722
3723         default:
3724                 bfa_sm_fault(ns->port->fcs, event);
3725         }
3726 }
3727
3728 static void
3729 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3730                                   enum vport_ns_event event)
3731 {
3732         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3733         bfa_trc(ns->port->fcs, event);
3734
3735         switch (event) {
3736         case NSSM_EVENT_RFTID_SENT:
3737                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3738                 break;
3739
3740         case NSSM_EVENT_PORT_OFFLINE:
3741                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3742                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3743                                            &ns->fcxp_wqe);
3744                 break;
3745
3746         default:
3747                 bfa_sm_fault(ns->port->fcs, event);
3748         }
3749 }
3750
3751 static void
3752 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3753                         enum vport_ns_event event)
3754 {
3755         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3756         bfa_trc(ns->port->fcs, event);
3757
3758         switch (event) {
3759         case NSSM_EVENT_RSP_OK:
3760                 /* Now move to register FC4 Features */
3761                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3762                 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3763                 break;
3764
3765         case NSSM_EVENT_RSP_ERROR:
3766                 /*
3767                  * Start timer for a delayed retry
3768                  */
3769                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3770                 ns->port->stats.ns_retries++;
3771                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3772                                     &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3773                                     BFA_FCS_RETRY_TIMEOUT);
3774                 break;
3775
3776         case NSSM_EVENT_PORT_OFFLINE:
3777                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3778                 bfa_fcxp_discard(ns->fcxp);
3779                 break;
3780
3781         default:
3782                 bfa_sm_fault(ns->port->fcs, event);
3783         }
3784 }
3785
3786 static void
3787 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3788                                 enum vport_ns_event event)
3789 {
3790         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3791         bfa_trc(ns->port->fcs, event);
3792
3793         switch (event) {
3794         case NSSM_EVENT_TIMEOUT:
3795                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3796                 bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3797                 break;
3798
3799         case NSSM_EVENT_PORT_OFFLINE:
3800                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3801                 bfa_timer_stop(&ns->timer);
3802                 break;
3803
3804         default:
3805                 bfa_sm_fault(ns->port->fcs, event);
3806         }
3807 }
3808
3809 static void
3810 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3811                                   enum vport_ns_event event)
3812 {
3813         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3814         bfa_trc(ns->port->fcs, event);
3815
3816         switch (event) {
3817         case NSSM_EVENT_RFFID_SENT:
3818                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3819                 break;
3820
3821         case NSSM_EVENT_PORT_OFFLINE:
3822                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3823                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3824                                            &ns->fcxp_wqe);
3825                 break;
3826
3827         default:
3828                 bfa_sm_fault(ns->port->fcs, event);
3829         }
3830 }
3831
3832 static void
3833 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3834                         enum vport_ns_event event)
3835 {
3836         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3837         bfa_trc(ns->port->fcs, event);
3838
3839         switch (event) {
3840         case NSSM_EVENT_RSP_OK:
3841
3842                 /*
3843                  * If min cfg mode is enabled, we donot initiate rport
3844                  * discovery with the fabric. Instead, we will retrieve the
3845                  * boot targets from HAL/FW.
3846                  */
3847                 if (__fcs_min_cfg(ns->port->fcs)) {
3848                         bfa_fcs_lport_ns_boot_target_disc(ns->port);
3849                         bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3850                         return;
3851                 }
3852
3853                 /*
3854                  * If the port role is Initiator Mode issue NS query.
3855                  * If it is Target Mode, skip this and go to online.
3856                  */
3857                 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3858                         bfa_sm_set_state(ns,
3859                                 bfa_fcs_lport_ns_sm_sending_gid_ft);
3860                         bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3861                 }
3862                 /*
3863                  * kick off mgmt srvr state machine
3864                  */
3865                 bfa_fcs_lport_ms_online(ns->port);
3866                 break;
3867
3868         case NSSM_EVENT_RSP_ERROR:
3869                 /*
3870                  * Start timer for a delayed retry
3871                  */
3872                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3873                 ns->port->stats.ns_retries++;
3874                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3875                                     &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3876                                     BFA_FCS_RETRY_TIMEOUT);
3877                 break;
3878
3879         case NSSM_EVENT_PORT_OFFLINE:
3880                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3881                 bfa_fcxp_discard(ns->fcxp);
3882                 break;
3883
3884         default:
3885                 bfa_sm_fault(ns->port->fcs, event);
3886         }
3887 }
3888
3889 static void
3890 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3891                                 enum vport_ns_event event)
3892 {
3893         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3894         bfa_trc(ns->port->fcs, event);
3895
3896         switch (event) {
3897         case NSSM_EVENT_TIMEOUT:
3898                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3899                 bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3900                 break;
3901
3902         case NSSM_EVENT_PORT_OFFLINE:
3903                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3904                 bfa_timer_stop(&ns->timer);
3905                 break;
3906
3907         default:
3908                 bfa_sm_fault(ns->port->fcs, event);
3909         }
3910 }
3911 static void
3912 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3913                                   enum vport_ns_event event)
3914 {
3915         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3916         bfa_trc(ns->port->fcs, event);
3917
3918         switch (event) {
3919         case NSSM_EVENT_GIDFT_SENT:
3920                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3921                 break;
3922
3923         case NSSM_EVENT_PORT_OFFLINE:
3924                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3925                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3926                                            &ns->fcxp_wqe);
3927                 break;
3928
3929         default:
3930                 bfa_sm_fault(ns->port->fcs, event);
3931         }
3932 }
3933
3934 static void
3935 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3936                         enum vport_ns_event event)
3937 {
3938         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3939         bfa_trc(ns->port->fcs, event);
3940
3941         switch (event) {
3942         case NSSM_EVENT_RSP_OK:
3943                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3944                 break;
3945
3946         case NSSM_EVENT_RSP_ERROR:
3947                 /*
3948                  * TBD: for certain reject codes, we don't need to retry
3949                  */
3950                 /*
3951                  * Start timer for a delayed retry
3952                  */
3953                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3954                 ns->port->stats.ns_retries++;
3955                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3956                                     &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3957                                     BFA_FCS_RETRY_TIMEOUT);
3958                 break;
3959
3960         case NSSM_EVENT_PORT_OFFLINE:
3961                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3962                 bfa_fcxp_discard(ns->fcxp);
3963                 break;
3964
3965         case  NSSM_EVENT_NS_QUERY:
3966                 break;
3967
3968         default:
3969                 bfa_sm_fault(ns->port->fcs, event);
3970         }
3971 }
3972
3973 static void
3974 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3975                                 enum vport_ns_event event)
3976 {
3977         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3978         bfa_trc(ns->port->fcs, event);
3979
3980         switch (event) {
3981         case NSSM_EVENT_TIMEOUT:
3982                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3983                 bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3984                 break;
3985
3986         case NSSM_EVENT_PORT_OFFLINE:
3987                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3988                 bfa_timer_stop(&ns->timer);
3989                 break;
3990
3991         default:
3992                 bfa_sm_fault(ns->port->fcs, event);
3993         }
3994 }
3995
3996 static void
3997 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3998                         enum vport_ns_event event)
3999 {
4000         bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
4001         bfa_trc(ns->port->fcs, event);
4002
4003         switch (event) {
4004         case NSSM_EVENT_PORT_OFFLINE:
4005                 bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4006                 break;
4007
4008         case NSSM_EVENT_NS_QUERY:
4009                 /*
4010                  * If the port role is Initiator Mode issue NS query.
4011                  * If it is Target Mode, skip this and go to online.
4012                  */
4013                 if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
4014                         bfa_sm_set_state(ns,
4015                                 bfa_fcs_lport_ns_sm_sending_gid_ft);
4016                         bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
4017                 };
4018                 break;
4019
4020         default:
4021                 bfa_sm_fault(ns->port->fcs, event);
4022         }
4023 }
4024
4025
4026
4027 /*
4028  *  ns_pvt Nameserver local functions
4029  */
4030
4031 static void
4032 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4033 {
4034         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4035         struct bfa_fcs_lport_s *port = ns->port;
4036         struct fchs_s fchs;
4037         int             len;
4038         struct bfa_fcxp_s *fcxp;
4039
4040         bfa_trc(port->fcs, port->pid);
4041
4042         fcxp = fcxp_alloced ? fcxp_alloced :
4043                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4044         if (!fcxp) {
4045                 port->stats.ns_plogi_alloc_wait++;
4046                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4047                                 bfa_fcs_lport_ns_send_plogi, ns, BFA_TRUE);
4048                 return;
4049         }
4050         ns->fcxp = fcxp;
4051
4052         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4053                              bfa_hton3b(FC_NAME_SERVER),
4054                              bfa_fcs_lport_get_fcid(port), 0,
4055                              port->port_cfg.pwwn, port->port_cfg.nwwn,
4056                              bfa_fcport_get_maxfrsize(port->fcs->bfa),
4057                              bfa_fcport_get_rx_bbcredit(port->fcs->bfa));
4058
4059         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4060                           FC_CLASS_3, len, &fchs,
4061                           bfa_fcs_lport_ns_plogi_response, (void *)ns,
4062                           FC_MAX_PDUSZ, FC_ELS_TOV);
4063         port->stats.ns_plogi_sent++;
4064
4065         bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
4066 }
4067
4068 static void
4069 bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4070                         void *cbarg, bfa_status_t req_status, u32 rsp_len,
4071                        u32 resid_len, struct fchs_s *rsp_fchs)
4072 {
4073         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4074         struct bfa_fcs_lport_s *port = ns->port;
4075         /* struct fc_logi_s *plogi_resp; */
4076         struct fc_els_cmd_s *els_cmd;
4077         struct fc_ls_rjt_s *ls_rjt;
4078
4079         bfa_trc(port->fcs, req_status);
4080         bfa_trc(port->fcs, port->port_cfg.pwwn);
4081
4082         /*
4083          * Sanity Checks
4084          */
4085         if (req_status != BFA_STATUS_OK) {
4086                 bfa_trc(port->fcs, req_status);
4087                 port->stats.ns_plogi_rsp_err++;
4088                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4089                 return;
4090         }
4091
4092         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4093
4094         switch (els_cmd->els_code) {
4095
4096         case FC_ELS_ACC:
4097                 if (rsp_len < sizeof(struct fc_logi_s)) {
4098                         bfa_trc(port->fcs, rsp_len);
4099                         port->stats.ns_plogi_acc_err++;
4100                         bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4101                         break;
4102                 }
4103                 port->stats.ns_plogi_accepts++;
4104                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4105                 break;
4106
4107         case FC_ELS_LS_RJT:
4108                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4109
4110                 bfa_trc(port->fcs, ls_rjt->reason_code);
4111                 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4112
4113                 port->stats.ns_rejects++;
4114
4115                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4116                 break;
4117
4118         default:
4119                 port->stats.ns_plogi_unknown_rsp++;
4120                 bfa_trc(port->fcs, els_cmd->els_code);
4121                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4122         }
4123 }
4124
4125 /*
4126  * Register node name for port_id
4127  */
4128 static void
4129 bfa_fcs_lport_ns_send_rnn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4130 {
4131         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4132         struct bfa_fcs_lport_s *port = ns->port;
4133         struct fchs_s  fchs;
4134         int     len;
4135         struct bfa_fcxp_s *fcxp;
4136
4137         bfa_trc(port->fcs, port->port_cfg.pwwn);
4138
4139         fcxp = fcxp_alloced ? fcxp_alloced :
4140                         bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4141         if (!fcxp) {
4142                 port->stats.ns_rnnid_alloc_wait++;
4143                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4144                                 bfa_fcs_lport_ns_send_rnn_id, ns, BFA_TRUE);
4145                 return;
4146         }
4147
4148         ns->fcxp = fcxp;
4149
4150         len = fc_rnnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4151                                 bfa_fcs_lport_get_fcid(port),
4152                                 bfa_fcs_lport_get_fcid(port),
4153                                 bfa_fcs_lport_get_nwwn(port));
4154
4155         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4156                           FC_CLASS_3, len, &fchs,
4157                           bfa_fcs_lport_ns_rnn_id_response, (void *)ns,
4158                           FC_MAX_PDUSZ, FC_FCCT_TOV);
4159
4160         port->stats.ns_rnnid_sent++;
4161         bfa_sm_send_event(ns, NSSM_EVENT_RNNID_SENT);
4162 }
4163
4164 static void
4165 bfa_fcs_lport_ns_rnn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4166                                 void *cbarg, bfa_status_t req_status,
4167                                 u32 rsp_len, u32 resid_len,
4168                                 struct fchs_s *rsp_fchs)
4169
4170 {
4171         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4172         struct bfa_fcs_lport_s *port = ns->port;
4173         struct ct_hdr_s *cthdr = NULL;
4174
4175         bfa_trc(port->fcs, port->port_cfg.pwwn);
4176
4177         /*
4178          * Sanity Checks
4179          */
4180         if (req_status != BFA_STATUS_OK) {
4181                 bfa_trc(port->fcs, req_status);
4182                 port->stats.ns_rnnid_rsp_err++;
4183                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4184                 return;
4185         }
4186
4187         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4188         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4189
4190         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4191                 port->stats.ns_rnnid_accepts++;
4192                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4193                 return;
4194         }
4195
4196         port->stats.ns_rnnid_rejects++;
4197         bfa_trc(port->fcs, cthdr->reason_code);
4198         bfa_trc(port->fcs, cthdr->exp_code);
4199         bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4200 }
4201
4202 /*
4203  * Register the symbolic node name for a given node name.
4204  */
4205 static void
4206 bfa_fcs_lport_ns_send_rsnn_nn(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4207 {
4208         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4209         struct bfa_fcs_lport_s *port = ns->port;
4210         struct fchs_s  fchs;
4211         int     len;
4212         struct bfa_fcxp_s *fcxp;
4213         u8 *nsymbl;
4214
4215         bfa_trc(port->fcs, port->port_cfg.pwwn);
4216
4217         fcxp = fcxp_alloced ? fcxp_alloced :
4218                         bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4219         if (!fcxp) {
4220                 port->stats.ns_rsnn_nn_alloc_wait++;
4221                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4222                                 bfa_fcs_lport_ns_send_rsnn_nn, ns, BFA_TRUE);
4223                 return;
4224         }
4225         ns->fcxp = fcxp;
4226
4227         nsymbl = (u8 *) &(bfa_fcs_lport_get_nsym_name(
4228                                         bfa_fcs_get_base_port(port->fcs)));
4229
4230         len = fc_rsnn_nn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4231                                 bfa_fcs_lport_get_fcid(port),
4232                                 bfa_fcs_lport_get_nwwn(port), nsymbl);
4233
4234         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4235                           FC_CLASS_3, len, &fchs,
4236                           bfa_fcs_lport_ns_rsnn_nn_response, (void *)ns,
4237                           FC_MAX_PDUSZ, FC_FCCT_TOV);
4238
4239         port->stats.ns_rsnn_nn_sent++;
4240
4241         bfa_sm_send_event(ns, NSSM_EVENT_RSNN_NN_SENT);
4242 }
4243
4244 static void
4245 bfa_fcs_lport_ns_rsnn_nn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4246                                 void *cbarg, bfa_status_t req_status,
4247                                 u32 rsp_len, u32 resid_len,
4248                                 struct fchs_s *rsp_fchs)
4249 {
4250         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4251         struct bfa_fcs_lport_s *port = ns->port;
4252         struct ct_hdr_s *cthdr = NULL;
4253
4254         bfa_trc(port->fcs, port->port_cfg.pwwn);
4255
4256         /*
4257          * Sanity Checks
4258          */
4259         if (req_status != BFA_STATUS_OK) {
4260                 bfa_trc(port->fcs, req_status);
4261                 port->stats.ns_rsnn_nn_rsp_err++;
4262                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4263                 return;
4264         }
4265
4266         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4267         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4268
4269         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4270                 port->stats.ns_rsnn_nn_accepts++;
4271                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4272                 return;
4273         }
4274
4275         port->stats.ns_rsnn_nn_rejects++;
4276         bfa_trc(port->fcs, cthdr->reason_code);
4277         bfa_trc(port->fcs, cthdr->exp_code);
4278         bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4279 }
4280
4281 /*
4282  * Register the symbolic port name.
4283  */
4284 static void
4285 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4286 {
4287         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4288         struct bfa_fcs_lport_s *port = ns->port;
4289         struct fchs_s fchs;
4290         int             len;
4291         struct bfa_fcxp_s *fcxp;
4292         u8         symbl[256];
4293         u8         *psymbl = &symbl[0];
4294
4295         memset(symbl, 0, sizeof(symbl));
4296
4297         bfa_trc(port->fcs, port->port_cfg.pwwn);
4298
4299         fcxp = fcxp_alloced ? fcxp_alloced :
4300                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4301         if (!fcxp) {
4302                 port->stats.ns_rspnid_alloc_wait++;
4303                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4304                                 bfa_fcs_lport_ns_send_rspn_id, ns, BFA_TRUE);
4305                 return;
4306         }
4307         ns->fcxp = fcxp;
4308
4309         /*
4310          * for V-Port, form a Port Symbolic Name
4311          */
4312         if (port->vport) {
4313                 /*
4314                  * For Vports, we append the vport's port symbolic name
4315                  * to that of the base port.
4316                  */
4317
4318                 strncpy((char *)psymbl,
4319                         (char *) &
4320                         (bfa_fcs_lport_get_psym_name
4321                          (bfa_fcs_get_base_port(port->fcs))),
4322                         strlen((char *) &
4323                                bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
4324                                                           (port->fcs))));
4325
4326                 /* Ensure we have a null terminating string. */
4327                 ((char *)psymbl)[strlen((char *) &
4328                         bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
4329                                                 (port->fcs)))] = 0;
4330                 strncat((char *)psymbl,
4331                         (char *) &(bfa_fcs_lport_get_psym_name(port)),
4332                 strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
4333         } else {
4334                 psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
4335         }
4336
4337         len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4338                               bfa_fcs_lport_get_fcid(port), 0, psymbl);
4339
4340         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4341                           FC_CLASS_3, len, &fchs,
4342                           bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
4343                           FC_MAX_PDUSZ, FC_FCCT_TOV);
4344
4345         port->stats.ns_rspnid_sent++;
4346
4347         bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
4348 }
4349
4350 static void
4351 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4352                                  void *cbarg, bfa_status_t req_status,
4353                                  u32 rsp_len, u32 resid_len,
4354                                  struct fchs_s *rsp_fchs)
4355 {
4356         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4357         struct bfa_fcs_lport_s *port = ns->port;
4358         struct ct_hdr_s *cthdr = NULL;
4359
4360         bfa_trc(port->fcs, port->port_cfg.pwwn);
4361
4362         /*
4363          * Sanity Checks
4364          */
4365         if (req_status != BFA_STATUS_OK) {
4366                 bfa_trc(port->fcs, req_status);
4367                 port->stats.ns_rspnid_rsp_err++;
4368                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4369                 return;
4370         }
4371
4372         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4373         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4374
4375         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4376                 port->stats.ns_rspnid_accepts++;
4377                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4378                 return;
4379         }
4380
4381         port->stats.ns_rspnid_rejects++;
4382         bfa_trc(port->fcs, cthdr->reason_code);
4383         bfa_trc(port->fcs, cthdr->exp_code);
4384         bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4385 }
4386
4387 /*
4388  * Register FC4-Types
4389  */
4390 static void
4391 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4392 {
4393         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4394         struct bfa_fcs_lport_s *port = ns->port;
4395         struct fchs_s fchs;
4396         int             len;
4397         struct bfa_fcxp_s *fcxp;
4398
4399         bfa_trc(port->fcs, port->port_cfg.pwwn);
4400
4401         fcxp = fcxp_alloced ? fcxp_alloced :
4402                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4403         if (!fcxp) {
4404                 port->stats.ns_rftid_alloc_wait++;
4405                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4406                                 bfa_fcs_lport_ns_send_rft_id, ns, BFA_TRUE);
4407                 return;
4408         }
4409         ns->fcxp = fcxp;
4410
4411         len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4412                      bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
4413
4414         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4415                           FC_CLASS_3, len, &fchs,
4416                           bfa_fcs_lport_ns_rft_id_response, (void *)ns,
4417                           FC_MAX_PDUSZ, FC_FCCT_TOV);
4418
4419         port->stats.ns_rftid_sent++;
4420         bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
4421 }
4422
4423 static void
4424 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4425                                 void *cbarg, bfa_status_t req_status,
4426                                 u32 rsp_len, u32 resid_len,
4427                                 struct fchs_s *rsp_fchs)
4428 {
4429         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4430         struct bfa_fcs_lport_s *port = ns->port;
4431         struct ct_hdr_s *cthdr = NULL;
4432
4433         bfa_trc(port->fcs, port->port_cfg.pwwn);
4434
4435         /*
4436          * Sanity Checks
4437          */
4438         if (req_status != BFA_STATUS_OK) {
4439                 bfa_trc(port->fcs, req_status);
4440                 port->stats.ns_rftid_rsp_err++;
4441                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4442                 return;
4443         }
4444
4445         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4446         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4447
4448         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4449                 port->stats.ns_rftid_accepts++;
4450                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4451                 return;
4452         }
4453
4454         port->stats.ns_rftid_rejects++;
4455         bfa_trc(port->fcs, cthdr->reason_code);
4456         bfa_trc(port->fcs, cthdr->exp_code);
4457         bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4458 }
4459
4460 /*
4461  * Register FC4-Features : Should be done after RFT_ID
4462  */
4463 static void
4464 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4465 {
4466         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4467         struct bfa_fcs_lport_s *port = ns->port;
4468         struct fchs_s fchs;
4469         int             len;
4470         struct bfa_fcxp_s *fcxp;
4471         u8                      fc4_ftrs = 0;
4472
4473         bfa_trc(port->fcs, port->port_cfg.pwwn);
4474
4475         fcxp = fcxp_alloced ? fcxp_alloced :
4476                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4477         if (!fcxp) {
4478                 port->stats.ns_rffid_alloc_wait++;
4479                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4480                                 bfa_fcs_lport_ns_send_rff_id, ns, BFA_TRUE);
4481                 return;
4482         }
4483         ns->fcxp = fcxp;
4484
4485         if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
4486                 fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
4487
4488         len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4489                              bfa_fcs_lport_get_fcid(port), 0,
4490                                  FC_TYPE_FCP, fc4_ftrs);
4491
4492         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4493                           FC_CLASS_3, len, &fchs,
4494                           bfa_fcs_lport_ns_rff_id_response, (void *)ns,
4495                           FC_MAX_PDUSZ, FC_FCCT_TOV);
4496
4497         port->stats.ns_rffid_sent++;
4498         bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
4499 }
4500
4501 static void
4502 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4503                                 void *cbarg, bfa_status_t req_status,
4504                                 u32 rsp_len, u32 resid_len,
4505                                 struct fchs_s *rsp_fchs)
4506 {
4507         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4508         struct bfa_fcs_lport_s *port = ns->port;
4509         struct ct_hdr_s *cthdr = NULL;
4510
4511         bfa_trc(port->fcs, port->port_cfg.pwwn);
4512
4513         /*
4514          * Sanity Checks
4515          */
4516         if (req_status != BFA_STATUS_OK) {
4517                 bfa_trc(port->fcs, req_status);
4518                 port->stats.ns_rffid_rsp_err++;
4519                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4520                 return;
4521         }
4522
4523         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4524         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4525
4526         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
4527                 port->stats.ns_rffid_accepts++;
4528                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4529                 return;
4530         }
4531
4532         port->stats.ns_rffid_rejects++;
4533         bfa_trc(port->fcs, cthdr->reason_code);
4534         bfa_trc(port->fcs, cthdr->exp_code);
4535
4536         if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
4537                 /* if this command is not supported, we don't retry */
4538                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4539         } else
4540                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4541 }
4542 /*
4543  * Query Fabric for FC4-Types Devices.
4544  *
4545 * TBD : Need to use a local (FCS private) response buffer, since the response
4546  * can be larger than 2K.
4547  */
4548 static void
4549 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4550 {
4551         struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
4552         struct bfa_fcs_lport_s *port = ns->port;
4553         struct fchs_s fchs;
4554         int             len;
4555         struct bfa_fcxp_s *fcxp;
4556
4557         bfa_trc(port->fcs, port->pid);
4558
4559         fcxp = fcxp_alloced ? fcxp_alloced :
4560                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
4561         if (!fcxp) {
4562                 port->stats.ns_gidft_alloc_wait++;
4563                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4564                                 bfa_fcs_lport_ns_send_gid_ft, ns, BFA_TRUE);
4565                 return;
4566         }
4567         ns->fcxp = fcxp;
4568
4569         /*
4570          * This query is only initiated for FCP initiator mode.
4571          */
4572         len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4573                               ns->port->pid, FC_TYPE_FCP);
4574
4575         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4576                           FC_CLASS_3, len, &fchs,
4577                           bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
4578                           bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
4579
4580         port->stats.ns_gidft_sent++;
4581
4582         bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
4583 }
4584
4585 static void
4586 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4587                                 void *cbarg, bfa_status_t req_status,
4588                                 u32 rsp_len, u32 resid_len,
4589                                 struct fchs_s *rsp_fchs)
4590 {
4591         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
4592         struct bfa_fcs_lport_s *port = ns->port;
4593         struct ct_hdr_s *cthdr = NULL;
4594         u32        n_pids;
4595
4596         bfa_trc(port->fcs, port->port_cfg.pwwn);
4597
4598         /*
4599          * Sanity Checks
4600          */
4601         if (req_status != BFA_STATUS_OK) {
4602                 bfa_trc(port->fcs, req_status);
4603                 port->stats.ns_gidft_rsp_err++;
4604                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4605                 return;
4606         }
4607
4608         if (resid_len != 0) {
4609                 /*
4610                  * TBD : we will need to allocate a larger buffer & retry the
4611                  * command
4612                  */
4613                 bfa_trc(port->fcs, rsp_len);
4614                 bfa_trc(port->fcs, resid_len);
4615                 return;
4616         }
4617
4618         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
4619         cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
4620
4621         switch (cthdr->cmd_rsp_code) {
4622
4623         case CT_RSP_ACCEPT:
4624
4625                 port->stats.ns_gidft_accepts++;
4626                 n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
4627                 bfa_trc(port->fcs, n_pids);
4628                 bfa_fcs_lport_ns_process_gidft_pids(port,
4629                                                    (u32 *) (cthdr + 1),
4630                                                    n_pids);
4631                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4632                 break;
4633
4634         case CT_RSP_REJECT:
4635
4636                 /*
4637                  * Check the reason code  & explanation.
4638                  * There may not have been any FC4 devices in the fabric
4639                  */
4640                 port->stats.ns_gidft_rejects++;
4641                 bfa_trc(port->fcs, cthdr->reason_code);
4642                 bfa_trc(port->fcs, cthdr->exp_code);
4643
4644                 if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4645                     && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4646
4647                         bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4648                 } else {
4649                         /*
4650                          * for all other errors, retry
4651                          */
4652                         bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4653                 }
4654                 break;
4655
4656         default:
4657                 port->stats.ns_gidft_unknown_rsp++;
4658                 bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4659                 bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4660         }
4661 }
4662
4663 /*
4664  *     This routine will be called by bfa_timer on timer timeouts.
4665  *
4666  *      param[in]       port - pointer to bfa_fcs_lport_t.
4667  *
4668  *      return
4669  *              void
4670  *
4671  *      Special Considerations:
4672  *
4673  *      note
4674  */
4675 static void
4676 bfa_fcs_lport_ns_timeout(void *arg)
4677 {
4678         struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4679
4680         ns->port->stats.ns_timeouts++;
4681         bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4682 }
4683
4684 /*
4685  * Process the PID list in GID_FT response
4686  */
4687 static void
4688 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4689                                    u32 n_pids)
4690 {
4691         struct fcgs_gidft_resp_s *gidft_entry;
4692         struct bfa_fcs_rport_s *rport;
4693         u32        ii;
4694         struct bfa_fcs_fabric_s *fabric = port->fabric;
4695         struct bfa_fcs_vport_s *vport;
4696         struct list_head *qe;
4697         u8 found = 0;
4698
4699         for (ii = 0; ii < n_pids; ii++) {
4700                 gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4701
4702                 if (gidft_entry->pid == port->pid)
4703                         continue;
4704
4705                 /*
4706                  * Ignore PID if it is of base port
4707                  * (Avoid vports discovering base port as remote port)
4708                  */
4709                 if (gidft_entry->pid == fabric->bport.pid)
4710                         continue;
4711
4712                 /*
4713                  * Ignore PID if it is of vport created on the same base port
4714                  * (Avoid vport discovering every other vport created on the
4715                  * same port as remote port)
4716                  */
4717                 list_for_each(qe, &fabric->vport_q) {
4718                         vport = (struct bfa_fcs_vport_s *) qe;
4719                         if (vport->lport.pid == gidft_entry->pid)
4720                                 found = 1;
4721                 }
4722
4723                 if (found) {
4724                         found = 0;
4725                         continue;
4726                 }
4727
4728                 /*
4729                  * Check if this rport already exists
4730                  */
4731                 rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4732                 if (rport == NULL) {
4733                         /*
4734                          * this is a new device. create rport
4735                          */
4736                         rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4737                 } else {
4738                         /*
4739                          * this rport already exists
4740                          */
4741                         bfa_fcs_rport_scn(rport);
4742                 }
4743
4744                 bfa_trc(port->fcs, gidft_entry->pid);
4745
4746                 /*
4747                  * if the last entry bit is set, bail out.
4748                  */
4749                 if (gidft_entry->last)
4750                         return;
4751         }
4752 }
4753
4754 /*
4755  *  fcs_ns_public FCS nameserver public interfaces
4756  */
4757
4758 /*
4759  * Functions called by port/fab.
4760  * These will send relevant Events to the ns state machine.
4761  */
4762 void
4763 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4764 {
4765         struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4766
4767         ns->port = port;
4768         bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4769 }
4770
4771 void
4772 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4773 {
4774         struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4775
4776         ns->port = port;
4777         bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4778 }
4779
4780 void
4781 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4782 {
4783         struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4784
4785         ns->port = port;
4786         bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4787 }
4788
4789 void
4790 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4791 {
4792         struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4793
4794         bfa_trc(port->fcs, port->pid);
4795         if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_online))
4796                 bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4797 }
4798
4799 static void
4800 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4801 {
4802
4803         struct bfa_fcs_rport_s *rport;
4804         u8 nwwns;
4805         wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
4806         int ii;
4807
4808         bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4809
4810         for (ii = 0 ; ii < nwwns; ++ii) {
4811                 rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4812                 WARN_ON(!rport);
4813         }
4814 }
4815
4816 void
4817 bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
4818 {
4819         struct bfa_fcs_lport_ns_s *ns = cbarg;
4820         struct bfa_fcs_lport_s *port = ns->port;
4821         struct fchs_s fchs;
4822         struct bfa_fcxp_s *fcxp;
4823         u8 symbl[256];
4824         u8 *psymbl = &symbl[0];
4825         int len;
4826
4827         if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
4828                 return;
4829
4830         /* Avoid sending RSPN in the following states. */
4831         if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) ||
4832             bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) ||
4833             bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi) ||
4834             bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_retry) ||
4835             bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry))
4836                 return;
4837
4838         memset(symbl, 0, sizeof(symbl));
4839         bfa_trc(port->fcs, port->port_cfg.pwwn);
4840
4841         fcxp = fcxp_alloced ? fcxp_alloced :
4842                bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
4843         if (!fcxp) {
4844                 port->stats.ns_rspnid_alloc_wait++;
4845                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
4846                         bfa_fcs_lport_ns_util_send_rspn_id, ns, BFA_FALSE);
4847                 return;
4848         }
4849
4850         ns->fcxp = fcxp;
4851
4852         if (port->vport) {
4853                 /*
4854                  * For Vports, we append the vport's port symbolic name
4855                  * to that of the base port.
4856                  */
4857                 strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name
4858                         (bfa_fcs_get_base_port(port->fcs))),
4859                         strlen((char *)&bfa_fcs_lport_get_psym_name(
4860                         bfa_fcs_get_base_port(port->fcs))));
4861
4862                 /* Ensure we have a null terminating string. */
4863                 ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name(
4864                  bfa_fcs_get_base_port(port->fcs)))] = 0;
4865
4866                 strncat((char *)psymbl,
4867                         (char *)&(bfa_fcs_lport_get_psym_name(port)),
4868                         strlen((char *)&bfa_fcs_lport_get_psym_name(port)));
4869         }
4870
4871         len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4872                               bfa_fcs_lport_get_fcid(port), 0, psymbl);
4873
4874         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4875                       FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
4876
4877         port->stats.ns_rspnid_sent++;
4878 }
4879
4880 /*
4881  * FCS SCN
4882  */
4883
4884 #define FC_QOS_RSCN_EVENT               0x0c
4885 #define FC_FABRIC_NAME_RSCN_EVENT       0x0d
4886
4887 /*
4888  * forward declarations
4889  */
4890 static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4891                                           struct bfa_fcxp_s *fcxp_alloced);
4892 static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
4893                                               struct bfa_fcxp_s *fcxp,
4894                                               void *cbarg,
4895                                               bfa_status_t req_status,
4896                                               u32 rsp_len,
4897                                               u32 resid_len,
4898                                               struct fchs_s *rsp_fchs);
4899 static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4900                                              struct fchs_s *rx_fchs);
4901 static void     bfa_fcs_lport_scn_timeout(void *arg);
4902
4903 /*
4904  *  fcs_scm_sm FCS SCN state machine
4905  */
4906
4907 /*
4908  * VPort SCN State Machine events
4909  */
4910 enum port_scn_event {
4911         SCNSM_EVENT_PORT_ONLINE = 1,
4912         SCNSM_EVENT_PORT_OFFLINE = 2,
4913         SCNSM_EVENT_RSP_OK = 3,
4914         SCNSM_EVENT_RSP_ERROR = 4,
4915         SCNSM_EVENT_TIMEOUT = 5,
4916         SCNSM_EVENT_SCR_SENT = 6,
4917 };
4918
4919 static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4920                                             enum port_scn_event event);
4921 static void     bfa_fcs_lport_scn_sm_sending_scr(
4922                                         struct bfa_fcs_lport_scn_s *scn,
4923                                         enum port_scn_event event);
4924 static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4925                                         enum port_scn_event event);
4926 static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4927                                               enum port_scn_event event);
4928 static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4929                                            enum port_scn_event event);
4930
4931 /*
4932  *      Starting state - awaiting link up.
4933  */
4934 static void
4935 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4936                         enum port_scn_event event)
4937 {
4938         switch (event) {
4939         case SCNSM_EVENT_PORT_ONLINE:
4940                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4941                 bfa_fcs_lport_scn_send_scr(scn, NULL);
4942                 break;
4943
4944         case SCNSM_EVENT_PORT_OFFLINE:
4945                 break;
4946
4947         default:
4948                 bfa_sm_fault(scn->port->fcs, event);
4949         }
4950 }
4951
4952 static void
4953 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4954                                 enum port_scn_event event)
4955 {
4956         switch (event) {
4957         case SCNSM_EVENT_SCR_SENT:
4958                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4959                 break;
4960
4961         case SCNSM_EVENT_PORT_OFFLINE:
4962                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4963                 bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4964                 break;
4965
4966         default:
4967                 bfa_sm_fault(scn->port->fcs, event);
4968         }
4969 }
4970
4971 static void
4972 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4973                         enum port_scn_event event)
4974 {
4975         struct bfa_fcs_lport_s *port = scn->port;
4976
4977         switch (event) {
4978         case SCNSM_EVENT_RSP_OK:
4979                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4980                 break;
4981
4982         case SCNSM_EVENT_RSP_ERROR:
4983                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4984                 bfa_timer_start(port->fcs->bfa, &scn->timer,
4985                                     bfa_fcs_lport_scn_timeout, scn,
4986                                     BFA_FCS_RETRY_TIMEOUT);
4987                 break;
4988
4989         case SCNSM_EVENT_PORT_OFFLINE:
4990                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4991                 bfa_fcxp_discard(scn->fcxp);
4992                 break;
4993
4994         default:
4995                 bfa_sm_fault(port->fcs, event);
4996         }
4997 }
4998
4999 static void
5000 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
5001                                 enum port_scn_event event)
5002 {
5003         switch (event) {
5004         case SCNSM_EVENT_TIMEOUT:
5005                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
5006                 bfa_fcs_lport_scn_send_scr(scn, NULL);
5007                 break;
5008
5009         case SCNSM_EVENT_PORT_OFFLINE:
5010                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5011                 bfa_timer_stop(&scn->timer);
5012                 break;
5013
5014         default:
5015                 bfa_sm_fault(scn->port->fcs, event);
5016         }
5017 }
5018
5019 static void
5020 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
5021                         enum port_scn_event event)
5022 {
5023         switch (event) {
5024         case SCNSM_EVENT_PORT_OFFLINE:
5025                 bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5026                 break;
5027
5028         default:
5029                 bfa_sm_fault(scn->port->fcs, event);
5030         }
5031 }
5032
5033
5034
5035 /*
5036  *  fcs_scn_private FCS SCN private functions
5037  */
5038
5039 /*
5040  * This routine will be called to send a SCR command.
5041  */
5042 static void
5043 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
5044 {
5045         struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
5046         struct bfa_fcs_lport_s *port = scn->port;
5047         struct fchs_s fchs;
5048         int             len;
5049         struct bfa_fcxp_s *fcxp;
5050
5051         bfa_trc(port->fcs, port->pid);
5052         bfa_trc(port->fcs, port->port_cfg.pwwn);
5053
5054         fcxp = fcxp_alloced ? fcxp_alloced :
5055                bfa_fcs_fcxp_alloc(port->fcs, BFA_TRUE);
5056         if (!fcxp) {
5057                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
5058                                 bfa_fcs_lport_scn_send_scr, scn, BFA_TRUE);
5059                 return;
5060         }
5061         scn->fcxp = fcxp;
5062
5063         /* Handle VU registrations for Base port only */
5064         if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
5065                 len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5066                                 port->fabric->lps->brcd_switch,
5067                                 port->pid, 0);
5068         } else {
5069             len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5070                                     BFA_FALSE,
5071                                     port->pid, 0);
5072         }
5073
5074         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
5075                           FC_CLASS_3, len, &fchs,
5076                           bfa_fcs_lport_scn_scr_response,
5077                           (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
5078
5079         bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
5080 }
5081
5082 static void
5083 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
5084                         void *cbarg, bfa_status_t req_status, u32 rsp_len,
5085                               u32 resid_len, struct fchs_s *rsp_fchs)
5086 {
5087         struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
5088         struct bfa_fcs_lport_s *port = scn->port;
5089         struct fc_els_cmd_s *els_cmd;
5090         struct fc_ls_rjt_s *ls_rjt;
5091
5092         bfa_trc(port->fcs, port->port_cfg.pwwn);
5093
5094         /*
5095          * Sanity Checks
5096          */
5097         if (req_status != BFA_STATUS_OK) {
5098                 bfa_trc(port->fcs, req_status);
5099                 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5100                 return;
5101         }
5102
5103         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
5104
5105         switch (els_cmd->els_code) {
5106
5107         case FC_ELS_ACC:
5108                 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
5109                 break;
5110
5111         case FC_ELS_LS_RJT:
5112
5113                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
5114
5115                 bfa_trc(port->fcs, ls_rjt->reason_code);
5116                 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
5117
5118                 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5119                 break;
5120
5121         default:
5122                 bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
5123         }
5124 }
5125
5126 /*
5127  * Send a LS Accept
5128  */
5129 static void
5130 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
5131                                 struct fchs_s *rx_fchs)
5132 {
5133         struct fchs_s fchs;
5134         struct bfa_fcxp_s *fcxp;
5135         struct bfa_rport_s *bfa_rport = NULL;
5136         int             len;
5137
5138         bfa_trc(port->fcs, rx_fchs->s_id);
5139
5140         fcxp = bfa_fcs_fcxp_alloc(port->fcs, BFA_FALSE);
5141         if (!fcxp)
5142                 return;
5143
5144         len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
5145                               rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
5146                               rx_fchs->ox_id);
5147
5148         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
5149                           BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
5150                           FC_MAX_PDUSZ, 0);
5151 }
5152
5153 /*
5154  *     This routine will be called by bfa_timer on timer timeouts.
5155  *
5156  *      param[in]       vport           - pointer to bfa_fcs_lport_t.
5157  *      param[out]      vport_status    - pointer to return vport status in
5158  *
5159  *      return
5160  *              void
5161  *
5162  *      Special Considerations:
5163  *
5164  *      note
5165  */
5166 static void
5167 bfa_fcs_lport_scn_timeout(void *arg)
5168 {
5169         struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
5170
5171         bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
5172 }
5173
5174
5175
5176 /*
5177  *  fcs_scn_public FCS state change notification public interfaces
5178  */
5179
5180 /*
5181  * Functions called by port/fab
5182  */
5183 void
5184 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
5185 {
5186         struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5187
5188         scn->port = port;
5189         bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
5190 }
5191
5192 void
5193 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
5194 {
5195         struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5196
5197         scn->port = port;
5198         bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
5199 }
5200
5201 void
5202 bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
5203 {
5204         struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
5205
5206         scn->port = port;
5207         bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
5208 }
5209
5210 static void
5211 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
5212 {
5213         struct bfa_fcs_rport_s *rport;
5214         struct bfa_fcs_fabric_s *fabric = port->fabric;
5215         struct bfa_fcs_vport_s *vport;
5216         struct list_head *qe;
5217
5218         bfa_trc(port->fcs, rpid);
5219
5220         /*
5221          * Ignore PID if it is of base port or of vports created on the
5222          * same base port. It is to avoid vports discovering base port or
5223          * other vports created on same base port as remote port
5224          */
5225         if (rpid == fabric->bport.pid)
5226                 return;
5227
5228         list_for_each(qe, &fabric->vport_q) {
5229                 vport = (struct bfa_fcs_vport_s *) qe;
5230                 if (vport->lport.pid == rpid)
5231                         return;
5232         }
5233         /*
5234          * If this is an unknown device, then it just came online.
5235          * Otherwise let rport handle the RSCN event.
5236          */
5237         rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
5238         if (!rport)
5239                 rport = bfa_fcs_lport_get_rport_by_old_pid(port, rpid);
5240
5241         if (rport == NULL) {
5242                 /*
5243                  * If min cfg mode is enabled, we donot need to
5244                  * discover any new rports.
5245                  */
5246                 if (!__fcs_min_cfg(port->fcs))
5247                         rport = bfa_fcs_rport_create(port, rpid);
5248         } else
5249                 bfa_fcs_rport_scn(rport);
5250 }
5251
5252 /*
5253  * rscn format based PID comparison
5254  */
5255 #define __fc_pid_match(__c0, __c1, __fmt)               \
5256         (((__fmt) == FC_RSCN_FORMAT_FABRIC) ||          \
5257          (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&         \
5258           ((__c0)[0] == (__c1)[0])) ||                          \
5259          (((__fmt) == FC_RSCN_FORMAT_AREA) &&           \
5260           ((__c0)[0] == (__c1)[0]) &&                           \
5261           ((__c0)[1] == (__c1)[1])))
5262
5263 static void
5264 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
5265                                 enum fc_rscn_format format,
5266                                 u32 rscn_pid)
5267 {
5268         struct bfa_fcs_rport_s *rport;
5269         struct list_head        *qe, *qe_next;
5270         u8        *c0, *c1;
5271
5272         bfa_trc(port->fcs, format);
5273         bfa_trc(port->fcs, rscn_pid);
5274
5275         c0 = (u8 *) &rscn_pid;
5276
5277         list_for_each_safe(qe, qe_next, &port->rport_q) {
5278                 rport = (struct bfa_fcs_rport_s *) qe;
5279                 c1 = (u8 *) &rport->pid;
5280                 if (__fc_pid_match(c0, c1, format))
5281                         bfa_fcs_rport_scn(rport);
5282         }
5283 }
5284
5285
5286 void
5287 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
5288                         struct fchs_s *fchs, u32 len)
5289 {
5290         struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
5291         int             num_entries;
5292         u32        rscn_pid;
5293         bfa_boolean_t   nsquery = BFA_FALSE, found;
5294         int             i = 0, j;
5295
5296         num_entries =
5297                 (be16_to_cpu(rscn->payldlen) -
5298                  sizeof(u32)) / sizeof(rscn->event[0]);
5299
5300         bfa_trc(port->fcs, num_entries);
5301
5302         port->stats.num_rscn++;
5303
5304         bfa_fcs_lport_scn_send_ls_acc(port, fchs);
5305
5306         for (i = 0; i < num_entries; i++) {
5307                 rscn_pid = rscn->event[i].portid;
5308
5309                 bfa_trc(port->fcs, rscn->event[i].format);
5310                 bfa_trc(port->fcs, rscn_pid);
5311
5312                 /* check for duplicate entries in the list */
5313                 found = BFA_FALSE;
5314                 for (j = 0; j < i; j++) {
5315                         if (rscn->event[j].portid == rscn_pid) {
5316                                 found = BFA_TRUE;
5317                                 break;
5318                         }
5319                 }
5320
5321                 /* if found in down the list, pid has been already processed */
5322                 if (found) {
5323                         bfa_trc(port->fcs, rscn_pid);
5324                         continue;
5325                 }
5326
5327                 switch (rscn->event[i].format) {
5328                 case FC_RSCN_FORMAT_PORTID:
5329                         if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
5330                                 /*
5331                                  * Ignore this event.
5332                                  * f/w would have processed it
5333                                  */
5334                                 bfa_trc(port->fcs, rscn_pid);
5335                         } else {
5336                                 port->stats.num_portid_rscn++;
5337                                 bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
5338                         }
5339                 break;
5340
5341                 case FC_RSCN_FORMAT_FABRIC:
5342                         if (rscn->event[i].qualifier ==
5343                                         FC_FABRIC_NAME_RSCN_EVENT) {
5344                                 bfa_fcs_lport_ms_fabric_rscn(port);
5345                                 break;
5346                         }
5347                         /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
5348
5349                 case FC_RSCN_FORMAT_AREA:
5350                 case FC_RSCN_FORMAT_DOMAIN:
5351                         nsquery = BFA_TRUE;
5352                         bfa_fcs_lport_scn_multiport_rscn(port,
5353                                                         rscn->event[i].format,
5354                                                         rscn_pid);
5355                         break;
5356
5357
5358                 default:
5359                         WARN_ON(1);
5360                         nsquery = BFA_TRUE;
5361                 }
5362         }
5363
5364         /*
5365          * If any of area, domain or fabric RSCN is received, do a fresh
5366          * discovery to find new devices.
5367          */
5368         if (nsquery)
5369                 bfa_fcs_lport_ns_query(port);
5370 }
5371
5372 /*
5373  * BFA FCS port
5374  */
5375 /*
5376  *  fcs_port_api BFA FCS port API
5377  */
5378 struct bfa_fcs_lport_s *
5379 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
5380 {
5381         return &fcs->fabric.bport;
5382 }
5383
5384 wwn_t
5385 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
5386                 int nrports, bfa_boolean_t bwwn)
5387 {
5388         struct list_head        *qh, *qe;
5389         struct bfa_fcs_rport_s *rport = NULL;
5390         int     i;
5391         struct bfa_fcs_s        *fcs;
5392
5393         if (port == NULL || nrports == 0)
5394                 return (wwn_t) 0;
5395
5396         fcs = port->fcs;
5397         bfa_trc(fcs, (u32) nrports);
5398
5399         i = 0;
5400         qh = &port->rport_q;
5401         qe = bfa_q_first(qh);
5402
5403         while ((qe != qh) && (i < nrports)) {
5404                 rport = (struct bfa_fcs_rport_s *) qe;
5405                 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5406                         qe = bfa_q_next(qe);
5407                         bfa_trc(fcs, (u32) rport->pwwn);
5408                         bfa_trc(fcs, rport->pid);
5409                         bfa_trc(fcs, i);
5410                         continue;
5411                 }
5412
5413                 if (bwwn) {
5414                         if (!memcmp(&wwn, &rport->pwwn, 8))
5415                                 break;
5416                 } else {
5417                         if (i == index)
5418                                 break;
5419                 }
5420
5421                 i++;
5422                 qe = bfa_q_next(qe);
5423         }
5424
5425         bfa_trc(fcs, i);
5426         if (rport)
5427                 return rport->pwwn;
5428         else
5429                 return (wwn_t) 0;
5430 }
5431
5432 void
5433 bfa_fcs_lport_get_rport_quals(struct bfa_fcs_lport_s *port,
5434                 struct bfa_rport_qualifier_s rports[], int *nrports)
5435 {
5436         struct list_head        *qh, *qe;
5437         struct bfa_fcs_rport_s *rport = NULL;
5438         int     i;
5439         struct bfa_fcs_s        *fcs;
5440
5441         if (port == NULL || rports == NULL || *nrports == 0)
5442                 return;
5443
5444         fcs = port->fcs;
5445         bfa_trc(fcs, (u32) *nrports);
5446
5447         i = 0;
5448         qh = &port->rport_q;
5449         qe = bfa_q_first(qh);
5450
5451         while ((qe != qh) && (i < *nrports)) {
5452                 rport = (struct bfa_fcs_rport_s *) qe;
5453                 if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
5454                         qe = bfa_q_next(qe);
5455                         bfa_trc(fcs, (u32) rport->pwwn);
5456                         bfa_trc(fcs, rport->pid);
5457                         bfa_trc(fcs, i);
5458                         continue;
5459                 }
5460
5461                 if (!rport->pwwn && !rport->pid) {
5462                         qe = bfa_q_next(qe);
5463                         continue;
5464                 }
5465
5466                 rports[i].pwwn = rport->pwwn;
5467                 rports[i].pid = rport->pid;
5468
5469                 i++;
5470                 qe = bfa_q_next(qe);
5471         }
5472
5473         bfa_trc(fcs, i);
5474         *nrports = i;
5475 }
5476
5477 /*
5478  * Iterate's through all the rport's in the given port to
5479  * determine the maximum operating speed.
5480  *
5481  * !!!! To be used in TRL Functionality only !!!!
5482  */
5483 bfa_port_speed_t
5484 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
5485 {
5486         struct list_head *qh, *qe;
5487         struct bfa_fcs_rport_s *rport = NULL;
5488         struct bfa_fcs_s        *fcs;
5489         bfa_port_speed_t max_speed = 0;
5490         struct bfa_port_attr_s port_attr;
5491         bfa_port_speed_t port_speed, rport_speed;
5492         bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
5493
5494
5495         if (port == NULL)
5496                 return 0;
5497
5498         fcs = port->fcs;
5499
5500         /* Get Physical port's current speed */
5501         bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
5502         port_speed = port_attr.speed;
5503         bfa_trc(fcs, port_speed);
5504
5505         qh = &port->rport_q;
5506         qe = bfa_q_first(qh);
5507
5508         while (qe != qh) {
5509                 rport = (struct bfa_fcs_rport_s *) qe;
5510                 if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
5511                         (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE) ||
5512                         (rport->scsi_function != BFA_RPORT_TARGET)) {
5513                         qe = bfa_q_next(qe);
5514                         continue;
5515                 }
5516
5517                 rport_speed = rport->rpf.rpsc_speed;
5518                 if ((trl_enabled) && (rport_speed ==
5519                         BFA_PORT_SPEED_UNKNOWN)) {
5520                         /* Use default ratelim speed setting */
5521                         rport_speed =
5522                                 bfa_fcport_get_ratelim_speed(port->fcs->bfa);
5523                 }
5524
5525                 if (rport_speed > max_speed)
5526                         max_speed = rport_speed;
5527
5528                 qe = bfa_q_next(qe);
5529         }
5530
5531         if (max_speed > port_speed)
5532                 max_speed = port_speed;
5533
5534         bfa_trc(fcs, max_speed);
5535         return max_speed;
5536 }
5537
5538 struct bfa_fcs_lport_s *
5539 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
5540 {
5541         struct bfa_fcs_vport_s *vport;
5542         bfa_fcs_vf_t   *vf;
5543
5544         WARN_ON(fcs == NULL);
5545
5546         vf = bfa_fcs_vf_lookup(fcs, vf_id);
5547         if (vf == NULL) {
5548                 bfa_trc(fcs, vf_id);
5549                 return NULL;
5550         }
5551
5552         if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
5553                 return &vf->bport;
5554
5555         vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
5556         if (vport)
5557                 return &vport->lport;
5558
5559         return NULL;
5560 }
5561
5562 /*
5563  *  API corresponding to NPIV_VPORT_GETINFO.
5564  */
5565 void
5566 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
5567          struct bfa_lport_info_s *port_info)
5568 {
5569
5570         bfa_trc(port->fcs, port->fabric->fabric_name);
5571
5572         if (port->vport == NULL) {
5573                 /*
5574                  * This is a Physical port
5575                  */
5576                 port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
5577
5578                 /*
5579                  * @todo : need to fix the state & reason
5580                  */
5581                 port_info->port_state = 0;
5582                 port_info->offline_reason = 0;
5583
5584                 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5585                 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5586
5587                 port_info->max_vports_supp =
5588                         bfa_lps_get_max_vport(port->fcs->bfa);
5589                 port_info->num_vports_inuse =
5590                         port->fabric->num_vports;
5591                 port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
5592                 port_info->num_rports_inuse = port->num_rports;
5593         } else {
5594                 /*
5595                  * This is a virtual port
5596                  */
5597                 port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
5598
5599                 /*
5600                  * @todo : need to fix the state & reason
5601                  */
5602                 port_info->port_state = 0;
5603                 port_info->offline_reason = 0;
5604
5605                 port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
5606                 port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
5607         }
5608 }
5609
5610 void
5611 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
5612          struct bfa_lport_stats_s *port_stats)
5613 {
5614         *port_stats = fcs_port->stats;
5615 }
5616
5617 void
5618 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
5619 {
5620         memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
5621 }
5622
5623 /*
5624  * FCS virtual port state machine
5625  */
5626
5627 #define __vport_fcs(__vp)       ((__vp)->lport.fcs)
5628 #define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
5629 #define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
5630 #define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
5631 #define __vport_fcid(__vp)      ((__vp)->lport.pid)
5632 #define __vport_fabric(__vp)    ((__vp)->lport.fabric)
5633 #define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
5634
5635 #define BFA_FCS_VPORT_MAX_RETRIES  5
5636 /*
5637  * Forward declarations
5638  */
5639 static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
5640 static void     bfa_fcs_vport_timeout(void *vport_arg);
5641 static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
5642 static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
5643
5644 /*
5645  *  fcs_vport_sm FCS virtual port state machine
5646  */
5647
5648 /*
5649  * VPort State Machine events
5650  */
5651 enum bfa_fcs_vport_event {
5652         BFA_FCS_VPORT_SM_CREATE = 1,    /*  vport create event */
5653         BFA_FCS_VPORT_SM_DELETE = 2,    /*  vport delete event */
5654         BFA_FCS_VPORT_SM_START = 3,     /*  vport start request */
5655         BFA_FCS_VPORT_SM_STOP = 4,      /*  stop: unsupported */
5656         BFA_FCS_VPORT_SM_ONLINE = 5,    /*  fabric online */
5657         BFA_FCS_VPORT_SM_OFFLINE = 6,   /*  fabric offline event */
5658         BFA_FCS_VPORT_SM_FRMSENT = 7,   /*  fdisc/logo sent events */
5659         BFA_FCS_VPORT_SM_RSP_OK = 8,    /*  good response */
5660         BFA_FCS_VPORT_SM_RSP_ERROR = 9, /*  error/bad response */
5661         BFA_FCS_VPORT_SM_TIMEOUT = 10,  /*  delay timer event */
5662         BFA_FCS_VPORT_SM_DELCOMP = 11,  /*  lport delete completion */
5663         BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,      /*  Dup wnn error*/
5664         BFA_FCS_VPORT_SM_RSP_FAILED = 13,       /*  non-retryable failure */
5665         BFA_FCS_VPORT_SM_STOPCOMP = 14, /* vport delete completion */
5666 };
5667
5668 static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
5669                                         enum bfa_fcs_vport_event event);
5670 static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
5671                                          enum bfa_fcs_vport_event event);
5672 static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5673                                          enum bfa_fcs_vport_event event);
5674 static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5675                                        enum bfa_fcs_vport_event event);
5676 static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5677                                              enum bfa_fcs_vport_event event);
5678 static void     bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
5679                                         enum bfa_fcs_vport_event event);
5680 static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5681                                         enum bfa_fcs_vport_event event);
5682 static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5683                                           enum bfa_fcs_vport_event event);
5684 static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5685                                          enum bfa_fcs_vport_event event);
5686 static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5687                                       enum bfa_fcs_vport_event event);
5688 static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5689                                       enum bfa_fcs_vport_event event);
5690 static void     bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
5691                                         enum bfa_fcs_vport_event event);
5692 static void     bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
5693                                         enum bfa_fcs_vport_event event);
5694
5695 static struct bfa_sm_table_s  vport_sm_table[] = {
5696         {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
5697         {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
5698         {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
5699         {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
5700         {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
5701         {BFA_SM(bfa_fcs_vport_sm_fdisc_rsp_wait), BFA_FCS_VPORT_FDISC_RSP_WAIT},
5702         {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
5703         {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
5704         {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
5705         {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
5706         {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
5707 };
5708
5709 /*
5710  * Beginning state.
5711  */
5712 static void
5713 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
5714                         enum bfa_fcs_vport_event event)
5715 {
5716         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5717         bfa_trc(__vport_fcs(vport), event);
5718
5719         switch (event) {
5720         case BFA_FCS_VPORT_SM_CREATE:
5721                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
5722                 bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
5723                 break;
5724
5725         default:
5726                 bfa_sm_fault(__vport_fcs(vport), event);
5727         }
5728 }
5729
5730 /*
5731  * Created state - a start event is required to start up the state machine.
5732  */
5733 static void
5734 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
5735                         enum bfa_fcs_vport_event event)
5736 {
5737         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5738         bfa_trc(__vport_fcs(vport), event);
5739
5740         switch (event) {
5741         case BFA_FCS_VPORT_SM_START:
5742                 if (bfa_sm_cmp_state(__vport_fabric(vport),
5743                                         bfa_fcs_fabric_sm_online)
5744                     && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
5745                         bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5746                         bfa_fcs_vport_do_fdisc(vport);
5747                 } else {
5748                         /*
5749                          * Fabric is offline or not NPIV capable, stay in
5750                          * offline state.
5751                          */
5752                         vport->vport_stats.fab_no_npiv++;
5753                         bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5754                 }
5755                 break;
5756
5757         case BFA_FCS_VPORT_SM_DELETE:
5758                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5759                 bfa_fcs_lport_delete(&vport->lport);
5760                 break;
5761
5762         case BFA_FCS_VPORT_SM_ONLINE:
5763         case BFA_FCS_VPORT_SM_OFFLINE:
5764                 /*
5765                  * Ignore ONLINE/OFFLINE events from fabric
5766                  * till vport is started.
5767                  */
5768                 break;
5769
5770         default:
5771                 bfa_sm_fault(__vport_fcs(vport), event);
5772         }
5773 }
5774
5775 /*
5776  * Offline state - awaiting ONLINE event from fabric SM.
5777  */
5778 static void
5779 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5780                         enum bfa_fcs_vport_event event)
5781 {
5782         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5783         bfa_trc(__vport_fcs(vport), event);
5784
5785         switch (event) {
5786         case BFA_FCS_VPORT_SM_DELETE:
5787                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5788                 bfa_fcs_lport_delete(&vport->lport);
5789                 break;
5790
5791         case BFA_FCS_VPORT_SM_ONLINE:
5792                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5793                 vport->fdisc_retries = 0;
5794                 bfa_fcs_vport_do_fdisc(vport);
5795                 break;
5796
5797         case BFA_FCS_VPORT_SM_STOP:
5798                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5799                 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
5800                 break;
5801
5802         case BFA_FCS_VPORT_SM_OFFLINE:
5803                 /*
5804                  * This can happen if the vport couldn't be initialzied
5805                  * due the fact that the npiv was not enabled on the switch.
5806                  * In that case we will put the vport in offline state.
5807                  * However, the link can go down and cause the this event to
5808                  * be sent when we are already offline. Ignore it.
5809                  */
5810                 break;
5811
5812         default:
5813                 bfa_sm_fault(__vport_fcs(vport), event);
5814         }
5815 }
5816
5817
5818 /*
5819  * FDISC is sent and awaiting reply from fabric.
5820  */
5821 static void
5822 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5823                         enum bfa_fcs_vport_event event)
5824 {
5825         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5826         bfa_trc(__vport_fcs(vport), event);
5827
5828         switch (event) {
5829         case BFA_FCS_VPORT_SM_DELETE:
5830                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_rsp_wait);
5831                 break;
5832
5833         case BFA_FCS_VPORT_SM_OFFLINE:
5834                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5835                 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5836                 break;
5837
5838         case BFA_FCS_VPORT_SM_RSP_OK:
5839                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5840                 bfa_fcs_lport_online(&vport->lport);
5841                 break;
5842
5843         case BFA_FCS_VPORT_SM_RSP_ERROR:
5844                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5845                 bfa_timer_start(__vport_bfa(vport), &vport->timer,
5846                                     bfa_fcs_vport_timeout, vport,
5847                                     BFA_FCS_RETRY_TIMEOUT);
5848                 break;
5849
5850         case BFA_FCS_VPORT_SM_RSP_FAILED:
5851                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5852                 break;
5853
5854         case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5855                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5856                 break;
5857
5858         default:
5859                 bfa_sm_fault(__vport_fcs(vport), event);
5860         }
5861 }
5862
5863 /*
5864  * FDISC attempt failed - a timer is active to retry FDISC.
5865  */
5866 static void
5867 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5868                              enum bfa_fcs_vport_event event)
5869 {
5870         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5871         bfa_trc(__vport_fcs(vport), event);
5872
5873         switch (event) {
5874         case BFA_FCS_VPORT_SM_DELETE:
5875                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5876                 bfa_timer_stop(&vport->timer);
5877                 bfa_fcs_lport_delete(&vport->lport);
5878                 break;
5879
5880         case BFA_FCS_VPORT_SM_OFFLINE:
5881                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5882                 bfa_timer_stop(&vport->timer);
5883                 break;
5884
5885         case BFA_FCS_VPORT_SM_TIMEOUT:
5886                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5887                 vport->vport_stats.fdisc_retries++;
5888                 vport->fdisc_retries++;
5889                 bfa_fcs_vport_do_fdisc(vport);
5890                 break;
5891
5892         default:
5893                 bfa_sm_fault(__vport_fcs(vport), event);
5894         }
5895 }
5896
5897 /*
5898  * FDISC is in progress and we got a vport delete request -
5899  * this is a wait state while we wait for fdisc response and
5900  * we will transition to the appropriate state - on rsp status.
5901  */
5902 static void
5903 bfa_fcs_vport_sm_fdisc_rsp_wait(struct bfa_fcs_vport_s *vport,
5904                                 enum bfa_fcs_vport_event event)
5905 {
5906         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5907         bfa_trc(__vport_fcs(vport), event);
5908
5909         switch (event) {
5910         case BFA_FCS_VPORT_SM_RSP_OK:
5911                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5912                 bfa_fcs_lport_delete(&vport->lport);
5913                 break;
5914
5915         case BFA_FCS_VPORT_SM_DELETE:
5916                 break;
5917
5918         case BFA_FCS_VPORT_SM_OFFLINE:
5919         case BFA_FCS_VPORT_SM_RSP_ERROR:
5920         case BFA_FCS_VPORT_SM_RSP_FAILED:
5921         case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5922                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5923                 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5924                 bfa_fcs_lport_delete(&vport->lport);
5925                 break;
5926
5927         default:
5928                 bfa_sm_fault(__vport_fcs(vport), event);
5929         }
5930 }
5931
5932 /*
5933  * Vport is online (FDISC is complete).
5934  */
5935 static void
5936 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5937                         enum bfa_fcs_vport_event event)
5938 {
5939         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5940         bfa_trc(__vport_fcs(vport), event);
5941
5942         switch (event) {
5943         case BFA_FCS_VPORT_SM_DELETE:
5944                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5945                 bfa_fcs_lport_delete(&vport->lport);
5946                 break;
5947
5948         case BFA_FCS_VPORT_SM_STOP:
5949                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_stopping);
5950                 bfa_sm_send_event(&vport->lport, BFA_FCS_PORT_SM_STOP);
5951                 break;
5952
5953         case BFA_FCS_VPORT_SM_OFFLINE:
5954                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5955                 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5956                 bfa_fcs_lport_offline(&vport->lport);
5957                 break;
5958
5959         default:
5960                 bfa_sm_fault(__vport_fcs(vport), event);
5961         }
5962 }
5963
5964 /*
5965  * Vport is being stopped - awaiting lport stop completion to send
5966  * LOGO to fabric.
5967  */
5968 static void
5969 bfa_fcs_vport_sm_stopping(struct bfa_fcs_vport_s *vport,
5970                           enum bfa_fcs_vport_event event)
5971 {
5972         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5973         bfa_trc(__vport_fcs(vport), event);
5974
5975         switch (event) {
5976         case BFA_FCS_VPORT_SM_STOPCOMP:
5977                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo_for_stop);
5978                 bfa_fcs_vport_do_logo(vport);
5979                 break;
5980
5981         case BFA_FCS_VPORT_SM_OFFLINE:
5982                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5983                 break;
5984
5985         default:
5986                 bfa_sm_fault(__vport_fcs(vport), event);
5987         }
5988 }
5989
5990 /*
5991  * Vport is being deleted - awaiting lport delete completion to send
5992  * LOGO to fabric.
5993  */
5994 static void
5995 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5996                         enum bfa_fcs_vport_event event)
5997 {
5998         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5999         bfa_trc(__vport_fcs(vport), event);
6000
6001         switch (event) {
6002         case BFA_FCS_VPORT_SM_DELETE:
6003                 break;
6004
6005         case BFA_FCS_VPORT_SM_DELCOMP:
6006                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
6007                 bfa_fcs_vport_do_logo(vport);
6008                 break;
6009
6010         case BFA_FCS_VPORT_SM_OFFLINE:
6011                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6012                 break;
6013
6014         default:
6015                 bfa_sm_fault(__vport_fcs(vport), event);
6016         }
6017 }
6018
6019 /*
6020  * Error State.
6021  * This state will be set when the Vport Creation fails due
6022  * to errors like Dup WWN. In this state only operation allowed
6023  * is a Vport Delete.
6024  */
6025 static void
6026 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
6027                         enum bfa_fcs_vport_event event)
6028 {
6029         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6030         bfa_trc(__vport_fcs(vport), event);
6031
6032         switch (event) {
6033         case BFA_FCS_VPORT_SM_DELETE:
6034                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
6035                 bfa_fcs_lport_delete(&vport->lport);
6036                 break;
6037
6038         default:
6039                 bfa_trc(__vport_fcs(vport), event);
6040         }
6041 }
6042
6043 /*
6044  * Lport cleanup is in progress since vport is being deleted. Fabric is
6045  * offline, so no LOGO is needed to complete vport deletion.
6046  */
6047 static void
6048 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
6049                         enum bfa_fcs_vport_event event)
6050 {
6051         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6052         bfa_trc(__vport_fcs(vport), event);
6053
6054         switch (event) {
6055         case BFA_FCS_VPORT_SM_DELCOMP:
6056                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6057                 bfa_fcs_vport_free(vport);
6058                 break;
6059
6060         case BFA_FCS_VPORT_SM_STOPCOMP:
6061                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6062                 break;
6063
6064         case BFA_FCS_VPORT_SM_DELETE:
6065                 break;
6066
6067         default:
6068                 bfa_sm_fault(__vport_fcs(vport), event);
6069         }
6070 }
6071
6072 /*
6073  * LOGO is sent to fabric. Vport stop is in progress. Lport stop cleanup
6074  * is done.
6075  */
6076 static void
6077 bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport,
6078                                enum bfa_fcs_vport_event event)
6079 {
6080         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6081         bfa_trc(__vport_fcs(vport), event);
6082
6083         switch (event) {
6084         case BFA_FCS_VPORT_SM_OFFLINE:
6085                 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6086                 /*
6087                  * !!! fall through !!!
6088                  */
6089
6090         case BFA_FCS_VPORT_SM_RSP_OK:
6091         case BFA_FCS_VPORT_SM_RSP_ERROR:
6092                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
6093                 break;
6094
6095         default:
6096                 bfa_sm_fault(__vport_fcs(vport), event);
6097         }
6098 }
6099
6100 /*
6101  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
6102  * is done.
6103  */
6104 static void
6105 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
6106                         enum bfa_fcs_vport_event event)
6107 {
6108         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6109         bfa_trc(__vport_fcs(vport), event);
6110
6111         switch (event) {
6112         case BFA_FCS_VPORT_SM_OFFLINE:
6113                 bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
6114                 /*
6115                  * !!! fall through !!!
6116                  */
6117
6118         case BFA_FCS_VPORT_SM_RSP_OK:
6119         case BFA_FCS_VPORT_SM_RSP_ERROR:
6120                 bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6121                 bfa_fcs_vport_free(vport);
6122                 break;
6123
6124         case BFA_FCS_VPORT_SM_DELETE:
6125                 break;
6126
6127         default:
6128                 bfa_sm_fault(__vport_fcs(vport), event);
6129         }
6130 }
6131
6132
6133
6134 /*
6135  *  fcs_vport_private FCS virtual port private functions
6136  */
6137 /*
6138  * Send AEN notification
6139  */
6140 static void
6141 bfa_fcs_vport_aen_post(struct bfa_fcs_lport_s *port,
6142                        enum bfa_lport_aen_event event)
6143 {
6144         struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;
6145         struct bfa_aen_entry_s  *aen_entry;
6146
6147         bfad_get_aen_entry(bfad, aen_entry);
6148         if (!aen_entry)
6149                 return;
6150
6151         aen_entry->aen_data.lport.vf_id = port->fabric->vf_id;
6152         aen_entry->aen_data.lport.roles = port->port_cfg.roles;
6153         aen_entry->aen_data.lport.ppwwn = bfa_fcs_lport_get_pwwn(
6154                                         bfa_fcs_get_base_port(port->fcs));
6155         aen_entry->aen_data.lport.lpwwn = bfa_fcs_lport_get_pwwn(port);
6156
6157         /* Send the AEN notification */
6158         bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,
6159                                   BFA_AEN_CAT_LPORT, event);
6160 }
6161
6162 /*
6163  * This routine will be called to send a FDISC command.
6164  */
6165 static void
6166 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
6167 {
6168         bfa_lps_fdisc(vport->lps, vport,
6169                 bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
6170                 __vport_pwwn(vport), __vport_nwwn(vport));
6171         vport->vport_stats.fdisc_sent++;
6172 }
6173
6174 static void
6175 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
6176 {
6177         u8              lsrjt_rsn = vport->lps->lsrjt_rsn;
6178         u8              lsrjt_expl = vport->lps->lsrjt_expl;
6179
6180         bfa_trc(__vport_fcs(vport), lsrjt_rsn);
6181         bfa_trc(__vport_fcs(vport), lsrjt_expl);
6182
6183         /* For certain reason codes, we don't want to retry. */
6184         switch (vport->lps->lsrjt_expl) {
6185         case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
6186         case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
6187                 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6188                         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6189                 else {
6190                         bfa_fcs_vport_aen_post(&vport->lport,
6191                                         BFA_LPORT_AEN_NPIV_DUP_WWN);
6192                         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
6193                 }
6194                 break;
6195
6196         case FC_LS_RJT_EXP_INSUFF_RES:
6197                 /*
6198                  * This means max logins per port/switch setting on the
6199                  * switch was exceeded.
6200                  */
6201                 if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
6202                         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6203                 else {
6204                         bfa_fcs_vport_aen_post(&vport->lport,
6205                                         BFA_LPORT_AEN_NPIV_FABRIC_MAX);
6206                         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
6207                 }
6208                 break;
6209
6210         default:
6211                 if (vport->fdisc_retries == 0)
6212                         bfa_fcs_vport_aen_post(&vport->lport,
6213                                         BFA_LPORT_AEN_NPIV_UNKNOWN);
6214                 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6215         }
6216 }
6217
6218 /*
6219  *      Called to send a logout to the fabric. Used when a V-Port is
6220  *      deleted/stopped.
6221  */
6222 static void
6223 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
6224 {
6225         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6226
6227         vport->vport_stats.logo_sent++;
6228         bfa_lps_fdisclogo(vport->lps);
6229 }
6230
6231
6232 /*
6233  *     This routine will be called by bfa_timer on timer timeouts.
6234  *
6235  *      param[in]       vport           - pointer to bfa_fcs_vport_t.
6236  *      param[out]      vport_status    - pointer to return vport status in
6237  *
6238  *      return
6239  *              void
6240  *
6241  *      Special Considerations:
6242  *
6243  *      note
6244  */
6245 static void
6246 bfa_fcs_vport_timeout(void *vport_arg)
6247 {
6248         struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
6249
6250         vport->vport_stats.fdisc_timeouts++;
6251         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
6252 }
6253
6254 static void
6255 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
6256 {
6257         struct bfad_vport_s *vport_drv =
6258                         (struct bfad_vport_s *)vport->vport_drv;
6259
6260         bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
6261         bfa_lps_delete(vport->lps);
6262
6263         if (vport_drv->comp_del) {
6264                 complete(vport_drv->comp_del);
6265                 return;
6266         }
6267
6268         /*
6269          * We queue the vport delete work to the IM work_q from here.
6270          * The memory for the bfad_vport_s is freed from the FC function
6271          * template vport_delete entry point.
6272          */
6273         bfad_im_port_delete(vport_drv->drv_port.bfad, &vport_drv->drv_port);
6274 }
6275
6276 /*
6277  *  fcs_vport_public FCS virtual port public interfaces
6278  */
6279
6280 /*
6281  * Online notification from fabric SM.
6282  */
6283 void
6284 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
6285 {
6286         vport->vport_stats.fab_online++;
6287         if (bfa_fcs_fabric_npiv_capable(__vport_fabric(vport)))
6288                 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6289         else
6290                 vport->vport_stats.fab_no_npiv++;
6291 }
6292
6293 /*
6294  * Offline notification from fabric SM.
6295  */
6296 void
6297 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
6298 {
6299         vport->vport_stats.fab_offline++;
6300         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6301 }
6302
6303 /*
6304  * Cleanup notification from fabric SM on link timer expiry.
6305  */
6306 void
6307 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
6308 {
6309         vport->vport_stats.fab_cleanup++;
6310 }
6311
6312 /*
6313  * Stop notification from fabric SM. To be invoked from within FCS.
6314  */
6315 void
6316 bfa_fcs_vport_fcs_stop(struct bfa_fcs_vport_s *vport)
6317 {
6318         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6319 }
6320
6321 /*
6322  * delete notification from fabric SM. To be invoked from within FCS.
6323  */
6324 void
6325 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
6326 {
6327         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6328 }
6329
6330 /*
6331  * Stop completion callback from associated lport
6332  */
6333 void
6334 bfa_fcs_vport_stop_comp(struct bfa_fcs_vport_s *vport)
6335 {
6336         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOPCOMP);
6337 }
6338
6339 /*
6340  * Delete completion callback from associated lport
6341  */
6342 void
6343 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
6344 {
6345         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
6346 }
6347
6348
6349
6350 /*
6351  *  fcs_vport_api Virtual port API
6352  */
6353
6354 /*
6355  *      Use this function to instantiate a new FCS vport object. This
6356  *      function will not trigger any HW initialization process (which will be
6357  *      done in vport_start() call)
6358  *
6359  *      param[in] vport -               pointer to bfa_fcs_vport_t. This space
6360  *                                      needs to be allocated by the driver.
6361  *      param[in] fcs           -       FCS instance
6362  *      param[in] vport_cfg     -       vport configuration
6363  *      param[in] vf_id         -       VF_ID if vport is created within a VF.
6364  *                                      FC_VF_ID_NULL to specify base fabric.
6365  *      param[in] vport_drv     -       Opaque handle back to the driver's vport
6366  *                                      structure
6367  *
6368  *      retval BFA_STATUS_OK - on success.
6369  *      retval BFA_STATUS_FAILED - on failure.
6370  */
6371 bfa_status_t
6372 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6373                 u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6374                 struct bfad_vport_s *vport_drv)
6375 {
6376         if (vport_cfg->pwwn == 0)
6377                 return BFA_STATUS_INVALID_WWN;
6378
6379         if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
6380                 return BFA_STATUS_VPORT_WWN_BP;
6381
6382         if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
6383                 return BFA_STATUS_VPORT_EXISTS;
6384
6385         if (fcs->fabric.num_vports ==
6386                         bfa_lps_get_max_vport(fcs->bfa))
6387                 return BFA_STATUS_VPORT_MAX;
6388
6389         vport->lps = bfa_lps_alloc(fcs->bfa);
6390         if (!vport->lps)
6391                 return BFA_STATUS_VPORT_MAX;
6392
6393         vport->vport_drv = vport_drv;
6394         vport_cfg->preboot_vp = BFA_FALSE;
6395
6396         bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
6397         bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
6398         bfa_fcs_lport_init(&vport->lport, vport_cfg);
6399         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
6400
6401         return BFA_STATUS_OK;
6402 }
6403
6404 /*
6405  *      Use this function to instantiate a new FCS PBC vport object. This
6406  *      function will not trigger any HW initialization process (which will be
6407  *      done in vport_start() call)
6408  *
6409  *      param[in] vport -       pointer to bfa_fcs_vport_t. This space
6410  *                              needs to be allocated by the driver.
6411  *      param[in] fcs   -       FCS instance
6412  *      param[in] vport_cfg     -       vport configuration
6413  *      param[in] vf_id         -       VF_ID if vport is created within a VF.
6414  *                                      FC_VF_ID_NULL to specify base fabric.
6415  *      param[in] vport_drv     -       Opaque handle back to the driver's vport
6416  *                                      structure
6417  *
6418  *      retval BFA_STATUS_OK - on success.
6419  *      retval BFA_STATUS_FAILED - on failure.
6420  */
6421 bfa_status_t
6422 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
6423                         u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
6424                         struct bfad_vport_s *vport_drv)
6425 {
6426         bfa_status_t rc;
6427
6428         rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
6429         vport->lport.port_cfg.preboot_vp = BFA_TRUE;
6430
6431         return rc;
6432 }
6433
6434 /*
6435  *      Use this function to findout if this is a pbc vport or not.
6436  *
6437  * @param[in] vport - pointer to bfa_fcs_vport_t.
6438  *
6439  * @returns None
6440  */
6441 bfa_boolean_t
6442 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
6443 {
6444
6445         if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
6446                 return BFA_TRUE;
6447         else
6448                 return BFA_FALSE;
6449
6450 }
6451
6452 /*
6453  * Use this function initialize the vport.
6454  *
6455  * @param[in] vport - pointer to bfa_fcs_vport_t.
6456  *
6457  * @returns None
6458  */
6459 bfa_status_t
6460 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
6461 {
6462         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
6463
6464         return BFA_STATUS_OK;
6465 }
6466
6467 /*
6468  *      Use this function quiese the vport object. This function will return
6469  *      immediately, when the vport is actually stopped, the
6470  *      bfa_drv_vport_stop_cb() will be called.
6471  *
6472  *      param[in] vport - pointer to bfa_fcs_vport_t.
6473  *
6474  *      return None
6475  */
6476 bfa_status_t
6477 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
6478 {
6479         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
6480
6481         return BFA_STATUS_OK;
6482 }
6483
6484 /*
6485  *      Use this function to delete a vport object. Fabric object should
6486  *      be stopped before this function call.
6487  *
6488  *      !!!!!!! Donot invoke this from within FCS  !!!!!!!
6489  *
6490  *      param[in] vport - pointer to bfa_fcs_vport_t.
6491  *
6492  *      return     None
6493  */
6494 bfa_status_t
6495 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
6496 {
6497
6498         if (vport->lport.port_cfg.preboot_vp)
6499                 return BFA_STATUS_PBC;
6500
6501         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
6502
6503         return BFA_STATUS_OK;
6504 }
6505
6506 /*
6507  *      Use this function to get vport's current status info.
6508  *
6509  *      param[in] vport         pointer to bfa_fcs_vport_t.
6510  *      param[out] attr         pointer to return vport attributes
6511  *
6512  *      return None
6513  */
6514 void
6515 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
6516                         struct bfa_vport_attr_s *attr)
6517 {
6518         if (vport == NULL || attr == NULL)
6519                 return;
6520
6521         memset(attr, 0, sizeof(struct bfa_vport_attr_s));
6522
6523         bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
6524         attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
6525 }
6526
6527
6528 /*
6529  *      Lookup a virtual port. Excludes base port from lookup.
6530  */
6531 struct bfa_fcs_vport_s *
6532 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
6533 {
6534         struct bfa_fcs_vport_s *vport;
6535         struct bfa_fcs_fabric_s *fabric;
6536
6537         bfa_trc(fcs, vf_id);
6538         bfa_trc(fcs, vpwwn);
6539
6540         fabric = bfa_fcs_vf_lookup(fcs, vf_id);
6541         if (!fabric) {
6542                 bfa_trc(fcs, vf_id);
6543                 return NULL;
6544         }
6545
6546         vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
6547         return vport;
6548 }
6549
6550 /*
6551  * FDISC Response
6552  */
6553 void
6554 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
6555 {
6556         struct bfa_fcs_vport_s *vport = uarg;
6557
6558         bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
6559         bfa_trc(__vport_fcs(vport), status);
6560
6561         switch (status) {
6562         case BFA_STATUS_OK:
6563                 /*
6564                  * Initialize the V-Port fields
6565                  */
6566                 __vport_fcid(vport) = vport->lps->lp_pid;
6567                 vport->vport_stats.fdisc_accepts++;
6568                 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6569                 break;
6570
6571         case BFA_STATUS_INVALID_MAC:
6572                 /* Only for CNA */
6573                 vport->vport_stats.fdisc_acc_bad++;
6574                 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6575
6576                 break;
6577
6578         case BFA_STATUS_EPROTOCOL:
6579                 switch (vport->lps->ext_status) {
6580                 case BFA_EPROTO_BAD_ACCEPT:
6581                         vport->vport_stats.fdisc_acc_bad++;
6582                         break;
6583
6584                 case BFA_EPROTO_UNKNOWN_RSP:
6585                         vport->vport_stats.fdisc_unknown_rsp++;
6586                         break;
6587
6588                 default:
6589                         break;
6590                 }
6591
6592                 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6593                 break;
6594
6595         case BFA_STATUS_FABRIC_RJT:
6596                 vport->vport_stats.fdisc_rejects++;
6597                 bfa_fcs_vport_fdisc_rejected(vport);
6598                 break;
6599
6600         default:
6601                 vport->vport_stats.fdisc_rsp_err++;
6602                 bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
6603         }
6604 }
6605
6606 /*
6607  * LOGO response
6608  */
6609 void
6610 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
6611 {
6612         struct bfa_fcs_vport_s *vport = uarg;
6613         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
6614 }
6615
6616 /*
6617  * Received clear virtual link
6618  */
6619 void
6620 bfa_cb_lps_cvl_event(void *bfad, void *uarg)
6621 {
6622         struct bfa_fcs_vport_s *vport = uarg;
6623
6624         /* Send an Offline followed by an ONLINE */
6625         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
6626         bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
6627 }