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