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