upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / scsi / bfa / ms.c
1 /*
2  * Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18
19 #include <bfa.h>
20 #include <bfa_svc.h>
21 #include "fcs_lport.h"
22 #include "fcs_rport.h"
23 #include "fcs_trcmod.h"
24 #include "fcs_fcxp.h"
25 #include "lport_priv.h"
26
27 BFA_TRC_FILE(FCS, MS);
28
29 #define BFA_FCS_MS_CMD_MAX_RETRIES  2
30 /*
31  * forward declarations
32  */
33 static void     bfa_fcs_port_ms_send_plogi(void *ms_cbarg,
34                                            struct bfa_fcxp_s *fcxp_alloced);
35 static void     bfa_fcs_port_ms_timeout(void *arg);
36 static void     bfa_fcs_port_ms_plogi_response(void *fcsarg,
37                                                struct bfa_fcxp_s *fcxp,
38                                                void *cbarg,
39                                                bfa_status_t req_status,
40                                                u32 rsp_len,
41                                                u32 resid_len,
42                                                struct fchs_s *rsp_fchs);
43
44 static void     bfa_fcs_port_ms_send_gmal(void *ms_cbarg,
45                                           struct bfa_fcxp_s *fcxp_alloced);
46 static void     bfa_fcs_port_ms_gmal_response(void *fcsarg,
47                                               struct bfa_fcxp_s *fcxp,
48                                               void *cbarg,
49                                               bfa_status_t req_status,
50                                               u32 rsp_len,
51                                               u32 resid_len,
52                                               struct fchs_s *rsp_fchs);
53 static void     bfa_fcs_port_ms_send_gfn(void *ms_cbarg,
54                                          struct bfa_fcxp_s *fcxp_alloced);
55 static void     bfa_fcs_port_ms_gfn_response(void *fcsarg,
56                                              struct bfa_fcxp_s *fcxp,
57                                              void *cbarg,
58                                              bfa_status_t req_status,
59                                              u32 rsp_len,
60                                              u32 resid_len,
61                                              struct fchs_s *rsp_fchs);
62 /**
63  *  fcs_ms_sm FCS MS state machine
64  */
65
66 /**
67  *  MS State Machine events
68  */
69 enum port_ms_event {
70         MSSM_EVENT_PORT_ONLINE = 1,
71         MSSM_EVENT_PORT_OFFLINE = 2,
72         MSSM_EVENT_RSP_OK = 3,
73         MSSM_EVENT_RSP_ERROR = 4,
74         MSSM_EVENT_TIMEOUT = 5,
75         MSSM_EVENT_FCXP_SENT = 6,
76         MSSM_EVENT_PORT_FABRIC_RSCN = 7
77 };
78
79 static void     bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
80                                            enum port_ms_event event);
81 static void     bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
82                                                  enum port_ms_event event);
83 static void     bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms,
84                                          enum port_ms_event event);
85 static void     bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
86                                                enum port_ms_event event);
87 static void     bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
88                                                 enum port_ms_event event);
89 static void     bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms,
90                                         enum port_ms_event event);
91 static void     bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
92                                               enum port_ms_event event);
93 static void     bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
94                                                enum port_ms_event event);
95 static void     bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms,
96                                        enum port_ms_event event);
97 static void     bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
98                                              enum port_ms_event event);
99 static void     bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
100                                           enum port_ms_event event);
101 /**
102  *              Start in offline state - awaiting NS to send start.
103  */
104 static void
105 bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms,
106                            enum port_ms_event event)
107 {
108         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
109         bfa_trc(ms->port->fcs, event);
110
111         switch (event) {
112         case MSSM_EVENT_PORT_ONLINE:
113                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
114                 bfa_fcs_port_ms_send_plogi(ms, NULL);
115                 break;
116
117         case MSSM_EVENT_PORT_OFFLINE:
118                 break;
119
120         default:
121                 bfa_sm_fault(ms->port->fcs, event);
122         }
123 }
124
125 static void
126 bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms,
127                                  enum port_ms_event event)
128 {
129         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
130         bfa_trc(ms->port->fcs, event);
131
132         switch (event) {
133         case MSSM_EVENT_FCXP_SENT:
134                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi);
135                 break;
136
137         case MSSM_EVENT_PORT_OFFLINE:
138                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
139                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
140                                        &ms->fcxp_wqe);
141                 break;
142
143         default:
144                 bfa_sm_fault(ms->port->fcs, event);
145         }
146 }
147
148 static void
149 bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
150 {
151         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
152         bfa_trc(ms->port->fcs, event);
153
154         switch (event) {
155         case MSSM_EVENT_RSP_ERROR:
156                 /*
157                  * Start timer for a delayed retry
158                  */
159                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry);
160                 ms->port->stats.ms_retries++;
161                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
162                                 bfa_fcs_port_ms_timeout, ms,
163                                 BFA_FCS_RETRY_TIMEOUT);
164                 break;
165
166         case MSSM_EVENT_RSP_OK:
167                 /*
168                  * since plogi is done, now invoke MS related sub-modules
169                  */
170                 bfa_fcs_port_fdmi_online(ms);
171
172                 /**
173                  * if this is a Vport, go to online state.
174                  */
175                 if (ms->port->vport) {
176                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
177                         break;
178                 }
179
180                 /*
181                  * For a base port we need to get the
182                  * switch's IP address.
183                  */
184                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
185                 bfa_fcs_port_ms_send_gmal(ms, NULL);
186                 break;
187
188         case MSSM_EVENT_PORT_OFFLINE:
189                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
190                 bfa_fcxp_discard(ms->fcxp);
191                 break;
192
193         default:
194                 bfa_sm_fault(ms->port->fcs, event);
195         }
196 }
197
198 static void
199 bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
200                                enum port_ms_event event)
201 {
202         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
203         bfa_trc(ms->port->fcs, event);
204
205         switch (event) {
206         case MSSM_EVENT_TIMEOUT:
207                 /*
208                  * Retry Timer Expired. Re-send
209                  */
210                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
211                 bfa_fcs_port_ms_send_plogi(ms, NULL);
212                 break;
213
214         case MSSM_EVENT_PORT_OFFLINE:
215                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
216                 bfa_timer_stop(&ms->timer);
217                 break;
218
219         default:
220                 bfa_sm_fault(ms->port->fcs, event);
221         }
222 }
223
224 static void
225 bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
226                           enum port_ms_event event)
227 {
228         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
229         bfa_trc(ms->port->fcs, event);
230
231         switch (event) {
232         case MSSM_EVENT_PORT_OFFLINE:
233                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
234                 break;
235
236         case MSSM_EVENT_PORT_FABRIC_RSCN:
237                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
238                 ms->retry_cnt = 0;
239                 bfa_fcs_port_ms_send_gfn(ms, NULL);
240                 break;
241
242         default:
243                 bfa_sm_fault(ms->port->fcs, event);
244         }
245 }
246
247 static void
248 bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
249                                 enum port_ms_event event)
250 {
251         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
252         bfa_trc(ms->port->fcs, event);
253
254         switch (event) {
255         case MSSM_EVENT_FCXP_SENT:
256                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
257                 break;
258
259         case MSSM_EVENT_PORT_OFFLINE:
260                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
261                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
262                                        &ms->fcxp_wqe);
263                 break;
264
265         default:
266                 bfa_sm_fault(ms->port->fcs, event);
267         }
268 }
269
270 static void
271 bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
272 {
273         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
274         bfa_trc(ms->port->fcs, event);
275
276         switch (event) {
277         case MSSM_EVENT_RSP_ERROR:
278                 /*
279                  * Start timer for a delayed retry
280                  */
281                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
282                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
283                         ms->port->stats.ms_retries++;
284                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
285                                         &ms->timer, bfa_fcs_port_ms_timeout, ms,
286                                         BFA_FCS_RETRY_TIMEOUT);
287                 } else {
288                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
289                         bfa_fcs_port_ms_send_gfn(ms, NULL);
290                         ms->retry_cnt = 0;
291                 }
292                 break;
293
294         case MSSM_EVENT_RSP_OK:
295                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
296                 bfa_fcs_port_ms_send_gfn(ms, NULL);
297                 break;
298
299         case MSSM_EVENT_PORT_OFFLINE:
300                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
301                 bfa_fcxp_discard(ms->fcxp);
302                 break;
303
304         default:
305                 bfa_sm_fault(ms->port->fcs, event);
306         }
307 }
308
309 static void
310 bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
311                               enum port_ms_event event)
312 {
313         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
314         bfa_trc(ms->port->fcs, event);
315
316         switch (event) {
317         case MSSM_EVENT_TIMEOUT:
318                 /*
319                  * Retry Timer Expired. Re-send
320                  */
321                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
322                 bfa_fcs_port_ms_send_gmal(ms, NULL);
323                 break;
324
325         case MSSM_EVENT_PORT_OFFLINE:
326                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
327                 bfa_timer_stop(&ms->timer);
328                 break;
329
330         default:
331                 bfa_sm_fault(ms->port->fcs, event);
332         }
333 }
334
335 /**
336  *  ms_pvt MS local functions
337  */
338
339 static void
340 bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
341 {
342         struct bfa_fcs_port_ms_s *ms = ms_cbarg;
343         struct bfa_fcs_port_s *port = ms->port;
344         struct fchs_s          fchs;
345         int             len;
346         struct bfa_fcxp_s *fcxp;
347
348         bfa_trc(port->fcs, port->pid);
349
350         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
351         if (!fcxp) {
352                 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
353                                     bfa_fcs_port_ms_send_gmal, ms);
354                 return;
355         }
356         ms->fcxp = fcxp;
357
358         len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
359                                 bfa_fcs_port_get_fcid(port),
360                                 bfa_lps_get_peer_nwwn(port->fabric->lps));
361
362         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
363                       FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
364                       (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
365
366         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
367 }
368
369 static void
370 bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
371                               void *cbarg, bfa_status_t req_status,
372                               u32 rsp_len, u32 resid_len,
373                               struct fchs_s *rsp_fchs)
374 {
375         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
376         struct bfa_fcs_port_s *port = ms->port;
377         struct ct_hdr_s       *cthdr = NULL;
378         struct fcgs_gmal_resp_s *gmal_resp;
379         struct fc_gmal_entry_s *gmal_entry;
380         u32        num_entries;
381         u8        *rsp_str;
382
383         bfa_trc(port->fcs, req_status);
384         bfa_trc(port->fcs, port->port_cfg.pwwn);
385
386         /*
387          * Sanity Checks
388          */
389         if (req_status != BFA_STATUS_OK) {
390                 bfa_trc(port->fcs, req_status);
391                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
392                 return;
393         }
394
395         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
396         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
397
398         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
399                 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
400                 num_entries = bfa_os_ntohl(gmal_resp->ms_len);
401                 if (num_entries == 0) {
402                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
403                         return;
404                 }
405                 /*
406                  * The response could contain multiple Entries.
407                  * Entries for SNMP interface, etc.
408                  * We look for the entry with a telnet prefix.
409                  * First "http://" entry refers to IP addr
410                  */
411
412                 gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
413                 while (num_entries > 0) {
414                         if (strncmp
415                             (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
416                              sizeof(gmal_entry->prefix)) == 0) {
417
418                                 /*
419                                  * if the IP address is terminating with a '/',
420                                  * remove it. *Byte 0 consists of the length
421                                  * of the string.
422                                  */
423                                 rsp_str = &(gmal_entry->prefix[0]);
424                                 if (rsp_str[gmal_entry->len - 1] == '/')
425                                         rsp_str[gmal_entry->len - 1] = 0;
426                                 /*
427                                  * copy IP Address to fabric
428                                  */
429                                 strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
430                                         gmal_entry->ip_addr,
431                                         BFA_FCS_FABRIC_IPADDR_SZ);
432                                 break;
433                         } else {
434                                 --num_entries;
435                                 ++gmal_entry;
436                         }
437                 }
438
439                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
440                 return;
441         }
442
443         bfa_trc(port->fcs, cthdr->reason_code);
444         bfa_trc(port->fcs, cthdr->exp_code);
445         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
446 }
447
448 static void
449 bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
450                                enum port_ms_event event)
451 {
452         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
453         bfa_trc(ms->port->fcs, event);
454
455         switch (event) {
456         case MSSM_EVENT_FCXP_SENT:
457                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
458                 break;
459
460         case MSSM_EVENT_PORT_OFFLINE:
461                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
462                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
463                                        &ms->fcxp_wqe);
464                 break;
465
466         default:
467                 bfa_sm_fault(ms->port->fcs, event);
468         }
469 }
470
471 static void
472 bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
473 {
474         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
475         bfa_trc(ms->port->fcs, event);
476
477         switch (event) {
478         case MSSM_EVENT_RSP_ERROR:
479                 /*
480                  * Start timer for a delayed retry
481                  */
482                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
483                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
484                         ms->port->stats.ms_retries++;
485                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
486                                         &ms->timer, bfa_fcs_port_ms_timeout, ms,
487                                         BFA_FCS_RETRY_TIMEOUT);
488                 } else {
489                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
490                         ms->retry_cnt = 0;
491                 }
492                 break;
493
494         case MSSM_EVENT_RSP_OK:
495                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
496                 break;
497
498         case MSSM_EVENT_PORT_OFFLINE:
499                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
500                 bfa_fcxp_discard(ms->fcxp);
501                 break;
502
503         default:
504                 bfa_sm_fault(ms->port->fcs, event);
505         }
506 }
507
508 static void
509 bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
510                              enum port_ms_event event)
511 {
512         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
513         bfa_trc(ms->port->fcs, event);
514
515         switch (event) {
516         case MSSM_EVENT_TIMEOUT:
517                 /*
518                  * Retry Timer Expired. Re-send
519                  */
520                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
521                 bfa_fcs_port_ms_send_gfn(ms, NULL);
522                 break;
523
524         case MSSM_EVENT_PORT_OFFLINE:
525                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
526                 bfa_timer_stop(&ms->timer);
527                 break;
528
529         default:
530                 bfa_sm_fault(ms->port->fcs, event);
531         }
532 }
533
534 /**
535  *  ms_pvt MS local functions
536  */
537
538 static void
539 bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
540 {
541         struct bfa_fcs_port_ms_s *ms = ms_cbarg;
542         struct bfa_fcs_port_s *port = ms->port;
543         struct fchs_s          fchs;
544         int             len;
545         struct bfa_fcxp_s *fcxp;
546
547         bfa_trc(port->fcs, port->pid);
548
549         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
550         if (!fcxp) {
551                 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
552                                     bfa_fcs_port_ms_send_gfn, ms);
553                 return;
554         }
555         ms->fcxp = fcxp;
556
557         len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
558                                bfa_fcs_port_get_fcid(port),
559                                bfa_lps_get_peer_nwwn(port->fabric->lps));
560
561         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
562                       FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
563                       (void *)ms, FC_MAX_PDUSZ, FC_FCCT_TOV);
564
565         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
566 }
567
568 static void
569 bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
570                              bfa_status_t req_status, u32 rsp_len,
571                                u32 resid_len, struct fchs_s *rsp_fchs)
572 {
573         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
574         struct bfa_fcs_port_s *port = ms->port;
575         struct ct_hdr_s       *cthdr = NULL;
576         wwn_t          *gfn_resp;
577
578         bfa_trc(port->fcs, req_status);
579         bfa_trc(port->fcs, port->port_cfg.pwwn);
580
581         /*
582          * Sanity Checks
583          */
584         if (req_status != BFA_STATUS_OK) {
585                 bfa_trc(port->fcs, req_status);
586                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
587                 return;
588         }
589
590         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
591         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
592
593         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
594                 gfn_resp = (wwn_t *) (cthdr + 1);
595                 /*
596                  * check if it has actually changed
597                  */
598                 if ((memcmp
599                      ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
600                       sizeof(wwn_t)) != 0))
601                         bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
602                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
603                 return;
604         }
605
606         bfa_trc(port->fcs, cthdr->reason_code);
607         bfa_trc(port->fcs, cthdr->exp_code);
608         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
609 }
610
611 /**
612  *  ms_pvt MS local functions
613  */
614
615 static void
616 bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
617 {
618         struct bfa_fcs_port_ms_s *ms = ms_cbarg;
619         struct bfa_fcs_port_s *port = ms->port;
620         struct fchs_s          fchs;
621         int             len;
622         struct bfa_fcxp_s *fcxp;
623
624         bfa_trc(port->fcs, port->pid);
625
626         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
627         if (!fcxp) {
628                 port->stats.ms_plogi_alloc_wait++;
629                 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
630                                     bfa_fcs_port_ms_send_plogi, ms);
631                 return;
632         }
633         ms->fcxp = fcxp;
634
635         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
636                              bfa_os_hton3b(FC_MGMT_SERVER),
637                              bfa_fcs_port_get_fcid(port), 0,
638                              port->port_cfg.pwwn, port->port_cfg.nwwn,
639                              bfa_fcport_get_maxfrsize(port->fcs->bfa));
640
641         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
642                       FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
643                       (void *)ms, FC_MAX_PDUSZ, FC_ELS_TOV);
644
645         port->stats.ms_plogi_sent++;
646         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
647 }
648
649 static void
650 bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
651                                void *cbarg, bfa_status_t req_status,
652                                u32 rsp_len, u32 resid_len,
653                                struct fchs_s *rsp_fchs)
654 {
655         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
656
657         struct bfa_fcs_port_s *port = ms->port;
658         struct fc_els_cmd_s   *els_cmd;
659         struct fc_ls_rjt_s    *ls_rjt;
660
661         bfa_trc(port->fcs, req_status);
662         bfa_trc(port->fcs, port->port_cfg.pwwn);
663
664         /*
665          * Sanity Checks
666          */
667         if (req_status != BFA_STATUS_OK) {
668                 port->stats.ms_plogi_rsp_err++;
669                 bfa_trc(port->fcs, req_status);
670                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
671                 return;
672         }
673
674         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
675
676         switch (els_cmd->els_code) {
677
678         case FC_ELS_ACC:
679                 if (rsp_len < sizeof(struct fc_logi_s)) {
680                         bfa_trc(port->fcs, rsp_len);
681                         port->stats.ms_plogi_acc_err++;
682                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
683                         break;
684                 }
685                 port->stats.ms_plogi_accepts++;
686                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
687                 break;
688
689         case FC_ELS_LS_RJT:
690                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
691
692                 bfa_trc(port->fcs, ls_rjt->reason_code);
693                 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
694
695                 port->stats.ms_rejects++;
696                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
697                 break;
698
699         default:
700                 port->stats.ms_plogi_unknown_rsp++;
701                 bfa_trc(port->fcs, els_cmd->els_code);
702                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
703         }
704 }
705
706 static void
707 bfa_fcs_port_ms_timeout(void *arg)
708 {
709         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
710
711         ms->port->stats.ms_timeouts++;
712         bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
713 }
714
715
716 void
717 bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
718 {
719         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
720
721         ms->port = port;
722         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
723
724         /*
725          * Invoke init routines of sub modules.
726          */
727         bfa_fcs_port_fdmi_init(ms);
728 }
729
730 void
731 bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
732 {
733         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
734
735         ms->port = port;
736         bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
737         bfa_fcs_port_fdmi_offline(ms);
738 }
739
740 void
741 bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
742 {
743         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
744
745         ms->port = port;
746         bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
747 }
748
749 void
750 bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
751 {
752         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
753
754         /*
755          * @todo.  Handle this only when in Online state
756          */
757         if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
758                 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
759 }