Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[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,