Merge branches 'irq-core-for-linus' and 'core-locking-for-linus' of git://git.kernel...
[pandora-kernel.git] / drivers / scsi / bfa / bfa_fcs_lport.c
1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 /**
19  *  bfa_fcs_lport.c BFA FCS port
20  */
21
22 #include "bfa_fcs.h"
23 #include "bfa_fcbuild.h"
24 #include "bfa_fc.h"
25 #include "bfad_drv.h"
26
27 BFA_TRC_FILE(FCS, PORT);
28
29 /**
30  * Forward declarations
31  */
32
33 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
34                                          struct fchs_s *rx_fchs, u8 reason_code,
35                                          u8 reason_code_expl);
36 static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
37                         struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
38 static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
39 static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
40 static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
41 static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
42 static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
43 static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
44 static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
45                         struct fchs_s *rx_fchs,
46                         struct fc_echo_s *echo, u16 len);
47 static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
48                         struct fchs_s *rx_fchs,
49                         struct fc_rnid_cmd_s *rnid, u16 len);
50 static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
51                         struct fc_rnid_general_topology_data_s *gen_topo_data);
52
53 static void     bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
54 static void     bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
55 static void     bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
56
57 static void     bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
58 static void     bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
59 static void     bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
60
61 static struct {
62         void            (*init) (struct bfa_fcs_lport_s *port);
63         void            (*online) (struct bfa_fcs_lport_s *port);
64         void            (*offline) (struct bfa_fcs_lport_s *port);
65 } __port_action[] = {
66         {
67         bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
68                         bfa_fcs_lport_unknown_offline}, {
69         bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
70                         bfa_fcs_lport_fab_offline}, {
71         bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
72                         bfa_fcs_lport_n2n_offline},
73         };
74
75 /**
76  *  fcs_port_sm FCS logical port state machine
77  */
78
79 enum bfa_fcs_lport_event {
80         BFA_FCS_PORT_SM_CREATE = 1,
81         BFA_FCS_PORT_SM_ONLINE = 2,
82         BFA_FCS_PORT_SM_OFFLINE = 3,
83         BFA_FCS_PORT_SM_DELETE = 4,
84         BFA_FCS_PORT_SM_DELRPORT = 5,
85 };
86
87 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
88                                         enum bfa_fcs_lport_event event);
89 static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
90                                         enum bfa_fcs_lport_event event);
91 static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
92                                         enum bfa_fcs_lport_event event);
93 static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
94                                         enum bfa_fcs_lport_event event);
95 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
96                                         enum bfa_fcs_lport_event event);
97
98 static void
99 bfa_fcs_lport_sm_uninit(
100         struct bfa_fcs_lport_s *port,
101         enum bfa_fcs_lport_event event)
102 {
103         bfa_trc(port->fcs, port->port_cfg.pwwn);
104         bfa_trc(port->fcs, event);
105
106         switch (event) {
107         case BFA_FCS_PORT_SM_CREATE:
108                 bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
109                 break;
110
111         default:
112                 bfa_sm_fault(port->fcs, event);
113         }
114 }
115
116 static void
117 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
118                         enum bfa_fcs_lport_event event)
119 {
120         bfa_trc(port->fcs, port->port_cfg.pwwn);
121         bfa_trc(port->fcs, event);
122
123         switch (event) {
124         case BFA_FCS_PORT_SM_ONLINE:
125                 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
126                 bfa_fcs_lport_online_actions(port);
127                 break;
128
129         case BFA_FCS_PORT_SM_DELETE:
130                 bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
131                 bfa_fcs_lport_deleted(port);
132                 break;
133
134         case BFA_FCS_PORT_SM_OFFLINE:
135                 break;
136
137         default:
138                 bfa_sm_fault(port->fcs, event);
139         }
140 }
141
142 static void
143 bfa_fcs_lport_sm_online(
144         struct bfa_fcs_lport_s *port,
145         enum bfa_fcs_lport_event event)
146 {
147         struct bfa_fcs_rport_s *rport;
148         struct list_head                *qe, *qen;
149
150         bfa_trc(port->fcs, port->port_cfg.pwwn);
151         bfa_trc(port->fcs, event);
152
153         switch (event) {
154         case BFA_FCS_PORT_SM_OFFLINE:
155                 bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
156                 bfa_fcs_lport_offline_actions(port);
157                 break;
158
159         case BFA_FCS_PORT_SM_DELETE:
160
161                 __port_action[port->fabric->fab_type].offline(port);
162
163                 if (port->num_rports == 0) {
164                         bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
165                         bfa_fcs_lport_deleted(port);
166                 } else {
167                         bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
168                         list_for_each_safe(qe, qen, &port->rport_q) {
169                                 rport = (struct bfa_fcs_rport_s *) qe;
170                                 bfa_fcs_rport_delete(rport);
171                         }
172                 }
173                 break;
174
175         case BFA_FCS_PORT_SM_DELRPORT:
176                 break;
177
178         default:
179                 bfa_sm_fault(port->fcs, event);
180         }
181 }
182
183 static void
184 bfa_fcs_lport_sm_offline(
185         struct bfa_fcs_lport_s *port,
186         enum bfa_fcs_lport_event event)
187 {
188         struct bfa_fcs_rport_s *rport;
189         struct list_head                *qe, *qen;
190
191         bfa_trc(port->fcs, port->port_cfg.pwwn);
192         bfa_trc(port->fcs, event);
193
194         switch (event) {
195         case BFA_FCS_PORT_SM_ONLINE:
196                 bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
197                 bfa_fcs_lport_online_actions(port);
198                 break;
199
200         case BFA_FCS_PORT_SM_DELETE:
201                 if (port->num_rports == 0) {
202                         bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
203                         bfa_fcs_lport_deleted(port);
204                 } else {
205                         bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
206                         list_for_each_safe(qe, qen, &port->rport_q) {
207                                 rport = (struct bfa_fcs_rport_s *) qe;
208                                 bfa_fcs_rport_delete(rport);
209                         }
210                 }
211                 break;
212
213         case BFA_FCS_PORT_SM_DELRPORT:
214         case BFA_FCS_PORT_SM_OFFLINE:
215                 break;
216
217         default:
218                 bfa_sm_fault(port->fcs, event);
219         }
220 }
221
222 static void
223 bfa_fcs_lport_sm_deleting(
224         struct bfa_fcs_lport_s *port,
225         enum bfa_fcs_lport_event event)
226 {
227         bfa_trc(port->fcs, port->port_cfg.pwwn);
228         bfa_trc(port->fcs, event);
229
230         switch (event) {
231         case BFA_FCS_PORT_SM_DELRPORT:
232                 if (port->num_rports == 0) {
233                         bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
234                         bfa_fcs_lport_deleted(port);
235                 }
236                 break;
237
238         default:
239                 bfa_sm_fault(port->fcs, event);
240         }
241 }
242
243 /**
244  *  fcs_port_pvt
245  */
246
247 /*
248  * Send a LS reject
249  */
250 static void
251 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
252                          u8 reason_code, u8 reason_code_expl)
253 {
254         struct fchs_s   fchs;
255         struct bfa_fcxp_s *fcxp;
256         struct bfa_rport_s *bfa_rport = NULL;
257         int             len;
258
259         bfa_trc(port->fcs, rx_fchs->d_id);
260         bfa_trc(port->fcs, rx_fchs->s_id);
261
262         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
263         if (!fcxp)
264                 return;
265
266         len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
267                               rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
268                               rx_fchs->ox_id, reason_code, reason_code_expl);
269
270         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
271                           BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
272                           FC_MAX_PDUSZ, 0);
273 }
274
275 /**
276  * Process incoming plogi from a remote port.
277  */
278 static void
279 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
280                 struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
281 {
282         struct bfa_fcs_rport_s *rport;
283
284         bfa_trc(port->fcs, rx_fchs->d_id);
285         bfa_trc(port->fcs, rx_fchs->s_id);
286
287         /*
288          * If min cfg mode is enabled, drop any incoming PLOGIs
289          */
290         if (__fcs_min_cfg(port->fcs)) {
291                 bfa_trc(port->fcs, rx_fchs->s_id);
292                 return;
293         }
294
295         if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
296                 bfa_trc(port->fcs, rx_fchs->s_id);
297                 /*
298                  * send a LS reject
299                  */
300                 bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
301                                         FC_LS_RJT_RSN_PROTOCOL_ERROR,
302                                         FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
303                 return;
304         }
305
306         /**
307          * Direct Attach P2P mode : verify address assigned by the r-port.
308          */
309         if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
310                 (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
311                            (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
312                 if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
313                         /* Address assigned to us cannot be a WKA */
314                         bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
315                                         FC_LS_RJT_RSN_PROTOCOL_ERROR,
316                                         FC_LS_RJT_EXP_INVALID_NPORT_ID);
317                         return;
318                 }
319                 port->pid  = rx_fchs->d_id;
320         }
321
322         /**
323          * First, check if we know the device by pwwn.
324          */
325         rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
326         if (rport) {
327                 /**
328                  * Direct Attach P2P mode : handle address assigned by r-port.
329                  */
330                 if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
331                         (memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
332                         (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
333                         port->pid  = rx_fchs->d_id;
334                         rport->pid = rx_fchs->s_id;
335                 }
336                 bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
337                 return;
338         }
339
340         /**
341          * Next, lookup rport by PID.
342          */
343         rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
344         if (!rport) {
345                 /**
346                  * Inbound PLOGI from a new device.
347                  */
348                 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
349                 return;
350         }
351
352         /**
353          * Rport is known only by PID.
354          */
355         if (rport->pwwn) {
356                 /**
357                  * This is a different device with the same pid. Old device
358                  * disappeared. Send implicit LOGO to old device.
359                  */
360                 bfa_assert(rport->pwwn != plogi->port_name);
361                 bfa_fcs_rport_logo_imp(rport);
362
363                 /**
364                  * Inbound PLOGI from a new device (with old PID).
365                  */
366                 bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
367                 return;
368         }
369
370         /**
371          * PLOGI crossing each other.
372          */
373         bfa_assert(rport->pwwn == WWN_NULL);
374         bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
375 }
376
377 /*
378  * Process incoming ECHO.
379  * Since it does not require a login, it is processed here.
380  */
381 static void
382 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
383                 struct fc_echo_s *echo, u16 rx_len)
384 {
385         struct fchs_s           fchs;
386         struct bfa_fcxp_s       *fcxp;
387         struct bfa_rport_s      *bfa_rport = NULL;
388         int                     len, pyld_len;
389
390         bfa_trc(port->fcs, rx_fchs->s_id);
391         bfa_trc(port->fcs, rx_fchs->d_id);
392
393         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
394         if (!fcxp)
395                 return;
396
397         len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
398                                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
399                                 rx_fchs->ox_id);
400
401         /*
402          * Copy the payload (if any) from the echo frame
403          */
404         pyld_len = rx_len - sizeof(struct fchs_s);
405         bfa_trc(port->fcs, rx_len);
406         bfa_trc(port->fcs, pyld_len);
407
408         if (pyld_len > len)
409                 memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
410                         sizeof(struct fc_echo_s), (echo + 1),
411                         (pyld_len - sizeof(struct fc_echo_s)));
412
413         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
414                         BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
415                         FC_MAX_PDUSZ, 0);
416 }
417
418 /*
419  * Process incoming RNID.
420  * Since it does not require a login, it is processed here.
421  */
422 static void
423 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
424                 struct fc_rnid_cmd_s *rnid, u16 rx_len)
425 {
426         struct fc_rnid_common_id_data_s common_id_data;
427         struct fc_rnid_general_topology_data_s gen_topo_data;
428         struct fchs_s   fchs;
429         struct bfa_fcxp_s *fcxp;
430         struct bfa_rport_s *bfa_rport = NULL;
431         u16     len;
432         u32     data_format;
433
434         bfa_trc(port->fcs, rx_fchs->s_id);
435         bfa_trc(port->fcs, rx_fchs->d_id);
436         bfa_trc(port->fcs, rx_len);
437
438         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
439         if (!fcxp)
440                 return;
441
442         /*
443          * Check Node Indentification Data Format
444          * We only support General Topology Discovery Format.
445          * For any other requested Data Formats, we return Common Node Id Data
446          * only, as per FC-LS.
447          */
448         bfa_trc(port->fcs, rnid->node_id_data_format);
449         if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
450                 data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
451                 /*
452                  * Get General topology data for this port
453                  */
454                 bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
455         } else {
456                 data_format = RNID_NODEID_DATA_FORMAT_COMMON;
457         }
458
459         /*
460          * Copy the Node Id Info
461          */
462         common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
463         common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
464
465         len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
466                                 rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
467                                 rx_fchs->ox_id, data_format, &common_id_data,
468                                 &gen_topo_data);
469
470         bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
471                         BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
472                         FC_MAX_PDUSZ, 0);
473 }
474
475 /*
476  *  Fill out General Topolpgy Discovery Data for RNID ELS.
477  */
478 static void
479 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
480                         struct fc_rnid_general_topology_data_s *gen_topo_data)
481 {
482         bfa_os_memset(gen_topo_data, 0,
483                       sizeof(struct fc_rnid_general_topology_data_s));
484
485         gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST);
486         gen_topo_data->phy_port_num = 0;        /* @todo */
487         gen_topo_data->num_attached_nodes = bfa_os_htonl(1);
488 }
489
490 static void
491 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
492 {
493         struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
494         char    lpwwn_buf[BFA_STRING_32];
495
496         bfa_trc(port->fcs, port->fabric->oper_type);
497
498         __port_action[port->fabric->fab_type].init(port);
499         __port_action[port->fabric->fab_type].online(port);
500
501         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
502         BFA_LOG(KERN_INFO, bfad, log_level,
503                 "Logical port online: WWN = %s Role = %s\n",
504                 lpwwn_buf, "Initiator");
505
506         bfad->bfad_flags |= BFAD_PORT_ONLINE;
507 }
508
509 static void
510 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
511 {
512         struct list_head        *qe, *qen;
513         struct bfa_fcs_rport_s *rport;
514         struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
515         char    lpwwn_buf[BFA_STRING_32];
516
517         bfa_trc(port->fcs, port->fabric->oper_type);
518
519         __port_action[port->fabric->fab_type].offline(port);
520
521         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
522         if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
523                 BFA_LOG(KERN_ERR, bfad, log_level,
524                 "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
525                 lpwwn_buf, "Initiator");
526         else
527                 BFA_LOG(KERN_INFO, bfad, log_level,
528                 "Logical port taken offline: WWN = %s Role = %s\n",
529                 lpwwn_buf, "Initiator");
530
531         list_for_each_safe(qe, qen, &port->rport_q) {
532                 rport = (struct bfa_fcs_rport_s *) qe;
533                 bfa_fcs_rport_offline(rport);
534         }
535 }
536
537 static void
538 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
539 {
540         bfa_assert(0);
541 }
542
543 static void
544 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
545 {
546         bfa_assert(0);
547 }
548
549 static void
550 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
551 {
552         bfa_assert(0);
553 }
554
555 static void
556 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
557 {
558         struct fchs_s fchs;
559         struct bfa_fcxp_s *fcxp;
560         int             len;
561
562         bfa_trc(port->fcs, rx_fchs->d_id);
563         bfa_trc(port->fcs, rx_fchs->s_id);
564
565         fcxp = bfa_fcs_fcxp_alloc(port->fcs);
566         if (!fcxp)
567                 return;
568
569         len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
570                         rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
571                         rx_fchs->ox_id, 0);
572
573         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
574                           BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
575                           FC_MAX_PDUSZ, 0);
576 }
577 static void
578 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
579 {
580         struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
581         char    lpwwn_buf[BFA_STRING_32];
582
583         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
584         BFA_LOG(KERN_INFO, bfad, log_level,
585                 "Logical port deleted: WWN = %s Role = %s\n",
586                 lpwwn_buf, "Initiator");
587
588         /* Base port will be deleted by the OS driver */
589         if (port->vport) {
590                 bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
591                                 port->fabric->vf_drv,
592                                 port->vport ? port->vport->vport_drv : NULL);
593                 bfa_fcs_vport_delete_comp(port->vport);
594         } else {
595                  bfa_fcs_fabric_port_delete_comp(port->fabric);
596         }
597 }
598
599
600
601 /**
602  *  fcs_lport_api BFA FCS port API
603  */
604 /**
605  *   Module initialization
606  */
607 void
608 bfa_fcs_lport_modinit(struct bfa_fcs_s *fcs)
609 {
610
611 }
612
613 /**
614  *   Module cleanup
615  */
616 void
617 bfa_fcs_lport_modexit(struct bfa_fcs_s *fcs)
618 {
619         bfa_fcs_modexit_comp(fcs);
620 }
621
622 /**
623  * Unsolicited frame receive handling.
624  */
625 void
626 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
627                         struct fchs_s *fchs, u16 len)
628 {
629         u32     pid = fchs->s_id;
630         struct bfa_fcs_rport_s *rport = NULL;
631         struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
632
633         bfa_stats(lport, uf_recvs);
634
635         if (!bfa_fcs_lport_is_online(lport)) {
636                 bfa_stats(lport, uf_recv_drops);
637                 return;
638         }
639
640         /**
641          * First, handle ELSs that donot require a login.
642          */
643         /*
644          * Handle PLOGI first
645          */
646         if ((fchs->type == FC_TYPE_ELS) &&
647                 (els_cmd->els_code == FC_ELS_PLOGI)) {
648                 bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
649                 return;
650         }
651
652         /*
653          * Handle ECHO separately.
654          */
655         if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
656                 bfa_fcs_lport_echo(lport, fchs,
657                                 (struct fc_echo_s *)els_cmd, len);
658                 return;
659         }
660
661         /*
662          * Handle RNID separately.
663          */
664         if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
665                 bfa_fcs_lport_rnid(lport, fchs,
666                         (struct fc_rnid_cmd_s *) els_cmd, len);
667                 return;
668         }
669
670         if (fchs->type == FC_TYPE_BLS) {
671                 if ((fchs->routing == FC_RTG_BASIC_LINK) &&
672                                 (fchs->cat_info == FC_CAT_ABTS))
673                         bfa_fcs_lport_abts_acc(lport, fchs);
674                 return;
675         }
676         /**
677          * look for a matching remote port ID
678          */
679         rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
680         if (rport) {
681                 bfa_trc(rport->fcs, fchs->s_id);
682                 bfa_trc(rport->fcs, fchs->d_id);
683                 bfa_trc(rport->fcs, fchs->type);
684
685                 bfa_fcs_rport_uf_recv(rport, fchs, len);
686                 return;
687         }
688
689         /**
690          * Only handles ELS frames for now.
691          */
692         if (fchs->type != FC_TYPE_ELS) {
693                 bfa_trc(lport->fcs, fchs->type);
694                 bfa_assert(0);
695                 return;
696         }
697
698         bfa_trc(lport->fcs, els_cmd->els_code);
699         if (els_cmd->els_code == FC_ELS_RSCN) {
700                 bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
701                 return;
702         }
703
704         if (els_cmd->els_code == FC_ELS_LOGO) {
705                 /**
706                  * @todo Handle LOGO frames received.
707                  */
708                 return;
709         }
710
711         if (els_cmd->els_code == FC_ELS_PRLI) {
712                 /**
713                  * @todo Handle PRLI frames received.
714                  */
715                 return;
716         }
717
718         /**
719          * Unhandled ELS frames. Send a LS_RJT.
720          */
721         bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
722                                  FC_LS_RJT_EXP_NO_ADDL_INFO);
723
724 }
725
726 /**
727  *   PID based Lookup for a R-Port in the Port R-Port Queue
728  */
729 struct bfa_fcs_rport_s *
730 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
731 {
732         struct bfa_fcs_rport_s *rport;
733         struct list_head        *qe;
734
735         list_for_each(qe, &port->rport_q) {
736                 rport = (struct bfa_fcs_rport_s *) qe;
737                 if (rport->pid == pid)
738                         return rport;
739         }
740
741         bfa_trc(port->fcs, pid);
742         return NULL;
743 }
744
745 /**
746  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
747  */
748 struct bfa_fcs_rport_s *
749 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
750 {
751         struct bfa_fcs_rport_s *rport;
752         struct list_head        *qe;
753
754         list_for_each(qe, &port->rport_q) {
755                 rport = (struct bfa_fcs_rport_s *) qe;
756                 if (wwn_is_equal(rport->pwwn, pwwn))
757                         return rport;
758         }
759
760         bfa_trc(port->fcs, pwwn);
761         return NULL;
762 }
763
764 /**
765  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
766  */
767 struct bfa_fcs_rport_s *
768 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
769 {
770         struct bfa_fcs_rport_s *rport;
771         struct list_head        *qe;
772
773         list_for_each(qe, &port->rport_q) {
774                 rport = (struct bfa_fcs_rport_s *) qe;
775                 if (wwn_is_equal(rport->nwwn, nwwn))
776                         return rport;
777         }
778
779         bfa_trc(port->fcs, nwwn);
780         return NULL;
781 }
782
783 /**
784  * Called by rport module when new rports are discovered.
785  */
786 void
787 bfa_fcs_lport_add_rport(
788         struct bfa_fcs_lport_s *port,
789         struct bfa_fcs_rport_s *rport)
790 {
791         list_add_tail(&rport->qe, &port->rport_q);
792         port->num_rports++;
793 }
794
795 /**
796  * Called by rport module to when rports are deleted.
797  */
798 void
799 bfa_fcs_lport_del_rport(
800         struct bfa_fcs_lport_s *port,
801         struct bfa_fcs_rport_s *rport)
802 {
803         bfa_assert(bfa_q_is_on_q(&port->rport_q, rport));
804         list_del(&rport->qe);
805         port->num_rports--;
806
807         bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
808 }
809
810 /**
811  * Called by fabric for base port when fabric login is complete.
812  * Called by vport for virtual ports when FDISC is complete.
813  */
814 void
815 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
816 {
817         bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
818 }
819
820 /**
821  * Called by fabric for base port when fabric goes offline.
822  * Called by vport for virtual ports when virtual port becomes offline.
823  */
824 void
825 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
826 {
827         bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
828 }
829
830 /**
831  * Called by fabric to delete base lport and associated resources.
832  *
833  * Called by vport to delete lport and associated resources. Should call
834  * bfa_fcs_vport_delete_comp() for vports on completion.
835  */
836 void
837 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
838 {
839         bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
840 }
841
842 /**
843  * Return TRUE if port is online, else return FALSE
844  */
845 bfa_boolean_t
846 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
847 {
848         return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
849 }
850
851 /**
852   * Attach time initialization of logical ports.
853  */
854 void
855 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
856                    u16 vf_id, struct bfa_fcs_vport_s *vport)
857 {
858         lport->fcs = fcs;
859         lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
860         lport->vport = vport;
861         lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) :
862                                   bfa_lps_get_tag(lport->fabric->lps);
863
864         INIT_LIST_HEAD(&lport->rport_q);
865         lport->num_rports = 0;
866 }
867
868 /**
869  * Logical port initialization of base or virtual port.
870  * Called by fabric for base port or by vport for virtual ports.
871  */
872
873 void
874 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
875         struct bfa_lport_cfg_s *port_cfg)
876 {
877         struct bfa_fcs_vport_s *vport = lport->vport;
878         struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
879         char    lpwwn_buf[BFA_STRING_32];
880
881         bfa_os_assign(lport->port_cfg, *port_cfg);
882
883         lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
884                                         lport->port_cfg.roles,
885                                         lport->fabric->vf_drv,
886                                         vport ? vport->vport_drv : NULL);
887
888         wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
889         BFA_LOG(KERN_INFO, bfad, log_level,
890                 "New logical port created: WWN = %s Role = %s\n",
891                 lpwwn_buf, "Initiator");
892
893         bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
894         bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
895 }
896
897 /**
898  *  fcs_lport_api
899  */
900
901 void
902 bfa_fcs_lport_get_attr(
903         struct bfa_fcs_lport_s *port,
904         struct bfa_lport_attr_s *port_attr)
905 {
906         if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
907                 port_attr->pid = port->pid;
908         else
909                 port_attr->pid = 0;
910
911         port_attr->port_cfg = port->port_cfg;
912
913         if (port->fabric) {
914                 port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric);
915                 port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric);
916                 port_attr->authfail =
917                         bfa_fcs_fabric_is_auth_failed(port->fabric);
918                 port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
919                 memcpy(port_attr->fabric_ip_addr,
920                         bfa_fcs_lport_get_fabric_ipaddr(port),
921                         BFA_FCS_FABRIC_IPADDR_SZ);
922
923                 if (port->vport != NULL) {
924                         port_attr->port_type = BFA_PORT_TYPE_VPORT;
925                         port_attr->fpma_mac =
926                                 bfa_lps_get_lp_mac(port->vport->lps);
927                 } else {
928                         port_attr->fpma_mac =
929                                 bfa_lps_get_lp_mac(port->fabric->lps);
930                 }
931         } else {
932                 port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
933                 port_attr->state = BFA_LPORT_UNINIT;
934         }
935 }
936
937 /**
938  *  bfa_fcs_lport_fab port fab functions
939  */
940
941 /**
942  *   Called by port to initialize fabric services of the base port.
943  */
944 static void
945 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
946 {
947         bfa_fcs_lport_ns_init(port);
948         bfa_fcs_lport_scn_init(port);
949         bfa_fcs_lport_ms_init(port);
950 }
951
952 /**
953  *   Called by port to notify transition to online state.
954  */
955 static void
956 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
957 {
958         bfa_fcs_lport_ns_online(port);
959         bfa_fcs_lport_scn_online(port);
960 }
961
962 /**
963  *   Called by port to notify transition to offline state.
964  */
965 static void
966 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
967 {
968         bfa_fcs_lport_ns_offline(port);
969         bfa_fcs_lport_scn_offline(port);
970         bfa_fcs_lport_ms_offline(port);
971 }
972
973 /**
974  *  bfa_fcs_lport_n2n  functions
975  */
976
977 /**
978  *   Called by fcs/port to initialize N2N topology.
979  */
980 static void
981 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
982 {
983 }
984
985 /**
986  *   Called by fcs/port to notify transition to online state.
987  */
988 static void
989 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
990 {
991         struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
992         struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
993         struct bfa_fcs_rport_s *rport;
994
995         bfa_trc(port->fcs, pcfg->pwwn);
996
997         /*
998          * If our PWWN is > than that of the r-port, we have to initiate PLOGI
999          * and assign an Address. if not, we need to wait for its PLOGI.
1000          *
1001          * If our PWWN is < than that of the remote port, it will send a PLOGI
1002          * with the PIDs assigned. The rport state machine take care of this
1003          * incoming PLOGI.
1004          */
1005         if (memcmp
1006             ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
1007              sizeof(wwn_t)) > 0) {
1008                 port->pid = N2N_LOCAL_PID;
1009                 /**
1010                  * First, check if we know the device by pwwn.
1011                  */
1012                 rport = bfa_fcs_lport_get_rport_by_pwwn(port,
1013                                                         n2n_port->rem_port_wwn);
1014                 if (rport) {
1015                         bfa_trc(port->fcs, rport->pid);
1016                         bfa_trc(port->fcs, rport->pwwn);
1017                         rport->pid = N2N_REMOTE_PID;
1018                         bfa_fcs_rport_online(rport);
1019                         return;
1020                 }
1021
1022                 /*
1023                  * In n2n there can be only one rport. Delete the old one
1024                  * whose pid should be zero, because it is offline.
1025                  */
1026                 if (port->num_rports > 0) {
1027                         rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1028                         bfa_assert(rport != NULL);
1029                         if (rport) {
1030                                 bfa_trc(port->fcs, rport->pwwn);
1031                                 bfa_fcs_rport_delete(rport);
1032                         }
1033                 }
1034                 bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1035         }
1036 }
1037
1038 /**
1039  *   Called by fcs/port to notify transition to offline state.
1040  */
1041 static void
1042 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1043 {
1044         struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1045
1046         bfa_trc(port->fcs, port->pid);
1047         port->pid = 0;
1048         n2n_port->rem_port_wwn = 0;
1049         n2n_port->reply_oxid = 0;
1050 }
1051
1052 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1053
1054 /*
1055  * forward declarations
1056  */
1057 static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1058                                             struct bfa_fcxp_s *fcxp_alloced);
1059 static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1060                                             struct bfa_fcxp_s *fcxp_alloced);
1061 static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1062                                            struct bfa_fcxp_s *fcxp_alloced);
1063 static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1064                                                 struct bfa_fcxp_s *fcxp,
1065                                                 void *cbarg,
1066                                                 bfa_status_t req_status,
1067                                                 u32 rsp_len,
1068                                                 u32 resid_len,
1069                                                 struct fchs_s *rsp_fchs);
1070 static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1071                                                 struct bfa_fcxp_s *fcxp,
1072                                                 void *cbarg,
1073                                                 bfa_status_t req_status,
1074                                                 u32 rsp_len,
1075                                                 u32 resid_len,
1076                                                 struct fchs_s *rsp_fchs);
1077 static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1078                                                struct bfa_fcxp_s *fcxp,
1079                                                void *cbarg,
1080                                                bfa_status_t req_status,
1081                                                u32 rsp_len,
1082                                                u32 resid_len,
1083                                                struct fchs_s *rsp_fchs);
1084 static void     bfa_fcs_lport_fdmi_timeout(void *arg);
1085 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1086                                                   u8 *pyld);
1087 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1088                                                   u8 *pyld);
1089 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1090                                                  u8 *pyld);
1091 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1092                                                        fdmi, u8 *pyld);
1093 static void     bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1094                                  struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1095 static void     bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1096                                   struct bfa_fcs_fdmi_port_attr_s *port_attr);
1097 /**
1098  *  fcs_fdmi_sm FCS FDMI state machine
1099  */
1100
1101 /**
1102  *  FDMI State Machine events
1103  */
1104 enum port_fdmi_event {
1105         FDMISM_EVENT_PORT_ONLINE = 1,
1106         FDMISM_EVENT_PORT_OFFLINE = 2,
1107         FDMISM_EVENT_RSP_OK = 4,
1108         FDMISM_EVENT_RSP_ERROR = 5,
1109         FDMISM_EVENT_TIMEOUT = 6,
1110         FDMISM_EVENT_RHBA_SENT = 7,
1111         FDMISM_EVENT_RPRT_SENT = 8,
1112         FDMISM_EVENT_RPA_SENT = 9,
1113 };
1114
1115 static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1116                                              enum port_fdmi_event event);
1117 static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
1118                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1119                                 enum port_fdmi_event event);
1120 static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1121                                           enum port_fdmi_event event);
1122 static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
1123                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1124                                 enum port_fdmi_event event);
1125 static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
1126                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1127                                 enum port_fdmi_event event);
1128 static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1129                                           enum port_fdmi_event event);
1130 static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
1131                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1132                                 enum port_fdmi_event event);
1133 static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
1134                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1135                                 enum port_fdmi_event event);
1136 static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1137                                          enum port_fdmi_event event);
1138 static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
1139                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1140                                 enum port_fdmi_event event);
1141 static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1142                                             enum port_fdmi_event event);
1143 static void     bfa_fcs_lport_fdmi_sm_disabled(
1144                                 struct bfa_fcs_lport_fdmi_s *fdmi,
1145                                 enum port_fdmi_event event);
1146 /**
1147  *      Start in offline state - awaiting MS to send start.
1148  */
1149 static void
1150 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1151                              enum port_fdmi_event event)
1152 {
1153         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1154
1155         bfa_trc(port->fcs, port->port_cfg.pwwn);
1156         bfa_trc(port->fcs, event);
1157
1158         fdmi->retry_cnt = 0;
1159
1160         switch (event) {
1161         case FDMISM_EVENT_PORT_ONLINE:
1162                 if (port->vport) {
1163                         /*
1164                          * For Vports, register a new port.
1165                          */
1166                         bfa_sm_set_state(fdmi,
1167                                          bfa_fcs_lport_fdmi_sm_sending_rprt);
1168                         bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1169                 } else {
1170                         /*
1171                          * For a base port, we should first register the HBA
1172                          * atribute. The HBA attribute also contains the base
1173                          *  port registration.
1174                          */
1175                         bfa_sm_set_state(fdmi,
1176                                          bfa_fcs_lport_fdmi_sm_sending_rhba);
1177                         bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1178                 }
1179                 break;
1180
1181         case FDMISM_EVENT_PORT_OFFLINE:
1182                 break;
1183
1184         default:
1185                 bfa_sm_fault(port->fcs, event);
1186         }
1187 }
1188
1189 static void
1190 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1191                                   enum port_fdmi_event event)
1192 {
1193         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1194
1195         bfa_trc(port->fcs, port->port_cfg.pwwn);
1196         bfa_trc(port->fcs, event);
1197
1198         switch (event) {
1199         case FDMISM_EVENT_RHBA_SENT:
1200                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1201                 break;
1202
1203         case FDMISM_EVENT_PORT_OFFLINE:
1204                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1205                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1206                                            &fdmi->fcxp_wqe);
1207                 break;
1208
1209         default:
1210                 bfa_sm_fault(port->fcs, event);
1211         }
1212 }
1213
1214 static void
1215 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1216                         enum port_fdmi_event event)
1217 {
1218         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1219
1220         bfa_trc(port->fcs, port->port_cfg.pwwn);
1221         bfa_trc(port->fcs, event);
1222
1223         switch (event) {
1224         case FDMISM_EVENT_RSP_ERROR:
1225                 /*
1226                  * if max retries have not been reached, start timer for a
1227                  * delayed retry
1228                  */
1229                 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1230                         bfa_sm_set_state(fdmi,
1231                                         bfa_fcs_lport_fdmi_sm_rhba_retry);
1232                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1233                                             &fdmi->timer,
1234                                             bfa_fcs_lport_fdmi_timeout, fdmi,
1235                                             BFA_FCS_RETRY_TIMEOUT);
1236                 } else {
1237                         /*
1238                          * set state to offline
1239                          */
1240                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1241                 }
1242                 break;
1243
1244         case FDMISM_EVENT_RSP_OK:
1245                 /*
1246                  * Initiate Register Port Attributes
1247                  */
1248                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1249                 fdmi->retry_cnt = 0;
1250                 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1251                 break;
1252
1253         case FDMISM_EVENT_PORT_OFFLINE:
1254                 bfa_fcxp_discard(fdmi->fcxp);
1255                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1256                 break;
1257
1258         default:
1259                 bfa_sm_fault(port->fcs, event);
1260         }
1261 }
1262
1263 static void
1264 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1265                                 enum port_fdmi_event event)
1266 {
1267         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1268
1269         bfa_trc(port->fcs, port->port_cfg.pwwn);
1270         bfa_trc(port->fcs, event);
1271
1272         switch (event) {
1273         case FDMISM_EVENT_TIMEOUT:
1274                 /*
1275                  * Retry Timer Expired. Re-send
1276                  */
1277                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1278                 bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1279                 break;
1280
1281         case FDMISM_EVENT_PORT_OFFLINE:
1282                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1283                 bfa_timer_stop(&fdmi->timer);
1284                 break;
1285
1286         default:
1287                 bfa_sm_fault(port->fcs, event);
1288         }
1289 }
1290
1291 /*
1292 * RPRT : Register Port
1293  */
1294 static void
1295 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1296                                   enum port_fdmi_event event)
1297 {
1298         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1299
1300         bfa_trc(port->fcs, port->port_cfg.pwwn);
1301         bfa_trc(port->fcs, event);
1302
1303         switch (event) {
1304         case FDMISM_EVENT_RPRT_SENT:
1305                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1306                 break;
1307
1308         case FDMISM_EVENT_PORT_OFFLINE:
1309                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1310                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1311                                            &fdmi->fcxp_wqe);
1312                 break;
1313
1314         default:
1315                 bfa_sm_fault(port->fcs, event);
1316         }
1317 }
1318
1319 static void
1320 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1321                         enum port_fdmi_event event)
1322 {
1323         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1324
1325         bfa_trc(port->fcs, port->port_cfg.pwwn);
1326         bfa_trc(port->fcs, event);
1327
1328         switch (event) {
1329         case FDMISM_EVENT_RSP_ERROR:
1330                 /*
1331                  * if max retries have not been reached, start timer for a
1332                  * delayed retry
1333                  */
1334                 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1335                         bfa_sm_set_state(fdmi,
1336                                         bfa_fcs_lport_fdmi_sm_rprt_retry);
1337                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1338                                             &fdmi->timer,
1339                                             bfa_fcs_lport_fdmi_timeout, fdmi,
1340                                             BFA_FCS_RETRY_TIMEOUT);
1341
1342                 } else {
1343                         /*
1344                          * set state to offline
1345                          */
1346                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1347                         fdmi->retry_cnt = 0;
1348                 }
1349                 break;
1350
1351         case FDMISM_EVENT_RSP_OK:
1352                 fdmi->retry_cnt = 0;
1353                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1354                 break;
1355
1356         case FDMISM_EVENT_PORT_OFFLINE:
1357                 bfa_fcxp_discard(fdmi->fcxp);
1358                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1359                 break;
1360
1361         default:
1362                 bfa_sm_fault(port->fcs, event);
1363         }
1364 }
1365
1366 static void
1367 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1368                                 enum port_fdmi_event event)
1369 {
1370         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1371
1372         bfa_trc(port->fcs, port->port_cfg.pwwn);
1373         bfa_trc(port->fcs, event);
1374
1375         switch (event) {
1376         case FDMISM_EVENT_TIMEOUT:
1377                 /*
1378                  * Retry Timer Expired. Re-send
1379                  */
1380                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1381                 bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1382                 break;
1383
1384         case FDMISM_EVENT_PORT_OFFLINE:
1385                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1386                 bfa_timer_stop(&fdmi->timer);
1387                 break;
1388
1389         default:
1390                 bfa_sm_fault(port->fcs, event);
1391         }
1392 }
1393
1394 /*
1395  * Register Port Attributes
1396  */
1397 static void
1398 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1399                                  enum port_fdmi_event event)
1400 {
1401         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1402
1403         bfa_trc(port->fcs, port->port_cfg.pwwn);
1404         bfa_trc(port->fcs, event);
1405
1406         switch (event) {
1407         case FDMISM_EVENT_RPA_SENT:
1408                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1409                 break;
1410
1411         case FDMISM_EVENT_PORT_OFFLINE:
1412                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1413                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1414                                            &fdmi->fcxp_wqe);
1415                 break;
1416
1417         default:
1418                 bfa_sm_fault(port->fcs, event);
1419         }
1420 }
1421
1422 static void
1423 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1424                         enum port_fdmi_event event)
1425 {
1426         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1427
1428         bfa_trc(port->fcs, port->port_cfg.pwwn);
1429         bfa_trc(port->fcs, event);
1430
1431         switch (event) {
1432         case FDMISM_EVENT_RSP_ERROR:
1433                 /*
1434                  * if max retries have not been reached, start timer for a
1435                  * delayed retry
1436                  */
1437                 if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1438                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1439                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1440                                             &fdmi->timer,
1441                                             bfa_fcs_lport_fdmi_timeout, fdmi,
1442                                             BFA_FCS_RETRY_TIMEOUT);
1443                 } else {
1444                         /*
1445                          * set state to offline
1446                          */
1447                         bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1448                         fdmi->retry_cnt = 0;
1449                 }
1450                 break;
1451
1452         case FDMISM_EVENT_RSP_OK:
1453                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1454                 fdmi->retry_cnt = 0;
1455                 break;
1456
1457         case FDMISM_EVENT_PORT_OFFLINE:
1458                 bfa_fcxp_discard(fdmi->fcxp);
1459                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1460                 break;
1461
1462         default:
1463                 bfa_sm_fault(port->fcs, event);
1464         }
1465 }
1466
1467 static void
1468 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1469                                enum port_fdmi_event event)
1470 {
1471         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1472
1473         bfa_trc(port->fcs, port->port_cfg.pwwn);
1474         bfa_trc(port->fcs, event);
1475
1476         switch (event) {
1477         case FDMISM_EVENT_TIMEOUT:
1478                 /*
1479                  * Retry Timer Expired. Re-send
1480                  */
1481                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1482                 bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1483                 break;
1484
1485         case FDMISM_EVENT_PORT_OFFLINE:
1486                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487                 bfa_timer_stop(&fdmi->timer);
1488                 break;
1489
1490         default:
1491                 bfa_sm_fault(port->fcs, event);
1492         }
1493 }
1494
1495 static void
1496 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1497                                 enum port_fdmi_event event)
1498 {
1499         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1500
1501         bfa_trc(port->fcs, port->port_cfg.pwwn);
1502         bfa_trc(port->fcs, event);
1503
1504         switch (event) {
1505         case FDMISM_EVENT_PORT_OFFLINE:
1506                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1507                 break;
1508
1509         default:
1510                 bfa_sm_fault(port->fcs, event);
1511         }
1512 }
1513 /**
1514  *  FDMI is disabled state.
1515  */
1516 static void
1517 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1518                              enum port_fdmi_event event)
1519 {
1520         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1521
1522         bfa_trc(port->fcs, port->port_cfg.pwwn);
1523         bfa_trc(port->fcs, event);
1524
1525         /* No op State. It can only be enabled at Driver Init. */
1526 }
1527
1528 /**
1529 *  RHBA : Register HBA Attributes.
1530  */
1531 static void
1532 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1533 {
1534         struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1535         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1536         struct fchs_s fchs;
1537         int             len, attr_len;
1538         struct bfa_fcxp_s *fcxp;
1539         u8        *pyld;
1540
1541         bfa_trc(port->fcs, port->port_cfg.pwwn);
1542
1543         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1544         if (!fcxp) {
1545                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1546                                         bfa_fcs_lport_fdmi_send_rhba, fdmi);
1547                 return;
1548         }
1549         fdmi->fcxp = fcxp;
1550
1551         pyld = bfa_fcxp_get_reqbuf(fcxp);
1552         bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
1553
1554         len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1555                                    FDMI_RHBA);
1556
1557         attr_len =
1558                 bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1559                                           (u8 *) ((struct ct_hdr_s *) pyld
1560                                                        + 1));
1561
1562         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1563                           FC_CLASS_3, (len + attr_len), &fchs,
1564                           bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1565                           FC_MAX_PDUSZ, FC_FCCT_TOV);
1566
1567         bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1568 }
1569
1570 static          u16
1571 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1572 {
1573         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1574         struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1575         struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1576         struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1577         struct fdmi_attr_s *attr;
1578         u8        *curr_ptr;
1579         u16        len, count;
1580
1581         /*
1582          * get hba attributes
1583          */
1584         bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1585
1586         rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1587         rhba->port_list.num_ports = bfa_os_htonl(1);
1588         rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1589
1590         len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1591
1592         count = 0;
1593         len += sizeof(rhba->hba_attr_blk.attr_count);
1594
1595         /*
1596          * fill out the invididual entries of the HBA attrib Block
1597          */
1598         curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1599
1600         /*
1601          * Node Name
1602          */
1603         attr = (struct fdmi_attr_s *) curr_ptr;
1604         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME);
1605         attr->len = sizeof(wwn_t);
1606         memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), attr->len);
1607         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1608         len += attr->len;
1609         count++;
1610         attr->len =
1611                 bfa_os_htons(attr->len + sizeof(attr->type) +
1612                              sizeof(attr->len));
1613
1614         /*
1615          * Manufacturer
1616          */
1617         attr = (struct fdmi_attr_s *) curr_ptr;
1618         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER);
1619         attr->len = (u16) strlen(fcs_hba_attr->manufacturer);
1620         memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len);
1621         attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1622                                                                  *fields need
1623                                                                  *to be 4 byte
1624                                                                  *aligned */
1625         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1626         len += attr->len;
1627         count++;
1628         attr->len =
1629                 bfa_os_htons(attr->len + sizeof(attr->type) +
1630                              sizeof(attr->len));
1631
1632         /*
1633          * Serial Number
1634          */
1635         attr = (struct fdmi_attr_s *) curr_ptr;
1636         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM);
1637         attr->len = (u16) strlen(fcs_hba_attr->serial_num);
1638         memcpy(attr->value, fcs_hba_attr->serial_num, attr->len);
1639         attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1640                                                                  *fields need
1641                                                                  *to be 4 byte
1642                                                                  *aligned */
1643         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1644         len += attr->len;
1645         count++;
1646         attr->len =
1647                 bfa_os_htons(attr->len + sizeof(attr->type) +
1648                              sizeof(attr->len));
1649
1650         /*
1651          * Model
1652          */
1653         attr = (struct fdmi_attr_s *) curr_ptr;
1654         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL);
1655         attr->len = (u16) strlen(fcs_hba_attr->model);
1656         memcpy(attr->value, fcs_hba_attr->model, attr->len);
1657         attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1658                                                                  *fields need
1659                                                                  *to be 4 byte
1660                                                                  *aligned */
1661         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1662         len += attr->len;
1663         count++;
1664         attr->len =
1665                 bfa_os_htons(attr->len + sizeof(attr->type) +
1666                              sizeof(attr->len));
1667
1668         /*
1669          * Model Desc
1670          */
1671         attr = (struct fdmi_attr_s *) curr_ptr;
1672         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC);
1673         attr->len = (u16) strlen(fcs_hba_attr->model_desc);
1674         memcpy(attr->value, fcs_hba_attr->model_desc, attr->len);
1675         attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1676                                                          *fields need
1677                                                          *to be 4 byte
1678                                                          *aligned */
1679         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1680         len += attr->len;
1681         count++;
1682         attr->len =
1683                 bfa_os_htons(attr->len + sizeof(attr->type) +
1684                              sizeof(attr->len));
1685
1686         /*
1687          * H/W Version
1688          */
1689         if (fcs_hba_attr->hw_version[0] != '\0') {
1690                 attr = (struct fdmi_attr_s *) curr_ptr;
1691                 attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION);
1692                 attr->len = (u16) strlen(fcs_hba_attr->hw_version);
1693                 memcpy(attr->value, fcs_hba_attr->hw_version, attr->len);
1694                 attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1695                                                                  *fields need
1696                                                                  *to be 4 byte
1697                                                                  *aligned */
1698                 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1699                 len += attr->len;
1700                 count++;
1701                 attr->len =
1702                         bfa_os_htons(attr->len + sizeof(attr->type) +
1703                                          sizeof(attr->len));
1704         }
1705
1706         /*
1707          * Driver Version
1708          */
1709         attr = (struct fdmi_attr_s *) curr_ptr;
1710         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1711         attr->len = (u16) strlen(fcs_hba_attr->driver_version);
1712         memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
1713         attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1714                                                          *fields need
1715                                                          *to be 4 byte
1716                                                          *aligned */
1717         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1718         len += attr->len;;
1719         count++;
1720         attr->len =
1721                 bfa_os_htons(attr->len + sizeof(attr->type) +
1722                              sizeof(attr->len));
1723
1724         /*
1725          * Option Rom Version
1726          */
1727         if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1728                 attr = (struct fdmi_attr_s *) curr_ptr;
1729                 attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION);
1730                 attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver);
1731                 memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len);
1732                 attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1733                                                                  *fields need
1734                                                                  *to be 4 byte
1735                                                                  *aligned */
1736                 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1737                 len += attr->len;
1738                 count++;
1739                 attr->len =
1740                         bfa_os_htons(attr->len + sizeof(attr->type) +
1741                                          sizeof(attr->len));
1742         }
1743
1744         /*
1745          * f/w Version = driver version
1746          */
1747         attr = (struct fdmi_attr_s *) curr_ptr;
1748         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION);
1749         attr->len = (u16) strlen(fcs_hba_attr->driver_version);
1750         memcpy(attr->value, fcs_hba_attr->driver_version, attr->len);
1751         attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1752                                                          *fields need
1753                                                          *to be 4 byte
1754                                                          *aligned */
1755         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1756         len += attr->len;
1757         count++;
1758         attr->len =
1759                 bfa_os_htons(attr->len + sizeof(attr->type) +
1760                              sizeof(attr->len));
1761
1762         /*
1763          * OS Name
1764          */
1765         if (fcs_hba_attr->os_name[0] != '\0') {
1766                 attr = (struct fdmi_attr_s *) curr_ptr;
1767                 attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME);
1768                 attr->len = (u16) strlen(fcs_hba_attr->os_name);
1769                 memcpy(attr->value, fcs_hba_attr->os_name, attr->len);
1770                 attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1771                                                              *fields need
1772                                                              *to be 4 byte
1773                                                              *aligned */
1774                 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1775                 len += attr->len;
1776                 count++;
1777                 attr->len =
1778                         bfa_os_htons(attr->len + sizeof(attr->type) +
1779                                         sizeof(attr->len));
1780         }
1781
1782         /*
1783          * MAX_CT_PAYLOAD
1784          */
1785         attr = (struct fdmi_attr_s *) curr_ptr;
1786         attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT);
1787         attr->len = sizeof(fcs_hba_attr->max_ct_pyld);
1788         memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len);
1789         len += attr->len;
1790         count++;
1791         attr->len =
1792                 bfa_os_htons(attr->len + sizeof(attr->type) +
1793                              sizeof(attr->len));
1794
1795         /*
1796          * Update size of payload
1797          */
1798         len += ((sizeof(attr->type) +
1799                  sizeof(attr->len)) * count);
1800
1801         rhba->hba_attr_blk.attr_count = bfa_os_htonl(count);
1802         return len;
1803 }
1804
1805 static void
1806 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1807                                 void *cbarg, bfa_status_t req_status,
1808                                 u32 rsp_len, u32 resid_len,
1809                                 struct fchs_s *rsp_fchs)
1810 {
1811         struct bfa_fcs_lport_fdmi_s *fdmi =
1812                                 (struct bfa_fcs_lport_fdmi_s *) cbarg;
1813         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1814         struct ct_hdr_s *cthdr = NULL;
1815
1816         bfa_trc(port->fcs, port->port_cfg.pwwn);
1817
1818         /*
1819          * Sanity Checks
1820          */
1821         if (req_status != BFA_STATUS_OK) {
1822                 bfa_trc(port->fcs, req_status);
1823                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1824                 return;
1825         }
1826
1827         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1828         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
1829
1830         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1831                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1832                 return;
1833         }
1834
1835         bfa_trc(port->fcs, cthdr->reason_code);
1836         bfa_trc(port->fcs, cthdr->exp_code);
1837         bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1838 }
1839
1840 /**
1841 *  RPRT : Register Port
1842  */
1843 static void
1844 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1845 {
1846         struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1847         struct bfa_fcs_lport_s *port = fdmi->ms->port;
1848         struct fchs_s fchs;
1849         u16        len, attr_len;
1850         struct bfa_fcxp_s *fcxp;
1851         u8        *pyld;
1852
1853         bfa_trc(port->fcs, port->port_cfg.pwwn);
1854
1855         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1856         if (!fcxp) {
1857                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1858                                         bfa_fcs_lport_fdmi_send_rprt, fdmi);
1859                 return;
1860         }
1861         fdmi->fcxp = fcxp;
1862
1863         pyld = bfa_fcxp_get_reqbuf(fcxp);
1864         bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
1865
1866         len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1867                                    FDMI_RPRT);
1868
1869         attr_len =
1870                 bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1871                                           (u8 *) ((struct ct_hdr_s *) pyld
1872                                                        + 1));
1873
1874         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1875                           FC_CLASS_3, len + attr_len, &fchs,
1876                           bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1877                           FC_MAX_PDUSZ, FC_FCCT_TOV);
1878
1879         bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1880 }
1881
1882 /**
1883  * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1884  */
1885 static          u16
1886 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1887                                        u8 *pyld)
1888 {
1889         struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1890         struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1891         struct fdmi_attr_s *attr;
1892         u8        *curr_ptr;
1893         u16        len;
1894         u8      count = 0;
1895
1896         /*
1897          * get port attributes
1898          */
1899         bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1900
1901         len = sizeof(port_attrib->attr_count);
1902
1903         /*
1904          * fill out the invididual entries
1905          */
1906         curr_ptr = (u8 *) &port_attrib->port_attr;
1907
1908         /*
1909          * FC4 Types
1910          */
1911         attr = (struct fdmi_attr_s *) curr_ptr;
1912         attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES);
1913         attr->len = sizeof(fcs_port_attr.supp_fc4_types);
1914         memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len);
1915         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1916         len += attr->len;
1917         ++count;
1918         attr->len =
1919                 bfa_os_htons(attr->len + sizeof(attr->type) +
1920                              sizeof(attr->len));
1921
1922         /*
1923          * Supported Speed
1924          */
1925         attr = (struct fdmi_attr_s *) curr_ptr;
1926         attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED);
1927         attr->len = sizeof(fcs_port_attr.supp_speed);
1928         memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len);
1929         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1930         len += attr->len;
1931         ++count;
1932         attr->len =
1933                 bfa_os_htons(attr->len + sizeof(attr->type) +
1934                              sizeof(attr->len));
1935
1936         /*
1937          * current Port Speed
1938          */
1939         attr = (struct fdmi_attr_s *) curr_ptr;
1940         attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED);
1941         attr->len = sizeof(fcs_port_attr.curr_speed);
1942         memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len);
1943         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1944         len += attr->len;
1945         ++count;
1946         attr->len =
1947                 bfa_os_htons(attr->len + sizeof(attr->type) +
1948                              sizeof(attr->len));
1949
1950         /*
1951          * max frame size
1952          */
1953         attr = (struct fdmi_attr_s *) curr_ptr;
1954         attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE);
1955         attr->len = sizeof(fcs_port_attr.max_frm_size);
1956         memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len);
1957         curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1958         len += attr->len;
1959         ++count;
1960         attr->len =
1961                 bfa_os_htons(attr->len + sizeof(attr->type) +
1962                              sizeof(attr->len));
1963
1964         /*
1965          * OS Device Name
1966          */
1967         if (fcs_port_attr.os_device_name[0] != '\0') {
1968                 attr = (struct fdmi_attr_s *) curr_ptr;
1969                 attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME);
1970                 attr->len = (u16) strlen(fcs_port_attr.os_device_name);
1971                 memcpy(attr->value, fcs_port_attr.os_device_name, attr->len);
1972                 attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1973                                                              *fields need
1974                                                              *to be 4 byte
1975                                                              *aligned */
1976                 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1977                 len += attr->len;
1978                 ++count;
1979                 attr->len =
1980                         bfa_os_htons(attr->len + sizeof(attr->type) +
1981                                         sizeof(attr->len));
1982         }
1983         /*
1984          * Host Name
1985          */
1986         if (fcs_port_attr.host_name[0] != '\0') {
1987                 attr = (struct fdmi_attr_s *) curr_ptr;
1988                 attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME);
1989                 attr->len = (u16) strlen(fcs_port_attr.host_name);
1990                 memcpy(attr->value, fcs_port_attr.host_name, attr->len);
1991                 attr->len = fc_roundup(attr->len, sizeof(u32)); /* variable
1992                                                              *fields need
1993                                                              *to be 4 byte
1994                                                              *aligned */
1995                 curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len;
1996                 len += attr->len;
1997                 ++count;
1998                 attr->len =
1999                         bfa_os_htons(attr->len + sizeof(attr->type) +
2000                                 sizeof(attr->len));
2001         }
2002
2003         /*
2004          * Update size of payload
2005          */
2006         port_attrib->attr_count = bfa_os_htonl(count);
2007         len += ((sizeof(attr->type) +
2008                  sizeof(attr->len)) * count);
2009         return len;
2010 }
2011
2012 static          u16
2013 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2014 {
2015         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2016         struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
2017         u16        len;
2018
2019         rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
2020         rprt->port_name = bfa_fcs_lport_get_pwwn(port);
2021
2022         len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2023                                 (u8 *) &rprt->port_attr_blk);
2024
2025         len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
2026
2027         return len;
2028 }
2029
2030 static void
2031 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2032                                 void *cbarg, bfa_status_t req_status,
2033                                 u32 rsp_len, u32 resid_len,
2034                                 struct fchs_s *rsp_fchs)
2035 {
2036         struct bfa_fcs_lport_fdmi_s *fdmi =
2037                         (struct bfa_fcs_lport_fdmi_s *) cbarg;
2038         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2039         struct ct_hdr_s *cthdr = NULL;
2040
2041         bfa_trc(port->fcs, port->port_cfg.pwwn);
2042
2043         /*
2044          * Sanity Checks
2045          */
2046         if (req_status != BFA_STATUS_OK) {
2047                 bfa_trc(port->fcs, req_status);
2048                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2049                 return;
2050         }
2051
2052         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2053         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
2054
2055         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2056                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2057                 return;
2058         }
2059
2060         bfa_trc(port->fcs, cthdr->reason_code);
2061         bfa_trc(port->fcs, cthdr->exp_code);
2062         bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2063 }
2064
2065 /**
2066 *  RPA : Register Port Attributes.
2067  */
2068 static void
2069 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2070 {
2071         struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2072         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2073         struct fchs_s fchs;
2074         u16        len, attr_len;
2075         struct bfa_fcxp_s *fcxp;
2076         u8        *pyld;
2077
2078         bfa_trc(port->fcs, port->port_cfg.pwwn);
2079
2080         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2081         if (!fcxp) {
2082                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2083                                         bfa_fcs_lport_fdmi_send_rpa, fdmi);
2084                 return;
2085         }
2086         fdmi->fcxp = fcxp;
2087
2088         pyld = bfa_fcxp_get_reqbuf(fcxp);
2089         bfa_os_memset(pyld, 0, FC_MAX_PDUSZ);
2090
2091         len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2092                                    FDMI_RPA);
2093
2094         attr_len =
2095                 bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2096                                          (u8 *) ((struct ct_hdr_s *) pyld
2097                                                       + 1));
2098
2099         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2100                           FC_CLASS_3, len + attr_len, &fchs,
2101                           bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2102                           FC_MAX_PDUSZ, FC_FCCT_TOV);
2103
2104         bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2105 }
2106
2107 static          u16
2108 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2109 {
2110         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2111         struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2112         u16        len;
2113
2114         rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2115
2116         len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2117                                 (u8 *) &rpa->port_attr_blk);
2118
2119         len += sizeof(rpa->port_name);
2120
2121         return len;
2122 }
2123
2124 static void
2125 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2126                         void *cbarg, bfa_status_t req_status, u32 rsp_len,
2127                         u32 resid_len, struct fchs_s *rsp_fchs)
2128 {
2129         struct bfa_fcs_lport_fdmi_s *fdmi =
2130                                 (struct bfa_fcs_lport_fdmi_s *) cbarg;
2131         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2132         struct ct_hdr_s *cthdr = NULL;
2133
2134         bfa_trc(port->fcs, port->port_cfg.pwwn);
2135
2136         /*
2137          * Sanity Checks
2138          */
2139         if (req_status != BFA_STATUS_OK) {
2140                 bfa_trc(port->fcs, req_status);
2141                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2142                 return;
2143         }
2144
2145         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2146         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
2147
2148         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2149                 bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2150                 return;
2151         }
2152
2153         bfa_trc(port->fcs, cthdr->reason_code);
2154         bfa_trc(port->fcs, cthdr->exp_code);
2155         bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2156 }
2157
2158 static void
2159 bfa_fcs_lport_fdmi_timeout(void *arg)
2160 {
2161         struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2162
2163         bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2164 }
2165
2166 void
2167 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2168                          struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2169 {
2170         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2171         struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2172
2173         bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2174
2175         bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2176                                         hba_attr->manufacturer);
2177         bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2178                                         hba_attr->serial_num);
2179         bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2180                                         hba_attr->model);
2181         bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2182                                         hba_attr->model_desc);
2183         bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2184                                         hba_attr->hw_version);
2185         bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2186                                         hba_attr->option_rom_ver);
2187         bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2188                                         hba_attr->fw_version);
2189
2190         strncpy(hba_attr->driver_version, (char *)driver_info->version,
2191                 sizeof(hba_attr->driver_version));
2192
2193         strncpy(hba_attr->os_name, driver_info->host_os_name,
2194                 sizeof(hba_attr->os_name));
2195
2196         /*
2197          * If there is a patch level, append it
2198          * to the os name along with a separator
2199          */
2200         if (driver_info->host_os_patch[0] != '\0') {
2201                 strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2202                         sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2203                 strncat(hba_attr->os_name, driver_info->host_os_patch,
2204                                 sizeof(driver_info->host_os_patch));
2205         }
2206
2207         hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ);
2208 }
2209
2210 void
2211 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2212                           struct bfa_fcs_fdmi_port_attr_s *port_attr)
2213 {
2214         struct bfa_fcs_lport_s *port = fdmi->ms->port;
2215         struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2216         struct bfa_port_attr_s pport_attr;
2217
2218         bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2219
2220         /*
2221          * get pport attributes from hal
2222          */
2223         bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2224
2225         /*
2226          * get FC4 type Bitmask
2227          */
2228         fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2229
2230         /*
2231          * Supported Speeds
2232          */
2233         port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS);
2234
2235         /*
2236          * Current Speed
2237          */
2238         port_attr->curr_speed = bfa_os_htonl(pport_attr.speed);
2239
2240         /*
2241          * Max PDU Size.
2242          */
2243         port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ);
2244
2245         /*
2246          * OS device Name
2247          */
2248         strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2249                 sizeof(port_attr->os_device_name));
2250
2251         /*
2252          * Host name
2253          */
2254         strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2255                 sizeof(port_attr->host_name));
2256
2257 }
2258
2259
2260 void
2261 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2262 {
2263         struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2264
2265         fdmi->ms = ms;
2266         if (ms->port->fcs->fdmi_enabled)
2267                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2268         else
2269                 bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2270 }
2271
2272 void
2273 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2274 {
2275         struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2276
2277         fdmi->ms = ms;
2278         bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2279 }
2280
2281 void
2282 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2283 {
2284         struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2285
2286         fdmi->ms = ms;
2287         bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2288 }
2289
2290 #define BFA_FCS_MS_CMD_MAX_RETRIES  2
2291
2292 /*
2293  * forward declarations
2294  */
2295 static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2296                                            struct bfa_fcxp_s *fcxp_alloced);
2297 static void     bfa_fcs_lport_ms_timeout(void *arg);
2298 static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2299                                                struct bfa_fcxp_s *fcxp,
2300                                                void *cbarg,
2301                                                bfa_status_t req_status,
2302                                                u32 rsp_len,
2303                                                u32 resid_len,
2304                                                struct fchs_s *rsp_fchs);
2305
2306 static void     bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2307                                         struct bfa_fcxp_s *fcxp_alloced);
2308 static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2309                                                struct bfa_fcxp_s *fcxp,
2310                                                void *cbarg,
2311                                                bfa_status_t req_status,
2312                                                u32 rsp_len,
2313                                                u32 resid_len,
2314                                                struct fchs_s *rsp_fchs);
2315 static void     bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2316                                         struct bfa_fcxp_s *fcxp_alloced);
2317 static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2318                                                struct bfa_fcxp_s *fcxp,
2319                                                void *cbarg,
2320                                                bfa_status_t req_status,
2321                                                u32 rsp_len,
2322                                                u32 resid_len,
2323                                                struct fchs_s *rsp_fchs);
2324 /**
2325  *  fcs_ms_sm FCS MS state machine
2326  */
2327
2328 /**
2329  *  MS State Machine events
2330  */
2331 enum port_ms_event {
2332         MSSM_EVENT_PORT_ONLINE = 1,
2333         MSSM_EVENT_PORT_OFFLINE = 2,
2334         MSSM_EVENT_RSP_OK = 3,
2335         MSSM_EVENT_RSP_ERROR = 4,
2336         MSSM_EVENT_TIMEOUT = 5,
2337         MSSM_EVENT_FCXP_SENT = 6,
2338         MSSM_EVENT_PORT_FABRIC_RSCN = 7
2339 };
2340
2341 static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2342                                            enum port_ms_event event);
2343 static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2344                                                  enum port_ms_event event);
2345 static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2346                                          enum port_ms_event event);
2347 static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2348                                                enum port_ms_event event);
2349 static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2350                                                  enum port_ms_event event);
2351 static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2352                                          enum port_ms_event event);
2353 static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2354                                                enum port_ms_event event);
2355 static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2356                                                  enum port_ms_event event);
2357 static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2358                                          enum port_ms_event event);
2359 static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2360                                                enum port_ms_event event);
2361 static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2362                                           enum port_ms_event event);
2363 /**
2364  *      Start in offline state - awaiting NS to send start.
2365  */
2366 static void
2367 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2368                                 enum port_ms_event event)
2369 {
2370         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2371         bfa_trc(ms->port->fcs, event);
2372
2373         switch (event) {
2374         case MSSM_EVENT_PORT_ONLINE:
2375                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2376                 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2377                 break;
2378
2379         case MSSM_EVENT_PORT_OFFLINE:
2380                 break;
2381
2382         default:
2383                 bfa_sm_fault(ms->port->fcs, event);
2384         }
2385 }
2386
2387 static void
2388 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2389                                 enum port_ms_event event)
2390 {
2391         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2392         bfa_trc(ms->port->fcs, event);
2393
2394         switch (event) {
2395         case MSSM_EVENT_FCXP_SENT:
2396                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2397                 break;
2398
2399         case MSSM_EVENT_PORT_OFFLINE:
2400                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2401                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2402                                            &ms->fcxp_wqe);
2403                 break;
2404
2405         default:
2406                 bfa_sm_fault(ms->port->fcs, event);
2407         }
2408 }
2409
2410 static void
2411 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2412                         enum port_ms_event event)
2413 {
2414         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2415         bfa_trc(ms->port->fcs, event);
2416
2417         switch (event) {
2418         case MSSM_EVENT_RSP_ERROR:
2419                 /*
2420                  * Start timer for a delayed retry
2421                  */
2422                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2423                 ms->port->stats.ms_retries++;
2424                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2425                                     &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2426                                     BFA_FCS_RETRY_TIMEOUT);
2427                 break;
2428
2429         case MSSM_EVENT_RSP_OK:
2430                 /*
2431                  * since plogi is done, now invoke MS related sub-modules
2432                  */
2433                 bfa_fcs_lport_fdmi_online(ms);
2434
2435                 /**
2436                  * if this is a Vport, go to online state.
2437                  */
2438                 if (ms->port->vport) {
2439                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2440                         break;
2441                 }
2442
2443                 /*
2444                  * For a base port we need to get the
2445                  * switch's IP address.
2446                  */
2447                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2448                 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2449                 break;
2450
2451         case MSSM_EVENT_PORT_OFFLINE:
2452                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2453                 bfa_fcxp_discard(ms->fcxp);
2454                 break;
2455
2456         default:
2457                 bfa_sm_fault(ms->port->fcs, event);
2458         }
2459 }
2460
2461 static void
2462 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2463                         enum port_ms_event event)
2464 {
2465         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2466         bfa_trc(ms->port->fcs, event);
2467
2468         switch (event) {
2469         case MSSM_EVENT_TIMEOUT:
2470                 /*
2471                  * Retry Timer Expired. Re-send
2472                  */
2473                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2474                 bfa_fcs_lport_ms_send_plogi(ms, NULL);
2475                 break;
2476
2477         case MSSM_EVENT_PORT_OFFLINE:
2478                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2479                 bfa_timer_stop(&ms->timer);
2480                 break;
2481
2482         default:
2483                 bfa_sm_fault(ms->port->fcs, event);
2484         }
2485 }
2486
2487 static void
2488 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2489                         enum port_ms_event event)
2490 {
2491         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2492         bfa_trc(ms->port->fcs, event);
2493
2494         switch (event) {
2495         case MSSM_EVENT_PORT_OFFLINE:
2496                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2497                 break;
2498
2499         case MSSM_EVENT_PORT_FABRIC_RSCN:
2500                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2501                 ms->retry_cnt = 0;
2502                 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2503                 break;
2504
2505         default:
2506                 bfa_sm_fault(ms->port->fcs, event);
2507         }
2508 }
2509
2510 static void
2511 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2512                                 enum port_ms_event event)
2513 {
2514         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2515         bfa_trc(ms->port->fcs, event);
2516
2517         switch (event) {
2518         case MSSM_EVENT_FCXP_SENT:
2519                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2520                 break;
2521
2522         case MSSM_EVENT_PORT_OFFLINE:
2523                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2524                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2525                                            &ms->fcxp_wqe);
2526                 break;
2527
2528         default:
2529                 bfa_sm_fault(ms->port->fcs, event);
2530         }
2531 }
2532
2533 static void
2534 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2535                                 enum port_ms_event event)
2536 {
2537         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2538         bfa_trc(ms->port->fcs, event);
2539
2540         switch (event) {
2541         case MSSM_EVENT_RSP_ERROR:
2542                 /*
2543                  * Start timer for a delayed retry
2544                  */
2545                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2546                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2547                         ms->port->stats.ms_retries++;
2548                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2549                                 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2550                                 BFA_FCS_RETRY_TIMEOUT);
2551                 } else {
2552                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2553                         bfa_fcs_lport_ms_send_gfn(ms, NULL);
2554                         ms->retry_cnt = 0;
2555                 }
2556                 break;
2557
2558         case MSSM_EVENT_RSP_OK:
2559                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2560                 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2561                 break;
2562
2563         case MSSM_EVENT_PORT_OFFLINE:
2564                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2565                 bfa_fcxp_discard(ms->fcxp);
2566                 break;
2567
2568         default:
2569                 bfa_sm_fault(ms->port->fcs, event);
2570         }
2571 }
2572
2573 static void
2574 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2575                                 enum port_ms_event event)
2576 {
2577         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2578         bfa_trc(ms->port->fcs, event);
2579
2580         switch (event) {
2581         case MSSM_EVENT_TIMEOUT:
2582                 /*
2583                  * Retry Timer Expired. Re-send
2584                  */
2585                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2586                 bfa_fcs_lport_ms_send_gmal(ms, NULL);
2587                 break;
2588
2589         case MSSM_EVENT_PORT_OFFLINE:
2590                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2591                 bfa_timer_stop(&ms->timer);
2592                 break;
2593
2594         default:
2595                 bfa_sm_fault(ms->port->fcs, event);
2596         }
2597 }
2598 /**
2599  *  ms_pvt MS local functions
2600  */
2601
2602 static void
2603 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2604 {
2605         struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2606         bfa_fcs_lport_t *port = ms->port;
2607         struct fchs_s   fchs;
2608         int             len;
2609         struct bfa_fcxp_s *fcxp;
2610
2611         bfa_trc(port->fcs, port->pid);
2612
2613         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2614         if (!fcxp) {
2615                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2616                                         bfa_fcs_lport_ms_send_gmal, ms);
2617                 return;
2618         }
2619         ms->fcxp = fcxp;
2620
2621         len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2622                              bfa_fcs_lport_get_fcid(port),
2623                                  bfa_lps_get_peer_nwwn(port->fabric->lps));
2624
2625         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2626                           FC_CLASS_3, len, &fchs,
2627                           bfa_fcs_lport_ms_gmal_response, (void *)ms,
2628                           FC_MAX_PDUSZ, FC_FCCT_TOV);
2629
2630         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2631 }
2632
2633 static void
2634 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2635                                 void *cbarg, bfa_status_t req_status,
2636                                 u32 rsp_len, u32 resid_len,
2637                                 struct fchs_s *rsp_fchs)
2638 {
2639         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2640         bfa_fcs_lport_t *port = ms->port;
2641         struct ct_hdr_s         *cthdr = NULL;
2642         struct fcgs_gmal_resp_s *gmal_resp;
2643         struct fcgs_gmal_entry_s *gmal_entry;
2644         u32             num_entries;
2645         u8                      *rsp_str;
2646
2647         bfa_trc(port->fcs, req_status);
2648         bfa_trc(port->fcs, port->port_cfg.pwwn);
2649
2650         /*
2651          * Sanity Checks
2652          */
2653         if (req_status != BFA_STATUS_OK) {
2654                 bfa_trc(port->fcs, req_status);
2655                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2656                 return;
2657         }
2658
2659         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2660         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
2661
2662         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2663                 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2664
2665                 num_entries = bfa_os_ntohl(gmal_resp->ms_len);
2666                 if (num_entries == 0) {
2667                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2668                         return;
2669                 }
2670                 /*
2671                 * The response could contain multiple Entries.
2672                 * Entries for SNMP interface, etc.
2673                 * We look for the entry with a telnet prefix.
2674                 * First "http://" entry refers to IP addr
2675                 */
2676
2677                 gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2678                 while (num_entries > 0) {
2679                         if (strncmp(gmal_entry->prefix,
2680                                 CT_GMAL_RESP_PREFIX_HTTP,
2681                                 sizeof(gmal_entry->prefix)) == 0) {
2682
2683                                 /*
2684                                 * if the IP address is terminating with a '/',
2685                                 * remove it.
2686                                 * Byte 0 consists of the length of the string.
2687                                 */
2688                                 rsp_str = &(gmal_entry->prefix[0]);
2689                                 if (rsp_str[gmal_entry->len-1] == '/')
2690                                         rsp_str[gmal_entry->len-1] = 0;
2691
2692                                 /* copy IP Address to fabric */
2693                                 strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2694                                         gmal_entry->ip_addr,
2695                                         BFA_FCS_FABRIC_IPADDR_SZ);
2696                                 break;
2697                         } else {
2698                                 --num_entries;
2699                                 ++gmal_entry;
2700                         }
2701                 }
2702
2703                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2704                 return;
2705         }
2706
2707         bfa_trc(port->fcs, cthdr->reason_code);
2708         bfa_trc(port->fcs, cthdr->exp_code);
2709         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2710 }
2711
2712 static void
2713 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2714                         enum port_ms_event event)
2715 {
2716         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2717         bfa_trc(ms->port->fcs, event);
2718
2719         switch (event) {
2720         case MSSM_EVENT_FCXP_SENT:
2721                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2722                 break;
2723
2724         case MSSM_EVENT_PORT_OFFLINE:
2725                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2726                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2727                                            &ms->fcxp_wqe);
2728                 break;
2729
2730         default:
2731                 bfa_sm_fault(ms->port->fcs, event);
2732         }
2733 }
2734
2735 static void
2736 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2737                         enum port_ms_event event)
2738 {
2739         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2740         bfa_trc(ms->port->fcs, event);
2741
2742         switch (event) {
2743         case MSSM_EVENT_RSP_ERROR:
2744                 /*
2745                  * Start timer for a delayed retry
2746                  */
2747                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2748                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2749                         ms->port->stats.ms_retries++;
2750                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2751                                 &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2752                                 BFA_FCS_RETRY_TIMEOUT);
2753                 } else {
2754                         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2755                         ms->retry_cnt = 0;
2756                 }
2757                 break;
2758
2759         case MSSM_EVENT_RSP_OK:
2760                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2761                 break;
2762
2763         case MSSM_EVENT_PORT_OFFLINE:
2764                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2765                 bfa_fcxp_discard(ms->fcxp);
2766                 break;
2767
2768         default:
2769                 bfa_sm_fault(ms->port->fcs, event);
2770         }
2771 }
2772
2773 static void
2774 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2775                                 enum port_ms_event event)
2776 {
2777         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2778         bfa_trc(ms->port->fcs, event);
2779
2780         switch (event) {
2781         case MSSM_EVENT_TIMEOUT:
2782                 /*
2783                  * Retry Timer Expired. Re-send
2784                  */
2785                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2786                 bfa_fcs_lport_ms_send_gfn(ms, NULL);
2787                 break;
2788
2789         case MSSM_EVENT_PORT_OFFLINE:
2790                 bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2791                 bfa_timer_stop(&ms->timer);
2792                 break;
2793
2794         default:
2795                 bfa_sm_fault(ms->port->fcs, event);
2796         }
2797 }
2798 /**
2799  *  ms_pvt MS local functions
2800  */
2801
2802 static void
2803 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2804 {
2805         struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2806         bfa_fcs_lport_t *port = ms->port;
2807         struct fchs_s           fchs;
2808         int                     len;
2809         struct bfa_fcxp_s *fcxp;
2810
2811         bfa_trc(port->fcs, port->pid);
2812
2813         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2814         if (!fcxp) {
2815                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2816                                         bfa_fcs_lport_ms_send_gfn, ms);
2817                 return;
2818         }
2819         ms->fcxp = fcxp;
2820
2821         len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2822                              bfa_fcs_lport_get_fcid(port),
2823                                  bfa_lps_get_peer_nwwn(port->fabric->lps));
2824
2825         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2826                           FC_CLASS_3, len, &fchs,
2827                           bfa_fcs_lport_ms_gfn_response, (void *)ms,
2828                           FC_MAX_PDUSZ, FC_FCCT_TOV);
2829
2830         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2831 }
2832
2833 static void
2834 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2835                         void *cbarg, bfa_status_t req_status, u32 rsp_len,
2836                         u32 resid_len, struct fchs_s *rsp_fchs)
2837 {
2838         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2839         bfa_fcs_lport_t *port = ms->port;
2840         struct ct_hdr_s *cthdr = NULL;
2841         wwn_t          *gfn_resp;
2842
2843         bfa_trc(port->fcs, req_status);
2844         bfa_trc(port->fcs, port->port_cfg.pwwn);
2845
2846         /*
2847          * Sanity Checks
2848          */
2849         if (req_status != BFA_STATUS_OK) {
2850                 bfa_trc(port->fcs, req_status);
2851                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2852                 return;
2853         }
2854
2855         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2856         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
2857
2858         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2859                 gfn_resp = (wwn_t *)(cthdr + 1);
2860                 /* check if it has actually changed */
2861                 if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2862                                 gfn_resp, sizeof(wwn_t)) != 0)) {
2863                         bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2864                 }
2865                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2866                 return;
2867         }
2868
2869         bfa_trc(port->fcs, cthdr->reason_code);
2870         bfa_trc(port->fcs, cthdr->exp_code);
2871         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2872 }
2873
2874 /**
2875  *  ms_pvt MS local functions
2876  */
2877
2878 static void
2879 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2880 {
2881         struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2882         struct bfa_fcs_lport_s *port = ms->port;
2883         struct fchs_s   fchs;
2884         int     len;
2885         struct bfa_fcxp_s *fcxp;
2886
2887         bfa_trc(port->fcs, port->pid);
2888
2889         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2890         if (!fcxp) {
2891                 port->stats.ms_plogi_alloc_wait++;
2892                 bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2893                                         bfa_fcs_lport_ms_send_plogi, ms);
2894                 return;
2895         }
2896         ms->fcxp = fcxp;
2897
2898         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2899                              bfa_os_hton3b(FC_MGMT_SERVER),
2900                              bfa_fcs_lport_get_fcid(port), 0,
2901                              port->port_cfg.pwwn, port->port_cfg.nwwn,
2902                                  bfa_fcport_get_maxfrsize(port->fcs->bfa));
2903
2904         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2905                           FC_CLASS_3, len, &fchs,
2906                           bfa_fcs_lport_ms_plogi_response, (void *)ms,
2907                           FC_MAX_PDUSZ, FC_ELS_TOV);
2908
2909         port->stats.ms_plogi_sent++;
2910         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2911 }
2912
2913 static void
2914 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2915                         void *cbarg, bfa_status_t req_status,
2916                         u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2917 {
2918         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2919         struct bfa_fcs_lport_s *port = ms->port;
2920         struct fc_els_cmd_s *els_cmd;
2921         struct fc_ls_rjt_s *ls_rjt;
2922
2923         bfa_trc(port->fcs, req_status);
2924         bfa_trc(port->fcs, port->port_cfg.pwwn);
2925
2926         /*
2927          * Sanity Checks
2928          */
2929         if (req_status != BFA_STATUS_OK) {
2930                 port->stats.ms_plogi_rsp_err++;
2931                 bfa_trc(port->fcs, req_status);
2932                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2933                 return;
2934         }
2935
2936         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2937
2938         switch (els_cmd->els_code) {
2939
2940         case FC_ELS_ACC:
2941                 if (rsp_len < sizeof(struct fc_logi_s)) {
2942                         bfa_trc(port->fcs, rsp_len);
2943                         port->stats.ms_plogi_acc_err++;
2944                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2945                         break;
2946                 }
2947                 port->stats.ms_plogi_accepts++;
2948                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2949                 break;
2950
2951         case FC_ELS_LS_RJT:
2952                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2953
2954                 bfa_trc(port->fcs, ls_rjt->reason_code);
2955                 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2956
2957                 port->stats.ms_rejects++;
2958                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2959                 break;
2960
2961         default:
2962                 port->stats.ms_plogi_unknown_rsp++;
2963                 bfa_trc(port->fcs, els_cmd->els_code);
2964                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2965         }
2966 }
2967
2968 static void
2969 bfa_fcs_lport_ms_timeout(void *arg)
2970 {
2971         struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2972
2973         ms->port->stats.ms_timeouts++;
2974         bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2975 }
2976
2977
2978 void
2979 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2980 {
2981         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2982
2983         ms->port = port;
2984         bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2985
2986         /*
2987          * Invoke init routines of sub modules.
2988          */
2989         bfa_fcs_lport_fdmi_init(ms);
2990 }
2991
2992 void
2993 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2994 {
2995         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2996
2997         ms->port = port;
2998         bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2999         bfa_fcs_lport_fdmi_offline(ms);
3000 }
3001
3002 void
3003 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
3004 {
3005         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3006
3007         ms->port = port;
3008         bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
3009 }
3010 void
3011 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
3012 {
3013         struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
3014
3015         /* todo.  Handle this only  when in Online state */
3016         if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
3017                 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
3018 }
3019
3020 /**
3021  * @page ns_sm_info VPORT NS State Machine
3022  *
3023  * @section ns_sm_interactions VPORT NS State Machine Interactions
3024  *
3025  * @section ns_sm VPORT NS State Machine
3026  * img ns_sm.jpg
3027  */
3028
3029 /*
3030  * forward declarations
3031  */
3032 static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
3033                                            struct bfa_fcxp_s *fcxp_alloced);
3034 static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
3035                                              struct bfa_fcxp_s *fcxp_alloced);
3036 static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
3037                                             struct bfa_fcxp_s *fcxp_alloced);
3038 static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
3039                                             struct bfa_fcxp_s *fcxp_alloced);
3040 static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
3041                                             struct bfa_fcxp_s *fcxp_alloced);
3042 static void     bfa_fcs_lport_ns_timeout(void *arg);
3043 static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
3044                                                struct bfa_fcxp_s *fcxp,
3045                                                void *cbarg,
3046                                                bfa_status_t req_status,
3047                                                u32 rsp_len,
3048                                                u32 resid_len,
3049                                                struct fchs_s *rsp_fchs);
3050 static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
3051                                                  struct bfa_fcxp_s *fcxp,
3052                                                  void *cbarg,
3053                                                  bfa_status_t req_status,
3054                                                  u32 rsp_len,
3055                                                  u32 resid_len,
3056                                          &n