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