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