libata-sff: separate out BMDMA qc_issue
[safe/jmp/linux-2.6] / 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                 bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer,
161                                 bfa_fcs_port_ms_timeout, ms,
162                                 BFA_FCS_RETRY_TIMEOUT);
163                 break;
164
165         case MSSM_EVENT_RSP_OK:
166                 /*
167                  * since plogi is done, now invoke MS related sub-modules
168                  */
169                 bfa_fcs_port_fdmi_online(ms);
170
171                 /**
172                  * if this is a Vport, go to online state.
173                  */
174                 if (ms->port->vport) {
175                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
176                         break;
177                 }
178
179                 /*
180                  * For a base port we need to get the
181                  * switch's IP address.
182                  */
183                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
184                 bfa_fcs_port_ms_send_gmal(ms, NULL);
185                 break;
186
187         case MSSM_EVENT_PORT_OFFLINE:
188                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
189                 bfa_fcxp_discard(ms->fcxp);
190                 break;
191
192         default:
193                 bfa_sm_fault(ms->port->fcs, event);
194         }
195 }
196
197 static void
198 bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms,
199                                enum port_ms_event event)
200 {
201         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
202         bfa_trc(ms->port->fcs, event);
203
204         switch (event) {
205         case MSSM_EVENT_TIMEOUT:
206                 /*
207                  * Retry Timer Expired. Re-send
208                  */
209                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending);
210                 bfa_fcs_port_ms_send_plogi(ms, NULL);
211                 break;
212
213         case MSSM_EVENT_PORT_OFFLINE:
214                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
215                 bfa_timer_stop(&ms->timer);
216                 break;
217
218         default:
219                 bfa_sm_fault(ms->port->fcs, event);
220         }
221 }
222
223 static void
224 bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms,
225                           enum port_ms_event event)
226 {
227         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
228         bfa_trc(ms->port->fcs, event);
229
230         switch (event) {
231         case MSSM_EVENT_PORT_OFFLINE:
232                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
233                 break;
234
235         case MSSM_EVENT_PORT_FABRIC_RSCN:
236                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
237                 ms->retry_cnt = 0;
238                 bfa_fcs_port_ms_send_gfn(ms, NULL);
239                 break;
240
241         default:
242                 bfa_sm_fault(ms->port->fcs, event);
243         }
244 }
245
246 static void
247 bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms,
248                                 enum port_ms_event event)
249 {
250         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
251         bfa_trc(ms->port->fcs, event);
252
253         switch (event) {
254         case MSSM_EVENT_FCXP_SENT:
255                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal);
256                 break;
257
258         case MSSM_EVENT_PORT_OFFLINE:
259                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
260                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
261                                        &ms->fcxp_wqe);
262                 break;
263
264         default:
265                 bfa_sm_fault(ms->port->fcs, event);
266         }
267 }
268
269 static void
270 bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
271 {
272         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
273         bfa_trc(ms->port->fcs, event);
274
275         switch (event) {
276         case MSSM_EVENT_RSP_ERROR:
277                 /*
278                  * Start timer for a delayed retry
279                  */
280                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
281                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry);
282                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
283                                         &ms->timer, bfa_fcs_port_ms_timeout, ms,
284                                         BFA_FCS_RETRY_TIMEOUT);
285                 } else {
286                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
287                         bfa_fcs_port_ms_send_gfn(ms, NULL);
288                         ms->retry_cnt = 0;
289                 }
290                 break;
291
292         case MSSM_EVENT_RSP_OK:
293                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
294                 bfa_fcs_port_ms_send_gfn(ms, NULL);
295                 break;
296
297         case MSSM_EVENT_PORT_OFFLINE:
298                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
299                 bfa_fcxp_discard(ms->fcxp);
300                 break;
301
302         default:
303                 bfa_sm_fault(ms->port->fcs, event);
304         }
305 }
306
307 static void
308 bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms,
309                               enum port_ms_event event)
310 {
311         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
312         bfa_trc(ms->port->fcs, event);
313
314         switch (event) {
315         case MSSM_EVENT_TIMEOUT:
316                 /*
317                  * Retry Timer Expired. Re-send
318                  */
319                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending);
320                 bfa_fcs_port_ms_send_gmal(ms, NULL);
321                 break;
322
323         case MSSM_EVENT_PORT_OFFLINE:
324                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
325                 bfa_timer_stop(&ms->timer);
326                 break;
327
328         default:
329                 bfa_sm_fault(ms->port->fcs, event);
330         }
331 }
332
333 /**
334  *  ms_pvt MS local functions
335  */
336
337 static void
338 bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
339 {
340         struct bfa_fcs_port_ms_s *ms = ms_cbarg;
341         struct bfa_fcs_port_s *port = ms->port;
342         struct fchs_s          fchs;
343         int             len;
344         struct bfa_fcxp_s *fcxp;
345
346         bfa_trc(port->fcs, port->pid);
347
348         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
349         if (!fcxp) {
350                 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
351                                     bfa_fcs_port_ms_send_gmal, ms);
352                 return;
353         }
354         ms->fcxp = fcxp;
355
356         len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
357                                 bfa_fcs_port_get_fcid(port),
358                                 bfa_lps_get_peer_nwwn(port->fabric->lps));
359
360         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
361                       FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response,
362                       (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
363
364         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
365 }
366
367 static void
368 bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
369                               void *cbarg, bfa_status_t req_status,
370                               u32 rsp_len, u32 resid_len,
371                               struct fchs_s *rsp_fchs)
372 {
373         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
374         struct bfa_fcs_port_s *port = ms->port;
375         struct ct_hdr_s       *cthdr = NULL;
376         struct fcgs_gmal_resp_s *gmal_resp;
377         struct fc_gmal_entry_s *gmal_entry;
378         u32        num_entries;
379         u8        *rsp_str;
380
381         bfa_trc(port->fcs, req_status);
382         bfa_trc(port->fcs, port->port_cfg.pwwn);
383
384         /*
385          * Sanity Checks
386          */
387         if (req_status != BFA_STATUS_OK) {
388                 bfa_trc(port->fcs, req_status);
389                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
390                 return;
391         }
392
393         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
394         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
395
396         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
397                 gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
398                 num_entries = bfa_os_ntohl(gmal_resp->ms_len);
399                 if (num_entries == 0) {
400                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
401                         return;
402                 }
403                 /*
404                  * The response could contain multiple Entries.
405                  * Entries for SNMP interface, etc.
406                  * We look for the entry with a telnet prefix.
407                  * First "http://" entry refers to IP addr
408                  */
409
410                 gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma;
411                 while (num_entries > 0) {
412                         if (strncmp
413                             (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP,
414                              sizeof(gmal_entry->prefix)) == 0) {
415
416                                 /*
417                                  * if the IP address is terminating with a '/',
418                                  * remove it. *Byte 0 consists of the length
419                                  * of the string.
420                                  */
421                                 rsp_str = &(gmal_entry->prefix[0]);
422                                 if (rsp_str[gmal_entry->len - 1] == '/')
423                                         rsp_str[gmal_entry->len - 1] = 0;
424                                 /*
425                                  * copy IP Address to fabric
426                                  */
427                                 strncpy(bfa_fcs_port_get_fabric_ipaddr(port),
428                                         gmal_entry->ip_addr,
429                                         BFA_FCS_FABRIC_IPADDR_SZ);
430                                 break;
431                         } else {
432                                 --num_entries;
433                                 ++gmal_entry;
434                         }
435                 }
436
437                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
438                 return;
439         }
440
441         bfa_trc(port->fcs, cthdr->reason_code);
442         bfa_trc(port->fcs, cthdr->exp_code);
443         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
444 }
445
446 static void
447 bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms,
448                                enum port_ms_event event)
449 {
450         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
451         bfa_trc(ms->port->fcs, event);
452
453         switch (event) {
454         case MSSM_EVENT_FCXP_SENT:
455                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn);
456                 break;
457
458         case MSSM_EVENT_PORT_OFFLINE:
459                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
460                 bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
461                                        &ms->fcxp_wqe);
462                 break;
463
464         default:
465                 bfa_sm_fault(ms->port->fcs, event);
466         }
467 }
468
469 static void
470 bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event)
471 {
472         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
473         bfa_trc(ms->port->fcs, event);
474
475         switch (event) {
476         case MSSM_EVENT_RSP_ERROR:
477                 /*
478                  * Start timer for a delayed retry
479                  */
480                 if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
481                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry);
482                         bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
483                                         &ms->timer, bfa_fcs_port_ms_timeout, ms,
484                                         BFA_FCS_RETRY_TIMEOUT);
485                 } else {
486                         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
487                         ms->retry_cnt = 0;
488                 }
489                 break;
490
491         case MSSM_EVENT_RSP_OK:
492                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online);
493                 break;
494
495         case MSSM_EVENT_PORT_OFFLINE:
496                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
497                 bfa_fcxp_discard(ms->fcxp);
498                 break;
499
500         default:
501                 bfa_sm_fault(ms->port->fcs, event);
502         }
503 }
504
505 static void
506 bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms,
507                              enum port_ms_event event)
508 {
509         bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
510         bfa_trc(ms->port->fcs, event);
511
512         switch (event) {
513         case MSSM_EVENT_TIMEOUT:
514                 /*
515                  * Retry Timer Expired. Re-send
516                  */
517                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending);
518                 bfa_fcs_port_ms_send_gfn(ms, NULL);
519                 break;
520
521         case MSSM_EVENT_PORT_OFFLINE:
522                 bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
523                 bfa_timer_stop(&ms->timer);
524                 break;
525
526         default:
527                 bfa_sm_fault(ms->port->fcs, event);
528         }
529 }
530
531 /**
532  *  ms_pvt MS local functions
533  */
534
535 static void
536 bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
537 {
538         struct bfa_fcs_port_ms_s *ms = ms_cbarg;
539         struct bfa_fcs_port_s *port = ms->port;
540         struct fchs_s          fchs;
541         int             len;
542         struct bfa_fcxp_s *fcxp;
543
544         bfa_trc(port->fcs, port->pid);
545
546         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
547         if (!fcxp) {
548                 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
549                                     bfa_fcs_port_ms_send_gfn, ms);
550                 return;
551         }
552         ms->fcxp = fcxp;
553
554         len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
555                                bfa_fcs_port_get_fcid(port),
556                                bfa_lps_get_peer_nwwn(port->fabric->lps));
557
558         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
559                       FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response,
560                       (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
561
562         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
563 }
564
565 static void
566 bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
567                              bfa_status_t req_status, u32 rsp_len,
568                                u32 resid_len, struct fchs_s *rsp_fchs)
569 {
570         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
571         struct bfa_fcs_port_s *port = ms->port;
572         struct ct_hdr_s       *cthdr = NULL;
573         wwn_t          *gfn_resp;
574
575         bfa_trc(port->fcs, req_status);
576         bfa_trc(port->fcs, port->port_cfg.pwwn);
577
578         /*
579          * Sanity Checks
580          */
581         if (req_status != BFA_STATUS_OK) {
582                 bfa_trc(port->fcs, req_status);
583                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
584                 return;
585         }
586
587         cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
588         cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
589
590         if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
591                 gfn_resp = (wwn_t *) (cthdr + 1);
592                 /*
593                  * check if it has actually changed
594                  */
595                 if ((memcmp
596                      ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp,
597                       sizeof(wwn_t)) != 0))
598                         bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
599                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
600                 return;
601         }
602
603         bfa_trc(port->fcs, cthdr->reason_code);
604         bfa_trc(port->fcs, cthdr->exp_code);
605         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
606 }
607
608 /**
609  *  ms_pvt MS local functions
610  */
611
612 static void
613 bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
614 {
615         struct bfa_fcs_port_ms_s *ms = ms_cbarg;
616         struct bfa_fcs_port_s *port = ms->port;
617         struct fchs_s          fchs;
618         int             len;
619         struct bfa_fcxp_s *fcxp;
620
621         bfa_trc(port->fcs, port->pid);
622
623         fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
624         if (!fcxp) {
625                 port->stats.ms_plogi_alloc_wait++;
626                 bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
627                                     bfa_fcs_port_ms_send_plogi, ms);
628                 return;
629         }
630         ms->fcxp = fcxp;
631
632         len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
633                              bfa_os_hton3b(FC_MGMT_SERVER),
634                              bfa_fcs_port_get_fcid(port), 0,
635                              port->port_cfg.pwwn, port->port_cfg.nwwn,
636                              bfa_fcport_get_maxfrsize(port->fcs->bfa));
637
638         bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
639                       FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response,
640                       (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV);
641
642         port->stats.ms_plogi_sent++;
643         bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
644 }
645
646 static void
647 bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
648                                void *cbarg, bfa_status_t req_status,
649                                u32 rsp_len, u32 resid_len,
650                                struct fchs_s *rsp_fchs)
651 {
652         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg;
653
654         struct bfa_fcs_port_s *port = ms->port;
655         struct fc_els_cmd_s   *els_cmd;
656         struct fc_ls_rjt_s    *ls_rjt;
657
658         bfa_trc(port->fcs, req_status);
659         bfa_trc(port->fcs, port->port_cfg.pwwn);
660
661         /*
662          * Sanity Checks
663          */
664         if (req_status != BFA_STATUS_OK) {
665                 port->stats.ms_plogi_rsp_err++;
666                 bfa_trc(port->fcs, req_status);
667                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
668                 return;
669         }
670
671         els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
672
673         switch (els_cmd->els_code) {
674
675         case FC_ELS_ACC:
676                 if (rsp_len < sizeof(struct fc_logi_s)) {
677                         bfa_trc(port->fcs, rsp_len);
678                         port->stats.ms_plogi_acc_err++;
679                         bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
680                         break;
681                 }
682                 port->stats.ms_plogi_accepts++;
683                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
684                 break;
685
686         case FC_ELS_LS_RJT:
687                 ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
688
689                 bfa_trc(port->fcs, ls_rjt->reason_code);
690                 bfa_trc(port->fcs, ls_rjt->reason_code_expl);
691
692                 port->stats.ms_rejects++;
693                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
694                 break;
695
696         default:
697                 port->stats.ms_plogi_unknown_rsp++;
698                 bfa_trc(port->fcs, els_cmd->els_code);
699                 bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
700         }
701 }
702
703 static void
704 bfa_fcs_port_ms_timeout(void *arg)
705 {
706         struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg;
707
708         ms->port->stats.ms_timeouts++;
709         bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
710 }
711
712
713 void
714 bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port)
715 {
716         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
717
718         ms->port = port;
719         bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline);
720
721         /*
722          * Invoke init routines of sub modules.
723          */
724         bfa_fcs_port_fdmi_init(ms);
725 }
726
727 void
728 bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port)
729 {
730         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
731
732         ms->port = port;
733         bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
734         bfa_fcs_port_fdmi_offline(ms);
735 }
736
737 void
738 bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port)
739 {
740         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
741
742         ms->port = port;
743         bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
744 }
745
746 void
747 bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port)
748 {
749         struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
750
751         /*
752          * @todo.  Handle this only when in Online state
753          */
754         if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online))
755                 bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
756 }