f674f9318629c71f3bf97a0c4c072175268303e4
[linux-flexiantxendom0-3.2.10.git] / drivers / scsi / bfa / bfa_fcs.c
1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17
18 /*
19  *  bfa_fcs.c BFA FCS main
20  */
21
22 #include "bfad_drv.h"
23 #include "bfa_fcs.h"
24 #include "bfa_fcbuild.h"
25
26 BFA_TRC_FILE(FCS, FCS);
27
28 /*
29  * FCS sub-modules
30  */
31 struct bfa_fcs_mod_s {
32         void            (*attach) (struct bfa_fcs_s *fcs);
33         void            (*modinit) (struct bfa_fcs_s *fcs);
34         void            (*modexit) (struct bfa_fcs_s *fcs);
35 };
36
37 #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
38
39 static struct bfa_fcs_mod_s fcs_modules[] = {
40         { bfa_fcs_port_attach, NULL, NULL },
41         { bfa_fcs_uf_attach, NULL, NULL },
42         { bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
43           bfa_fcs_fabric_modexit },
44 };
45
46 /*
47  *  fcs_api BFA FCS API
48  */
49
50 static void
51 bfa_fcs_exit_comp(void *fcs_cbarg)
52 {
53         struct bfa_fcs_s      *fcs = fcs_cbarg;
54         struct bfad_s         *bfad = fcs->bfad;
55
56         complete(&bfad->comp);
57 }
58
59
60
61 /*
62  *  fcs_api BFA FCS API
63  */
64
65 /*
66  * fcs attach -- called once to initialize data structures at driver attach time
67  */
68 void
69 bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
70                bfa_boolean_t min_cfg)
71 {
72         int             i;
73         struct bfa_fcs_mod_s  *mod;
74
75         fcs->bfa = bfa;
76         fcs->bfad = bfad;
77         fcs->min_cfg = min_cfg;
78
79         bfa->fcs = BFA_TRUE;
80         fcbuild_init();
81
82         for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
83                 mod = &fcs_modules[i];
84                 if (mod->attach)
85                         mod->attach(fcs);
86         }
87 }
88
89 /*
90  * fcs initialization, called once after bfa initialization is complete
91  */
92 void
93 bfa_fcs_init(struct bfa_fcs_s *fcs)
94 {
95         int             i, npbc_vports;
96         struct bfa_fcs_mod_s  *mod;
97         struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];
98
99         for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) {
100                 mod = &fcs_modules[i];
101                 if (mod->modinit)
102                         mod->modinit(fcs);
103         }
104         /* Initialize pbc vports */
105         if (!fcs->min_cfg) {
106                 npbc_vports =
107                     bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);
108                 for (i = 0; i < npbc_vports; i++)
109                         bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);
110         }
111 }
112
113
114 /*
115  *      brief
116  *              FCS driver details initialization.
117  *
118  *      param[in]               fcs             FCS instance
119  *      param[in]               driver_info     Driver Details
120  *
121  *      return None
122  */
123 void
124 bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
125                         struct bfa_fcs_driver_info_s *driver_info)
126 {
127
128         fcs->driver_info = *driver_info;
129
130         bfa_fcs_fabric_psymb_init(&fcs->fabric);
131 }
132
133 /*
134  *      brief
135  *              FCS instance cleanup and exit.
136  *
137  *      param[in]               fcs                     FCS instance
138  *      return None
139  */
140 void
141 bfa_fcs_exit(struct bfa_fcs_s *fcs)
142 {
143         struct bfa_fcs_mod_s  *mod;
144         int             nmods, i;
145
146         bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
147
148         nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]);
149
150         for (i = 0; i < nmods; i++) {
151
152                 mod = &fcs_modules[i];
153                 if (mod->modexit) {
154                         bfa_wc_up(&fcs->wc);
155                         mod->modexit(fcs);
156                 }
157         }
158
159         bfa_wc_wait(&fcs->wc);
160 }
161
162
163 /*
164  * Fabric module implementation.
165  */
166
167 #define BFA_FCS_FABRIC_RETRY_DELAY      (2000)  /* Milliseconds */
168 #define BFA_FCS_FABRIC_CLEANUP_DELAY    (10000) /* Milliseconds */
169
170 #define bfa_fcs_fabric_set_opertype(__fabric) do {                      \
171                 if (bfa_fcport_get_topology((__fabric)->fcs->bfa)       \
172                     == BFA_PORT_TOPOLOGY_P2P)                           \
173                         (__fabric)->oper_type = BFA_PORT_TYPE_NPORT;    \
174                 else                                                    \
175                         (__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;   \
176 } while (0)
177
178 /*
179  * forward declarations
180  */
181 static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);
182 static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);
183 static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);
184 static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);
185 static void bfa_fcs_fabric_delay(void *cbarg);
186 static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);
187 static void bfa_fcs_fabric_delete_comp(void *cbarg);
188 static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,
189                                       struct fchs_s *fchs, u16 len);
190 static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
191                                          struct fchs_s *fchs, u16 len);
192 static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);
193 static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,
194                                          struct bfa_fcxp_s *fcxp, void *cbarg,
195                                          bfa_status_t status,
196                                          u32 rsp_len,
197                                          u32 resid_len,
198                                          struct fchs_s *rspfchs);
199
200 static void     bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
201                                          enum bfa_fcs_fabric_event event);
202 static void     bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
203                                           enum bfa_fcs_fabric_event event);
204 static void     bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
205                                            enum bfa_fcs_fabric_event event);
206 static void     bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
207                                         enum bfa_fcs_fabric_event event);
208 static void     bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
209                                               enum bfa_fcs_fabric_event event);
210 static void     bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
211                                        enum bfa_fcs_fabric_event event);
212 static void     bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
213                                            enum bfa_fcs_fabric_event event);
214 static void     bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
215                                        enum bfa_fcs_fabric_event event);
216 static void     bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
217                                             enum bfa_fcs_fabric_event event);
218 static void     bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
219                                            enum bfa_fcs_fabric_event event);
220 static void     bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
221                                            enum bfa_fcs_fabric_event event);
222 /*
223  *   Beginning state before fabric creation.
224  */
225 static void
226 bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,
227                          enum bfa_fcs_fabric_event event)
228 {
229         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
230         bfa_trc(fabric->fcs, event);
231
232         switch (event) {
233         case BFA_FCS_FABRIC_SM_CREATE:
234                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);
235                 bfa_fcs_fabric_init(fabric);
236                 bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);
237                 break;
238
239         case BFA_FCS_FABRIC_SM_LINK_UP:
240         case BFA_FCS_FABRIC_SM_LINK_DOWN:
241                 break;
242
243         default:
244                 bfa_sm_fault(fabric->fcs, event);
245         }
246 }
247
248 /*
249  *   Beginning state before fabric creation.
250  */
251 static void
252 bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,
253                           enum bfa_fcs_fabric_event event)
254 {
255         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
256         bfa_trc(fabric->fcs, event);
257
258         switch (event) {
259         case BFA_FCS_FABRIC_SM_START:
260                 if (bfa_fcport_is_linkup(fabric->fcs->bfa)) {
261                         bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
262                         bfa_fcs_fabric_login(fabric);
263                 } else
264                         bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
265                 break;
266
267         case BFA_FCS_FABRIC_SM_LINK_UP:
268         case BFA_FCS_FABRIC_SM_LINK_DOWN:
269                 break;
270
271         case BFA_FCS_FABRIC_SM_DELETE:
272                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
273                 bfa_wc_down(&fabric->fcs->wc);
274                 break;
275
276         default:
277                 bfa_sm_fault(fabric->fcs, event);
278         }
279 }
280
281 /*
282  *   Link is down, awaiting LINK UP event from port. This is also the
283  *   first state at fabric creation.
284  */
285 static void
286 bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,
287                            enum bfa_fcs_fabric_event event)
288 {
289         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
290         bfa_trc(fabric->fcs, event);
291
292         switch (event) {
293         case BFA_FCS_FABRIC_SM_LINK_UP:
294                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
295                 bfa_fcs_fabric_login(fabric);
296                 break;
297
298         case BFA_FCS_FABRIC_SM_RETRY_OP:
299                 break;
300
301         case BFA_FCS_FABRIC_SM_DELETE:
302                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
303                 bfa_fcs_fabric_delete(fabric);
304                 break;
305
306         default:
307                 bfa_sm_fault(fabric->fcs, event);
308         }
309 }
310
311 /*
312  *   FLOGI is in progress, awaiting FLOGI reply.
313  */
314 static void
315 bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,
316                         enum bfa_fcs_fabric_event event)
317 {
318         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
319         bfa_trc(fabric->fcs, event);
320
321         switch (event) {
322         case BFA_FCS_FABRIC_SM_CONT_OP:
323
324                 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
325                                            fabric->bb_credit);
326                 fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;
327
328                 if (fabric->auth_reqd && fabric->is_auth) {
329                         bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);
330                         bfa_trc(fabric->fcs, event);
331                 } else {
332                         bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
333                         bfa_fcs_fabric_notify_online(fabric);
334                 }
335                 break;
336
337         case BFA_FCS_FABRIC_SM_RETRY_OP:
338                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);
339                 bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,
340                                 bfa_fcs_fabric_delay, fabric,
341                                 BFA_FCS_FABRIC_RETRY_DELAY);
342                 break;
343
344         case BFA_FCS_FABRIC_SM_LOOPBACK:
345                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);
346                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
347                 bfa_fcs_fabric_set_opertype(fabric);
348                 break;
349
350         case BFA_FCS_FABRIC_SM_NO_FABRIC:
351                 fabric->fab_type = BFA_FCS_FABRIC_N2N;
352                 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
353                                            fabric->bb_credit);
354                 bfa_fcs_fabric_notify_online(fabric);
355                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);
356                 break;
357
358         case BFA_FCS_FABRIC_SM_LINK_DOWN:
359                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
360                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
361                 break;
362
363         case BFA_FCS_FABRIC_SM_DELETE:
364                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
365                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
366                 bfa_fcs_fabric_delete(fabric);
367                 break;
368
369         default:
370                 bfa_sm_fault(fabric->fcs, event);
371         }
372 }
373
374
375 static void
376 bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,
377                               enum bfa_fcs_fabric_event event)
378 {
379         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
380         bfa_trc(fabric->fcs, event);
381
382         switch (event) {
383         case BFA_FCS_FABRIC_SM_DELAYED:
384                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);
385                 bfa_fcs_fabric_login(fabric);
386                 break;
387
388         case BFA_FCS_FABRIC_SM_LINK_DOWN:
389                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
390                 bfa_timer_stop(&fabric->delay_timer);
391                 break;
392
393         case BFA_FCS_FABRIC_SM_DELETE:
394                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
395                 bfa_timer_stop(&fabric->delay_timer);
396                 bfa_fcs_fabric_delete(fabric);
397                 break;
398
399         default:
400                 bfa_sm_fault(fabric->fcs, event);
401         }
402 }
403
404 /*
405  *   Authentication is in progress, awaiting authentication results.
406  */
407 static void
408 bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,
409                        enum bfa_fcs_fabric_event event)
410 {
411         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
412         bfa_trc(fabric->fcs, event);
413
414         switch (event) {
415         case BFA_FCS_FABRIC_SM_AUTH_FAILED:
416                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
417                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
418                 break;
419
420         case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
421                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);
422                 bfa_fcs_fabric_notify_online(fabric);
423                 break;
424
425         case BFA_FCS_FABRIC_SM_PERF_EVFP:
426                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);
427                 break;
428
429         case BFA_FCS_FABRIC_SM_LINK_DOWN:
430                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
431                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
432                 break;
433
434         case BFA_FCS_FABRIC_SM_DELETE:
435                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
436                 bfa_fcs_fabric_delete(fabric);
437                 break;
438
439         default:
440                 bfa_sm_fault(fabric->fcs, event);
441         }
442 }
443
444 /*
445  *   Authentication failed
446  */
447 void
448 bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,
449                               enum bfa_fcs_fabric_event event)
450 {
451         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
452         bfa_trc(fabric->fcs, event);
453
454         switch (event) {
455         case BFA_FCS_FABRIC_SM_LINK_DOWN:
456                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
457                 bfa_fcs_fabric_notify_offline(fabric);
458                 break;
459
460         case BFA_FCS_FABRIC_SM_DELETE:
461                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
462                 bfa_fcs_fabric_delete(fabric);
463                 break;
464
465         default:
466                 bfa_sm_fault(fabric->fcs, event);
467         }
468 }
469
470 /*
471  *   Port is in loopback mode.
472  */
473 void
474 bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,
475                            enum bfa_fcs_fabric_event event)
476 {
477         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
478         bfa_trc(fabric->fcs, event);
479
480         switch (event) {
481         case BFA_FCS_FABRIC_SM_LINK_DOWN:
482                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
483                 bfa_fcs_fabric_notify_offline(fabric);
484                 break;
485
486         case BFA_FCS_FABRIC_SM_DELETE:
487                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
488                 bfa_fcs_fabric_delete(fabric);
489                 break;
490
491         default:
492                 bfa_sm_fault(fabric->fcs, event);
493         }
494 }
495
496 /*
497  *   There is no attached fabric - private loop or NPort-to-NPort topology.
498  */
499 static void
500 bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,
501                            enum bfa_fcs_fabric_event event)
502 {
503         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
504         bfa_trc(fabric->fcs, event);
505
506         switch (event) {
507         case BFA_FCS_FABRIC_SM_LINK_DOWN:
508                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
509                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
510                 bfa_fcs_fabric_notify_offline(fabric);
511                 break;
512
513         case BFA_FCS_FABRIC_SM_DELETE:
514                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
515                 bfa_fcs_fabric_delete(fabric);
516                 break;
517
518         case BFA_FCS_FABRIC_SM_NO_FABRIC:
519                 bfa_trc(fabric->fcs, fabric->bb_credit);
520                 bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,
521                                            fabric->bb_credit);
522                 break;
523
524         default:
525                 bfa_sm_fault(fabric->fcs, event);
526         }
527 }
528
529 /*
530  *   Fabric is online - normal operating state.
531  */
532 void
533 bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
534                          enum bfa_fcs_fabric_event event)
535 {
536         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
537         bfa_trc(fabric->fcs, event);
538
539         switch (event) {
540         case BFA_FCS_FABRIC_SM_LINK_DOWN:
541                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);
542                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
543                 bfa_fcs_fabric_notify_offline(fabric);
544                 break;
545
546         case BFA_FCS_FABRIC_SM_DELETE:
547                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);
548                 bfa_fcs_fabric_delete(fabric);
549                 break;
550
551         case BFA_FCS_FABRIC_SM_AUTH_FAILED:
552                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);
553                 bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);
554                 break;
555
556         case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:
557                 break;
558
559         default:
560                 bfa_sm_fault(fabric->fcs, event);
561         }
562 }
563
564 /*
565  *   Exchanging virtual fabric parameters.
566  */
567 static void
568 bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,
569                        enum bfa_fcs_fabric_event event)
570 {
571         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
572         bfa_trc(fabric->fcs, event);
573
574         switch (event) {
575         case BFA_FCS_FABRIC_SM_CONT_OP:
576                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);
577                 break;
578
579         case BFA_FCS_FABRIC_SM_ISOLATE:
580                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);
581                 break;
582
583         default:
584                 bfa_sm_fault(fabric->fcs, event);
585         }
586 }
587
588 /*
589  *   EVFP exchange complete and VFT tagging is enabled.
590  */
591 static void
592 bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,
593                             enum bfa_fcs_fabric_event event)
594 {
595         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
596         bfa_trc(fabric->fcs, event);
597 }
598
599 /*
600  *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).
601  */
602 static void
603 bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
604                            enum bfa_fcs_fabric_event event)
605 {
606         struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
607         char    pwwn_ptr[BFA_STRING_32];
608
609         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
610         bfa_trc(fabric->fcs, event);
611         wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
612
613         BFA_LOG(KERN_INFO, bfad, bfa_log_level,
614                 "Port is isolated due to VF_ID mismatch. "
615                 "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
616                 pwwn_ptr, fabric->fcs->port_vfid,
617                 fabric->event_arg.swp_vfid);
618 }
619
620 /*
621  *   Fabric is being deleted, awaiting vport delete completions.
622  */
623 static void
624 bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,
625                            enum bfa_fcs_fabric_event event)
626 {
627         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
628         bfa_trc(fabric->fcs, event);
629
630         switch (event) {
631         case BFA_FCS_FABRIC_SM_DELCOMP:
632                 bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
633                 bfa_wc_down(&fabric->fcs->wc);
634                 break;
635
636         case BFA_FCS_FABRIC_SM_LINK_UP:
637                 break;
638
639         case BFA_FCS_FABRIC_SM_LINK_DOWN:
640                 bfa_fcs_fabric_notify_offline(fabric);
641                 break;
642
643         default:
644                 bfa_sm_fault(fabric->fcs, event);
645         }
646 }
647
648
649
650 /*
651  *  fcs_fabric_private fabric private functions
652  */
653
654 static void
655 bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)
656 {
657         struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
658
659         port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;
660         port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;
661         port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;
662 }
663
664 /*
665  * Port Symbolic Name Creation for base port.
666  */
667 void
668 bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
669 {
670         struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;
671         char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};
672         struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;
673
674         bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
675
676         /* Model name/number */
677         strncpy((char *)&port_cfg->sym_name, model,
678                 BFA_FCS_PORT_SYMBNAME_MODEL_SZ);
679         strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
680                 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
681
682         /* Driver Version */
683         strncat((char *)&port_cfg->sym_name, (char *)driver_info->version,
684                 BFA_FCS_PORT_SYMBNAME_VERSION_SZ);
685         strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
686                 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
687
688         /* Host machine name */
689         strncat((char *)&port_cfg->sym_name,
690                 (char *)driver_info->host_machine_name,
691                 BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ);
692         strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
693                 sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
694
695         /*
696          * Host OS Info :
697          * If OS Patch Info is not there, do not truncate any bytes from the
698          * OS name string and instead copy the entire OS info string (64 bytes).
699          */
700         if (driver_info->host_os_patch[0] == '\0') {
701                 strncat((char *)&port_cfg->sym_name,
702                         (char *)driver_info->host_os_name,
703                         BFA_FCS_OS_STR_LEN);
704                 strncat((char *)&port_cfg->sym_name,
705                         BFA_FCS_PORT_SYMBNAME_SEPARATOR,
706                         sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
707         } else {
708                 strncat((char *)&port_cfg->sym_name,
709                         (char *)driver_info->host_os_name,
710                         BFA_FCS_PORT_SYMBNAME_OSINFO_SZ);
711                 strncat((char *)&port_cfg->sym_name,
712                         BFA_FCS_PORT_SYMBNAME_SEPARATOR,
713                         sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
714
715                 /* Append host OS Patch Info */
716                 strncat((char *)&port_cfg->sym_name,
717                         (char *)driver_info->host_os_patch,
718                         BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ);
719         }
720
721         /* null terminate */
722         port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
723 }
724
725 /*
726  * bfa lps login completion callback
727  */
728 void
729 bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)
730 {
731         struct bfa_fcs_fabric_s *fabric = uarg;
732
733         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
734         bfa_trc(fabric->fcs, status);
735
736         switch (status) {
737         case BFA_STATUS_OK:
738                 fabric->stats.flogi_accepts++;
739                 break;
740
741         case BFA_STATUS_INVALID_MAC:
742                 /* Only for CNA */
743                 fabric->stats.flogi_acc_err++;
744                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
745
746                 return;
747
748         case BFA_STATUS_EPROTOCOL:
749                 switch (fabric->lps->ext_status) {
750                 case BFA_EPROTO_BAD_ACCEPT:
751                         fabric->stats.flogi_acc_err++;
752                         break;
753
754                 case BFA_EPROTO_UNKNOWN_RSP:
755                         fabric->stats.flogi_unknown_rsp++;
756                         break;
757
758                 default:
759                         break;
760                 }
761                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
762
763                 return;
764
765         case BFA_STATUS_FABRIC_RJT:
766                 fabric->stats.flogi_rejects++;
767                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
768                 return;
769
770         default:
771                 fabric->stats.flogi_rsp_err++;
772                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);
773                 return;
774         }
775
776         fabric->bb_credit = fabric->lps->pr_bbcred;
777         bfa_trc(fabric->fcs, fabric->bb_credit);
778
779         if (!(fabric->lps->brcd_switch))
780                 fabric->fabric_name =  fabric->lps->pr_nwwn;
781
782         /*
783          * Check port type. It should be 1 = F-port.
784          */
785         if (fabric->lps->fport) {
786                 fabric->bport.pid = fabric->lps->lp_pid;
787                 fabric->is_npiv = fabric->lps->npiv_en;
788                 fabric->is_auth = fabric->lps->auth_req;
789                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);
790         } else {
791                 /*
792                  * Nport-2-Nport direct attached
793                  */
794                 fabric->bport.port_topo.pn2n.rem_port_wwn =
795                         fabric->lps->pr_pwwn;
796                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
797         }
798
799         bfa_trc(fabric->fcs, fabric->bport.pid);
800         bfa_trc(fabric->fcs, fabric->is_npiv);
801         bfa_trc(fabric->fcs, fabric->is_auth);
802 }
803 /*
804  *              Allocate and send FLOGI.
805  */
806 static void
807 bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)
808 {
809         struct bfa_s            *bfa = fabric->fcs->bfa;
810         struct bfa_lport_cfg_s  *pcfg = &fabric->bport.port_cfg;
811         u8                      alpa = 0;
812
813         if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)
814                 alpa = bfa_fcport_get_myalpa(bfa);
815
816         bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),
817                       pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);
818
819         fabric->stats.flogi_sent++;
820 }
821
822 static void
823 bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)
824 {
825         struct bfa_fcs_vport_s *vport;
826         struct list_head              *qe, *qen;
827
828         bfa_trc(fabric->fcs, fabric->fabric_name);
829
830         bfa_fcs_fabric_set_opertype(fabric);
831         fabric->stats.fabric_onlines++;
832
833         /*
834          * notify online event to base and then virtual ports
835          */
836         bfa_fcs_lport_online(&fabric->bport);
837
838         list_for_each_safe(qe, qen, &fabric->vport_q) {
839                 vport = (struct bfa_fcs_vport_s *) qe;
840                 bfa_fcs_vport_online(vport);
841         }
842 }
843
844 static void
845 bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)
846 {
847         struct bfa_fcs_vport_s *vport;
848         struct list_head              *qe, *qen;
849
850         bfa_trc(fabric->fcs, fabric->fabric_name);
851         fabric->stats.fabric_offlines++;
852
853         /*
854          * notify offline event first to vports and then base port.
855          */
856         list_for_each_safe(qe, qen, &fabric->vport_q) {
857                 vport = (struct bfa_fcs_vport_s *) qe;
858                 bfa_fcs_vport_offline(vport);
859         }
860
861         bfa_fcs_lport_offline(&fabric->bport);
862
863         fabric->fabric_name = 0;
864         fabric->fabric_ip_addr[0] = 0;
865 }
866
867 static void
868 bfa_fcs_fabric_delay(void *cbarg)
869 {
870         struct bfa_fcs_fabric_s *fabric = cbarg;
871
872         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);
873 }
874
875 /*
876  * Delete all vports and wait for vport delete completions.
877  */
878 static void
879 bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)
880 {
881         struct bfa_fcs_vport_s *vport;
882         struct list_head              *qe, *qen;
883
884         list_for_each_safe(qe, qen, &fabric->vport_q) {
885                 vport = (struct bfa_fcs_vport_s *) qe;
886                 bfa_fcs_vport_fcs_delete(vport);
887         }
888
889         bfa_fcs_lport_delete(&fabric->bport);
890         bfa_wc_wait(&fabric->wc);
891 }
892
893 static void
894 bfa_fcs_fabric_delete_comp(void *cbarg)
895 {
896         struct bfa_fcs_fabric_s *fabric = cbarg;
897
898         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);
899 }
900
901 /*
902  *  fcs_fabric_public fabric public functions
903  */
904
905 /*
906  * Attach time initialization.
907  */
908 void
909 bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
910 {
911         struct bfa_fcs_fabric_s *fabric;
912
913         fabric = &fcs->fabric;
914         memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
915
916         /*
917          * Initialize base fabric.
918          */
919         fabric->fcs = fcs;
920         INIT_LIST_HEAD(&fabric->vport_q);
921         INIT_LIST_HEAD(&fabric->vf_q);
922         fabric->lps = bfa_lps_alloc(fcs->bfa);
923         WARN_ON(!fabric->lps);
924
925         /*
926          * Initialize fabric delete completion handler. Fabric deletion is
927          * complete when the last vport delete is complete.
928          */
929         bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
930         bfa_wc_up(&fabric->wc); /* For the base port */
931
932         bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
933         bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
934 }
935
936 void
937 bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
938 {
939         bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
940         bfa_trc(fcs, 0);
941 }
942
943 /*
944  *   Module cleanup
945  */
946 void
947 bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
948 {
949         struct bfa_fcs_fabric_s *fabric;
950
951         bfa_trc(fcs, 0);
952
953         /*
954          * Cleanup base fabric.
955          */
956         fabric = &fcs->fabric;
957         bfa_lps_delete(fabric->lps);
958         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
959 }
960
961 /*
962  * Fabric module start -- kick starts FCS actions
963  */
964 void
965 bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)
966 {
967         struct bfa_fcs_fabric_s *fabric;
968
969         bfa_trc(fcs, 0);
970         fabric = &fcs->fabric;
971         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);
972 }
973
974
975 /*
976  *   Link up notification from BFA physical port module.
977  */
978 void
979 bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)
980 {
981         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
982         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);
983 }
984
985 /*
986  *   Link down notification from BFA physical port module.
987  */
988 void
989 bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)
990 {
991         bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);
992         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);
993 }
994
995 /*
996  *   A child vport is being created in the fabric.
997  *
998  *   Call from vport module at vport creation. A list of base port and vports
999  *   belonging to a fabric is maintained to propagate link events.
1000  *
1001  *   param[in] fabric - Fabric instance. This can be a base fabric or vf.
1002  *   param[in] vport  - Vport being created.
1003  *
1004  *   @return None (always succeeds)
1005  */
1006 void
1007 bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
1008                         struct bfa_fcs_vport_s *vport)
1009 {
1010         /*
1011          * - add vport to fabric's vport_q
1012          */
1013         bfa_trc(fabric->fcs, fabric->vf_id);
1014
1015         list_add_tail(&vport->qe, &fabric->vport_q);
1016         fabric->num_vports++;
1017         bfa_wc_up(&fabric->wc);
1018 }
1019
1020 /*
1021  *   A child vport is being deleted from fabric.
1022  *
1023  *   Vport is being deleted.
1024  */
1025 void
1026 bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,
1027                         struct bfa_fcs_vport_s *vport)
1028 {
1029         list_del(&vport->qe);
1030         fabric->num_vports--;
1031         bfa_wc_down(&fabric->wc);
1032 }
1033
1034
1035 /*
1036  * Lookup for a vport withing a fabric given its pwwn
1037  */
1038 struct bfa_fcs_vport_s *
1039 bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
1040 {
1041         struct bfa_fcs_vport_s *vport;
1042         struct list_head              *qe;
1043
1044         list_for_each(qe, &fabric->vport_q) {
1045                 vport = (struct bfa_fcs_vport_s *) qe;
1046                 if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)
1047                         return vport;
1048         }
1049
1050         return NULL;
1051 }
1052
1053
1054 /*
1055  *  Get OUI of the attached switch.
1056  *
1057  *  Note : Use of this function should be avoided as much as possible.
1058  *         This function should be used only if there is any requirement
1059 *          to check for FOS version below 6.3.
1060  *         To check if the attached fabric is a brocade fabric, use
1061  *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
1062  *         or above only.
1063  */
1064
1065 u16
1066 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)
1067 {
1068         wwn_t fab_nwwn;
1069         u8 *tmp;
1070         u16 oui;
1071
1072         fab_nwwn = fabric->lps->pr_nwwn;
1073
1074         tmp = (u8 *)&fab_nwwn;
1075         oui = (tmp[3] << 8) | tmp[4];
1076
1077         return oui;
1078 }
1079 /*
1080  *              Unsolicited frame receive handling.
1081  */
1082 void
1083 bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1084                        u16 len)
1085 {
1086         u32     pid = fchs->d_id;
1087         struct bfa_fcs_vport_s *vport;
1088         struct list_head              *qe;
1089         struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1090         struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;
1091
1092         bfa_trc(fabric->fcs, len);
1093         bfa_trc(fabric->fcs, pid);
1094
1095         /*
1096          * Look for our own FLOGI frames being looped back. This means an
1097          * external loopback cable is in place. Our own FLOGI frames are
1098          * sometimes looped back when switch port gets temporarily bypassed.
1099          */
1100         if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&
1101             (els_cmd->els_code == FC_ELS_FLOGI) &&
1102             (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {
1103                 bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);
1104                 return;
1105         }
1106
1107         /*
1108          * FLOGI/EVFP exchanges should be consumed by base fabric.
1109          */
1110         if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {
1111                 bfa_trc(fabric->fcs, pid);
1112                 bfa_fcs_fabric_process_uf(fabric, fchs, len);
1113                 return;
1114         }
1115
1116         if (fabric->bport.pid == pid) {
1117                 /*
1118                  * All authentication frames should be routed to auth
1119                  */
1120                 bfa_trc(fabric->fcs, els_cmd->els_code);
1121                 if (els_cmd->els_code == FC_ELS_AUTH) {
1122                         bfa_trc(fabric->fcs, els_cmd->els_code);
1123                         return;
1124                 }
1125
1126                 bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));
1127                 bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1128                 return;
1129         }
1130
1131         /*
1132          * look for a matching local port ID
1133          */
1134         list_for_each(qe, &fabric->vport_q) {
1135                 vport = (struct bfa_fcs_vport_s *) qe;
1136                 if (vport->lport.pid == pid) {
1137                         bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);
1138                         return;
1139                 }
1140         }
1141         bfa_trc(fabric->fcs, els_cmd->els_code);
1142         bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);
1143 }
1144
1145 /*
1146  *              Unsolicited frames to be processed by fabric.
1147  */
1148 static void
1149 bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,
1150                           u16 len)
1151 {
1152         struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1153
1154         bfa_trc(fabric->fcs, els_cmd->els_code);
1155
1156         switch (els_cmd->els_code) {
1157         case FC_ELS_FLOGI:
1158                 bfa_fcs_fabric_process_flogi(fabric, fchs, len);
1159                 break;
1160
1161         default:
1162                 /*
1163                  * need to generate a LS_RJT
1164                  */
1165                 break;
1166         }
1167 }
1168
1169 /*
1170  *      Process incoming FLOGI
1171  */
1172 static void
1173 bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,
1174                         struct fchs_s *fchs, u16 len)
1175 {
1176         struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);
1177         struct bfa_fcs_lport_s *bport = &fabric->bport;
1178
1179         bfa_trc(fabric->fcs, fchs->s_id);
1180
1181         fabric->stats.flogi_rcvd++;
1182         /*
1183          * Check port type. It should be 0 = n-port.
1184          */
1185         if (flogi->csp.port_type) {
1186                 /*
1187                  * @todo: may need to send a LS_RJT
1188                  */
1189                 bfa_trc(fabric->fcs, flogi->port_name);
1190                 fabric->stats.flogi_rejected++;
1191                 return;
1192         }
1193
1194         fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);
1195         bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;
1196         bport->port_topo.pn2n.reply_oxid = fchs->ox_id;
1197
1198         /*
1199          * Send a Flogi Acc
1200          */
1201         bfa_fcs_fabric_send_flogi_acc(fabric);
1202         bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
1203 }
1204
1205 static void
1206 bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)
1207 {
1208         struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;
1209         struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;
1210         struct bfa_s      *bfa = fabric->fcs->bfa;
1211         struct bfa_fcxp_s *fcxp;
1212         u16     reqlen;
1213         struct fchs_s   fchs;
1214
1215         fcxp = bfa_fcs_fcxp_alloc(fabric->fcs);
1216         /*
1217          * Do not expect this failure -- expect remote node to retry
1218          */
1219         if (!fcxp)
1220                 return;
1221
1222         reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
1223                                     bfa_hton3b(FC_FABRIC_PORT),
1224                                     n2n_port->reply_oxid, pcfg->pwwn,
1225                                     pcfg->nwwn,
1226                                     bfa_fcport_get_maxfrsize(bfa),
1227                                     bfa_fcport_get_rx_bbcredit(bfa));
1228
1229         bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->lp_tag,
1230                       BFA_FALSE, FC_CLASS_3,
1231                       reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,
1232                       FC_MAX_PDUSZ, 0);
1233 }
1234
1235 /*
1236  *   Flogi Acc completion callback.
1237  */
1238 static void
1239 bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
1240                              bfa_status_t status, u32 rsp_len,
1241                              u32 resid_len, struct fchs_s *rspfchs)
1242 {
1243         struct bfa_fcs_fabric_s *fabric = cbarg;
1244
1245         bfa_trc(fabric->fcs, status);
1246 }
1247
1248 /*
1249  *
1250  * @param[in] fabric - fabric
1251  * @param[in] wwn_t - new fabric name
1252  *
1253  * @return - none
1254  */
1255 void
1256 bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
1257                                wwn_t fabric_name)
1258 {
1259         struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;
1260         char    pwwn_ptr[BFA_STRING_32];
1261         char    fwwn_ptr[BFA_STRING_32];
1262
1263         bfa_trc(fabric->fcs, fabric_name);
1264
1265         if (fabric->fabric_name == 0) {
1266                 /*
1267                  * With BRCD switches, we don't get Fabric Name in FLOGI.
1268                  * Don't generate a fabric name change event in this case.
1269                  */
1270                 fabric->fabric_name = fabric_name;
1271         } else {
1272                 fabric->fabric_name = fabric_name;
1273                 wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
1274                 wwn2str(fwwn_ptr,
1275                         bfa_fcs_lport_get_fabric_name(&fabric->bport));
1276                 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
1277                         "Base port WWN = %s Fabric WWN = %s\n",
1278                         pwwn_ptr, fwwn_ptr);
1279         }
1280 }
1281
1282 /*
1283  *      Returns FCS vf structure for a given vf_id.
1284  *
1285  *      param[in]       vf_id - VF_ID
1286  *
1287  *      return
1288  *      If lookup succeeds, retuns fcs vf object, otherwise returns NULL
1289  */
1290 bfa_fcs_vf_t   *
1291 bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)
1292 {
1293         bfa_trc(fcs, vf_id);
1294         if (vf_id == FC_VF_ID_NULL)
1295                 return &fcs->fabric;
1296
1297         return NULL;
1298 }
1299
1300 /*
1301  * BFA FCS PPORT ( physical port)
1302  */
1303 static void
1304 bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
1305 {
1306         struct bfa_fcs_s      *fcs = cbarg;
1307
1308         bfa_trc(fcs, event);
1309
1310         switch (event) {
1311         case BFA_PORT_LINKUP:
1312                 bfa_fcs_fabric_link_up(&fcs->fabric);
1313                 break;
1314
1315         case BFA_PORT_LINKDOWN:
1316                 bfa_fcs_fabric_link_down(&fcs->fabric);
1317                 break;
1318
1319         default:
1320                 WARN_ON(1);
1321         }
1322 }
1323
1324 void
1325 bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
1326 {
1327         bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
1328 }
1329
1330 /*
1331  * BFA FCS UF ( Unsolicited Frames)
1332  */
1333
1334 /*
1335  *              BFA callback for unsolicited frame receive handler.
1336  *
1337  * @param[in]           cbarg           callback arg for receive handler
1338  * @param[in]           uf              unsolicited frame descriptor
1339  *
1340  * @return None
1341  */
1342 static void
1343 bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
1344 {
1345         struct bfa_fcs_s        *fcs = (struct bfa_fcs_s *) cbarg;
1346         struct fchs_s   *fchs = bfa_uf_get_frmbuf(uf);
1347         u16     len = bfa_uf_get_frmlen(uf);
1348         struct fc_vft_s *vft;
1349         struct bfa_fcs_fabric_s *fabric;
1350
1351         /*
1352          * check for VFT header
1353          */
1354         if (fchs->routing == FC_RTG_EXT_HDR &&
1355             fchs->cat_info == FC_CAT_VFT_HDR) {
1356                 bfa_stats(fcs, uf.tagged);
1357                 vft = bfa_uf_get_frmbuf(uf);
1358                 if (fcs->port_vfid == vft->vf_id)
1359                         fabric = &fcs->fabric;
1360                 else
1361                         fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
1362
1363                 /*
1364                  * drop frame if vfid is unknown
1365                  */
1366                 if (!fabric) {
1367                         WARN_ON(1);
1368                         bfa_stats(fcs, uf.vfid_unknown);
1369                         bfa_uf_free(uf);
1370                         return;
1371                 }
1372
1373                 /*
1374                  * skip vft header
1375                  */
1376                 fchs = (struct fchs_s *) (vft + 1);
1377                 len -= sizeof(struct fc_vft_s);
1378
1379                 bfa_trc(fcs, vft->vf_id);
1380         } else {
1381                 bfa_stats(fcs, uf.untagged);
1382                 fabric = &fcs->fabric;
1383         }
1384
1385         bfa_trc(fcs, ((u32 *) fchs)[0]);
1386         bfa_trc(fcs, ((u32 *) fchs)[1]);
1387         bfa_trc(fcs, ((u32 *) fchs)[2]);
1388         bfa_trc(fcs, ((u32 *) fchs)[3]);
1389         bfa_trc(fcs, ((u32 *) fchs)[4]);
1390         bfa_trc(fcs, ((u32 *) fchs)[5]);
1391         bfa_trc(fcs, len);
1392
1393         bfa_fcs_fabric_uf_recv(fabric, fchs, len);
1394         bfa_uf_free(uf);
1395 }
1396
1397 void
1398 bfa_fcs_uf_attach(struct bfa_fcs_s *fcs)
1399 {
1400         bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
1401 }