cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bfa_fcs.c (39763B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
      4 * Copyright (c) 2014- QLogic Corporation.
      5 * All rights reserved
      6 * www.qlogic.com
      7 *
      8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
      9 */
     10
     11/*
     12 *  bfa_fcs.c BFA FCS main
     13 */
     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 API
     24 */
     25
     26static void
     27bfa_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 complete
     37 */
     38void
     39bfa_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 API
     47 */
     48
     49/*
     50 * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
     51 * with values learned during bfa_init firmware GETATTR REQ.
     52 */
     53void
     54bfa_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 */
     67void
     68bfa_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 initialization
     78 */
     79void
     80bfa_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 *	brief
     96 *		FCS driver details initialization.
     97 *
     98 *	param[in]		fcs		FCS instance
     99 *	param[in]		driver_info	Driver Details
    100 *
    101 *	return None
    102 */
    103void
    104bfa_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 *	brief
    116 *		FCS instance cleanup and exit.
    117 *
    118 *	param[in]		fcs			FCS instance
    119 *	return None
    120 */
    121void
    122bfa_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 declarations
    152 */
    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 void
    204bfa_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 void
    230bfa_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 the
    275 *   first state at fabric creation.
    276 */
    277static void
    278bfa_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 void
    324bfa_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 void
    385bfa_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 void
    417bfa_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 failed
    455 */
    456void
    457bfa_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 */
    482void
    483bfa_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 void
    509bfa_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 */
    544void
    545bfa_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 void
    591bfa_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 void
    615bfa_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 void
    626bfa_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 void
    647bfa_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 void
    675bfa_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		else
    700			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 FLOGO
    710 */
    711static void
    712bfa_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 down
    728		 * 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 functions
    739 */
    740
    741static void
    742bfa_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 */
    754void
    755bfa_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	strlcpy(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 the
    785	 * 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 vports
    814 */
    815void
    816bfa_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	strlcpy(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 callback
    852 */
    853void
    854bfa_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 attached
    918		 */
    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 void
    933bfa_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 void
    947bfa_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 ports
    959	 */
    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 void
    969bfa_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 void
    992bfa_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 void
   1003bfa_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 void
   1025bfa_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 void
   1040bfa_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 void
   1048bfa_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 functions
   1057 */
   1058
   1059/*
   1060 * Fabric module stop -- stop FCS actions
   1061 */
   1062void
   1063bfa_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 actions
   1074 */
   1075void
   1076bfa_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 */
   1089void
   1090bfa_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 */
   1099void
   1100bfa_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 vports
   1110 *   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 */
   1117void
   1118bfa_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_q
   1123	 */
   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 */
   1136void
   1137bfa_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 pwwn
   1148 */
   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 requirement
   1170*          to check for FOS version below 6.3.
   1171 *         To check if the attached fabric is a brocade fabric, use
   1172 *         bfa_lps_is_brcd_fabric() which works for FOS versions 6.3
   1173 *         or above only.
   1174 */
   1175
   1176u16
   1177bfa_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 */
   1193void
   1194bfa_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 an
   1208	 * external loopback cable is in place. Our own FLOGI frames are
   1209	 * 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 auth
   1230		 */
   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 ID
   1244	 */
   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 void
   1263bfa_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_RJT
   1278		 */
   1279		break;
   1280	}
   1281}
   1282
   1283/*
   1284 *	Process	incoming FLOGI
   1285 */
   1286static void
   1287bfa_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_RJT
   1302		 */
   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 Acc
   1314	 */
   1315	bfa_fcs_fabric_send_flogi_acc(fabric);
   1316	bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC);
   1317}
   1318
   1319static void
   1320bfa_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 retry
   1332	 */
   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 void
   1353bfa_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 notification
   1365 */
   1366static void
   1367bfa_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 - fabric
   1388 * @param[in] wwn_t - new fabric name
   1389 *
   1390 * @return - none
   1391 */
   1392void
   1393bfa_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
   1421void
   1422bfa_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_ID
   1432 *
   1433 *	return
   1434 *	If lookup succeeds, retuns fcs vf object, otherwise returns NULL
   1435 */
   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 returned
   1450 *	@param[out]	lpwwn	returned logical port wwn list
   1451 *	@param[in,out]	nlports in:size of lpwwn list;
   1452 *				out:total elements present,
   1453 *				actual elements returned is limited by the size
   1454 */
   1455void
   1456bfa_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 void
   1489bfa_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 handler
   1517 * @param[in]		uf		unsolicited frame descriptor
   1518 *
   1519 * @return None
   1520 */
   1521static void
   1522bfa_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 header
   1532	 */
   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		else
   1540			fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id);
   1541
   1542		/*
   1543		 * drop frame if vfid is unknown
   1544		 */
   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 header
   1554		 */
   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 time
   1578 */
   1579void
   1580bfa_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 is
   1609	 * 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}