brintos

brintos / linux-shallow public Read only

0
0
Text · 38.8 KiB · e52ce9b Raw
1617 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.4 * Copyright (c) 2014- QLogic Corporation.5 * All rights reserved6 * www.qlogic.com7 *8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.9 */10 11/*12 *  bfa_fcs.c BFA FCS main13 */14 15#include "bfad_drv.h"16#include "bfad_im.h"17#include "bfa_fcs.h"18#include "bfa_fcbuild.h"19 20BFA_TRC_FILE(FCS, FCS);21 22/*23 *  fcs_api BFA FCS API24 */25 26static void27bfa_fcs_exit_comp(void *fcs_cbarg)28{29	struct bfa_fcs_s      *fcs = fcs_cbarg;30	struct bfad_s         *bfad = fcs->bfad;31 32	complete(&bfad->comp);33}34 35/*36 * fcs initialization, called once after bfa initialization is complete37 */38void39bfa_fcs_init(struct bfa_fcs_s *fcs)40{41	bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);42	bfa_trc(fcs, 0);43}44 45/*46 *  fcs_api BFA FCS API47 */48 49/*50 * FCS update cfg - reset the pwwn/nwwn of fabric base logical port51 * with values learned during bfa_init firmware GETATTR REQ.52 */53void54bfa_fcs_update_cfg(struct bfa_fcs_s *fcs)55{56	struct bfa_fcs_fabric_s *fabric = &fcs->fabric;57	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;58	struct bfa_ioc_s *ioc = &fabric->fcs->bfa->ioc;59 60	port_cfg->nwwn = ioc->attr->nwwn;61	port_cfg->pwwn = ioc->attr->pwwn;62}63 64/*65 * Stop FCS operations.66 */67void68bfa_fcs_stop(struct bfa_fcs_s *fcs)69{70	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);71	bfa_wc_up(&fcs->wc);72	bfa_fcs_fabric_modstop(fcs);73	bfa_wc_wait(&fcs->wc);74}75 76/*77 * fcs pbc vport initialization78 */79void80bfa_fcs_pbc_vport_init(struct bfa_fcs_s *fcs)81{82	int i, npbc_vports;83	struct bfi_pbc_vport_s pbc_vports[BFI_PBC_MAX_VPORTS];84 85	/* Initialize pbc vports */86	if (!fcs->min_cfg) {87		npbc_vports =88			bfa_iocfc_get_pbc_vports(fcs->bfa, pbc_vports);89		for (i = 0; i < npbc_vports; i++)90			bfa_fcb_pbc_vport_create(fcs->bfa->bfad, pbc_vports[i]);91	}92}93 94/*95 *	brief96 *		FCS driver details initialization.97 *98 *	param[in]		fcs		FCS instance99 *	param[in]		driver_info	Driver Details100 *101 *	return None102 */103void104bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,105			struct bfa_fcs_driver_info_s *driver_info)106{107 108	fcs->driver_info = *driver_info;109 110	bfa_fcs_fabric_psymb_init(&fcs->fabric);111	bfa_fcs_fabric_nsymb_init(&fcs->fabric);112}113 114/*115 *	brief116 *		FCS instance cleanup and exit.117 *118 *	param[in]		fcs			FCS instance119 *	return None120 */121void122bfa_fcs_exit(struct bfa_fcs_s *fcs)123{124	bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);125	bfa_wc_up(&fcs->wc);126	bfa_trc(fcs, 0);127	bfa_lps_delete(fcs->fabric.lps);128	bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_DELETE);129	bfa_wc_wait(&fcs->wc);130}131 132/*133 * Fabric module implementation.134 */135 136#define BFA_FCS_FABRIC_RETRY_DELAY	(2000)	/* Milliseconds */137#define BFA_FCS_FABRIC_CLEANUP_DELAY	(10000)	/* Milliseconds */138 139#define bfa_fcs_fabric_set_opertype(__fabric) do {			\140	if (bfa_fcport_get_topology((__fabric)->fcs->bfa)		\141				== BFA_PORT_TOPOLOGY_P2P) {		\142		if (fabric->fab_type == BFA_FCS_FABRIC_SWITCHED)	\143			(__fabric)->oper_type = BFA_PORT_TYPE_NPORT;	\144		else							\145			(__fabric)->oper_type = BFA_PORT_TYPE_P2P;	\146	} else								\147		(__fabric)->oper_type = BFA_PORT_TYPE_NLPORT;		\148} while (0)149 150/*151 * forward declarations152 */153static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric);154static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric);155static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric);156static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric);157static void bfa_fcs_fabric_delay(void *cbarg);158static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric);159static void bfa_fcs_fabric_delete_comp(void *cbarg);160static void bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric);161static void bfa_fcs_fabric_stop_comp(void *cbarg);162static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric,163				      struct fchs_s *fchs, u16 len);164static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,165					 struct fchs_s *fchs, u16 len);166static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric);167static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg,168					 struct bfa_fcxp_s *fcxp, void *cbarg,169					 bfa_status_t status,170					 u32 rsp_len,171					 u32 resid_len,172					 struct fchs_s *rspfchs);173 174static void	bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,175					 enum bfa_fcs_fabric_event event);176static void	bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,177					  enum bfa_fcs_fabric_event event);178static void	bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,179					   enum bfa_fcs_fabric_event event);180static void	bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,181					enum bfa_fcs_fabric_event event);182static void	bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,183					      enum bfa_fcs_fabric_event event);184static void	bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,185				       enum bfa_fcs_fabric_event event);186static void	bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,187					   enum bfa_fcs_fabric_event event);188static void	bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,189				       enum bfa_fcs_fabric_event event);190static void	bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,191					    enum bfa_fcs_fabric_event event);192static void	bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,193					   enum bfa_fcs_fabric_event event);194static void	bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,195					   enum bfa_fcs_fabric_event event);196static void	bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,197					   enum bfa_fcs_fabric_event event);198static void	bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,199					  enum bfa_fcs_fabric_event event);200/*201 *   Beginning state before fabric creation.202 */203static void204bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric,205			 enum bfa_fcs_fabric_event event)206{207	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);208	bfa_trc(fabric->fcs, event);209 210	switch (event) {211	case BFA_FCS_FABRIC_SM_CREATE:212		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);213		bfa_fcs_fabric_init(fabric);214		bfa_fcs_lport_init(&fabric->bport, &fabric->bport.port_cfg);215		break;216 217	case BFA_FCS_FABRIC_SM_LINK_UP:218	case BFA_FCS_FABRIC_SM_LINK_DOWN:219		break;220 221	default:222		bfa_sm_fault(fabric->fcs, event);223	}224}225 226/*227 *   Beginning state before fabric creation.228 */229static void230bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric,231			  enum bfa_fcs_fabric_event event)232{233	struct bfa_s	*bfa = fabric->fcs->bfa;234 235	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);236	bfa_trc(fabric->fcs, event);237 238	switch (event) {239	case BFA_FCS_FABRIC_SM_START:240		if (!bfa_fcport_is_linkup(fabric->fcs->bfa)) {241			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);242			break;243		}244		if (bfa_fcport_get_topology(bfa) ==245				BFA_PORT_TOPOLOGY_LOOP) {246			fabric->fab_type = BFA_FCS_FABRIC_LOOP;247			fabric->bport.pid = bfa_fcport_get_myalpa(bfa);248			fabric->bport.pid = bfa_hton3b(fabric->bport.pid);249			bfa_sm_set_state(fabric,250					bfa_fcs_fabric_sm_online);251			bfa_fcs_fabric_set_opertype(fabric);252			bfa_fcs_lport_online(&fabric->bport);253		} else {254			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);255			bfa_fcs_fabric_login(fabric);256		}257		break;258 259	case BFA_FCS_FABRIC_SM_LINK_UP:260	case BFA_FCS_FABRIC_SM_LINK_DOWN:261		break;262 263	case BFA_FCS_FABRIC_SM_DELETE:264		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);265		bfa_fcs_fabric_delete(fabric);266		break;267 268	default:269		bfa_sm_fault(fabric->fcs, event);270	}271}272 273/*274 *   Link is down, awaiting LINK UP event from port. This is also the275 *   first state at fabric creation.276 */277static void278bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric,279			   enum bfa_fcs_fabric_event event)280{281	struct bfa_s	*bfa = fabric->fcs->bfa;282 283	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);284	bfa_trc(fabric->fcs, event);285 286	switch (event) {287	case BFA_FCS_FABRIC_SM_LINK_UP:288		if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP) {289			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);290			bfa_fcs_fabric_login(fabric);291			break;292		}293		fabric->fab_type = BFA_FCS_FABRIC_LOOP;294		fabric->bport.pid = bfa_fcport_get_myalpa(bfa);295		fabric->bport.pid = bfa_hton3b(fabric->bport.pid);296		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);297		bfa_fcs_fabric_set_opertype(fabric);298		bfa_fcs_lport_online(&fabric->bport);299		break;300 301	case BFA_FCS_FABRIC_SM_RETRY_OP:302	case BFA_FCS_FABRIC_SM_LOOPBACK:303		break;304 305	case BFA_FCS_FABRIC_SM_DELETE:306		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);307		bfa_fcs_fabric_delete(fabric);308		break;309 310	case BFA_FCS_FABRIC_SM_STOP:311		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);312		bfa_fcs_fabric_stop(fabric);313		break;314 315	default:316		bfa_sm_fault(fabric->fcs, event);317	}318}319 320/*321 *   FLOGI is in progress, awaiting FLOGI reply.322 */323static void324bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric,325			enum bfa_fcs_fabric_event event)326{327	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);328	bfa_trc(fabric->fcs, event);329 330	switch (event) {331	case BFA_FCS_FABRIC_SM_CONT_OP:332 333		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,334					   fabric->bb_credit);335		fabric->fab_type = BFA_FCS_FABRIC_SWITCHED;336 337		if (fabric->auth_reqd && fabric->is_auth) {338			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth);339			bfa_trc(fabric->fcs, event);340		} else {341			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);342			bfa_fcs_fabric_notify_online(fabric);343		}344		break;345 346	case BFA_FCS_FABRIC_SM_RETRY_OP:347		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry);348		bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer,349				bfa_fcs_fabric_delay, fabric,350				BFA_FCS_FABRIC_RETRY_DELAY);351		break;352 353	case BFA_FCS_FABRIC_SM_LOOPBACK:354		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback);355		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);356		bfa_fcs_fabric_set_opertype(fabric);357		break;358 359	case BFA_FCS_FABRIC_SM_NO_FABRIC:360		fabric->fab_type = BFA_FCS_FABRIC_N2N;361		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,362					   fabric->bb_credit);363		bfa_fcs_fabric_notify_online(fabric);364		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric);365		break;366 367	case BFA_FCS_FABRIC_SM_LINK_DOWN:368		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);369		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);370		break;371 372	case BFA_FCS_FABRIC_SM_DELETE:373		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);374		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);375		bfa_fcs_fabric_delete(fabric);376		break;377 378	default:379		bfa_sm_fault(fabric->fcs, event);380	}381}382 383 384static void385bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric,386			      enum bfa_fcs_fabric_event event)387{388	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);389	bfa_trc(fabric->fcs, event);390 391	switch (event) {392	case BFA_FCS_FABRIC_SM_DELAYED:393		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi);394		bfa_fcs_fabric_login(fabric);395		break;396 397	case BFA_FCS_FABRIC_SM_LINK_DOWN:398		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);399		bfa_timer_stop(&fabric->delay_timer);400		break;401 402	case BFA_FCS_FABRIC_SM_DELETE:403		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);404		bfa_timer_stop(&fabric->delay_timer);405		bfa_fcs_fabric_delete(fabric);406		break;407 408	default:409		bfa_sm_fault(fabric->fcs, event);410	}411}412 413/*414 *   Authentication is in progress, awaiting authentication results.415 */416static void417bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric,418		       enum bfa_fcs_fabric_event event)419{420	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);421	bfa_trc(fabric->fcs, event);422 423	switch (event) {424	case BFA_FCS_FABRIC_SM_AUTH_FAILED:425		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);426		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);427		break;428 429	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:430		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online);431		bfa_fcs_fabric_notify_online(fabric);432		break;433 434	case BFA_FCS_FABRIC_SM_PERF_EVFP:435		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp);436		break;437 438	case BFA_FCS_FABRIC_SM_LINK_DOWN:439		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);440		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);441		break;442 443	case BFA_FCS_FABRIC_SM_DELETE:444		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);445		bfa_fcs_fabric_delete(fabric);446		break;447 448	default:449		bfa_sm_fault(fabric->fcs, event);450	}451}452 453/*454 *   Authentication failed455 */456void457bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric,458			      enum bfa_fcs_fabric_event event)459{460	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);461	bfa_trc(fabric->fcs, event);462 463	switch (event) {464	case BFA_FCS_FABRIC_SM_LINK_DOWN:465		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);466		bfa_fcs_fabric_notify_offline(fabric);467		break;468 469	case BFA_FCS_FABRIC_SM_DELETE:470		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);471		bfa_fcs_fabric_delete(fabric);472		break;473 474	default:475		bfa_sm_fault(fabric->fcs, event);476	}477}478 479/*480 *   Port is in loopback mode.481 */482void483bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric,484			   enum bfa_fcs_fabric_event event)485{486	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);487	bfa_trc(fabric->fcs, event);488 489	switch (event) {490	case BFA_FCS_FABRIC_SM_LINK_DOWN:491		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);492		bfa_fcs_fabric_notify_offline(fabric);493		break;494 495	case BFA_FCS_FABRIC_SM_DELETE:496		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);497		bfa_fcs_fabric_delete(fabric);498		break;499 500	default:501		bfa_sm_fault(fabric->fcs, event);502	}503}504 505/*506 *   There is no attached fabric - private loop or NPort-to-NPort topology.507 */508static void509bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric,510			   enum bfa_fcs_fabric_event event)511{512	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);513	bfa_trc(fabric->fcs, event);514 515	switch (event) {516	case BFA_FCS_FABRIC_SM_LINK_DOWN:517		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);518		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);519		bfa_fcs_fabric_notify_offline(fabric);520		break;521 522	case BFA_FCS_FABRIC_SM_DELETE:523		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);524		bfa_fcs_fabric_delete(fabric);525		break;526 527	case BFA_FCS_FABRIC_SM_NO_FABRIC:528		bfa_trc(fabric->fcs, fabric->bb_credit);529		bfa_fcport_set_tx_bbcredit(fabric->fcs->bfa,530					   fabric->bb_credit);531		break;532 533	case BFA_FCS_FABRIC_SM_RETRY_OP:534		break;535 536	default:537		bfa_sm_fault(fabric->fcs, event);538	}539}540 541/*542 *   Fabric is online - normal operating state.543 */544void545bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,546			 enum bfa_fcs_fabric_event event)547{548	struct bfa_s	*bfa = fabric->fcs->bfa;549 550	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);551	bfa_trc(fabric->fcs, event);552 553	switch (event) {554	case BFA_FCS_FABRIC_SM_LINK_DOWN:555		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown);556		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {557			bfa_fcs_lport_offline(&fabric->bport);558		} else {559			bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);560			bfa_fcs_fabric_notify_offline(fabric);561		}562		break;563 564	case BFA_FCS_FABRIC_SM_DELETE:565		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting);566		bfa_fcs_fabric_delete(fabric);567		break;568 569	case BFA_FCS_FABRIC_SM_STOP:570		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_stopping);571		bfa_fcs_fabric_stop(fabric);572		break;573 574	case BFA_FCS_FABRIC_SM_AUTH_FAILED:575		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed);576		bfa_sm_send_event(fabric->lps, BFA_LPS_SM_OFFLINE);577		break;578 579	case BFA_FCS_FABRIC_SM_AUTH_SUCCESS:580		break;581 582	default:583		bfa_sm_fault(fabric->fcs, event);584	}585}586 587/*588 *   Exchanging virtual fabric parameters.589 */590static void591bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric,592		       enum bfa_fcs_fabric_event event)593{594	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);595	bfa_trc(fabric->fcs, event);596 597	switch (event) {598	case BFA_FCS_FABRIC_SM_CONT_OP:599		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done);600		break;601 602	case BFA_FCS_FABRIC_SM_ISOLATE:603		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated);604		break;605 606	default:607		bfa_sm_fault(fabric->fcs, event);608	}609}610 611/*612 *   EVFP exchange complete and VFT tagging is enabled.613 */614static void615bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric,616			    enum bfa_fcs_fabric_event event)617{618	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);619	bfa_trc(fabric->fcs, event);620}621 622/*623 *   Port is isolated after EVFP exchange due to VF_ID mismatch (N and F).624 */625static void626bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,627			   enum bfa_fcs_fabric_event event)628{629	struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;630	char	pwwn_ptr[BFA_STRING_32];631 632	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);633	bfa_trc(fabric->fcs, event);634	wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);635 636	BFA_LOG(KERN_INFO, bfad, bfa_log_level,637		"Port is isolated due to VF_ID mismatch. "638		"PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",639		pwwn_ptr, fabric->fcs->port_vfid,640		fabric->event_arg.swp_vfid);641}642 643/*644 *   Fabric is being deleted, awaiting vport delete completions.645 */646static void647bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric,648			   enum bfa_fcs_fabric_event event)649{650	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);651	bfa_trc(fabric->fcs, event);652 653	switch (event) {654	case BFA_FCS_FABRIC_SM_DELCOMP:655		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);656		bfa_wc_down(&fabric->fcs->wc);657		break;658 659	case BFA_FCS_FABRIC_SM_LINK_UP:660		break;661 662	case BFA_FCS_FABRIC_SM_LINK_DOWN:663		bfa_fcs_fabric_notify_offline(fabric);664		break;665 666	default:667		bfa_sm_fault(fabric->fcs, event);668	}669}670 671/*672 * Fabric is being stopped, awaiting vport stop completions.673 */674static void675bfa_fcs_fabric_sm_stopping(struct bfa_fcs_fabric_s *fabric,676			   enum bfa_fcs_fabric_event event)677{678	struct bfa_s	*bfa = fabric->fcs->bfa;679 680	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);681	bfa_trc(fabric->fcs, event);682 683	switch (event) {684	case BFA_FCS_FABRIC_SM_STOPCOMP:685		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) {686			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);687		} else {688			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);689			bfa_sm_send_event(fabric->lps, BFA_LPS_SM_LOGOUT);690		}691		break;692 693	case BFA_FCS_FABRIC_SM_LINK_UP:694		break;695 696	case BFA_FCS_FABRIC_SM_LINK_DOWN:697		if (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)698			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);699		else700			bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_cleanup);701		break;702 703	default:704		bfa_sm_fault(fabric->fcs, event);705	}706}707 708/*709 * Fabric is being stopped, cleanup without FLOGO710 */711static void712bfa_fcs_fabric_sm_cleanup(struct bfa_fcs_fabric_s *fabric,713			  enum bfa_fcs_fabric_event event)714{715	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);716	bfa_trc(fabric->fcs, event);717 718	switch (event) {719	case BFA_FCS_FABRIC_SM_STOPCOMP:720	case BFA_FCS_FABRIC_SM_LOGOCOMP:721		bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created);722		bfa_wc_down(&(fabric->fcs)->wc);723		break;724 725	case BFA_FCS_FABRIC_SM_LINK_DOWN:726		/*727		 * Ignore - can get this event if we get notified about IOC down728		 * before the fabric completion callbk is done.729		 */730		break;731 732	default:733		bfa_sm_fault(fabric->fcs, event);734	}735}736 737/*738 *  fcs_fabric_private fabric private functions739 */740 741static void742bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric)743{744	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;745 746	port_cfg->roles = BFA_LPORT_ROLE_FCP_IM;747	port_cfg->nwwn = fabric->fcs->bfa->ioc.attr->nwwn;748	port_cfg->pwwn = fabric->fcs->bfa->ioc.attr->pwwn;749}750 751/*752 * Port Symbolic Name Creation for base port.753 */754void755bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)756{757	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;758	char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};759	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;760 761	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);762 763	/* Model name/number */764	strscpy(port_cfg->sym_name.symname, model,765		BFA_SYMNAME_MAXLEN);766	strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,767		BFA_SYMNAME_MAXLEN);768 769	/* Driver Version */770	strlcat(port_cfg->sym_name.symname, driver_info->version,771		BFA_SYMNAME_MAXLEN);772	strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,773		BFA_SYMNAME_MAXLEN);774 775	/* Host machine name */776	strlcat(port_cfg->sym_name.symname,777		driver_info->host_machine_name,778		BFA_SYMNAME_MAXLEN);779	strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,780		BFA_SYMNAME_MAXLEN);781 782	/*783	 * Host OS Info :784	 * If OS Patch Info is not there, do not truncate any bytes from the785	 * OS name string and instead copy the entire OS info string (64 bytes).786	 */787	if (driver_info->host_os_patch[0] == '\0') {788		strlcat(port_cfg->sym_name.symname,789			driver_info->host_os_name,790			BFA_SYMNAME_MAXLEN);791		strlcat(port_cfg->sym_name.symname,792			BFA_FCS_PORT_SYMBNAME_SEPARATOR,793			BFA_SYMNAME_MAXLEN);794	} else {795		strlcat(port_cfg->sym_name.symname,796			driver_info->host_os_name,797			BFA_SYMNAME_MAXLEN);798		strlcat(port_cfg->sym_name.symname,799			BFA_FCS_PORT_SYMBNAME_SEPARATOR,800			BFA_SYMNAME_MAXLEN);801 802		/* Append host OS Patch Info */803		strlcat(port_cfg->sym_name.symname,804			driver_info->host_os_patch,805			BFA_SYMNAME_MAXLEN);806	}807 808	/* null terminate */809	port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;810}811 812/*813 * Node Symbolic Name Creation for base port and all vports814 */815void816bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)817{818	struct bfa_lport_cfg_s *port_cfg = &fabric->bport.port_cfg;819	char model[BFA_ADAPTER_MODEL_NAME_LEN] = {0};820	struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info;821 822	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);823 824	/* Model name/number */825	strscpy(port_cfg->node_sym_name.symname, model,826		BFA_SYMNAME_MAXLEN);827	strlcat(port_cfg->node_sym_name.symname,828			BFA_FCS_PORT_SYMBNAME_SEPARATOR,829			BFA_SYMNAME_MAXLEN);830 831	/* Driver Version */832	strlcat(port_cfg->node_sym_name.symname, (char *)driver_info->version,833		BFA_SYMNAME_MAXLEN);834	strlcat(port_cfg->node_sym_name.symname,835			BFA_FCS_PORT_SYMBNAME_SEPARATOR,836			BFA_SYMNAME_MAXLEN);837 838	/* Host machine name */839	strlcat(port_cfg->node_sym_name.symname,840		driver_info->host_machine_name,841		BFA_SYMNAME_MAXLEN);842	strlcat(port_cfg->node_sym_name.symname,843			BFA_FCS_PORT_SYMBNAME_SEPARATOR,844			BFA_SYMNAME_MAXLEN);845 846	/* null terminate */847	port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;848}849 850/*851 * bfa lps login completion callback852 */853void854bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status)855{856	struct bfa_fcs_fabric_s *fabric = uarg;857 858	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);859	bfa_trc(fabric->fcs, status);860 861	switch (status) {862	case BFA_STATUS_OK:863		fabric->stats.flogi_accepts++;864		break;865 866	case BFA_STATUS_INVALID_MAC:867		/* Only for CNA */868		fabric->stats.flogi_acc_err++;869		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);870 871		return;872 873	case BFA_STATUS_EPROTOCOL:874		switch (fabric->lps->ext_status) {875		case BFA_EPROTO_BAD_ACCEPT:876			fabric->stats.flogi_acc_err++;877			break;878 879		case BFA_EPROTO_UNKNOWN_RSP:880			fabric->stats.flogi_unknown_rsp++;881			break;882 883		default:884			break;885		}886		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);887 888		return;889 890	case BFA_STATUS_FABRIC_RJT:891		fabric->stats.flogi_rejects++;892		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);893		return;894 895	default:896		fabric->stats.flogi_rsp_err++;897		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP);898		return;899	}900 901	fabric->bb_credit = fabric->lps->pr_bbcred;902	bfa_trc(fabric->fcs, fabric->bb_credit);903 904	if (!(fabric->lps->brcd_switch))905		fabric->fabric_name =  fabric->lps->pr_nwwn;906 907	/*908	 * Check port type. It should be 1 = F-port.909	 */910	if (fabric->lps->fport) {911		fabric->bport.pid = fabric->lps->lp_pid;912		fabric->is_npiv = fabric->lps->npiv_en;913		fabric->is_auth = fabric->lps->auth_req;914		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP);915	} else {916		/*917		 * Nport-2-Nport direct attached918		 */919		fabric->bport.port_topo.pn2n.rem_port_wwn =920			fabric->lps->pr_pwwn;921		fabric->fab_type = BFA_FCS_FABRIC_N2N;922		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);923	}924 925	bfa_trc(fabric->fcs, fabric->bport.pid);926	bfa_trc(fabric->fcs, fabric->is_npiv);927	bfa_trc(fabric->fcs, fabric->is_auth);928}929/*930 *		Allocate and send FLOGI.931 */932static void933bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric)934{935	struct bfa_s		*bfa = fabric->fcs->bfa;936	struct bfa_lport_cfg_s	*pcfg = &fabric->bport.port_cfg;937	u8			alpa = 0;938 939 940	bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_fcport_get_maxfrsize(bfa),941		      pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd);942 943	fabric->stats.flogi_sent++;944}945 946static void947bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric)948{949	struct bfa_fcs_vport_s *vport;950	struct list_head	      *qe, *qen;951 952	bfa_trc(fabric->fcs, fabric->fabric_name);953 954	bfa_fcs_fabric_set_opertype(fabric);955	fabric->stats.fabric_onlines++;956 957	/*958	 * notify online event to base and then virtual ports959	 */960	bfa_fcs_lport_online(&fabric->bport);961 962	list_for_each_safe(qe, qen, &fabric->vport_q) {963		vport = (struct bfa_fcs_vport_s *) qe;964		bfa_fcs_vport_online(vport);965	}966}967 968static void969bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric)970{971	struct bfa_fcs_vport_s *vport;972	struct list_head	      *qe, *qen;973 974	bfa_trc(fabric->fcs, fabric->fabric_name);975	fabric->stats.fabric_offlines++;976 977	/*978	 * notify offline event first to vports and then base port.979	 */980	list_for_each_safe(qe, qen, &fabric->vport_q) {981		vport = (struct bfa_fcs_vport_s *) qe;982		bfa_fcs_vport_offline(vport);983	}984 985	bfa_fcs_lport_offline(&fabric->bport);986 987	fabric->fabric_name = 0;988	fabric->fabric_ip_addr[0] = 0;989}990 991static void992bfa_fcs_fabric_delay(void *cbarg)993{994	struct bfa_fcs_fabric_s *fabric = cbarg;995 996	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED);997}998 999/*1000 * Stop all vports and wait for vport stop completions.1001 */1002static void1003bfa_fcs_fabric_stop(struct bfa_fcs_fabric_s *fabric)1004{1005	struct bfa_fcs_vport_s *vport;1006	struct list_head	*qe, *qen;1007 1008	bfa_wc_init(&fabric->stop_wc, bfa_fcs_fabric_stop_comp, fabric);1009 1010	list_for_each_safe(qe, qen, &fabric->vport_q) {1011		vport = (struct bfa_fcs_vport_s *) qe;1012		bfa_wc_up(&fabric->stop_wc);1013		bfa_fcs_vport_fcs_stop(vport);1014	}1015 1016	bfa_wc_up(&fabric->stop_wc);1017	bfa_fcs_lport_stop(&fabric->bport);1018	bfa_wc_wait(&fabric->stop_wc);1019}1020 1021/*1022 * Delete all vports and wait for vport delete completions.1023 */1024static void1025bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric)1026{1027	struct bfa_fcs_vport_s *vport;1028	struct list_head	      *qe, *qen;1029 1030	list_for_each_safe(qe, qen, &fabric->vport_q) {1031		vport = (struct bfa_fcs_vport_s *) qe;1032		bfa_fcs_vport_fcs_delete(vport);1033	}1034 1035	bfa_fcs_lport_delete(&fabric->bport);1036	bfa_wc_wait(&fabric->wc);1037}1038 1039static void1040bfa_fcs_fabric_delete_comp(void *cbarg)1041{1042	struct bfa_fcs_fabric_s *fabric = cbarg;1043 1044	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP);1045}1046 1047static void1048bfa_fcs_fabric_stop_comp(void *cbarg)1049{1050	struct bfa_fcs_fabric_s *fabric = cbarg;1051 1052	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOPCOMP);1053}1054 1055/*1056 *  fcs_fabric_public fabric public functions1057 */1058 1059/*1060 * Fabric module stop -- stop FCS actions1061 */1062void1063bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs)1064{1065	struct bfa_fcs_fabric_s *fabric;1066 1067	bfa_trc(fcs, 0);1068	fabric = &fcs->fabric;1069	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_STOP);1070}1071 1072/*1073 * Fabric module start -- kick starts FCS actions1074 */1075void1076bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs)1077{1078	struct bfa_fcs_fabric_s *fabric;1079 1080	bfa_trc(fcs, 0);1081	fabric = &fcs->fabric;1082	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START);1083}1084 1085 1086/*1087 *   Link up notification from BFA physical port module.1088 */1089void1090bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric)1091{1092	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);1093	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP);1094}1095 1096/*1097 *   Link down notification from BFA physical port module.1098 */1099void1100bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric)1101{1102	bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn);1103	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN);1104}1105 1106/*1107 *   A child vport is being created in the fabric.1108 *1109 *   Call from vport module at vport creation. A list of base port and vports1110 *   belonging to a fabric is maintained to propagate link events.1111 *1112 *   param[in] fabric - Fabric instance. This can be a base fabric or vf.1113 *   param[in] vport  - Vport being created.1114 *1115 *   @return None (always succeeds)1116 */1117void1118bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,1119			struct bfa_fcs_vport_s *vport)1120{1121	/*1122	 * - add vport to fabric's vport_q1123	 */1124	bfa_trc(fabric->fcs, fabric->vf_id);1125 1126	list_add_tail(&vport->qe, &fabric->vport_q);1127	fabric->num_vports++;1128	bfa_wc_up(&fabric->wc);1129}1130 1131/*1132 *   A child vport is being deleted from fabric.1133 *1134 *   Vport is being deleted.1135 */1136void1137bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric,1138			struct bfa_fcs_vport_s *vport)1139{1140	list_del(&vport->qe);1141	fabric->num_vports--;1142	bfa_wc_down(&fabric->wc);1143}1144 1145 1146/*1147 * Lookup for a vport within a fabric given its pwwn1148 */1149struct bfa_fcs_vport_s *1150bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)1151{1152	struct bfa_fcs_vport_s *vport;1153	struct list_head	      *qe;1154 1155	list_for_each(qe, &fabric->vport_q) {1156		vport = (struct bfa_fcs_vport_s *) qe;1157		if (bfa_fcs_lport_get_pwwn(&vport->lport) == pwwn)1158			return vport;1159	}1160 1161	return NULL;1162}1163 1164 1165/*1166 *  Get OUI of the attached switch.1167 *1168 *  Note : Use of this function should be avoided as much as possible.1169 *         This function should be used only if there is any requirement1170*          to check for FOS version below 6.3.1171 *         To check if the attached fabric is a brocade fabric, use1172 *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.31173 *         or above only.1174 */1175 1176u161177bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric)1178{1179	wwn_t fab_nwwn;1180	u8 *tmp;1181	u16 oui;1182 1183	fab_nwwn = fabric->lps->pr_nwwn;1184 1185	tmp = (u8 *)&fab_nwwn;1186	oui = (tmp[3] << 8) | tmp[4];1187 1188	return oui;1189}1190/*1191 *		Unsolicited frame receive handling.1192 */1193void1194bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,1195		       u16 len)1196{1197	u32	pid = fchs->d_id;1198	struct bfa_fcs_vport_s *vport;1199	struct list_head	      *qe;1200	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);1201	struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd;1202 1203	bfa_trc(fabric->fcs, len);1204	bfa_trc(fabric->fcs, pid);1205 1206	/*1207	 * Look for our own FLOGI frames being looped back. This means an1208	 * external loopback cable is in place. Our own FLOGI frames are1209	 * sometimes looped back when switch port gets temporarily bypassed.1210	 */1211	if ((pid == bfa_ntoh3b(FC_FABRIC_PORT)) &&1212	    (els_cmd->els_code == FC_ELS_FLOGI) &&1213	    (flogi->port_name == bfa_fcs_lport_get_pwwn(&fabric->bport))) {1214		bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK);1215		return;1216	}1217 1218	/*1219	 * FLOGI/EVFP exchanges should be consumed by base fabric.1220	 */1221	if (fchs->d_id == bfa_hton3b(FC_FABRIC_PORT)) {1222		bfa_trc(fabric->fcs, pid);1223		bfa_fcs_fabric_process_uf(fabric, fchs, len);1224		return;1225	}1226 1227	if (fabric->bport.pid == pid) {1228		/*1229		 * All authentication frames should be routed to auth1230		 */1231		bfa_trc(fabric->fcs, els_cmd->els_code);1232		if (els_cmd->els_code == FC_ELS_AUTH) {1233			bfa_trc(fabric->fcs, els_cmd->els_code);1234			return;1235		}1236 1237		bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs));1238		bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);1239		return;1240	}1241 1242	/*1243	 * look for a matching local port ID1244	 */1245	list_for_each(qe, &fabric->vport_q) {1246		vport = (struct bfa_fcs_vport_s *) qe;1247		if (vport->lport.pid == pid) {1248			bfa_fcs_lport_uf_recv(&vport->lport, fchs, len);1249			return;1250		}1251	}1252 1253	if (!bfa_fcs_fabric_is_switched(fabric))1254		bfa_fcs_lport_uf_recv(&fabric->bport, fchs, len);1255 1256	bfa_trc(fabric->fcs, fchs->type);1257}1258 1259/*1260 *		Unsolicited frames to be processed by fabric.1261 */1262static void1263bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs,1264			  u16 len)1265{1266	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);1267 1268	bfa_trc(fabric->fcs, els_cmd->els_code);1269 1270	switch (els_cmd->els_code) {1271	case FC_ELS_FLOGI:1272		bfa_fcs_fabric_process_flogi(fabric, fchs, len);1273		break;1274 1275	default:1276		/*1277		 * need to generate a LS_RJT1278		 */1279		break;1280	}1281}1282 1283/*1284 *	Process	incoming FLOGI1285 */1286static void1287bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric,1288			struct fchs_s *fchs, u16 len)1289{1290	struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1);1291	struct bfa_fcs_lport_s *bport = &fabric->bport;1292 1293	bfa_trc(fabric->fcs, fchs->s_id);1294 1295	fabric->stats.flogi_rcvd++;1296	/*1297	 * Check port type. It should be 0 = n-port.1298	 */1299	if (flogi->csp.port_type) {1300		/*1301		 * @todo: may need to send a LS_RJT1302		 */1303		bfa_trc(fabric->fcs, flogi->port_name);1304		fabric->stats.flogi_rejected++;1305		return;1306	}1307 1308	fabric->bb_credit = be16_to_cpu(flogi->csp.bbcred);1309	bport->port_topo.pn2n.rem_port_wwn = flogi->port_name;1310	bport->port_topo.pn2n.reply_oxid = fchs->ox_id;1311 1312	/*1313	 * Send a Flogi Acc1314	 */1315	bfa_fcs_fabric_send_flogi_acc(fabric);1316	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);1317}1318 1319static void1320bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric)1321{1322	struct bfa_lport_cfg_s *pcfg = &fabric->bport.port_cfg;1323	struct bfa_fcs_lport_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n;1324	struct bfa_s	  *bfa = fabric->fcs->bfa;1325	struct bfa_fcxp_s *fcxp;1326	u16	reqlen;1327	struct fchs_s	fchs;1328 1329	fcxp = bfa_fcs_fcxp_alloc(fabric->fcs, BFA_FALSE);1330	/*1331	 * Do not expect this failure -- expect remote node to retry1332	 */1333	if (!fcxp)1334		return;1335 1336	reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),1337				    bfa_hton3b(FC_FABRIC_PORT),1338				    n2n_port->reply_oxid, pcfg->pwwn,1339				    pcfg->nwwn,1340				    bfa_fcport_get_maxfrsize(bfa),1341				    bfa_fcport_get_rx_bbcredit(bfa), 0);1342 1343	bfa_fcxp_send(fcxp, NULL, fabric->vf_id, fabric->lps->bfa_tag,1344		      BFA_FALSE, FC_CLASS_3,1345		      reqlen, &fchs, bfa_fcs_fabric_flogiacc_comp, fabric,1346		      FC_MAX_PDUSZ, 0);1347}1348 1349/*1350 *   Flogi Acc completion callback.1351 */1352static void1353bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,1354			     bfa_status_t status, u32 rsp_len,1355			     u32 resid_len, struct fchs_s *rspfchs)1356{1357	struct bfa_fcs_fabric_s *fabric = cbarg;1358 1359	bfa_trc(fabric->fcs, status);1360}1361 1362 1363/*1364 * Send AEN notification1365 */1366static void1367bfa_fcs_fabric_aen_post(struct bfa_fcs_lport_s *port,1368			enum bfa_port_aen_event event)1369{1370	struct bfad_s *bfad = (struct bfad_s *)port->fabric->fcs->bfad;1371	struct bfa_aen_entry_s  *aen_entry;1372 1373	bfad_get_aen_entry(bfad, aen_entry);1374	if (!aen_entry)1375		return;1376 1377	aen_entry->aen_data.port.pwwn = bfa_fcs_lport_get_pwwn(port);1378	aen_entry->aen_data.port.fwwn = bfa_fcs_lport_get_fabric_name(port);1379 1380	/* Send the AEN notification */1381	bfad_im_post_vendor_event(aen_entry, bfad, ++port->fcs->fcs_aen_seq,1382				  BFA_AEN_CAT_PORT, event);1383}1384 1385/*1386 *1387 * @param[in] fabric - fabric1388 * @param[in] wwn_t - new fabric name1389 *1390 * @return - none1391 */1392void1393bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,1394			       wwn_t fabric_name)1395{1396	struct bfad_s *bfad = (struct bfad_s *)fabric->fcs->bfad;1397	char	pwwn_ptr[BFA_STRING_32];1398	char	fwwn_ptr[BFA_STRING_32];1399 1400	bfa_trc(fabric->fcs, fabric_name);1401 1402	if (fabric->fabric_name == 0) {1403		/*1404		 * With BRCD switches, we don't get Fabric Name in FLOGI.1405		 * Don't generate a fabric name change event in this case.1406		 */1407		fabric->fabric_name = fabric_name;1408	} else {1409		fabric->fabric_name = fabric_name;1410		wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));1411		wwn2str(fwwn_ptr,1412			bfa_fcs_lport_get_fabric_name(&fabric->bport));1413		BFA_LOG(KERN_WARNING, bfad, bfa_log_level,1414			"Base port WWN = %s Fabric WWN = %s\n",1415			pwwn_ptr, fwwn_ptr);1416		bfa_fcs_fabric_aen_post(&fabric->bport,1417				BFA_PORT_AEN_FABRIC_NAME_CHANGE);1418	}1419}1420 1421void1422bfa_cb_lps_flogo_comp(void *bfad, void *uarg)1423{1424	struct bfa_fcs_fabric_s *fabric = uarg;1425	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOGOCOMP);1426}1427 1428/*1429 *	Returns FCS vf structure for a given vf_id.1430 *1431 *	param[in]	vf_id - VF_ID1432 *1433 *	return1434 *	If lookup succeeds, returns fcs vf object, otherwise returns NULL1435 */1436bfa_fcs_vf_t   *1437bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id)1438{1439	bfa_trc(fcs, vf_id);1440	if (vf_id == FC_VF_ID_NULL)1441		return &fcs->fabric;1442 1443	return NULL;1444}1445 1446/*1447 *	Return the list of local logical ports present in the given VF.1448 *1449 *	@param[in]	vf	vf for which logical ports are returned1450 *	@param[out]	lpwwn	returned logical port wwn list1451 *	@param[in,out]	nlports in:size of lpwwn list;1452 *				out:total elements present,1453 *				actual elements returned is limited by the size1454 */1455void1456bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports)1457{1458	struct list_head *qe;1459	struct bfa_fcs_vport_s *vport;1460	int	i = 0;1461	struct bfa_fcs_s	*fcs;1462 1463	if (vf == NULL || lpwwn == NULL || *nlports == 0)1464		return;1465 1466	fcs = vf->fcs;1467 1468	bfa_trc(fcs, vf->vf_id);1469	bfa_trc(fcs, (uint32_t) *nlports);1470 1471	lpwwn[i++] = vf->bport.port_cfg.pwwn;1472 1473	list_for_each(qe, &vf->vport_q) {1474		if (i >= *nlports)1475			break;1476 1477		vport = (struct bfa_fcs_vport_s *) qe;1478		lpwwn[i++] = vport->lport.port_cfg.pwwn;1479	}1480 1481	bfa_trc(fcs, i);1482	*nlports = i;1483}1484 1485/*1486 * BFA FCS PPORT ( physical port)1487 */1488static void1489bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)1490{1491	struct bfa_fcs_s      *fcs = cbarg;1492 1493	bfa_trc(fcs, event);1494 1495	switch (event) {1496	case BFA_PORT_LINKUP:1497		bfa_fcs_fabric_link_up(&fcs->fabric);1498		break;1499 1500	case BFA_PORT_LINKDOWN:1501		bfa_fcs_fabric_link_down(&fcs->fabric);1502		break;1503 1504	default:1505		WARN_ON(1);1506	}1507}1508 1509/*1510 * BFA FCS UF ( Unsolicited Frames)1511 */1512 1513/*1514 *		BFA callback for unsolicited frame receive handler.1515 *1516 * @param[in]		cbarg		callback arg for receive handler1517 * @param[in]		uf		unsolicited frame descriptor1518 *1519 * @return None1520 */1521static void1522bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)1523{1524	struct bfa_fcs_s	*fcs = (struct bfa_fcs_s *) cbarg;1525	struct fchs_s	*fchs = bfa_uf_get_frmbuf(uf);1526	u16	len = bfa_uf_get_frmlen(uf);1527	struct fc_vft_s *vft;1528	struct bfa_fcs_fabric_s *fabric;1529 1530	/*1531	 * check for VFT header1532	 */1533	if (fchs->routing == FC_RTG_EXT_HDR &&1534	    fchs->cat_info == FC_CAT_VFT_HDR) {1535		bfa_stats(fcs, uf.tagged);1536		vft = bfa_uf_get_frmbuf(uf);1537		if (fcs->port_vfid == vft->vf_id)1538			fabric = &fcs->fabric;1539		else1540			fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);1541 1542		/*1543		 * drop frame if vfid is unknown1544		 */1545		if (!fabric) {1546			WARN_ON(1);1547			bfa_stats(fcs, uf.vfid_unknown);1548			bfa_uf_free(uf);1549			return;1550		}1551 1552		/*1553		 * skip vft header1554		 */1555		fchs = (struct fchs_s *) (vft + 1);1556		len -= sizeof(struct fc_vft_s);1557 1558		bfa_trc(fcs, vft->vf_id);1559	} else {1560		bfa_stats(fcs, uf.untagged);1561		fabric = &fcs->fabric;1562	}1563 1564	bfa_trc(fcs, ((u32 *) fchs)[0]);1565	bfa_trc(fcs, ((u32 *) fchs)[1]);1566	bfa_trc(fcs, ((u32 *) fchs)[2]);1567	bfa_trc(fcs, ((u32 *) fchs)[3]);1568	bfa_trc(fcs, ((u32 *) fchs)[4]);1569	bfa_trc(fcs, ((u32 *) fchs)[5]);1570	bfa_trc(fcs, len);1571 1572	bfa_fcs_fabric_uf_recv(fabric, fchs, len);1573	bfa_uf_free(uf);1574}1575 1576/*1577 * fcs attach -- called once to initialize data structures at driver attach time1578 */1579void1580bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,1581	       bfa_boolean_t min_cfg)1582{1583	struct bfa_fcs_fabric_s *fabric = &fcs->fabric;1584 1585	fcs->bfa = bfa;1586	fcs->bfad = bfad;1587	fcs->min_cfg = min_cfg;1588	fcs->num_rport_logins = 0;1589 1590	bfa->fcs = BFA_TRUE;1591	fcbuild_init();1592 1593	bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);1594	bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);1595 1596	memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));1597 1598	/*1599	 * Initialize base fabric.1600	 */1601	fabric->fcs = fcs;1602	INIT_LIST_HEAD(&fabric->vport_q);1603	INIT_LIST_HEAD(&fabric->vf_q);1604	fabric->lps = bfa_lps_alloc(fcs->bfa);1605	WARN_ON(!fabric->lps);1606 1607	/*1608	 * Initialize fabric delete completion handler. Fabric deletion is1609	 * complete when the last vport delete is complete.1610	 */1611	bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);1612	bfa_wc_up(&fabric->wc); /* For the base port */1613 1614	bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);1615	bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);1616}1617