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