xref: /openbmc/linux/drivers/scsi/bfa/bfa_fcs.c (revision c7cbb022)
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 within 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 }
1402