brintos

brintos / linux-shallow public Read only

0
0
Text · 163.2 KiB · 9f33aa3 Raw
6870 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#include "bfad_drv.h"12#include "bfad_im.h"13#include "bfa_plog.h"14#include "bfa_cs.h"15#include "bfa_modules.h"16 17BFA_TRC_FILE(HAL, FCXP);18 19/*20 * LPS related definitions21 */22#define BFA_LPS_MIN_LPORTS      (1)23#define BFA_LPS_MAX_LPORTS      (256)24 25/*26 * Maximum Vports supported per physical port or vf.27 */28#define BFA_LPS_MAX_VPORTS_SUPP_CB  25529#define BFA_LPS_MAX_VPORTS_SUPP_CT  19030 31 32/*33 * FC PORT related definitions34 */35/*36 * The port is considered disabled if corresponding physical port or IOC are37 * disabled explicitly38 */39#define BFA_PORT_IS_DISABLED(bfa) \40	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \41	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))42 43/*44 * RPORT related definitions45 */46#define bfa_rport_offline_cb(__rp) do {					\47	if ((__rp)->bfa->fcs)						\48		bfa_cb_rport_offline((__rp)->rport_drv);      \49	else {								\50		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\51				__bfa_cb_rport_offline, (__rp));      \52	}								\53} while (0)54 55#define bfa_rport_online_cb(__rp) do {					\56	if ((__rp)->bfa->fcs)						\57		bfa_cb_rport_online((__rp)->rport_drv);      \58	else {								\59		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\60				  __bfa_cb_rport_online, (__rp));      \61		}							\62} while (0)63 64/*65 * forward declarations FCXP related functions66 */67static void	__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);68static void	hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,69				struct bfi_fcxp_send_rsp_s *fcxp_rsp);70static void	hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,71				struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);72static void	bfa_fcxp_qresume(void *cbarg);73static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,74				struct bfi_fcxp_send_req_s *send_req);75 76/*77 * forward declarations for LPS functions78 */79static void bfa_lps_login_rsp(struct bfa_s *bfa,80				struct bfi_lps_login_rsp_s *rsp);81static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);82static void bfa_lps_logout_rsp(struct bfa_s *bfa,83				struct bfi_lps_logout_rsp_s *rsp);84static void bfa_lps_reqq_resume(void *lps_arg);85static void bfa_lps_free(struct bfa_lps_s *lps);86static void bfa_lps_send_login(struct bfa_lps_s *lps);87static void bfa_lps_send_logout(struct bfa_lps_s *lps);88static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);89static void bfa_lps_login_comp(struct bfa_lps_s *lps);90static void bfa_lps_logout_comp(struct bfa_lps_s *lps);91static void bfa_lps_cvl_event(struct bfa_lps_s *lps);92 93/*94 * forward declaration for LPS state machine95 */96static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);97static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);98static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event99					event);100static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);101static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,102					enum bfa_lps_event event);103static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);104static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event105					event);106 107/*108 * forward declaration for FC Port functions109 */110static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);111static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);112static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);113static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);114static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);115static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);116static void bfa_fcport_scn(struct bfa_fcport_s *fcport,117			enum bfa_port_linkstate event, bfa_boolean_t trunk);118static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,119				enum bfa_port_linkstate event);120static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);121static void bfa_fcport_stats_get_timeout(void *cbarg);122static void bfa_fcport_stats_clr_timeout(void *cbarg);123static void bfa_trunk_iocdisable(struct bfa_s *bfa);124 125/*126 * forward declaration for FC PORT state machine127 */128static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,129					enum bfa_fcport_sm_event event);130static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,131					enum bfa_fcport_sm_event event);132static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,133					enum bfa_fcport_sm_event event);134static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,135					enum bfa_fcport_sm_event event);136static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,137					enum bfa_fcport_sm_event event);138static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,139					enum bfa_fcport_sm_event event);140static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,141					enum bfa_fcport_sm_event event);142static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,143					enum bfa_fcport_sm_event event);144static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,145					enum bfa_fcport_sm_event event);146static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,147					enum bfa_fcport_sm_event event);148static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,149					enum bfa_fcport_sm_event event);150static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,151					enum bfa_fcport_sm_event event);152static void	bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,153					enum bfa_fcport_sm_event event);154static void     bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,155					enum bfa_fcport_sm_event event);156static void	bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,157					enum bfa_fcport_sm_event event);158 159static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,160					enum bfa_fcport_ln_sm_event event);161static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,162					enum bfa_fcport_ln_sm_event event);163static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,164					enum bfa_fcport_ln_sm_event event);165static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,166					enum bfa_fcport_ln_sm_event event);167static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,168					enum bfa_fcport_ln_sm_event event);169static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,170					enum bfa_fcport_ln_sm_event event);171static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,172					enum bfa_fcport_ln_sm_event event);173 174struct bfa_fcport_sm_table_s {175	bfa_fcport_sm_t sm;		/*  state machine function	*/176	enum bfa_port_states state;	/*  state machine encoding	*/177	char		*name;		/*  state name for display	*/178};179 180static inline enum bfa_port_states181bfa_fcport_sm_to_state(struct bfa_fcport_sm_table_s *smt, bfa_fcport_sm_t sm)182{183	int i = 0;184 185	while (smt[i].sm && smt[i].sm != sm)186		i++;187	return smt[i].state;188}189 190static struct bfa_fcport_sm_table_s hal_port_sm_table[] = {191	{BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},192	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},193	{BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},194	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},195	{BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},196	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},197	{BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},198	{BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},199	{BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},200	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},201	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},202	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},203	{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},204	{BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},205	{BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},206};207 208 209/*210 * forward declaration for RPORT related functions211 */212static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);213static void		bfa_rport_free(struct bfa_rport_s *rport);214static bfa_boolean_t	bfa_rport_send_fwcreate(struct bfa_rport_s *rp);215static bfa_boolean_t	bfa_rport_send_fwdelete(struct bfa_rport_s *rp);216static bfa_boolean_t	bfa_rport_send_fwspeed(struct bfa_rport_s *rp);217static void		__bfa_cb_rport_online(void *cbarg,218						bfa_boolean_t complete);219static void		__bfa_cb_rport_offline(void *cbarg,220						bfa_boolean_t complete);221 222/*223 * forward declaration for RPORT state machine224 */225static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,226					enum bfa_rport_event event);227static void     bfa_rport_sm_created(struct bfa_rport_s *rp,228					enum bfa_rport_event event);229static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,230					enum bfa_rport_event event);231static void     bfa_rport_sm_online(struct bfa_rport_s *rp,232					enum bfa_rport_event event);233static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,234					enum bfa_rport_event event);235static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,236					enum bfa_rport_event event);237static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,238					enum bfa_rport_event event);239static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,240					enum bfa_rport_event event);241static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,242					enum bfa_rport_event event);243static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,244					enum bfa_rport_event event);245static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,246					enum bfa_rport_event event);247static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,248					enum bfa_rport_event event);249static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,250					enum bfa_rport_event event);251 252/*253 * PLOG related definitions254 */255static int256plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)257{258	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&259		(pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))260		return 1;261 262	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&263		(pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))264		return 1;265 266	return 0;267}268 269static void270bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)271{272	u16 tail;273	struct bfa_plog_rec_s *pl_recp;274 275	if (plog->plog_enabled == 0)276		return;277 278	if (plkd_validate_logrec(pl_rec)) {279		WARN_ON(1);280		return;281	}282 283	tail = plog->tail;284 285	pl_recp = &(plog->plog_recs[tail]);286 287	memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));288 289	pl_recp->tv = ktime_get_real_seconds();290	BFA_PL_LOG_REC_INCR(plog->tail);291 292	if (plog->head == plog->tail)293		BFA_PL_LOG_REC_INCR(plog->head);294}295 296void297bfa_plog_init(struct bfa_plog_s *plog)298{299	memset((char *)plog, 0, sizeof(struct bfa_plog_s));300 301	memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);302	plog->head = plog->tail = 0;303	plog->plog_enabled = 1;304}305 306void307bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,308		enum bfa_plog_eid event,309		u16 misc, char *log_str)310{311	struct bfa_plog_rec_s  lp;312 313	if (plog->plog_enabled) {314		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));315		lp.mid = mid;316		lp.eid = event;317		lp.log_type = BFA_PL_LOG_TYPE_STRING;318		lp.misc = misc;319		strscpy(lp.log_entry.string_log, log_str,320			BFA_PL_STRING_LOG_SZ);321		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';322		bfa_plog_add(plog, &lp);323	}324}325 326void327bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,328		enum bfa_plog_eid event,329		u16 misc, u32 *intarr, u32 num_ints)330{331	struct bfa_plog_rec_s  lp;332	u32 i;333 334	if (num_ints > BFA_PL_INT_LOG_SZ)335		num_ints = BFA_PL_INT_LOG_SZ;336 337	if (plog->plog_enabled) {338		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));339		lp.mid = mid;340		lp.eid = event;341		lp.log_type = BFA_PL_LOG_TYPE_INT;342		lp.misc = misc;343 344		for (i = 0; i < num_ints; i++)345			lp.log_entry.int_log[i] = intarr[i];346 347		lp.log_num_ints = (u8) num_ints;348 349		bfa_plog_add(plog, &lp);350	}351}352 353void354bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,355			enum bfa_plog_eid event,356			u16 misc, struct fchs_s *fchdr)357{358	u32	*tmp_int = (u32 *) fchdr;359	u32	ints[BFA_PL_INT_LOG_SZ];360 361	if (plog->plog_enabled) {362		ints[0] = tmp_int[0];363		ints[1] = tmp_int[1];364		ints[2] = tmp_int[4];365 366		bfa_plog_intarr(plog, mid, event, misc, ints, 3);367	}368}369 370void371bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,372		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,373		      u32 pld_w0)374{375	u32	*tmp_int = (u32 *) fchdr;376	u32	ints[BFA_PL_INT_LOG_SZ];377 378	if (plog->plog_enabled) {379		ints[0] = tmp_int[0];380		ints[1] = tmp_int[1];381		ints[2] = tmp_int[4];382		ints[3] = pld_w0;383 384		bfa_plog_intarr(plog, mid, event, misc, ints, 4);385	}386}387 388 389/*390 *  fcxp_pvt BFA FCXP private functions391 */392 393static void394claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)395{396	u16	i;397	struct bfa_fcxp_s *fcxp;398 399	fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);400	memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);401 402	INIT_LIST_HEAD(&mod->fcxp_req_free_q);403	INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);404	INIT_LIST_HEAD(&mod->fcxp_active_q);405	INIT_LIST_HEAD(&mod->fcxp_req_unused_q);406	INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);407 408	mod->fcxp_list = fcxp;409 410	for (i = 0; i < mod->num_fcxps; i++) {411		fcxp->fcxp_mod = mod;412		fcxp->fcxp_tag = i;413 414		if (i < (mod->num_fcxps / 2)) {415			list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);416			fcxp->req_rsp = BFA_TRUE;417		} else {418			list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);419			fcxp->req_rsp = BFA_FALSE;420		}421 422		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);423		fcxp->reqq_waiting = BFA_FALSE;424 425		fcxp = fcxp + 1;426	}427 428	bfa_mem_kva_curp(mod) = (void *)fcxp;429}430 431void432bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,433		struct bfa_s *bfa)434{435	struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);436	struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);437	struct bfa_mem_dma_s *seg_ptr;438	u16	nsegs, idx, per_seg_fcxp;439	u16	num_fcxps = cfg->fwcfg.num_fcxp_reqs;440	u32	per_fcxp_sz;441 442	if (num_fcxps == 0)443		return;444 445	if (cfg->drvcfg.min_cfg)446		per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;447	else448		per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;449 450	/* dma memory */451	nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);452	per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);453 454	bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {455		if (num_fcxps >= per_seg_fcxp) {456			num_fcxps -= per_seg_fcxp;457			bfa_mem_dma_setup(minfo, seg_ptr,458				per_seg_fcxp * per_fcxp_sz);459		} else460			bfa_mem_dma_setup(minfo, seg_ptr,461				num_fcxps * per_fcxp_sz);462	}463 464	/* kva memory */465	bfa_mem_kva_setup(minfo, fcxp_kva,466		cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));467}468 469void470bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,471		struct bfa_pcidev_s *pcidev)472{473	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);474 475	mod->bfa = bfa;476	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;477 478	/*479	 * Initialize FCXP request and response payload sizes.480	 */481	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;482	if (!cfg->drvcfg.min_cfg)483		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;484 485	INIT_LIST_HEAD(&mod->req_wait_q);486	INIT_LIST_HEAD(&mod->rsp_wait_q);487 488	claim_fcxps_mem(mod);489}490 491void492bfa_fcxp_iocdisable(struct bfa_s *bfa)493{494	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);495	struct bfa_fcxp_s *fcxp;496	struct list_head	      *qe, *qen;497 498	/* Enqueue unused fcxp resources to free_q */499	list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);500	list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);501 502	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {503		fcxp = (struct bfa_fcxp_s *) qe;504		if (fcxp->caller == NULL) {505			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,506					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);507			bfa_fcxp_free(fcxp);508		} else {509			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;510			bfa_cb_queue(bfa, &fcxp->hcb_qe,511				     __bfa_fcxp_send_cbfn, fcxp);512		}513	}514}515 516static struct bfa_fcxp_s *517bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)518{519	struct bfa_fcxp_s *fcxp;520 521	if (req)522		bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);523	else524		bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);525 526	if (fcxp)527		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);528 529	return fcxp;530}531 532static void533bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,534	       struct bfa_s *bfa,535	       u8 *use_ibuf,536	       u32 *nr_sgles,537	       bfa_fcxp_get_sgaddr_t *r_sga_cbfn,538	       bfa_fcxp_get_sglen_t *r_sglen_cbfn,539	       struct list_head *r_sgpg_q,540	       int n_sgles,541	       bfa_fcxp_get_sgaddr_t sga_cbfn,542	       bfa_fcxp_get_sglen_t sglen_cbfn)543{544 545	WARN_ON(bfa == NULL);546 547	bfa_trc(bfa, fcxp->fcxp_tag);548 549	if (n_sgles == 0) {550		*use_ibuf = 1;551	} else {552		WARN_ON(*sga_cbfn == NULL);553		WARN_ON(*sglen_cbfn == NULL);554 555		*use_ibuf = 0;556		*r_sga_cbfn = sga_cbfn;557		*r_sglen_cbfn = sglen_cbfn;558 559		*nr_sgles = n_sgles;560 561		/*562		 * alloc required sgpgs563		 */564		if (n_sgles > BFI_SGE_INLINE)565			WARN_ON(1);566	}567 568}569 570static void571bfa_fcxp_init(struct bfa_fcxp_s *fcxp,572	       void *caller, struct bfa_s *bfa, int nreq_sgles,573	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,574	       bfa_fcxp_get_sglen_t req_sglen_cbfn,575	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,576	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)577{578 579	WARN_ON(bfa == NULL);580 581	bfa_trc(bfa, fcxp->fcxp_tag);582 583	fcxp->caller = caller;584 585	bfa_fcxp_init_reqrsp(fcxp, bfa,586		&fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,587		&fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,588		nreq_sgles, req_sga_cbfn, req_sglen_cbfn);589 590	bfa_fcxp_init_reqrsp(fcxp, bfa,591		&fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,592		&fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,593		nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);594 595}596 597static void598bfa_fcxp_put(struct bfa_fcxp_s *fcxp)599{600	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;601	struct bfa_fcxp_wqe_s *wqe;602 603	if (fcxp->req_rsp)604		bfa_q_deq(&mod->req_wait_q, &wqe);605	else606		bfa_q_deq(&mod->rsp_wait_q, &wqe);607 608	if (wqe) {609		bfa_trc(mod->bfa, fcxp->fcxp_tag);610 611		bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,612			wqe->nrsp_sgles, wqe->req_sga_cbfn,613			wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,614			wqe->rsp_sglen_cbfn);615 616		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);617		return;618	}619 620	WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));621	list_del(&fcxp->qe);622 623	if (fcxp->req_rsp)624		list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);625	else626		list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);627}628 629static void630bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,631		   bfa_status_t req_status, u32 rsp_len,632		   u32 resid_len, struct fchs_s *rsp_fchs)633{634	/* discarded fcxp completion */635}636 637static void638__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)639{640	struct bfa_fcxp_s *fcxp = cbarg;641 642	if (complete) {643		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,644				fcxp->rsp_status, fcxp->rsp_len,645				fcxp->residue_len, &fcxp->rsp_fchs);646	} else {647		bfa_fcxp_free(fcxp);648	}649}650 651static void652hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)653{654	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);655	struct bfa_fcxp_s	*fcxp;656	u16		fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);657 658	bfa_trc(bfa, fcxp_tag);659 660	fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);661 662	/*663	 * @todo f/w should not set residue to non-0 when everything664	 *	 is received.665	 */666	if (fcxp_rsp->req_status == BFA_STATUS_OK)667		fcxp_rsp->residue_len = 0;668	else669		fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);670 671	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);672 673	WARN_ON(fcxp->send_cbfn == NULL);674 675	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);676 677	if (fcxp->send_cbfn != NULL) {678		bfa_trc(mod->bfa, (NULL == fcxp->caller));679		if (fcxp->caller == NULL) {680			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,681					fcxp_rsp->req_status, fcxp_rsp->rsp_len,682					fcxp_rsp->residue_len, &fcxp_rsp->fchs);683			/*684			 * fcxp automatically freed on return from the callback685			 */686			bfa_fcxp_free(fcxp);687		} else {688			fcxp->rsp_status = fcxp_rsp->req_status;689			fcxp->rsp_len = fcxp_rsp->rsp_len;690			fcxp->residue_len = fcxp_rsp->residue_len;691			fcxp->rsp_fchs = fcxp_rsp->fchs;692 693			bfa_cb_queue(bfa, &fcxp->hcb_qe,694					__bfa_fcxp_send_cbfn, fcxp);695		}696	} else {697		bfa_trc(bfa, (NULL == fcxp->send_cbfn));698	}699}700 701static void702hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,703		 struct fchs_s *fchs)704{705	/*706	 * TODO: TX ox_id707	 */708	if (reqlen > 0) {709		if (fcxp->use_ireqbuf) {710			u32	pld_w0 =711				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));712 713			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,714					BFA_PL_EID_TX,715					reqlen + sizeof(struct fchs_s), fchs,716					pld_w0);717		} else {718			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,719					BFA_PL_EID_TX,720					reqlen + sizeof(struct fchs_s),721					fchs);722		}723	} else {724		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,725			       reqlen + sizeof(struct fchs_s), fchs);726	}727}728 729static void730hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,731		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)732{733	if (fcxp_rsp->rsp_len > 0) {734		if (fcxp->use_irspbuf) {735			u32	pld_w0 =736				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));737 738			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,739					      BFA_PL_EID_RX,740					      (u16) fcxp_rsp->rsp_len,741					      &fcxp_rsp->fchs, pld_w0);742		} else {743			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,744				       BFA_PL_EID_RX,745				       (u16) fcxp_rsp->rsp_len,746				       &fcxp_rsp->fchs);747		}748	} else {749		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,750			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);751	}752}753 754/*755 * Handler to resume sending fcxp when space in available in cpe queue.756 */757static void758bfa_fcxp_qresume(void *cbarg)759{760	struct bfa_fcxp_s		*fcxp = cbarg;761	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;762	struct bfi_fcxp_send_req_s	*send_req;763 764	fcxp->reqq_waiting = BFA_FALSE;765	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);766	bfa_fcxp_queue(fcxp, send_req);767}768 769/*770 * Queue fcxp send request to foimrware.771 */772static void773bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)774{775	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;776	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;777	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;778	struct bfa_rport_s		*rport = reqi->bfa_rport;779 780	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,781		    bfa_fn_lpu(bfa));782 783	send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);784	if (rport) {785		send_req->rport_fw_hndl = rport->fw_handle;786		send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);787		if (send_req->max_frmsz == 0)788			send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);789	} else {790		send_req->rport_fw_hndl = 0;791		send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);792	}793 794	send_req->vf_id = cpu_to_be16(reqi->vf_id);795	send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);796	send_req->class = reqi->class;797	send_req->rsp_timeout = rspi->rsp_timeout;798	send_req->cts = reqi->cts;799	send_req->fchs = reqi->fchs;800 801	send_req->req_len = cpu_to_be32(reqi->req_tot_len);802	send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);803 804	/*805	 * setup req sgles806	 */807	if (fcxp->use_ireqbuf == 1) {808		bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,809					BFA_FCXP_REQ_PLD_PA(fcxp));810	} else {811		if (fcxp->nreq_sgles > 0) {812			WARN_ON(fcxp->nreq_sgles != 1);813			bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,814				fcxp->req_sga_cbfn(fcxp->caller, 0));815		} else {816			WARN_ON(reqi->req_tot_len != 0);817			bfa_alen_set(&send_req->rsp_alen, 0, 0);818		}819	}820 821	/*822	 * setup rsp sgles823	 */824	if (fcxp->use_irspbuf == 1) {825		WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);826 827		bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,828					BFA_FCXP_RSP_PLD_PA(fcxp));829	} else {830		if (fcxp->nrsp_sgles > 0) {831			WARN_ON(fcxp->nrsp_sgles != 1);832			bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,833				fcxp->rsp_sga_cbfn(fcxp->caller, 0));834 835		} else {836			WARN_ON(rspi->rsp_maxlen != 0);837			bfa_alen_set(&send_req->rsp_alen, 0, 0);838		}839	}840 841	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);842 843	bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);844 845	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));846	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));847}848 849/*850 * Allocate an FCXP instance to send a response or to send a request851 * that has a response. Request/response buffers are allocated by caller.852 *853 * @param[in]	bfa		BFA bfa instance854 * @param[in]	nreq_sgles	Number of SG elements required for request855 *				buffer. 0, if fcxp internal buffers are	used.856 *				Use bfa_fcxp_get_reqbuf() to get the857 *				internal req buffer.858 * @param[in]	req_sgles	SG elements describing request buffer. Will be859 *				copied in by BFA and hence can be freed on860 *				return from this function.861 * @param[in]	get_req_sga	function ptr to be called to get a request SG862 *				Address (given the sge index).863 * @param[in]	get_req_sglen	function ptr to be called to get a request SG864 *				len (given the sge index).865 * @param[in]	get_rsp_sga	function ptr to be called to get a response SG866 *				Address (given the sge index).867 * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG868 *				len (given the sge index).869 * @param[in]	req		Allocated FCXP is used to send req or rsp?870 *				request - BFA_TRUE, response - BFA_FALSE871 *872 * @return FCXP instance. NULL on failure.873 */874struct bfa_fcxp_s *875bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,876		int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,877		bfa_fcxp_get_sglen_t req_sglen_cbfn,878		bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,879		bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)880{881	struct bfa_fcxp_s *fcxp = NULL;882 883	WARN_ON(bfa == NULL);884 885	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);886	if (fcxp == NULL)887		return NULL;888 889	bfa_trc(bfa, fcxp->fcxp_tag);890 891	bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,892			req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);893 894	return fcxp;895}896 897/*898 * Get the internal request buffer pointer899 *900 * @param[in]	fcxp	BFA fcxp pointer901 *902 * @return		pointer to the internal request buffer903 */904void *905bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)906{907	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;908	void	*reqbuf;909 910	WARN_ON(fcxp->use_ireqbuf != 1);911	reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,912				mod->req_pld_sz + mod->rsp_pld_sz);913	return reqbuf;914}915 916u32917bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)918{919	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;920 921	return mod->req_pld_sz;922}923 924/*925 * Get the internal response buffer pointer926 *927 * @param[in]	fcxp	BFA fcxp pointer928 *929 * @return		pointer to the internal request buffer930 */931void *932bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)933{934	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;935	void	*fcxp_buf;936 937	WARN_ON(fcxp->use_irspbuf != 1);938 939	fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,940				mod->req_pld_sz + mod->rsp_pld_sz);941 942	/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */943	return ((u8 *) fcxp_buf) + mod->req_pld_sz;944}945 946/*947 * Free the BFA FCXP948 *949 * @param[in]	fcxp			BFA fcxp pointer950 *951 * @return		void952 */953void954bfa_fcxp_free(struct bfa_fcxp_s *fcxp)955{956	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;957 958	WARN_ON(fcxp == NULL);959	bfa_trc(mod->bfa, fcxp->fcxp_tag);960	bfa_fcxp_put(fcxp);961}962 963/*964 * Send a FCXP request965 *966 * @param[in]	fcxp	BFA fcxp pointer967 * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports968 * @param[in]	vf_id	virtual Fabric ID969 * @param[in]	lp_tag	lport tag970 * @param[in]	cts	use Continuous sequence971 * @param[in]	cos	fc Class of Service972 * @param[in]	reqlen	request length, does not include FCHS length973 * @param[in]	fchs	fc Header Pointer. The header content will be copied974 *			in by BFA.975 *976 * @param[in]	cbfn	call back function to be called on receiving977 *								the response978 * @param[in]	cbarg	arg for cbfn979 * @param[in]	rsp_timeout980 *			response timeout981 *982 * @return		bfa_status_t983 */984void985bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,986	      u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,987	      u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,988	      void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)989{990	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;991	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;992	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;993	struct bfi_fcxp_send_req_s	*send_req;994 995	bfa_trc(bfa, fcxp->fcxp_tag);996 997	/*998	 * setup request/response info999	 */1000	reqi->bfa_rport = rport;1001	reqi->vf_id = vf_id;1002	reqi->lp_tag = lp_tag;1003	reqi->class = cos;1004	rspi->rsp_timeout = rsp_timeout;1005	reqi->cts = cts;1006	reqi->fchs = *fchs;1007	reqi->req_tot_len = reqlen;1008	rspi->rsp_maxlen = rsp_maxlen;1009	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;1010	fcxp->send_cbarg = cbarg;1011 1012	/*1013	 * If no room in CPE queue, wait for space in request queue1014	 */1015	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);1016	if (!send_req) {1017		bfa_trc(bfa, fcxp->fcxp_tag);1018		fcxp->reqq_waiting = BFA_TRUE;1019		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);1020		return;1021	}1022 1023	bfa_fcxp_queue(fcxp, send_req);1024}1025 1026/*1027 * Abort a BFA FCXP1028 *1029 * @param[in]	fcxp	BFA fcxp pointer1030 *1031 * @return		void1032 */1033bfa_status_t1034bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)1035{1036	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);1037	WARN_ON(1);1038	return BFA_STATUS_OK;1039}1040 1041void1042bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,1043	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,1044	       void *caller, int nreq_sgles,1045	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,1046	       bfa_fcxp_get_sglen_t req_sglen_cbfn,1047	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,1048	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)1049{1050	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);1051 1052	if (req)1053		WARN_ON(!list_empty(&mod->fcxp_req_free_q));1054	else1055		WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));1056 1057	wqe->alloc_cbfn = alloc_cbfn;1058	wqe->alloc_cbarg = alloc_cbarg;1059	wqe->caller = caller;1060	wqe->bfa = bfa;1061	wqe->nreq_sgles = nreq_sgles;1062	wqe->nrsp_sgles = nrsp_sgles;1063	wqe->req_sga_cbfn = req_sga_cbfn;1064	wqe->req_sglen_cbfn = req_sglen_cbfn;1065	wqe->rsp_sga_cbfn = rsp_sga_cbfn;1066	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;1067 1068	if (req)1069		list_add_tail(&wqe->qe, &mod->req_wait_q);1070	else1071		list_add_tail(&wqe->qe, &mod->rsp_wait_q);1072}1073 1074void1075bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)1076{1077	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);1078 1079	WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||1080		!bfa_q_is_on_q(&mod->rsp_wait_q, wqe));1081	list_del(&wqe->qe);1082}1083 1084void1085bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)1086{1087	/*1088	 * If waiting for room in request queue, cancel reqq wait1089	 * and free fcxp.1090	 */1091	if (fcxp->reqq_waiting) {1092		fcxp->reqq_waiting = BFA_FALSE;1093		bfa_reqq_wcancel(&fcxp->reqq_wqe);1094		bfa_fcxp_free(fcxp);1095		return;1096	}1097 1098	fcxp->send_cbfn = bfa_fcxp_null_comp;1099}1100 1101void1102bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)1103{1104	switch (msg->mhdr.msg_id) {1105	case BFI_FCXP_I2H_SEND_RSP:1106		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);1107		break;1108 1109	default:1110		bfa_trc(bfa, msg->mhdr.msg_id);1111		WARN_ON(1);1112	}1113}1114 1115u321116bfa_fcxp_get_maxrsp(struct bfa_s *bfa)1117{1118	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);1119 1120	return mod->rsp_pld_sz;1121}1122 1123void1124bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)1125{1126	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);1127	struct list_head	*qe;1128	int	i;1129 1130	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {1131		if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {1132			bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);1133			list_add_tail(qe, &mod->fcxp_req_unused_q);1134		} else {1135			bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);1136			list_add_tail(qe, &mod->fcxp_rsp_unused_q);1137		}1138	}1139}1140 1141/*1142 *  BFA LPS state machine functions1143 */1144 1145/*1146 * Init state -- no login1147 */1148static void1149bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)1150{1151	bfa_trc(lps->bfa, lps->bfa_tag);1152	bfa_trc(lps->bfa, event);1153 1154	switch (event) {1155	case BFA_LPS_SM_LOGIN:1156		if (bfa_reqq_full(lps->bfa, lps->reqq)) {1157			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);1158			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);1159		} else {1160			bfa_sm_set_state(lps, bfa_lps_sm_login);1161			bfa_lps_send_login(lps);1162		}1163 1164		if (lps->fdisc)1165			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1166				BFA_PL_EID_LOGIN, 0, "FDISC Request");1167		else1168			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1169				BFA_PL_EID_LOGIN, 0, "FLOGI Request");1170		break;1171 1172	case BFA_LPS_SM_LOGOUT:1173		bfa_lps_logout_comp(lps);1174		break;1175 1176	case BFA_LPS_SM_DELETE:1177		bfa_lps_free(lps);1178		break;1179 1180	case BFA_LPS_SM_RX_CVL:1181	case BFA_LPS_SM_OFFLINE:1182		break;1183 1184	case BFA_LPS_SM_FWRSP:1185		/*1186		 * Could happen when fabric detects loopback and discards1187		 * the lps request. Fw will eventually sent out the timeout1188		 * Just ignore1189		 */1190		break;1191	case BFA_LPS_SM_SET_N2N_PID:1192		/*1193		 * When topology is set to loop, bfa_lps_set_n2n_pid() sends1194		 * this event. Ignore this event.1195		 */1196		break;1197 1198	default:1199		bfa_sm_fault(lps->bfa, event);1200	}1201}1202 1203/*1204 * login is in progress -- awaiting response from firmware1205 */1206static void1207bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)1208{1209	bfa_trc(lps->bfa, lps->bfa_tag);1210	bfa_trc(lps->bfa, event);1211 1212	switch (event) {1213	case BFA_LPS_SM_FWRSP:1214		if (lps->status == BFA_STATUS_OK) {1215			bfa_sm_set_state(lps, bfa_lps_sm_online);1216			if (lps->fdisc)1217				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1218					BFA_PL_EID_LOGIN, 0, "FDISC Accept");1219			else1220				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1221					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");1222			/* If N2N, send the assigned PID to FW */1223			bfa_trc(lps->bfa, lps->fport);1224			bfa_trc(lps->bfa, lps->lp_pid);1225 1226			if (!lps->fport && lps->lp_pid)1227				bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);1228		} else {1229			bfa_sm_set_state(lps, bfa_lps_sm_init);1230			if (lps->fdisc)1231				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1232					BFA_PL_EID_LOGIN, 0,1233					"FDISC Fail (RJT or timeout)");1234			else1235				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1236					BFA_PL_EID_LOGIN, 0,1237					"FLOGI Fail (RJT or timeout)");1238		}1239		bfa_lps_login_comp(lps);1240		break;1241 1242	case BFA_LPS_SM_OFFLINE:1243	case BFA_LPS_SM_DELETE:1244		bfa_sm_set_state(lps, bfa_lps_sm_init);1245		break;1246 1247	case BFA_LPS_SM_SET_N2N_PID:1248		bfa_trc(lps->bfa, lps->fport);1249		bfa_trc(lps->bfa, lps->lp_pid);1250		break;1251 1252	default:1253		bfa_sm_fault(lps->bfa, event);1254	}1255}1256 1257/*1258 * login pending - awaiting space in request queue1259 */1260static void1261bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)1262{1263	bfa_trc(lps->bfa, lps->bfa_tag);1264	bfa_trc(lps->bfa, event);1265 1266	switch (event) {1267	case BFA_LPS_SM_RESUME:1268		bfa_sm_set_state(lps, bfa_lps_sm_login);1269		bfa_lps_send_login(lps);1270		break;1271 1272	case BFA_LPS_SM_OFFLINE:1273	case BFA_LPS_SM_DELETE:1274		bfa_sm_set_state(lps, bfa_lps_sm_init);1275		bfa_reqq_wcancel(&lps->wqe);1276		break;1277 1278	case BFA_LPS_SM_RX_CVL:1279		/*1280		 * Login was not even sent out; so when getting out1281		 * of this state, it will appear like a login retry1282		 * after Clear virtual link1283		 */1284		break;1285 1286	default:1287		bfa_sm_fault(lps->bfa, event);1288	}1289}1290 1291/*1292 * login complete1293 */1294static void1295bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)1296{1297	bfa_trc(lps->bfa, lps->bfa_tag);1298	bfa_trc(lps->bfa, event);1299 1300	switch (event) {1301	case BFA_LPS_SM_LOGOUT:1302		if (bfa_reqq_full(lps->bfa, lps->reqq)) {1303			bfa_sm_set_state(lps, bfa_lps_sm_logowait);1304			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);1305		} else {1306			bfa_sm_set_state(lps, bfa_lps_sm_logout);1307			bfa_lps_send_logout(lps);1308		}1309		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1310			BFA_PL_EID_LOGO, 0, "Logout");1311		break;1312 1313	case BFA_LPS_SM_RX_CVL:1314		bfa_sm_set_state(lps, bfa_lps_sm_init);1315 1316		/* Let the vport module know about this event */1317		bfa_lps_cvl_event(lps);1318		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1319			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");1320		break;1321 1322	case BFA_LPS_SM_SET_N2N_PID:1323		if (bfa_reqq_full(lps->bfa, lps->reqq)) {1324			bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);1325			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);1326		} else1327			bfa_lps_send_set_n2n_pid(lps);1328		break;1329 1330	case BFA_LPS_SM_OFFLINE:1331	case BFA_LPS_SM_DELETE:1332		bfa_sm_set_state(lps, bfa_lps_sm_init);1333		break;1334 1335	default:1336		bfa_sm_fault(lps->bfa, event);1337	}1338}1339 1340/*1341 * login complete1342 */1343static void1344bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)1345{1346	bfa_trc(lps->bfa, lps->bfa_tag);1347	bfa_trc(lps->bfa, event);1348 1349	switch (event) {1350	case BFA_LPS_SM_RESUME:1351		bfa_sm_set_state(lps, bfa_lps_sm_online);1352		bfa_lps_send_set_n2n_pid(lps);1353		break;1354 1355	case BFA_LPS_SM_LOGOUT:1356		bfa_sm_set_state(lps, bfa_lps_sm_logowait);1357		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1358			BFA_PL_EID_LOGO, 0, "Logout");1359		break;1360 1361	case BFA_LPS_SM_RX_CVL:1362		bfa_sm_set_state(lps, bfa_lps_sm_init);1363		bfa_reqq_wcancel(&lps->wqe);1364 1365		/* Let the vport module know about this event */1366		bfa_lps_cvl_event(lps);1367		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,1368			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");1369		break;1370 1371	case BFA_LPS_SM_OFFLINE:1372	case BFA_LPS_SM_DELETE:1373		bfa_sm_set_state(lps, bfa_lps_sm_init);1374		bfa_reqq_wcancel(&lps->wqe);1375		break;1376 1377	default:1378		bfa_sm_fault(lps->bfa, event);1379	}1380}1381 1382/*1383 * logout in progress - awaiting firmware response1384 */1385static void1386bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)1387{1388	bfa_trc(lps->bfa, lps->bfa_tag);1389	bfa_trc(lps->bfa, event);1390 1391	switch (event) {1392	case BFA_LPS_SM_FWRSP:1393	case BFA_LPS_SM_OFFLINE:1394		bfa_sm_set_state(lps, bfa_lps_sm_init);1395		bfa_lps_logout_comp(lps);1396		break;1397 1398	case BFA_LPS_SM_DELETE:1399		bfa_sm_set_state(lps, bfa_lps_sm_init);1400		break;1401 1402	default:1403		bfa_sm_fault(lps->bfa, event);1404	}1405}1406 1407/*1408 * logout pending -- awaiting space in request queue1409 */1410static void1411bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)1412{1413	bfa_trc(lps->bfa, lps->bfa_tag);1414	bfa_trc(lps->bfa, event);1415 1416	switch (event) {1417	case BFA_LPS_SM_RESUME:1418		bfa_sm_set_state(lps, bfa_lps_sm_logout);1419		bfa_lps_send_logout(lps);1420		break;1421 1422	case BFA_LPS_SM_OFFLINE:1423	case BFA_LPS_SM_DELETE:1424		bfa_sm_set_state(lps, bfa_lps_sm_init);1425		bfa_reqq_wcancel(&lps->wqe);1426		break;1427 1428	default:1429		bfa_sm_fault(lps->bfa, event);1430	}1431}1432 1433 1434 1435/*1436 *  lps_pvt BFA LPS private functions1437 */1438 1439/*1440 * return memory requirement1441 */1442void1443bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,1444		struct bfa_s *bfa)1445{1446	struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);1447 1448	if (cfg->drvcfg.min_cfg)1449		bfa_mem_kva_setup(minfo, lps_kva,1450			sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);1451	else1452		bfa_mem_kva_setup(minfo, lps_kva,1453			sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);1454}1455 1456/*1457 * bfa module attach at initialization time1458 */1459void1460bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,1461	struct bfa_pcidev_s *pcidev)1462{1463	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1464	struct bfa_lps_s	*lps;1465	int			i;1466 1467	mod->num_lps = BFA_LPS_MAX_LPORTS;1468	if (cfg->drvcfg.min_cfg)1469		mod->num_lps = BFA_LPS_MIN_LPORTS;1470	else1471		mod->num_lps = BFA_LPS_MAX_LPORTS;1472	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);1473 1474	bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);1475 1476	INIT_LIST_HEAD(&mod->lps_free_q);1477	INIT_LIST_HEAD(&mod->lps_active_q);1478	INIT_LIST_HEAD(&mod->lps_login_q);1479 1480	for (i = 0; i < mod->num_lps; i++, lps++) {1481		lps->bfa	= bfa;1482		lps->bfa_tag	= (u8) i;1483		lps->reqq	= BFA_REQQ_LPS;1484		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);1485		list_add_tail(&lps->qe, &mod->lps_free_q);1486	}1487}1488 1489/*1490 * IOC in disabled state -- consider all lps offline1491 */1492void1493bfa_lps_iocdisable(struct bfa_s *bfa)1494{1495	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1496	struct bfa_lps_s	*lps;1497	struct list_head		*qe, *qen;1498 1499	list_for_each_safe(qe, qen, &mod->lps_active_q) {1500		lps = (struct bfa_lps_s *) qe;1501		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);1502	}1503	list_for_each_safe(qe, qen, &mod->lps_login_q) {1504		lps = (struct bfa_lps_s *) qe;1505		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);1506	}1507	list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);1508}1509 1510/*1511 * Firmware login response1512 */1513static void1514bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)1515{1516	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1517	struct bfa_lps_s	*lps;1518 1519	WARN_ON(rsp->bfa_tag >= mod->num_lps);1520	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);1521 1522	lps->status = rsp->status;1523	switch (rsp->status) {1524	case BFA_STATUS_OK:1525		lps->fw_tag	= rsp->fw_tag;1526		lps->fport	= rsp->f_port;1527		if (lps->fport)1528			lps->lp_pid = rsp->lp_pid;1529		lps->npiv_en	= rsp->npiv_en;1530		lps->pr_bbcred	= be16_to_cpu(rsp->bb_credit);1531		lps->pr_pwwn	= rsp->port_name;1532		lps->pr_nwwn	= rsp->node_name;1533		lps->auth_req	= rsp->auth_req;1534		lps->lp_mac	= rsp->lp_mac;1535		lps->brcd_switch = rsp->brcd_switch;1536		lps->fcf_mac	= rsp->fcf_mac;1537 1538		break;1539 1540	case BFA_STATUS_FABRIC_RJT:1541		lps->lsrjt_rsn = rsp->lsrjt_rsn;1542		lps->lsrjt_expl = rsp->lsrjt_expl;1543 1544		break;1545 1546	case BFA_STATUS_EPROTOCOL:1547		lps->ext_status = rsp->ext_status;1548 1549		break;1550 1551	case BFA_STATUS_VPORT_MAX:1552		if (rsp->ext_status)1553			bfa_lps_no_res(lps, rsp->ext_status);1554		break;1555 1556	default:1557		/* Nothing to do with other status */1558		break;1559	}1560 1561	list_del(&lps->qe);1562	list_add_tail(&lps->qe, &mod->lps_active_q);1563	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);1564}1565 1566static void1567bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)1568{1569	struct bfa_s		*bfa = first_lps->bfa;1570	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1571	struct list_head	*qe, *qe_next;1572	struct bfa_lps_s	*lps;1573 1574	bfa_trc(bfa, count);1575 1576	qe = bfa_q_next(first_lps);1577 1578	while (count && qe) {1579		qe_next = bfa_q_next(qe);1580		lps = (struct bfa_lps_s *)qe;1581		bfa_trc(bfa, lps->bfa_tag);1582		lps->status = first_lps->status;1583		list_del(&lps->qe);1584		list_add_tail(&lps->qe, &mod->lps_active_q);1585		bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);1586		qe = qe_next;1587		count--;1588	}1589}1590 1591/*1592 * Firmware logout response1593 */1594static void1595bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)1596{1597	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1598	struct bfa_lps_s	*lps;1599 1600	WARN_ON(rsp->bfa_tag >= mod->num_lps);1601	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);1602 1603	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);1604}1605 1606/*1607 * Firmware received a Clear virtual link request (for FCoE)1608 */1609static void1610bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)1611{1612	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1613	struct bfa_lps_s	*lps;1614 1615	lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);1616 1617	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);1618}1619 1620/*1621 * Space is available in request queue, resume queueing request to firmware.1622 */1623static void1624bfa_lps_reqq_resume(void *lps_arg)1625{1626	struct bfa_lps_s	*lps = lps_arg;1627 1628	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);1629}1630 1631/*1632 * lps is freed -- triggered by vport delete1633 */1634static void1635bfa_lps_free(struct bfa_lps_s *lps)1636{1637	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);1638 1639	lps->lp_pid = 0;1640	list_del(&lps->qe);1641	list_add_tail(&lps->qe, &mod->lps_free_q);1642}1643 1644/*1645 * send login request to firmware1646 */1647static void1648bfa_lps_send_login(struct bfa_lps_s *lps)1649{1650	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);1651	struct bfi_lps_login_req_s	*m;1652 1653	m = bfa_reqq_next(lps->bfa, lps->reqq);1654	WARN_ON(!m);1655 1656	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,1657		bfa_fn_lpu(lps->bfa));1658 1659	m->bfa_tag	= lps->bfa_tag;1660	m->alpa		= lps->alpa;1661	m->pdu_size	= cpu_to_be16(lps->pdusz);1662	m->pwwn		= lps->pwwn;1663	m->nwwn		= lps->nwwn;1664	m->fdisc	= lps->fdisc;1665	m->auth_en	= lps->auth_en;1666 1667	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);1668	list_del(&lps->qe);1669	list_add_tail(&lps->qe, &mod->lps_login_q);1670}1671 1672/*1673 * send logout request to firmware1674 */1675static void1676bfa_lps_send_logout(struct bfa_lps_s *lps)1677{1678	struct bfi_lps_logout_req_s *m;1679 1680	m = bfa_reqq_next(lps->bfa, lps->reqq);1681	WARN_ON(!m);1682 1683	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,1684		bfa_fn_lpu(lps->bfa));1685 1686	m->fw_tag = lps->fw_tag;1687	m->port_name = lps->pwwn;1688	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);1689}1690 1691/*1692 * send n2n pid set request to firmware1693 */1694static void1695bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)1696{1697	struct bfi_lps_n2n_pid_req_s *m;1698 1699	m = bfa_reqq_next(lps->bfa, lps->reqq);1700	WARN_ON(!m);1701 1702	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,1703		bfa_fn_lpu(lps->bfa));1704 1705	m->fw_tag = lps->fw_tag;1706	m->lp_pid = lps->lp_pid;1707	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);1708}1709 1710/*1711 * Indirect login completion handler for non-fcs1712 */1713static void1714bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)1715{1716	struct bfa_lps_s *lps	= arg;1717 1718	if (!complete)1719		return;1720 1721	if (lps->fdisc)1722		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);1723	else1724		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);1725}1726 1727/*1728 * Login completion handler -- direct call for fcs, queue for others1729 */1730static void1731bfa_lps_login_comp(struct bfa_lps_s *lps)1732{1733	if (!lps->bfa->fcs) {1734		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,1735			lps);1736		return;1737	}1738 1739	if (lps->fdisc)1740		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);1741	else1742		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);1743}1744 1745/*1746 * Indirect logout completion handler for non-fcs1747 */1748static void1749bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)1750{1751	struct bfa_lps_s *lps	= arg;1752 1753	if (!complete)1754		return;1755 1756	if (lps->fdisc)1757		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);1758	else1759		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);1760}1761 1762/*1763 * Logout completion handler -- direct call for fcs, queue for others1764 */1765static void1766bfa_lps_logout_comp(struct bfa_lps_s *lps)1767{1768	if (!lps->bfa->fcs) {1769		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,1770			lps);1771		return;1772	}1773	if (lps->fdisc)1774		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);1775}1776 1777/*1778 * Clear virtual link completion handler for non-fcs1779 */1780static void1781bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)1782{1783	struct bfa_lps_s *lps	= arg;1784 1785	if (!complete)1786		return;1787 1788	/* Clear virtual link to base port will result in link down */1789	if (lps->fdisc)1790		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);1791}1792 1793/*1794 * Received Clear virtual link event --direct call for fcs,1795 * queue for others1796 */1797static void1798bfa_lps_cvl_event(struct bfa_lps_s *lps)1799{1800	if (!lps->bfa->fcs) {1801		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,1802			lps);1803		return;1804	}1805 1806	/* Clear virtual link to base port will result in link down */1807	if (lps->fdisc)1808		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);1809}1810 1811 1812 1813/*1814 *  lps_public BFA LPS public functions1815 */1816 1817u321818bfa_lps_get_max_vport(struct bfa_s *bfa)1819{1820	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)1821		return BFA_LPS_MAX_VPORTS_SUPP_CT;1822	else1823		return BFA_LPS_MAX_VPORTS_SUPP_CB;1824}1825 1826/*1827 * Allocate a lport srvice tag.1828 */1829struct bfa_lps_s  *1830bfa_lps_alloc(struct bfa_s *bfa)1831{1832	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1833	struct bfa_lps_s	*lps = NULL;1834 1835	bfa_q_deq(&mod->lps_free_q, &lps);1836 1837	if (lps == NULL)1838		return NULL;1839 1840	list_add_tail(&lps->qe, &mod->lps_active_q);1841 1842	bfa_sm_set_state(lps, bfa_lps_sm_init);1843	return lps;1844}1845 1846/*1847 * Free lport service tag. This can be called anytime after an alloc.1848 * No need to wait for any pending login/logout completions.1849 */1850void1851bfa_lps_delete(struct bfa_lps_s *lps)1852{1853	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);1854}1855 1856/*1857 * Initiate a lport login.1858 */1859void1860bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,1861	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)1862{1863	lps->uarg	= uarg;1864	lps->alpa	= alpa;1865	lps->pdusz	= pdusz;1866	lps->pwwn	= pwwn;1867	lps->nwwn	= nwwn;1868	lps->fdisc	= BFA_FALSE;1869	lps->auth_en	= auth_en;1870	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);1871}1872 1873/*1874 * Initiate a lport fdisc login.1875 */1876void1877bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,1878	wwn_t nwwn)1879{1880	lps->uarg	= uarg;1881	lps->alpa	= 0;1882	lps->pdusz	= pdusz;1883	lps->pwwn	= pwwn;1884	lps->nwwn	= nwwn;1885	lps->fdisc	= BFA_TRUE;1886	lps->auth_en	= BFA_FALSE;1887	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);1888}1889 1890 1891/*1892 * Initiate a lport FDSIC logout.1893 */1894void1895bfa_lps_fdisclogo(struct bfa_lps_s *lps)1896{1897	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);1898}1899 1900u81901bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)1902{1903	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);1904 1905	return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;1906}1907 1908/*1909 * Return lport services tag given the pid1910 */1911u81912bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)1913{1914	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1915	struct bfa_lps_s	*lps;1916	int			i;1917 1918	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {1919		if (lps->lp_pid == pid)1920			return lps->bfa_tag;1921	}1922 1923	/* Return base port tag anyway */1924	return 0;1925}1926 1927 1928/*1929 * return port id assigned to the base lport1930 */1931u321932bfa_lps_get_base_pid(struct bfa_s *bfa)1933{1934	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);1935 1936	return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;1937}1938 1939/*1940 * Set PID in case of n2n (which is assigned during PLOGI)1941 */1942void1943bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)1944{1945	bfa_trc(lps->bfa, lps->bfa_tag);1946	bfa_trc(lps->bfa, n2n_pid);1947 1948	lps->lp_pid = n2n_pid;1949	bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);1950}1951 1952/*1953 * LPS firmware message class handler.1954 */1955void1956bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)1957{1958	union bfi_lps_i2h_msg_u	msg;1959 1960	bfa_trc(bfa, m->mhdr.msg_id);1961	msg.msg = m;1962 1963	switch (m->mhdr.msg_id) {1964	case BFI_LPS_I2H_LOGIN_RSP:1965		bfa_lps_login_rsp(bfa, msg.login_rsp);1966		break;1967 1968	case BFI_LPS_I2H_LOGOUT_RSP:1969		bfa_lps_logout_rsp(bfa, msg.logout_rsp);1970		break;1971 1972	case BFI_LPS_I2H_CVL_EVENT:1973		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);1974		break;1975 1976	default:1977		bfa_trc(bfa, m->mhdr.msg_id);1978		WARN_ON(1);1979	}1980}1981 1982static void1983bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)1984{1985	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;1986	struct bfa_aen_entry_s  *aen_entry;1987 1988	bfad_get_aen_entry(bfad, aen_entry);1989	if (!aen_entry)1990		return;1991 1992	aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);1993	aen_entry->aen_data.port.pwwn = fcport->pwwn;1994 1995	/* Send the AEN notification */1996	bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,1997				  BFA_AEN_CAT_PORT, event);1998}1999 2000/*2001 * FC PORT state machine functions2002 */2003static void2004bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,2005			enum bfa_fcport_sm_event event)2006{2007	bfa_trc(fcport->bfa, event);2008 2009	switch (event) {2010	case BFA_FCPORT_SM_START:2011		/*2012		 * Start event after IOC is configured and BFA is started.2013		 */2014		fcport->use_flash_cfg = BFA_TRUE;2015 2016		if (bfa_fcport_send_enable(fcport)) {2017			bfa_trc(fcport->bfa, BFA_TRUE);2018			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2019		} else {2020			bfa_trc(fcport->bfa, BFA_FALSE);2021			bfa_sm_set_state(fcport,2022					bfa_fcport_sm_enabling_qwait);2023		}2024		break;2025 2026	case BFA_FCPORT_SM_ENABLE:2027		/*2028		 * Port is persistently configured to be in enabled state. Do2029		 * not change state. Port enabling is done when START event is2030		 * received.2031		 */2032		break;2033 2034	case BFA_FCPORT_SM_DISABLE:2035		/*2036		 * If a port is persistently configured to be disabled, the2037		 * first event will a port disable request.2038		 */2039		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);2040		break;2041 2042	case BFA_FCPORT_SM_HWFAIL:2043		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2044		break;2045 2046	default:2047		bfa_sm_fault(fcport->bfa, event);2048	}2049}2050 2051static void2052bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,2053				enum bfa_fcport_sm_event event)2054{2055	char pwwn_buf[BFA_STRING_32];2056	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;2057	bfa_trc(fcport->bfa, event);2058 2059	switch (event) {2060	case BFA_FCPORT_SM_QRESUME:2061		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2062		bfa_fcport_send_enable(fcport);2063		break;2064 2065	case BFA_FCPORT_SM_STOP:2066		bfa_reqq_wcancel(&fcport->reqq_wait);2067		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2068		break;2069 2070	case BFA_FCPORT_SM_ENABLE:2071		/*2072		 * Already enable is in progress.2073		 */2074		break;2075 2076	case BFA_FCPORT_SM_DISABLE:2077		/*2078		 * Just send disable request to firmware when room becomes2079		 * available in request queue.2080		 */2081		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);2082		bfa_reqq_wcancel(&fcport->reqq_wait);2083		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2084				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");2085		wwn2str(pwwn_buf, fcport->pwwn);2086		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2087			"Base port disabled: WWN = %s\n", pwwn_buf);2088		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);2089		break;2090 2091	case BFA_FCPORT_SM_LINKUP:2092	case BFA_FCPORT_SM_LINKDOWN:2093		/*2094		 * Possible to get link events when doing back-to-back2095		 * enable/disables.2096		 */2097		break;2098 2099	case BFA_FCPORT_SM_HWFAIL:2100		bfa_reqq_wcancel(&fcport->reqq_wait);2101		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2102		break;2103 2104	case BFA_FCPORT_SM_FAA_MISCONFIG:2105		bfa_fcport_reset_linkinfo(fcport);2106		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2107		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);2108		break;2109 2110	default:2111		bfa_sm_fault(fcport->bfa, event);2112	}2113}2114 2115static void2116bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,2117						enum bfa_fcport_sm_event event)2118{2119	char pwwn_buf[BFA_STRING_32];2120	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;2121	bfa_trc(fcport->bfa, event);2122 2123	switch (event) {2124	case BFA_FCPORT_SM_FWRSP:2125	case BFA_FCPORT_SM_LINKDOWN:2126		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);2127		break;2128 2129	case BFA_FCPORT_SM_LINKUP:2130		bfa_fcport_update_linkinfo(fcport);2131		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);2132 2133		WARN_ON(!fcport->event_cbfn);2134		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);2135		break;2136 2137	case BFA_FCPORT_SM_ENABLE:2138		/*2139		 * Already being enabled.2140		 */2141		break;2142 2143	case BFA_FCPORT_SM_DISABLE:2144		if (bfa_fcport_send_disable(fcport))2145			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);2146		else2147			bfa_sm_set_state(fcport,2148					 bfa_fcport_sm_disabling_qwait);2149 2150		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2151				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");2152		wwn2str(pwwn_buf, fcport->pwwn);2153		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2154			"Base port disabled: WWN = %s\n", pwwn_buf);2155		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);2156		break;2157 2158	case BFA_FCPORT_SM_STOP:2159		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2160		break;2161 2162	case BFA_FCPORT_SM_HWFAIL:2163		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2164		break;2165 2166	case BFA_FCPORT_SM_FAA_MISCONFIG:2167		bfa_fcport_reset_linkinfo(fcport);2168		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2169		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);2170		break;2171 2172	default:2173		bfa_sm_fault(fcport->bfa, event);2174	}2175}2176 2177static void2178bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,2179						enum bfa_fcport_sm_event event)2180{2181	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;2182	char pwwn_buf[BFA_STRING_32];2183	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;2184 2185	bfa_trc(fcport->bfa, event);2186 2187	switch (event) {2188	case BFA_FCPORT_SM_LINKUP:2189		bfa_fcport_update_linkinfo(fcport);2190		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);2191		WARN_ON(!fcport->event_cbfn);2192		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2193				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");2194		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {2195 2196			bfa_trc(fcport->bfa,2197				pevent->link_state.attr.vc_fcf.fcf.fipenabled);2198			bfa_trc(fcport->bfa,2199				pevent->link_state.attr.vc_fcf.fcf.fipfailed);2200 2201			if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)2202				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2203					BFA_PL_EID_FIP_FCF_DISC, 0,2204					"FIP FCF Discovery Failed");2205			else2206				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2207					BFA_PL_EID_FIP_FCF_DISC, 0,2208					"FIP FCF Discovered");2209		}2210 2211		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);2212		wwn2str(pwwn_buf, fcport->pwwn);2213		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2214			"Base port online: WWN = %s\n", pwwn_buf);2215		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);2216 2217		/* If QoS is enabled and it is not online, send AEN */2218		if (fcport->cfg.qos_enabled &&2219		    fcport->qos_attr.state != BFA_QOS_ONLINE)2220			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);2221		break;2222 2223	case BFA_FCPORT_SM_LINKDOWN:2224		/*2225		 * Possible to get link down event.2226		 */2227		break;2228 2229	case BFA_FCPORT_SM_ENABLE:2230		/*2231		 * Already enabled.2232		 */2233		break;2234 2235	case BFA_FCPORT_SM_DISABLE:2236		if (bfa_fcport_send_disable(fcport))2237			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);2238		else2239			bfa_sm_set_state(fcport,2240					 bfa_fcport_sm_disabling_qwait);2241 2242		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2243				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");2244		wwn2str(pwwn_buf, fcport->pwwn);2245		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2246			"Base port disabled: WWN = %s\n", pwwn_buf);2247		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);2248		break;2249 2250	case BFA_FCPORT_SM_STOP:2251		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2252		break;2253 2254	case BFA_FCPORT_SM_HWFAIL:2255		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2256		break;2257 2258	case BFA_FCPORT_SM_FAA_MISCONFIG:2259		bfa_fcport_reset_linkinfo(fcport);2260		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2261		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);2262		break;2263 2264	default:2265		bfa_sm_fault(fcport->bfa, event);2266	}2267}2268 2269static void2270bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,2271	enum bfa_fcport_sm_event event)2272{2273	char pwwn_buf[BFA_STRING_32];2274	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;2275 2276	bfa_trc(fcport->bfa, event);2277 2278	switch (event) {2279	case BFA_FCPORT_SM_ENABLE:2280		/*2281		 * Already enabled.2282		 */2283		break;2284 2285	case BFA_FCPORT_SM_DISABLE:2286		if (bfa_fcport_send_disable(fcport))2287			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);2288		else2289			bfa_sm_set_state(fcport,2290					 bfa_fcport_sm_disabling_qwait);2291 2292		bfa_fcport_reset_linkinfo(fcport);2293		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);2294		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2295				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");2296		wwn2str(pwwn_buf, fcport->pwwn);2297		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2298			"Base port offline: WWN = %s\n", pwwn_buf);2299		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);2300		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2301			"Base port disabled: WWN = %s\n", pwwn_buf);2302		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);2303		break;2304 2305	case BFA_FCPORT_SM_LINKDOWN:2306		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);2307		bfa_fcport_reset_linkinfo(fcport);2308		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);2309		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2310				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");2311		wwn2str(pwwn_buf, fcport->pwwn);2312		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {2313			BFA_LOG(KERN_INFO, bfad, bfa_log_level,2314				"Base port offline: WWN = %s\n", pwwn_buf);2315			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);2316		} else {2317			BFA_LOG(KERN_ERR, bfad, bfa_log_level,2318				"Base port (WWN = %s) "2319				"lost fabric connectivity\n", pwwn_buf);2320			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2321		}2322		break;2323 2324	case BFA_FCPORT_SM_STOP:2325		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2326		bfa_fcport_reset_linkinfo(fcport);2327		wwn2str(pwwn_buf, fcport->pwwn);2328		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {2329			BFA_LOG(KERN_INFO, bfad, bfa_log_level,2330				"Base port offline: WWN = %s\n", pwwn_buf);2331			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);2332		} else {2333			BFA_LOG(KERN_ERR, bfad, bfa_log_level,2334				"Base port (WWN = %s) "2335				"lost fabric connectivity\n", pwwn_buf);2336			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2337		}2338		break;2339 2340	case BFA_FCPORT_SM_HWFAIL:2341		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2342		bfa_fcport_reset_linkinfo(fcport);2343		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);2344		wwn2str(pwwn_buf, fcport->pwwn);2345		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {2346			BFA_LOG(KERN_INFO, bfad, bfa_log_level,2347				"Base port offline: WWN = %s\n", pwwn_buf);2348			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);2349		} else {2350			BFA_LOG(KERN_ERR, bfad, bfa_log_level,2351				"Base port (WWN = %s) "2352				"lost fabric connectivity\n", pwwn_buf);2353			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2354		}2355		break;2356 2357	case BFA_FCPORT_SM_FAA_MISCONFIG:2358		bfa_fcport_reset_linkinfo(fcport);2359		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2360		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);2361		break;2362 2363	default:2364		bfa_sm_fault(fcport->bfa, event);2365	}2366}2367 2368static void2369bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,2370				 enum bfa_fcport_sm_event event)2371{2372	bfa_trc(fcport->bfa, event);2373 2374	switch (event) {2375	case BFA_FCPORT_SM_QRESUME:2376		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);2377		bfa_fcport_send_disable(fcport);2378		break;2379 2380	case BFA_FCPORT_SM_STOP:2381		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2382		bfa_reqq_wcancel(&fcport->reqq_wait);2383		break;2384 2385	case BFA_FCPORT_SM_ENABLE:2386		bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);2387		break;2388 2389	case BFA_FCPORT_SM_DISABLE:2390		/*2391		 * Already being disabled.2392		 */2393		break;2394 2395	case BFA_FCPORT_SM_LINKUP:2396	case BFA_FCPORT_SM_LINKDOWN:2397		/*2398		 * Possible to get link events when doing back-to-back2399		 * enable/disables.2400		 */2401		break;2402 2403	case BFA_FCPORT_SM_HWFAIL:2404		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);2405		bfa_reqq_wcancel(&fcport->reqq_wait);2406		break;2407 2408	case BFA_FCPORT_SM_FAA_MISCONFIG:2409		bfa_fcport_reset_linkinfo(fcport);2410		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);2411		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);2412		break;2413 2414	default:2415		bfa_sm_fault(fcport->bfa, event);2416	}2417}2418 2419static void2420bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,2421				 enum bfa_fcport_sm_event event)2422{2423	bfa_trc(fcport->bfa, event);2424 2425	switch (event) {2426	case BFA_FCPORT_SM_QRESUME:2427		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);2428		bfa_fcport_send_disable(fcport);2429		if (bfa_fcport_send_enable(fcport))2430			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2431		else2432			bfa_sm_set_state(fcport,2433					 bfa_fcport_sm_enabling_qwait);2434		break;2435 2436	case BFA_FCPORT_SM_STOP:2437		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2438		bfa_reqq_wcancel(&fcport->reqq_wait);2439		break;2440 2441	case BFA_FCPORT_SM_ENABLE:2442		break;2443 2444	case BFA_FCPORT_SM_DISABLE:2445		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);2446		break;2447 2448	case BFA_FCPORT_SM_LINKUP:2449	case BFA_FCPORT_SM_LINKDOWN:2450		/*2451		 * Possible to get link events when doing back-to-back2452		 * enable/disables.2453		 */2454		break;2455 2456	case BFA_FCPORT_SM_HWFAIL:2457		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);2458		bfa_reqq_wcancel(&fcport->reqq_wait);2459		break;2460 2461	default:2462		bfa_sm_fault(fcport->bfa, event);2463	}2464}2465 2466static void2467bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,2468						enum bfa_fcport_sm_event event)2469{2470	char pwwn_buf[BFA_STRING_32];2471	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;2472	bfa_trc(fcport->bfa, event);2473 2474	switch (event) {2475	case BFA_FCPORT_SM_FWRSP:2476		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);2477		break;2478 2479	case BFA_FCPORT_SM_DISABLE:2480		/*2481		 * Already being disabled.2482		 */2483		break;2484 2485	case BFA_FCPORT_SM_ENABLE:2486		if (bfa_fcport_send_enable(fcport))2487			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2488		else2489			bfa_sm_set_state(fcport,2490					 bfa_fcport_sm_enabling_qwait);2491 2492		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2493				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");2494		wwn2str(pwwn_buf, fcport->pwwn);2495		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2496			"Base port enabled: WWN = %s\n", pwwn_buf);2497		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);2498		break;2499 2500	case BFA_FCPORT_SM_STOP:2501		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2502		break;2503 2504	case BFA_FCPORT_SM_LINKUP:2505	case BFA_FCPORT_SM_LINKDOWN:2506		/*2507		 * Possible to get link events when doing back-to-back2508		 * enable/disables.2509		 */2510		break;2511 2512	case BFA_FCPORT_SM_HWFAIL:2513		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);2514		break;2515 2516	default:2517		bfa_sm_fault(fcport->bfa, event);2518	}2519}2520 2521static void2522bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,2523						enum bfa_fcport_sm_event event)2524{2525	char pwwn_buf[BFA_STRING_32];2526	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;2527	bfa_trc(fcport->bfa, event);2528 2529	switch (event) {2530	case BFA_FCPORT_SM_START:2531		/*2532		 * Ignore start event for a port that is disabled.2533		 */2534		break;2535 2536	case BFA_FCPORT_SM_STOP:2537		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2538		break;2539 2540	case BFA_FCPORT_SM_ENABLE:2541		if (bfa_fcport_send_enable(fcport))2542			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2543		else2544			bfa_sm_set_state(fcport,2545					 bfa_fcport_sm_enabling_qwait);2546 2547		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2548				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");2549		wwn2str(pwwn_buf, fcport->pwwn);2550		BFA_LOG(KERN_INFO, bfad, bfa_log_level,2551			"Base port enabled: WWN = %s\n", pwwn_buf);2552		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);2553		break;2554 2555	case BFA_FCPORT_SM_DISABLE:2556		/*2557		 * Already disabled.2558		 */2559		break;2560 2561	case BFA_FCPORT_SM_HWFAIL:2562		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);2563		break;2564 2565	case BFA_FCPORT_SM_DPORTENABLE:2566		bfa_sm_set_state(fcport, bfa_fcport_sm_dport);2567		break;2568 2569	case BFA_FCPORT_SM_DDPORTENABLE:2570		bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);2571		break;2572 2573	default:2574		bfa_sm_fault(fcport->bfa, event);2575	}2576}2577 2578static void2579bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,2580			 enum bfa_fcport_sm_event event)2581{2582	bfa_trc(fcport->bfa, event);2583 2584	switch (event) {2585	case BFA_FCPORT_SM_START:2586		if (bfa_fcport_send_enable(fcport))2587			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2588		else2589			bfa_sm_set_state(fcport,2590					 bfa_fcport_sm_enabling_qwait);2591		break;2592 2593	default:2594		/*2595		 * Ignore all other events.2596		 */2597		;2598	}2599}2600 2601/*2602 * Port is enabled. IOC is down/failed.2603 */2604static void2605bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,2606			 enum bfa_fcport_sm_event event)2607{2608	bfa_trc(fcport->bfa, event);2609 2610	switch (event) {2611	case BFA_FCPORT_SM_START:2612		if (bfa_fcport_send_enable(fcport))2613			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);2614		else2615			bfa_sm_set_state(fcport,2616					 bfa_fcport_sm_enabling_qwait);2617		break;2618 2619	default:2620		/*2621		 * Ignore all events.2622		 */2623		;2624	}2625}2626 2627/*2628 * Port is disabled. IOC is down/failed.2629 */2630static void2631bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,2632			 enum bfa_fcport_sm_event event)2633{2634	bfa_trc(fcport->bfa, event);2635 2636	switch (event) {2637	case BFA_FCPORT_SM_START:2638		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);2639		break;2640 2641	case BFA_FCPORT_SM_ENABLE:2642		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2643		break;2644 2645	default:2646		/*2647		 * Ignore all events.2648		 */2649		;2650	}2651}2652 2653static void2654bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)2655{2656	bfa_trc(fcport->bfa, event);2657 2658	switch (event) {2659	case BFA_FCPORT_SM_DPORTENABLE:2660	case BFA_FCPORT_SM_DISABLE:2661	case BFA_FCPORT_SM_ENABLE:2662	case BFA_FCPORT_SM_START:2663		/*2664		 * Ignore event for a port that is dport2665		 */2666		break;2667 2668	case BFA_FCPORT_SM_STOP:2669		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2670		break;2671 2672	case BFA_FCPORT_SM_HWFAIL:2673		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);2674		break;2675 2676	case BFA_FCPORT_SM_DPORTDISABLE:2677		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);2678		break;2679 2680	default:2681		bfa_sm_fault(fcport->bfa, event);2682	}2683}2684 2685static void2686bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,2687			enum bfa_fcport_sm_event event)2688{2689	bfa_trc(fcport->bfa, event);2690 2691	switch (event) {2692	case BFA_FCPORT_SM_DISABLE:2693	case BFA_FCPORT_SM_DDPORTDISABLE:2694		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);2695		break;2696 2697	case BFA_FCPORT_SM_DPORTENABLE:2698	case BFA_FCPORT_SM_DPORTDISABLE:2699	case BFA_FCPORT_SM_ENABLE:2700	case BFA_FCPORT_SM_START:2701		/*2702		 * Ignore event for a port that is ddport2703		 */2704		break;2705 2706	case BFA_FCPORT_SM_STOP:2707		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2708		break;2709 2710	case BFA_FCPORT_SM_HWFAIL:2711		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);2712		break;2713 2714	default:2715		bfa_sm_fault(fcport->bfa, event);2716	}2717}2718 2719static void2720bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,2721			    enum bfa_fcport_sm_event event)2722{2723	bfa_trc(fcport->bfa, event);2724 2725	switch (event) {2726	case BFA_FCPORT_SM_DPORTENABLE:2727	case BFA_FCPORT_SM_ENABLE:2728	case BFA_FCPORT_SM_START:2729		/*2730		 * Ignore event for a port as there is FAA misconfig2731		 */2732		break;2733 2734	case BFA_FCPORT_SM_DISABLE:2735		if (bfa_fcport_send_disable(fcport))2736			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);2737		else2738			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);2739 2740		bfa_fcport_reset_linkinfo(fcport);2741		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);2742		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,2743			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");2744		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);2745		break;2746 2747	case BFA_FCPORT_SM_STOP:2748		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);2749		break;2750 2751	case BFA_FCPORT_SM_HWFAIL:2752		bfa_fcport_reset_linkinfo(fcport);2753		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);2754		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);2755		break;2756 2757	default:2758		bfa_sm_fault(fcport->bfa, event);2759	}2760}2761 2762/*2763 * Link state is down2764 */2765static void2766bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,2767		enum bfa_fcport_ln_sm_event event)2768{2769	bfa_trc(ln->fcport->bfa, event);2770 2771	switch (event) {2772	case BFA_FCPORT_LN_SM_LINKUP:2773		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);2774		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);2775		break;2776 2777	default:2778		bfa_sm_fault(ln->fcport->bfa, event);2779	}2780}2781 2782/*2783 * Link state is waiting for down notification2784 */2785static void2786bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,2787		enum bfa_fcport_ln_sm_event event)2788{2789	bfa_trc(ln->fcport->bfa, event);2790 2791	switch (event) {2792	case BFA_FCPORT_LN_SM_LINKUP:2793		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);2794		break;2795 2796	case BFA_FCPORT_LN_SM_NOTIFICATION:2797		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);2798		break;2799 2800	default:2801		bfa_sm_fault(ln->fcport->bfa, event);2802	}2803}2804 2805/*2806 * Link state is waiting for down notification and there is a pending up2807 */2808static void2809bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,2810		enum bfa_fcport_ln_sm_event event)2811{2812	bfa_trc(ln->fcport->bfa, event);2813 2814	switch (event) {2815	case BFA_FCPORT_LN_SM_LINKDOWN:2816		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);2817		break;2818 2819	case BFA_FCPORT_LN_SM_NOTIFICATION:2820		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);2821		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);2822		break;2823 2824	default:2825		bfa_sm_fault(ln->fcport->bfa, event);2826	}2827}2828 2829/*2830 * Link state is up2831 */2832static void2833bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,2834		enum bfa_fcport_ln_sm_event event)2835{2836	bfa_trc(ln->fcport->bfa, event);2837 2838	switch (event) {2839	case BFA_FCPORT_LN_SM_LINKDOWN:2840		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);2841		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);2842		break;2843 2844	default:2845		bfa_sm_fault(ln->fcport->bfa, event);2846	}2847}2848 2849/*2850 * Link state is waiting for up notification2851 */2852static void2853bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,2854		enum bfa_fcport_ln_sm_event event)2855{2856	bfa_trc(ln->fcport->bfa, event);2857 2858	switch (event) {2859	case BFA_FCPORT_LN_SM_LINKDOWN:2860		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);2861		break;2862 2863	case BFA_FCPORT_LN_SM_NOTIFICATION:2864		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);2865		break;2866 2867	default:2868		bfa_sm_fault(ln->fcport->bfa, event);2869	}2870}2871 2872/*2873 * Link state is waiting for up notification and there is a pending down2874 */2875static void2876bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,2877		enum bfa_fcport_ln_sm_event event)2878{2879	bfa_trc(ln->fcport->bfa, event);2880 2881	switch (event) {2882	case BFA_FCPORT_LN_SM_LINKUP:2883		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);2884		break;2885 2886	case BFA_FCPORT_LN_SM_NOTIFICATION:2887		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);2888		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);2889		break;2890 2891	default:2892		bfa_sm_fault(ln->fcport->bfa, event);2893	}2894}2895 2896/*2897 * Link state is waiting for up notification and there are pending down and up2898 */2899static void2900bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,2901			enum bfa_fcport_ln_sm_event event)2902{2903	bfa_trc(ln->fcport->bfa, event);2904 2905	switch (event) {2906	case BFA_FCPORT_LN_SM_LINKDOWN:2907		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);2908		break;2909 2910	case BFA_FCPORT_LN_SM_NOTIFICATION:2911		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);2912		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);2913		break;2914 2915	default:2916		bfa_sm_fault(ln->fcport->bfa, event);2917	}2918}2919 2920static void2921__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)2922{2923	struct bfa_fcport_ln_s *ln = cbarg;2924 2925	if (complete)2926		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);2927	else2928		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);2929}2930 2931/*2932 * Send SCN notification to upper layers.2933 * trunk - false if caller is fcport to ignore fcport event in trunked mode2934 */2935static void2936bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,2937	bfa_boolean_t trunk)2938{2939	if (fcport->cfg.trunked && !trunk)2940		return;2941 2942	switch (event) {2943	case BFA_PORT_LINKUP:2944		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);2945		break;2946	case BFA_PORT_LINKDOWN:2947		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);2948		break;2949	default:2950		WARN_ON(1);2951	}2952}2953 2954static void2955bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)2956{2957	struct bfa_fcport_s *fcport = ln->fcport;2958 2959	if (fcport->bfa->fcs) {2960		fcport->event_cbfn(fcport->event_cbarg, event);2961		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);2962	} else {2963		ln->ln_event = event;2964		bfa_cb_queue(fcport->bfa, &ln->ln_qe,2965			__bfa_cb_fcport_event, ln);2966	}2967}2968 2969#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \2970							BFA_CACHELINE_SZ))2971 2972void2973bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,2974		   struct bfa_s *bfa)2975{2976	struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);2977 2978	bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);2979}2980 2981static void2982bfa_fcport_qresume(void *cbarg)2983{2984	struct bfa_fcport_s *fcport = cbarg;2985 2986	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);2987}2988 2989static void2990bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)2991{2992	struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;2993 2994	fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);2995	fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);2996	fcport->stats = (union bfa_fcport_stats_u *)2997				bfa_mem_dma_virt(fcport_dma);2998}2999 3000/*3001 * Memory initialization.3002 */3003void3004bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,3005		struct bfa_pcidev_s *pcidev)3006{3007	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3008	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;3009	struct bfa_fcport_ln_s *ln = &fcport->ln;3010 3011	fcport->bfa = bfa;3012	ln->fcport = fcport;3013 3014	bfa_fcport_mem_claim(fcport);3015 3016	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);3017	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);3018 3019	/*3020	 * initialize time stamp for stats reset3021	 */3022	fcport->stats_reset_time = ktime_get_seconds();3023	fcport->stats_dma_ready = BFA_FALSE;3024 3025	/*3026	 * initialize and set default configuration3027	 */3028	port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;3029	port_cfg->speed = BFA_PORT_SPEED_AUTO;3030	port_cfg->trunked = BFA_FALSE;3031	port_cfg->maxfrsize = 0;3032 3033	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;3034	port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;3035	port_cfg->qos_bw.med = BFA_QOS_BW_MED;3036	port_cfg->qos_bw.low = BFA_QOS_BW_LOW;3037 3038	fcport->fec_state = BFA_FEC_OFFLINE;3039 3040	INIT_LIST_HEAD(&fcport->stats_pending_q);3041	INIT_LIST_HEAD(&fcport->statsclr_pending_q);3042 3043	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);3044}3045 3046void3047bfa_fcport_start(struct bfa_s *bfa)3048{3049	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);3050}3051 3052/*3053 * Called when IOC failure is detected.3054 */3055void3056bfa_fcport_iocdisable(struct bfa_s *bfa)3057{3058	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3059 3060	bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);3061	bfa_trunk_iocdisable(bfa);3062}3063 3064/*3065 * Update loop info in fcport for SCN online3066 */3067static void3068bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,3069			struct bfa_fcport_loop_info_s *loop_info)3070{3071	fcport->myalpa = loop_info->myalpa;3072	fcport->alpabm_valid =3073			loop_info->alpabm_val;3074	memcpy(fcport->alpabm.alpa_bm,3075			loop_info->alpabm.alpa_bm,3076			sizeof(struct fc_alpabm_s));3077}3078 3079static void3080bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)3081{3082	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;3083	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;3084 3085	fcport->speed = pevent->link_state.speed;3086	fcport->topology = pevent->link_state.topology;3087 3088	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {3089		bfa_fcport_update_loop_info(fcport,3090				&pevent->link_state.attr.loop_info);3091		return;3092	}3093 3094	/* QoS Details */3095	fcport->qos_attr = pevent->link_state.qos_attr;3096	fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;3097 3098	if (fcport->cfg.bb_cr_enabled)3099		fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;3100 3101	fcport->fec_state = pevent->link_state.fec_state;3102 3103	/*3104	 * update trunk state if applicable3105	 */3106	if (!fcport->cfg.trunked)3107		trunk->attr.state = BFA_TRUNK_DISABLED;3108 3109	/* update FCoE specific */3110	fcport->fcoe_vlan =3111		be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);3112 3113	bfa_trc(fcport->bfa, fcport->speed);3114	bfa_trc(fcport->bfa, fcport->topology);3115}3116 3117static void3118bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)3119{3120	fcport->speed = BFA_PORT_SPEED_UNKNOWN;3121	fcport->topology = BFA_PORT_TOPOLOGY_NONE;3122	fcport->fec_state = BFA_FEC_OFFLINE;3123}3124 3125/*3126 * Send port enable message to firmware.3127 */3128static bfa_boolean_t3129bfa_fcport_send_enable(struct bfa_fcport_s *fcport)3130{3131	struct bfi_fcport_enable_req_s *m;3132 3133	/*3134	 * Increment message tag before queue check, so that responses to old3135	 * requests are discarded.3136	 */3137	fcport->msgtag++;3138 3139	/*3140	 * check for room in queue to send request now3141	 */3142	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);3143	if (!m) {3144		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,3145							&fcport->reqq_wait);3146		return BFA_FALSE;3147	}3148 3149	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,3150			bfa_fn_lpu(fcport->bfa));3151	m->nwwn = fcport->nwwn;3152	m->pwwn = fcport->pwwn;3153	m->port_cfg = fcport->cfg;3154	m->msgtag = fcport->msgtag;3155	m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);3156	m->use_flash_cfg = fcport->use_flash_cfg;3157	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);3158	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);3159	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);3160 3161	/*3162	 * queue I/O message to firmware3163	 */3164	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);3165	return BFA_TRUE;3166}3167 3168/*3169 * Send port disable message to firmware.3170 */3171static	bfa_boolean_t3172bfa_fcport_send_disable(struct bfa_fcport_s *fcport)3173{3174	struct bfi_fcport_req_s *m;3175 3176	/*3177	 * Increment message tag before queue check, so that responses to old3178	 * requests are discarded.3179	 */3180	fcport->msgtag++;3181 3182	/*3183	 * check for room in queue to send request now3184	 */3185	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);3186	if (!m) {3187		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,3188							&fcport->reqq_wait);3189		return BFA_FALSE;3190	}3191 3192	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,3193			bfa_fn_lpu(fcport->bfa));3194	m->msgtag = fcport->msgtag;3195 3196	/*3197	 * queue I/O message to firmware3198	 */3199	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);3200 3201	return BFA_TRUE;3202}3203 3204static void3205bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)3206{3207	fcport->pwwn = fcport->bfa->ioc.attr->pwwn;3208	fcport->nwwn = fcport->bfa->ioc.attr->nwwn;3209 3210	bfa_trc(fcport->bfa, fcport->pwwn);3211	bfa_trc(fcport->bfa, fcport->nwwn);3212}3213 3214static void3215bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,3216	struct bfa_qos_stats_s *s)3217{3218	u32	*dip = (u32 *) d;3219	__be32	*sip = (__be32 *) s;3220	int		i;3221 3222	/* Now swap the 32 bit fields */3223	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)3224		dip[i] = be32_to_cpu(sip[i]);3225}3226 3227static void3228bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,3229	struct bfa_fcoe_stats_s *s)3230{3231	u32	*dip = (u32 *) d;3232	__be32	*sip = (__be32 *) s;3233	int		i;3234 3235	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));3236	     i = i + 2) {3237#ifdef __BIG_ENDIAN3238		dip[i] = be32_to_cpu(sip[i]);3239		dip[i + 1] = be32_to_cpu(sip[i + 1]);3240#else3241		dip[i] = be32_to_cpu(sip[i + 1]);3242		dip[i + 1] = be32_to_cpu(sip[i]);3243#endif3244	}3245}3246 3247static void3248__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)3249{3250	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;3251	struct bfa_cb_pending_q_s *cb;3252	struct list_head *qe, *qen;3253	union bfa_fcport_stats_u *ret;3254 3255	if (complete) {3256		time64_t time = ktime_get_seconds();3257 3258		list_for_each_safe(qe, qen, &fcport->stats_pending_q) {3259			bfa_q_deq(&fcport->stats_pending_q, &qe);3260			cb = (struct bfa_cb_pending_q_s *)qe;3261			if (fcport->stats_status == BFA_STATUS_OK) {3262				ret = (union bfa_fcport_stats_u *)cb->data;3263				/* Swap FC QoS or FCoE stats */3264				if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))3265					bfa_fcport_qos_stats_swap(&ret->fcqos,3266							&fcport->stats->fcqos);3267				else {3268					bfa_fcport_fcoe_stats_swap(&ret->fcoe,3269							&fcport->stats->fcoe);3270					ret->fcoe.secs_reset =3271						time - fcport->stats_reset_time;3272				}3273			}3274			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,3275					fcport->stats_status);3276		}3277		fcport->stats_status = BFA_STATUS_OK;3278	} else {3279		INIT_LIST_HEAD(&fcport->stats_pending_q);3280		fcport->stats_status = BFA_STATUS_OK;3281	}3282}3283 3284static void3285bfa_fcport_stats_get_timeout(void *cbarg)3286{3287	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;3288 3289	bfa_trc(fcport->bfa, fcport->stats_qfull);3290 3291	if (fcport->stats_qfull) {3292		bfa_reqq_wcancel(&fcport->stats_reqq_wait);3293		fcport->stats_qfull = BFA_FALSE;3294	}3295 3296	fcport->stats_status = BFA_STATUS_ETIMER;3297	__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);3298}3299 3300static void3301bfa_fcport_send_stats_get(void *cbarg)3302{3303	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;3304	struct bfi_fcport_req_s *msg;3305 3306	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);3307 3308	if (!msg) {3309		fcport->stats_qfull = BFA_TRUE;3310		bfa_reqq_winit(&fcport->stats_reqq_wait,3311				bfa_fcport_send_stats_get, fcport);3312		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,3313				&fcport->stats_reqq_wait);3314		return;3315	}3316	fcport->stats_qfull = BFA_FALSE;3317 3318	memset(msg, 0, sizeof(struct bfi_fcport_req_s));3319	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,3320			bfa_fn_lpu(fcport->bfa));3321	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);3322}3323 3324static void3325__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)3326{3327	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;3328	struct bfa_cb_pending_q_s *cb;3329	struct list_head *qe, *qen;3330 3331	if (complete) {3332		/*3333		 * re-initialize time stamp for stats reset3334		 */3335		fcport->stats_reset_time = ktime_get_seconds();3336		list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {3337			bfa_q_deq(&fcport->statsclr_pending_q, &qe);3338			cb = (struct bfa_cb_pending_q_s *)qe;3339			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,3340						fcport->stats_status);3341		}3342		fcport->stats_status = BFA_STATUS_OK;3343	} else {3344		INIT_LIST_HEAD(&fcport->statsclr_pending_q);3345		fcport->stats_status = BFA_STATUS_OK;3346	}3347}3348 3349static void3350bfa_fcport_stats_clr_timeout(void *cbarg)3351{3352	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;3353 3354	bfa_trc(fcport->bfa, fcport->stats_qfull);3355 3356	if (fcport->stats_qfull) {3357		bfa_reqq_wcancel(&fcport->stats_reqq_wait);3358		fcport->stats_qfull = BFA_FALSE;3359	}3360 3361	fcport->stats_status = BFA_STATUS_ETIMER;3362	__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);3363}3364 3365static void3366bfa_fcport_send_stats_clear(void *cbarg)3367{3368	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;3369	struct bfi_fcport_req_s *msg;3370 3371	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);3372 3373	if (!msg) {3374		fcport->stats_qfull = BFA_TRUE;3375		bfa_reqq_winit(&fcport->stats_reqq_wait,3376				bfa_fcport_send_stats_clear, fcport);3377		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,3378						&fcport->stats_reqq_wait);3379		return;3380	}3381	fcport->stats_qfull = BFA_FALSE;3382 3383	memset(msg, 0, sizeof(struct bfi_fcport_req_s));3384	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,3385			bfa_fn_lpu(fcport->bfa));3386	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);3387}3388 3389/*3390 * Handle trunk SCN event from firmware.3391 */3392static void3393bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)3394{3395	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;3396	struct bfi_fcport_trunk_link_s *tlink;3397	struct bfa_trunk_link_attr_s *lattr;3398	enum bfa_trunk_state state_prev;3399	int i;3400	int link_bm = 0;3401 3402	bfa_trc(fcport->bfa, fcport->cfg.trunked);3403	WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&3404		   scn->trunk_state != BFA_TRUNK_OFFLINE);3405 3406	bfa_trc(fcport->bfa, trunk->attr.state);3407	bfa_trc(fcport->bfa, scn->trunk_state);3408	bfa_trc(fcport->bfa, scn->trunk_speed);3409 3410	/*3411	 * Save off new state for trunk attribute query3412	 */3413	state_prev = trunk->attr.state;3414	if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))3415		trunk->attr.state = scn->trunk_state;3416	trunk->attr.speed = scn->trunk_speed;3417	for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {3418		lattr = &trunk->attr.link_attr[i];3419		tlink = &scn->tlink[i];3420 3421		lattr->link_state = tlink->state;3422		lattr->trunk_wwn  = tlink->trunk_wwn;3423		lattr->fctl	  = tlink->fctl;3424		lattr->speed	  = tlink->speed;3425		lattr->deskew	  = be32_to_cpu(tlink->deskew);3426 3427		if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {3428			fcport->speed	 = tlink->speed;3429			fcport->topology = BFA_PORT_TOPOLOGY_P2P;3430			link_bm |= 1 << i;3431		}3432 3433		bfa_trc(fcport->bfa, lattr->link_state);3434		bfa_trc(fcport->bfa, lattr->trunk_wwn);3435		bfa_trc(fcport->bfa, lattr->fctl);3436		bfa_trc(fcport->bfa, lattr->speed);3437		bfa_trc(fcport->bfa, lattr->deskew);3438	}3439 3440	switch (link_bm) {3441	case 3:3442		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,3443			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");3444		break;3445	case 2:3446		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,3447			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");3448		break;3449	case 1:3450		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,3451			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");3452		break;3453	default:3454		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,3455			BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");3456	}3457 3458	/*3459	 * Notify upper layers if trunk state changed.3460	 */3461	if ((state_prev != trunk->attr.state) ||3462		(scn->trunk_state == BFA_TRUNK_OFFLINE)) {3463		bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?3464			BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);3465	}3466}3467 3468static void3469bfa_trunk_iocdisable(struct bfa_s *bfa)3470{3471	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3472	int i = 0;3473 3474	/*3475	 * In trunked mode, notify upper layers that link is down3476	 */3477	if (fcport->cfg.trunked) {3478		if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)3479			bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);3480 3481		fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;3482		fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;3483		for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {3484			fcport->trunk.attr.link_attr[i].trunk_wwn = 0;3485			fcport->trunk.attr.link_attr[i].fctl =3486						BFA_TRUNK_LINK_FCTL_NORMAL;3487			fcport->trunk.attr.link_attr[i].link_state =3488						BFA_TRUNK_LINK_STATE_DN_LINKDN;3489			fcport->trunk.attr.link_attr[i].speed =3490						BFA_PORT_SPEED_UNKNOWN;3491			fcport->trunk.attr.link_attr[i].deskew = 0;3492		}3493	}3494}3495 3496/*3497 * Called to initialize port attributes3498 */3499void3500bfa_fcport_init(struct bfa_s *bfa)3501{3502	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3503 3504	/*3505	 * Initialize port attributes from IOC hardware data.3506	 */3507	bfa_fcport_set_wwns(fcport);3508	if (fcport->cfg.maxfrsize == 0)3509		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);3510	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);3511	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);3512 3513	if (bfa_fcport_is_pbcdisabled(bfa))3514		bfa->modules.port.pbc_disabled = BFA_TRUE;3515 3516	WARN_ON(!fcport->cfg.maxfrsize);3517	WARN_ON(!fcport->cfg.rx_bbcredit);3518	WARN_ON(!fcport->speed_sup);3519}3520 3521/*3522 * Firmware message handler.3523 */3524void3525bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)3526{3527	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3528	union bfi_fcport_i2h_msg_u i2hmsg;3529 3530	i2hmsg.msg = msg;3531	fcport->event_arg.i2hmsg = i2hmsg;3532 3533	bfa_trc(bfa, msg->mhdr.msg_id);3534	bfa_trc(bfa, bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm));3535 3536	switch (msg->mhdr.msg_id) {3537	case BFI_FCPORT_I2H_ENABLE_RSP:3538		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {3539 3540			fcport->stats_dma_ready = BFA_TRUE;3541			if (fcport->use_flash_cfg) {3542				fcport->cfg = i2hmsg.penable_rsp->port_cfg;3543				fcport->cfg.maxfrsize =3544					cpu_to_be16(fcport->cfg.maxfrsize);3545				fcport->cfg.path_tov =3546					cpu_to_be16(fcport->cfg.path_tov);3547				fcport->cfg.q_depth =3548					cpu_to_be16(fcport->cfg.q_depth);3549 3550				if (fcport->cfg.trunked)3551					fcport->trunk.attr.state =3552						BFA_TRUNK_OFFLINE;3553				else3554					fcport->trunk.attr.state =3555						BFA_TRUNK_DISABLED;3556				fcport->qos_attr.qos_bw =3557					i2hmsg.penable_rsp->port_cfg.qos_bw;3558				fcport->use_flash_cfg = BFA_FALSE;3559			}3560 3561			if (fcport->cfg.qos_enabled)3562				fcport->qos_attr.state = BFA_QOS_OFFLINE;3563			else3564				fcport->qos_attr.state = BFA_QOS_DISABLED;3565 3566			fcport->qos_attr.qos_bw_op =3567					i2hmsg.penable_rsp->port_cfg.qos_bw;3568 3569			if (fcport->cfg.bb_cr_enabled)3570				fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;3571			else3572				fcport->bbcr_attr.state = BFA_BBCR_DISABLED;3573 3574			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);3575		}3576		break;3577 3578	case BFI_FCPORT_I2H_DISABLE_RSP:3579		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)3580			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);3581		break;3582 3583	case BFI_FCPORT_I2H_EVENT:3584		if (fcport->cfg.bb_cr_enabled)3585			fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;3586		else3587			fcport->bbcr_attr.state = BFA_BBCR_DISABLED;3588 3589		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)3590			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);3591		else {3592			if (i2hmsg.event->link_state.linkstate_rsn ==3593			    BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)3594				bfa_sm_send_event(fcport,3595						  BFA_FCPORT_SM_FAA_MISCONFIG);3596			else3597				bfa_sm_send_event(fcport,3598						  BFA_FCPORT_SM_LINKDOWN);3599		}3600		fcport->qos_attr.qos_bw_op =3601				i2hmsg.event->link_state.qos_attr.qos_bw_op;3602		break;3603 3604	case BFI_FCPORT_I2H_TRUNK_SCN:3605		bfa_trunk_scn(fcport, i2hmsg.trunk_scn);3606		break;3607 3608	case BFI_FCPORT_I2H_STATS_GET_RSP:3609		/*3610		 * check for timer pop before processing the rsp3611		 */3612		if (list_empty(&fcport->stats_pending_q) ||3613		    (fcport->stats_status == BFA_STATUS_ETIMER))3614			break;3615 3616		bfa_timer_stop(&fcport->timer);3617		fcport->stats_status = i2hmsg.pstatsget_rsp->status;3618		__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);3619		break;3620 3621	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:3622		/*3623		 * check for timer pop before processing the rsp3624		 */3625		if (list_empty(&fcport->statsclr_pending_q) ||3626		    (fcport->stats_status == BFA_STATUS_ETIMER))3627			break;3628 3629		bfa_timer_stop(&fcport->timer);3630		fcport->stats_status = BFA_STATUS_OK;3631		__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);3632		break;3633 3634	case BFI_FCPORT_I2H_ENABLE_AEN:3635		bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);3636		break;3637 3638	case BFI_FCPORT_I2H_DISABLE_AEN:3639		bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);3640		break;3641 3642	default:3643		WARN_ON(1);3644	break;3645	}3646}3647 3648/*3649 * Registered callback for port events.3650 */3651void3652bfa_fcport_event_register(struct bfa_s *bfa,3653				void (*cbfn) (void *cbarg,3654				enum bfa_port_linkstate event),3655				void *cbarg)3656{3657	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3658 3659	fcport->event_cbfn = cbfn;3660	fcport->event_cbarg = cbarg;3661}3662 3663bfa_status_t3664bfa_fcport_enable(struct bfa_s *bfa)3665{3666	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3667 3668	if (bfa_fcport_is_pbcdisabled(bfa))3669		return BFA_STATUS_PBC;3670 3671	if (bfa_ioc_is_disabled(&bfa->ioc))3672		return BFA_STATUS_IOC_DISABLED;3673 3674	if (fcport->diag_busy)3675		return BFA_STATUS_DIAG_BUSY;3676 3677	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);3678	return BFA_STATUS_OK;3679}3680 3681bfa_status_t3682bfa_fcport_disable(struct bfa_s *bfa)3683{3684	if (bfa_fcport_is_pbcdisabled(bfa))3685		return BFA_STATUS_PBC;3686 3687	if (bfa_ioc_is_disabled(&bfa->ioc))3688		return BFA_STATUS_IOC_DISABLED;3689 3690	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);3691	return BFA_STATUS_OK;3692}3693 3694/* If PBC is disabled on port, return error */3695bfa_status_t3696bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)3697{3698	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3699	struct bfa_iocfc_s *iocfc = &bfa->iocfc;3700	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;3701 3702	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {3703		bfa_trc(bfa, fcport->pwwn);3704		return BFA_STATUS_PBC;3705	}3706	return BFA_STATUS_OK;3707}3708 3709/*3710 * Configure port speed.3711 */3712bfa_status_t3713bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)3714{3715	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3716 3717	bfa_trc(bfa, speed);3718 3719	if (fcport->cfg.trunked == BFA_TRUE)3720		return BFA_STATUS_TRUNK_ENABLED;3721	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&3722			(speed == BFA_PORT_SPEED_16GBPS))3723		return BFA_STATUS_UNSUPP_SPEED;3724	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {3725		bfa_trc(bfa, fcport->speed_sup);3726		return BFA_STATUS_UNSUPP_SPEED;3727	}3728 3729	/* Port speed entered needs to be checked */3730	if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {3731		/* For CT2, 1G is not supported */3732		if ((speed == BFA_PORT_SPEED_1GBPS) &&3733		    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))3734			return BFA_STATUS_UNSUPP_SPEED;3735 3736		/* Already checked for Auto Speed and Max Speed supp */3737		if (!(speed == BFA_PORT_SPEED_1GBPS ||3738		      speed == BFA_PORT_SPEED_2GBPS ||3739		      speed == BFA_PORT_SPEED_4GBPS ||3740		      speed == BFA_PORT_SPEED_8GBPS ||3741		      speed == BFA_PORT_SPEED_16GBPS ||3742		      speed == BFA_PORT_SPEED_AUTO))3743			return BFA_STATUS_UNSUPP_SPEED;3744	} else {3745		if (speed != BFA_PORT_SPEED_10GBPS)3746			return BFA_STATUS_UNSUPP_SPEED;3747	}3748 3749	fcport->cfg.speed = speed;3750 3751	return BFA_STATUS_OK;3752}3753 3754/*3755 * Get current speed.3756 */3757enum bfa_port_speed3758bfa_fcport_get_speed(struct bfa_s *bfa)3759{3760	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3761 3762	return fcport->speed;3763}3764 3765/*3766 * Configure port topology.3767 */3768bfa_status_t3769bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)3770{3771	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3772 3773	bfa_trc(bfa, topology);3774	bfa_trc(bfa, fcport->cfg.topology);3775 3776	switch (topology) {3777	case BFA_PORT_TOPOLOGY_P2P:3778		break;3779 3780	case BFA_PORT_TOPOLOGY_LOOP:3781		if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||3782			(fcport->qos_attr.state != BFA_QOS_DISABLED))3783			return BFA_STATUS_ERROR_QOS_ENABLED;3784		if (fcport->cfg.ratelimit != BFA_FALSE)3785			return BFA_STATUS_ERROR_TRL_ENABLED;3786		if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||3787			(fcport->trunk.attr.state != BFA_TRUNK_DISABLED))3788			return BFA_STATUS_ERROR_TRUNK_ENABLED;3789		if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||3790			(fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))3791			return BFA_STATUS_UNSUPP_SPEED;3792		if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))3793			return BFA_STATUS_LOOP_UNSUPP_MEZZ;3794		if (bfa_fcport_is_dport(bfa) != BFA_FALSE)3795			return BFA_STATUS_DPORT_ERR;3796		if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)3797			return BFA_STATUS_DPORT_ERR;3798		break;3799 3800	case BFA_PORT_TOPOLOGY_AUTO:3801		break;3802 3803	default:3804		return BFA_STATUS_EINVAL;3805	}3806 3807	fcport->cfg.topology = topology;3808	return BFA_STATUS_OK;3809}3810 3811/*3812 * Get current topology.3813 */3814enum bfa_port_topology3815bfa_fcport_get_topology(struct bfa_s *bfa)3816{3817	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3818 3819	return fcport->topology;3820}3821 3822/*3823 * Get config topology.3824 */3825enum bfa_port_topology3826bfa_fcport_get_cfg_topology(struct bfa_s *bfa)3827{3828	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3829 3830	return fcport->cfg.topology;3831}3832 3833bfa_status_t3834bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)3835{3836	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3837 3838	bfa_trc(bfa, alpa);3839	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);3840	bfa_trc(bfa, fcport->cfg.hardalpa);3841 3842	fcport->cfg.cfg_hardalpa = BFA_TRUE;3843	fcport->cfg.hardalpa = alpa;3844 3845	return BFA_STATUS_OK;3846}3847 3848bfa_status_t3849bfa_fcport_clr_hardalpa(struct bfa_s *bfa)3850{3851	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3852 3853	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);3854	bfa_trc(bfa, fcport->cfg.hardalpa);3855 3856	fcport->cfg.cfg_hardalpa = BFA_FALSE;3857	return BFA_STATUS_OK;3858}3859 3860bfa_boolean_t3861bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)3862{3863	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3864 3865	*alpa = fcport->cfg.hardalpa;3866	return fcport->cfg.cfg_hardalpa;3867}3868 3869u83870bfa_fcport_get_myalpa(struct bfa_s *bfa)3871{3872	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3873 3874	return fcport->myalpa;3875}3876 3877bfa_status_t3878bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)3879{3880	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3881 3882	bfa_trc(bfa, maxfrsize);3883	bfa_trc(bfa, fcport->cfg.maxfrsize);3884 3885	/* with in range */3886	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))3887		return BFA_STATUS_INVLD_DFSZ;3888 3889	/* power of 2, if not the max frame size of 2112 */3890	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))3891		return BFA_STATUS_INVLD_DFSZ;3892 3893	fcport->cfg.maxfrsize = maxfrsize;3894	return BFA_STATUS_OK;3895}3896 3897u163898bfa_fcport_get_maxfrsize(struct bfa_s *bfa)3899{3900	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3901 3902	return fcport->cfg.maxfrsize;3903}3904 3905u83906bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)3907{3908	if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)3909		return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;3910 3911	else3912		return 0;3913}3914 3915void3916bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)3917{3918	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3919 3920	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;3921}3922 3923/*3924 * Get port attributes.3925 */3926 3927wwn_t3928bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)3929{3930	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3931	if (node)3932		return fcport->nwwn;3933	else3934		return fcport->pwwn;3935}3936 3937void3938bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)3939{3940	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3941 3942	memset(attr, 0, sizeof(struct bfa_port_attr_s));3943 3944	attr->nwwn = fcport->nwwn;3945	attr->pwwn = fcport->pwwn;3946 3947	attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;3948	attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;3949 3950	memcpy(&attr->pport_cfg, &fcport->cfg,3951		sizeof(struct bfa_port_cfg_s));3952	/* speed attributes */3953	attr->pport_cfg.speed = fcport->cfg.speed;3954	attr->speed_supported = fcport->speed_sup;3955	attr->speed = fcport->speed;3956	attr->cos_supported = FC_CLASS_3;3957 3958	/* topology attributes */3959	attr->pport_cfg.topology = fcport->cfg.topology;3960	attr->topology = fcport->topology;3961	attr->pport_cfg.trunked = fcport->cfg.trunked;3962 3963	/* beacon attributes */3964	attr->beacon = fcport->beacon;3965	attr->link_e2e_beacon = fcport->link_e2e_beacon;3966 3967	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);3968	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);3969	attr->port_state = bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm);3970 3971	attr->fec_state = fcport->fec_state;3972 3973	/* PBC Disabled State */3974	if (bfa_fcport_is_pbcdisabled(bfa))3975		attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;3976	else {3977		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))3978			attr->port_state = BFA_PORT_ST_IOCDIS;3979		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))3980			attr->port_state = BFA_PORT_ST_FWMISMATCH;3981	}3982 3983	/* FCoE vlan */3984	attr->fcoe_vlan = fcport->fcoe_vlan;3985}3986 3987#define BFA_FCPORT_STATS_TOV	10003988 3989/*3990 * Fetch port statistics (FCQoS or FCoE).3991 */3992bfa_status_t3993bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)3994{3995	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);3996 3997	if (!bfa_iocfc_is_operational(bfa) ||3998	    !fcport->stats_dma_ready)3999		return BFA_STATUS_IOC_NON_OP;4000 4001	if (!list_empty(&fcport->statsclr_pending_q))4002		return BFA_STATUS_DEVBUSY;4003 4004	if (list_empty(&fcport->stats_pending_q)) {4005		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);4006		bfa_fcport_send_stats_get(fcport);4007		bfa_timer_start(bfa, &fcport->timer,4008				bfa_fcport_stats_get_timeout,4009				fcport, BFA_FCPORT_STATS_TOV);4010	} else4011		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);4012 4013	return BFA_STATUS_OK;4014}4015 4016/*4017 * Reset port statistics (FCQoS or FCoE).4018 */4019bfa_status_t4020bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)4021{4022	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4023 4024	if (!bfa_iocfc_is_operational(bfa) ||4025	    !fcport->stats_dma_ready)4026		return BFA_STATUS_IOC_NON_OP;4027 4028	if (!list_empty(&fcport->stats_pending_q))4029		return BFA_STATUS_DEVBUSY;4030 4031	if (list_empty(&fcport->statsclr_pending_q)) {4032		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);4033		bfa_fcport_send_stats_clear(fcport);4034		bfa_timer_start(bfa, &fcport->timer,4035				bfa_fcport_stats_clr_timeout,4036				fcport, BFA_FCPORT_STATS_TOV);4037	} else4038		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);4039 4040	return BFA_STATUS_OK;4041}4042 4043/*4044 * Fetch port attributes.4045 */4046bfa_boolean_t4047bfa_fcport_is_disabled(struct bfa_s *bfa)4048{4049	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4050 4051	return bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm) ==4052		BFA_PORT_ST_DISABLED;4053 4054}4055 4056bfa_boolean_t4057bfa_fcport_is_dport(struct bfa_s *bfa)4058{4059	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4060 4061	return (bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm) ==4062		BFA_PORT_ST_DPORT);4063}4064 4065bfa_boolean_t4066bfa_fcport_is_ddport(struct bfa_s *bfa)4067{4068	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4069 4070	return (bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm) ==4071		BFA_PORT_ST_DDPORT);4072}4073 4074bfa_status_t4075bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)4076{4077	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4078	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);4079 4080	bfa_trc(bfa, ioc_type);4081 4082	if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))4083		return BFA_STATUS_QOS_BW_INVALID;4084 4085	if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)4086		return BFA_STATUS_QOS_BW_INVALID;4087 4088	if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||4089	    (qos_bw->low > qos_bw->high))4090		return BFA_STATUS_QOS_BW_INVALID;4091 4092	if ((ioc_type == BFA_IOC_TYPE_FC) &&4093	    (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))4094		fcport->cfg.qos_bw = *qos_bw;4095 4096	return BFA_STATUS_OK;4097}4098 4099bfa_boolean_t4100bfa_fcport_is_ratelim(struct bfa_s *bfa)4101{4102	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4103 4104	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;4105 4106}4107 4108/*4109 *	Enable/Disable FAA feature in port config4110 */4111void4112bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)4113{4114	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4115 4116	bfa_trc(bfa, state);4117	fcport->cfg.faa_state = state;4118}4119 4120/*4121 * Get default minimum ratelim speed4122 */4123enum bfa_port_speed4124bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)4125{4126	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4127 4128	bfa_trc(bfa, fcport->cfg.trl_def_speed);4129	return fcport->cfg.trl_def_speed;4130 4131}4132 4133void4134bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,4135		  bfa_boolean_t link_e2e_beacon)4136{4137	struct bfa_s *bfa = dev;4138	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4139 4140	bfa_trc(bfa, beacon);4141	bfa_trc(bfa, link_e2e_beacon);4142	bfa_trc(bfa, fcport->beacon);4143	bfa_trc(bfa, fcport->link_e2e_beacon);4144 4145	fcport->beacon = beacon;4146	fcport->link_e2e_beacon = link_e2e_beacon;4147}4148 4149bfa_boolean_t4150bfa_fcport_is_linkup(struct bfa_s *bfa)4151{4152	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4153 4154	return	(!fcport->cfg.trunked &&4155		 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||4156		(fcport->cfg.trunked &&4157		 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);4158}4159 4160bfa_boolean_t4161bfa_fcport_is_qos_enabled(struct bfa_s *bfa)4162{4163	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4164 4165	return fcport->cfg.qos_enabled;4166}4167 4168bfa_boolean_t4169bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)4170{4171	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4172 4173	return fcport->cfg.trunked;4174}4175 4176bfa_status_t4177bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)4178{4179	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4180 4181	bfa_trc(bfa, on_off);4182 4183	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)4184		return BFA_STATUS_BBCR_FC_ONLY;4185 4186	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&4187		(bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))4188		return BFA_STATUS_CMD_NOTSUPP_MEZZ;4189 4190	if (on_off) {4191		if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)4192			return BFA_STATUS_TOPOLOGY_LOOP;4193 4194		if (fcport->cfg.qos_enabled)4195			return BFA_STATUS_ERROR_QOS_ENABLED;4196 4197		if (fcport->cfg.trunked)4198			return BFA_STATUS_TRUNK_ENABLED;4199 4200		if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&4201			(fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))4202			return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;4203 4204		if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)4205			return BFA_STATUS_FEATURE_NOT_SUPPORTED;4206 4207		if (fcport->cfg.bb_cr_enabled) {4208			if (bb_scn != fcport->cfg.bb_scn)4209				return BFA_STATUS_BBCR_CFG_NO_CHANGE;4210			else4211				return BFA_STATUS_NO_CHANGE;4212		}4213 4214		if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))4215			bb_scn = BFA_BB_SCN_DEF;4216 4217		fcport->cfg.bb_cr_enabled = on_off;4218		fcport->cfg.bb_scn = bb_scn;4219	} else {4220		if (!fcport->cfg.bb_cr_enabled)4221			return BFA_STATUS_NO_CHANGE;4222 4223		fcport->cfg.bb_cr_enabled = on_off;4224		fcport->cfg.bb_scn = 0;4225	}4226 4227	return BFA_STATUS_OK;4228}4229 4230bfa_status_t4231bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,4232		struct bfa_bbcr_attr_s *bbcr_attr)4233{4234	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);4235 4236	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)4237		return BFA_STATUS_BBCR_FC_ONLY;4238 4239	if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)4240		return BFA_STATUS_TOPOLOGY_LOOP;4241 4242	*bbcr_attr = fcport->bbcr_attr;4243 4244	return BFA_STATUS_OK;4245}4246 4247void4248bfa_fcport_dportenable(struct bfa_s *bfa)4249{4250	/*4251	 * Assume caller check for port is in disable state4252	 */4253	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);4254	bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);4255}4256 4257void4258bfa_fcport_dportdisable(struct bfa_s *bfa)4259{4260	/*4261	 * Assume caller check for port is in disable state4262	 */4263	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);4264	bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);4265}4266 4267static void4268bfa_fcport_ddportenable(struct bfa_s *bfa)4269{4270	/*4271	 * Assume caller check for port is in disable state4272	 */4273	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);4274}4275 4276static void4277bfa_fcport_ddportdisable(struct bfa_s *bfa)4278{4279	/*4280	 * Assume caller check for port is in disable state4281	 */4282	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);4283}4284 4285/*4286 * Rport State machine functions4287 */4288/*4289 * Beginning state, only online event expected.4290 */4291static void4292bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)4293{4294	bfa_trc(rp->bfa, rp->rport_tag);4295	bfa_trc(rp->bfa, event);4296 4297	switch (event) {4298	case BFA_RPORT_SM_CREATE:4299		bfa_stats(rp, sm_un_cr);4300		bfa_sm_set_state(rp, bfa_rport_sm_created);4301		break;4302 4303	default:4304		bfa_stats(rp, sm_un_unexp);4305		bfa_sm_fault(rp->bfa, event);4306	}4307}4308 4309static void4310bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)4311{4312	bfa_trc(rp->bfa, rp->rport_tag);4313	bfa_trc(rp->bfa, event);4314 4315	switch (event) {4316	case BFA_RPORT_SM_ONLINE:4317		bfa_stats(rp, sm_cr_on);4318		if (bfa_rport_send_fwcreate(rp))4319			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);4320		else4321			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);4322		break;4323 4324	case BFA_RPORT_SM_DELETE:4325		bfa_stats(rp, sm_cr_del);4326		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4327		bfa_rport_free(rp);4328		break;4329 4330	case BFA_RPORT_SM_HWFAIL:4331		bfa_stats(rp, sm_cr_hwf);4332		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4333		break;4334 4335	default:4336		bfa_stats(rp, sm_cr_unexp);4337		bfa_sm_fault(rp->bfa, event);4338	}4339}4340 4341/*4342 * Waiting for rport create response from firmware.4343 */4344static void4345bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)4346{4347	bfa_trc(rp->bfa, rp->rport_tag);4348	bfa_trc(rp->bfa, event);4349 4350	switch (event) {4351	case BFA_RPORT_SM_FWRSP:4352		bfa_stats(rp, sm_fwc_rsp);4353		bfa_sm_set_state(rp, bfa_rport_sm_online);4354		bfa_rport_online_cb(rp);4355		break;4356 4357	case BFA_RPORT_SM_DELETE:4358		bfa_stats(rp, sm_fwc_del);4359		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);4360		break;4361 4362	case BFA_RPORT_SM_OFFLINE:4363		bfa_stats(rp, sm_fwc_off);4364		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);4365		break;4366 4367	case BFA_RPORT_SM_HWFAIL:4368		bfa_stats(rp, sm_fwc_hwf);4369		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4370		break;4371 4372	default:4373		bfa_stats(rp, sm_fwc_unexp);4374		bfa_sm_fault(rp->bfa, event);4375	}4376}4377 4378/*4379 * Request queue is full, awaiting queue resume to send create request.4380 */4381static void4382bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)4383{4384	bfa_trc(rp->bfa, rp->rport_tag);4385	bfa_trc(rp->bfa, event);4386 4387	switch (event) {4388	case BFA_RPORT_SM_QRESUME:4389		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);4390		bfa_rport_send_fwcreate(rp);4391		break;4392 4393	case BFA_RPORT_SM_DELETE:4394		bfa_stats(rp, sm_fwc_del);4395		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4396		bfa_reqq_wcancel(&rp->reqq_wait);4397		bfa_rport_free(rp);4398		break;4399 4400	case BFA_RPORT_SM_OFFLINE:4401		bfa_stats(rp, sm_fwc_off);4402		bfa_sm_set_state(rp, bfa_rport_sm_offline);4403		bfa_reqq_wcancel(&rp->reqq_wait);4404		bfa_rport_offline_cb(rp);4405		break;4406 4407	case BFA_RPORT_SM_HWFAIL:4408		bfa_stats(rp, sm_fwc_hwf);4409		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4410		bfa_reqq_wcancel(&rp->reqq_wait);4411		break;4412 4413	default:4414		bfa_stats(rp, sm_fwc_unexp);4415		bfa_sm_fault(rp->bfa, event);4416	}4417}4418 4419/*4420 * Online state - normal parking state.4421 */4422static void4423bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)4424{4425	struct bfi_rport_qos_scn_s *qos_scn;4426 4427	bfa_trc(rp->bfa, rp->rport_tag);4428	bfa_trc(rp->bfa, event);4429 4430	switch (event) {4431	case BFA_RPORT_SM_OFFLINE:4432		bfa_stats(rp, sm_on_off);4433		if (bfa_rport_send_fwdelete(rp))4434			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);4435		else4436			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);4437		break;4438 4439	case BFA_RPORT_SM_DELETE:4440		bfa_stats(rp, sm_on_del);4441		if (bfa_rport_send_fwdelete(rp))4442			bfa_sm_set_state(rp, bfa_rport_sm_deleting);4443		else4444			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);4445		break;4446 4447	case BFA_RPORT_SM_HWFAIL:4448		bfa_stats(rp, sm_on_hwf);4449		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4450		break;4451 4452	case BFA_RPORT_SM_SET_SPEED:4453		bfa_rport_send_fwspeed(rp);4454		break;4455 4456	case BFA_RPORT_SM_QOS_SCN:4457		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;4458		rp->qos_attr = qos_scn->new_qos_attr;4459		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);4460		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);4461		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);4462		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);4463 4464		qos_scn->old_qos_attr.qos_flow_id  =4465			be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);4466		qos_scn->new_qos_attr.qos_flow_id  =4467			be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);4468 4469		if (qos_scn->old_qos_attr.qos_flow_id !=4470			qos_scn->new_qos_attr.qos_flow_id)4471			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,4472						    qos_scn->old_qos_attr,4473						    qos_scn->new_qos_attr);4474		if (qos_scn->old_qos_attr.qos_priority !=4475			qos_scn->new_qos_attr.qos_priority)4476			bfa_cb_rport_qos_scn_prio(rp->rport_drv,4477						  qos_scn->old_qos_attr,4478						  qos_scn->new_qos_attr);4479		break;4480 4481	default:4482		bfa_stats(rp, sm_on_unexp);4483		bfa_sm_fault(rp->bfa, event);4484	}4485}4486 4487/*4488 * Firmware rport is being deleted - awaiting f/w response.4489 */4490static void4491bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)4492{4493	bfa_trc(rp->bfa, rp->rport_tag);4494	bfa_trc(rp->bfa, event);4495 4496	switch (event) {4497	case BFA_RPORT_SM_FWRSP:4498		bfa_stats(rp, sm_fwd_rsp);4499		bfa_sm_set_state(rp, bfa_rport_sm_offline);4500		bfa_rport_offline_cb(rp);4501		break;4502 4503	case BFA_RPORT_SM_DELETE:4504		bfa_stats(rp, sm_fwd_del);4505		bfa_sm_set_state(rp, bfa_rport_sm_deleting);4506		break;4507 4508	case BFA_RPORT_SM_HWFAIL:4509		bfa_stats(rp, sm_fwd_hwf);4510		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4511		bfa_rport_offline_cb(rp);4512		break;4513 4514	default:4515		bfa_stats(rp, sm_fwd_unexp);4516		bfa_sm_fault(rp->bfa, event);4517	}4518}4519 4520static void4521bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)4522{4523	bfa_trc(rp->bfa, rp->rport_tag);4524	bfa_trc(rp->bfa, event);4525 4526	switch (event) {4527	case BFA_RPORT_SM_QRESUME:4528		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);4529		bfa_rport_send_fwdelete(rp);4530		break;4531 4532	case BFA_RPORT_SM_DELETE:4533		bfa_stats(rp, sm_fwd_del);4534		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);4535		break;4536 4537	case BFA_RPORT_SM_HWFAIL:4538		bfa_stats(rp, sm_fwd_hwf);4539		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4540		bfa_reqq_wcancel(&rp->reqq_wait);4541		bfa_rport_offline_cb(rp);4542		break;4543 4544	default:4545		bfa_stats(rp, sm_fwd_unexp);4546		bfa_sm_fault(rp->bfa, event);4547	}4548}4549 4550/*4551 * Offline state.4552 */4553static void4554bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)4555{4556	bfa_trc(rp->bfa, rp->rport_tag);4557	bfa_trc(rp->bfa, event);4558 4559	switch (event) {4560	case BFA_RPORT_SM_DELETE:4561		bfa_stats(rp, sm_off_del);4562		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4563		bfa_rport_free(rp);4564		break;4565 4566	case BFA_RPORT_SM_ONLINE:4567		bfa_stats(rp, sm_off_on);4568		if (bfa_rport_send_fwcreate(rp))4569			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);4570		else4571			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);4572		break;4573 4574	case BFA_RPORT_SM_HWFAIL:4575		bfa_stats(rp, sm_off_hwf);4576		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4577		break;4578 4579	case BFA_RPORT_SM_OFFLINE:4580		bfa_rport_offline_cb(rp);4581		break;4582 4583	default:4584		bfa_stats(rp, sm_off_unexp);4585		bfa_sm_fault(rp->bfa, event);4586	}4587}4588 4589/*4590 * Rport is deleted, waiting for firmware response to delete.4591 */4592static void4593bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)4594{4595	bfa_trc(rp->bfa, rp->rport_tag);4596	bfa_trc(rp->bfa, event);4597 4598	switch (event) {4599	case BFA_RPORT_SM_FWRSP:4600		bfa_stats(rp, sm_del_fwrsp);4601		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4602		bfa_rport_free(rp);4603		break;4604 4605	case BFA_RPORT_SM_HWFAIL:4606		bfa_stats(rp, sm_del_hwf);4607		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4608		bfa_rport_free(rp);4609		break;4610 4611	default:4612		bfa_sm_fault(rp->bfa, event);4613	}4614}4615 4616static void4617bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)4618{4619	bfa_trc(rp->bfa, rp->rport_tag);4620	bfa_trc(rp->bfa, event);4621 4622	switch (event) {4623	case BFA_RPORT_SM_QRESUME:4624		bfa_stats(rp, sm_del_fwrsp);4625		bfa_sm_set_state(rp, bfa_rport_sm_deleting);4626		bfa_rport_send_fwdelete(rp);4627		break;4628 4629	case BFA_RPORT_SM_HWFAIL:4630		bfa_stats(rp, sm_del_hwf);4631		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4632		bfa_reqq_wcancel(&rp->reqq_wait);4633		bfa_rport_free(rp);4634		break;4635 4636	default:4637		bfa_sm_fault(rp->bfa, event);4638	}4639}4640 4641/*4642 * Waiting for rport create response from firmware. A delete is pending.4643 */4644static void4645bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,4646				enum bfa_rport_event event)4647{4648	bfa_trc(rp->bfa, rp->rport_tag);4649	bfa_trc(rp->bfa, event);4650 4651	switch (event) {4652	case BFA_RPORT_SM_FWRSP:4653		bfa_stats(rp, sm_delp_fwrsp);4654		if (bfa_rport_send_fwdelete(rp))4655			bfa_sm_set_state(rp, bfa_rport_sm_deleting);4656		else4657			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);4658		break;4659 4660	case BFA_RPORT_SM_HWFAIL:4661		bfa_stats(rp, sm_delp_hwf);4662		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4663		bfa_rport_free(rp);4664		break;4665 4666	default:4667		bfa_stats(rp, sm_delp_unexp);4668		bfa_sm_fault(rp->bfa, event);4669	}4670}4671 4672/*4673 * Waiting for rport create response from firmware. Rport offline is pending.4674 */4675static void4676bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,4677				 enum bfa_rport_event event)4678{4679	bfa_trc(rp->bfa, rp->rport_tag);4680	bfa_trc(rp->bfa, event);4681 4682	switch (event) {4683	case BFA_RPORT_SM_FWRSP:4684		bfa_stats(rp, sm_offp_fwrsp);4685		if (bfa_rport_send_fwdelete(rp))4686			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);4687		else4688			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);4689		break;4690 4691	case BFA_RPORT_SM_DELETE:4692		bfa_stats(rp, sm_offp_del);4693		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);4694		break;4695 4696	case BFA_RPORT_SM_HWFAIL:4697		bfa_stats(rp, sm_offp_hwf);4698		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);4699		bfa_rport_offline_cb(rp);4700		break;4701 4702	default:4703		bfa_stats(rp, sm_offp_unexp);4704		bfa_sm_fault(rp->bfa, event);4705	}4706}4707 4708/*4709 * IOC h/w failed.4710 */4711static void4712bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)4713{4714	bfa_trc(rp->bfa, rp->rport_tag);4715	bfa_trc(rp->bfa, event);4716 4717	switch (event) {4718	case BFA_RPORT_SM_OFFLINE:4719		bfa_stats(rp, sm_iocd_off);4720		bfa_rport_offline_cb(rp);4721		break;4722 4723	case BFA_RPORT_SM_DELETE:4724		bfa_stats(rp, sm_iocd_del);4725		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4726		bfa_rport_free(rp);4727		break;4728 4729	case BFA_RPORT_SM_ONLINE:4730		bfa_stats(rp, sm_iocd_on);4731		if (bfa_rport_send_fwcreate(rp))4732			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);4733		else4734			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);4735		break;4736 4737	case BFA_RPORT_SM_HWFAIL:4738		break;4739 4740	default:4741		bfa_stats(rp, sm_iocd_unexp);4742		bfa_sm_fault(rp->bfa, event);4743	}4744}4745 4746 4747 4748/*4749 *  bfa_rport_private BFA rport private functions4750 */4751 4752static void4753__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)4754{4755	struct bfa_rport_s *rp = cbarg;4756 4757	if (complete)4758		bfa_cb_rport_online(rp->rport_drv);4759}4760 4761static void4762__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)4763{4764	struct bfa_rport_s *rp = cbarg;4765 4766	if (complete)4767		bfa_cb_rport_offline(rp->rport_drv);4768}4769 4770static void4771bfa_rport_qresume(void *cbarg)4772{4773	struct bfa_rport_s	*rp = cbarg;4774 4775	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);4776}4777 4778void4779bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,4780		struct bfa_s *bfa)4781{4782	struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);4783 4784	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)4785		cfg->fwcfg.num_rports = BFA_RPORT_MIN;4786 4787	/* kva memory */4788	bfa_mem_kva_setup(minfo, rport_kva,4789		cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));4790}4791 4792void4793bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,4794		struct bfa_pcidev_s *pcidev)4795{4796	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);4797	struct bfa_rport_s *rp;4798	u16 i;4799 4800	INIT_LIST_HEAD(&mod->rp_free_q);4801	INIT_LIST_HEAD(&mod->rp_active_q);4802	INIT_LIST_HEAD(&mod->rp_unused_q);4803 4804	rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);4805	mod->rps_list = rp;4806	mod->num_rports = cfg->fwcfg.num_rports;4807 4808	WARN_ON(!mod->num_rports ||4809		   (mod->num_rports & (mod->num_rports - 1)));4810 4811	for (i = 0; i < mod->num_rports; i++, rp++) {4812		memset(rp, 0, sizeof(struct bfa_rport_s));4813		rp->bfa = bfa;4814		rp->rport_tag = i;4815		bfa_sm_set_state(rp, bfa_rport_sm_uninit);4816 4817		/*4818		 *  - is unused4819		 */4820		if (i)4821			list_add_tail(&rp->qe, &mod->rp_free_q);4822 4823		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);4824	}4825 4826	/*4827	 * consume memory4828	 */4829	bfa_mem_kva_curp(mod) = (u8 *) rp;4830}4831 4832void4833bfa_rport_iocdisable(struct bfa_s *bfa)4834{4835	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);4836	struct bfa_rport_s *rport;4837	struct list_head *qe, *qen;4838 4839	/* Enqueue unused rport resources to free_q */4840	list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);4841 4842	list_for_each_safe(qe, qen, &mod->rp_active_q) {4843		rport = (struct bfa_rport_s *) qe;4844		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);4845	}4846}4847 4848static struct bfa_rport_s *4849bfa_rport_alloc(struct bfa_rport_mod_s *mod)4850{4851	struct bfa_rport_s *rport;4852 4853	bfa_q_deq(&mod->rp_free_q, &rport);4854	if (rport)4855		list_add_tail(&rport->qe, &mod->rp_active_q);4856 4857	return rport;4858}4859 4860static void4861bfa_rport_free(struct bfa_rport_s *rport)4862{4863	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);4864 4865	WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));4866	list_del(&rport->qe);4867	list_add_tail(&rport->qe, &mod->rp_free_q);4868}4869 4870static bfa_boolean_t4871bfa_rport_send_fwcreate(struct bfa_rport_s *rp)4872{4873	struct bfi_rport_create_req_s *m;4874 4875	/*4876	 * check for room in queue to send request now4877	 */4878	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);4879	if (!m) {4880		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);4881		return BFA_FALSE;4882	}4883 4884	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,4885			bfa_fn_lpu(rp->bfa));4886	m->bfa_handle = rp->rport_tag;4887	m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);4888	m->pid = rp->rport_info.pid;4889	m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);4890	m->local_pid = rp->rport_info.local_pid;4891	m->fc_class = rp->rport_info.fc_class;4892	m->vf_en = rp->rport_info.vf_en;4893	m->vf_id = rp->rport_info.vf_id;4894	m->cisc = rp->rport_info.cisc;4895 4896	/*4897	 * queue I/O message to firmware4898	 */4899	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);4900	return BFA_TRUE;4901}4902 4903static bfa_boolean_t4904bfa_rport_send_fwdelete(struct bfa_rport_s *rp)4905{4906	struct bfi_rport_delete_req_s *m;4907 4908	/*4909	 * check for room in queue to send request now4910	 */4911	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);4912	if (!m) {4913		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);4914		return BFA_FALSE;4915	}4916 4917	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,4918			bfa_fn_lpu(rp->bfa));4919	m->fw_handle = rp->fw_handle;4920 4921	/*4922	 * queue I/O message to firmware4923	 */4924	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);4925	return BFA_TRUE;4926}4927 4928static bfa_boolean_t4929bfa_rport_send_fwspeed(struct bfa_rport_s *rp)4930{4931	struct bfa_rport_speed_req_s *m;4932 4933	/*4934	 * check for room in queue to send request now4935	 */4936	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);4937	if (!m) {4938		bfa_trc(rp->bfa, rp->rport_info.speed);4939		return BFA_FALSE;4940	}4941 4942	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,4943			bfa_fn_lpu(rp->bfa));4944	m->fw_handle = rp->fw_handle;4945	m->speed = (u8)rp->rport_info.speed;4946 4947	/*4948	 * queue I/O message to firmware4949	 */4950	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);4951	return BFA_TRUE;4952}4953 4954 4955 4956/*4957 *  bfa_rport_public4958 */4959 4960/*4961 * Rport interrupt processing.4962 */4963void4964bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)4965{4966	union bfi_rport_i2h_msg_u msg;4967	struct bfa_rport_s *rp;4968 4969	bfa_trc(bfa, m->mhdr.msg_id);4970 4971	msg.msg = m;4972 4973	switch (m->mhdr.msg_id) {4974	case BFI_RPORT_I2H_CREATE_RSP:4975		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);4976		rp->fw_handle = msg.create_rsp->fw_handle;4977		rp->qos_attr = msg.create_rsp->qos_attr;4978		bfa_rport_set_lunmask(bfa, rp);4979		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);4980		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);4981		break;4982 4983	case BFI_RPORT_I2H_DELETE_RSP:4984		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);4985		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);4986		bfa_rport_unset_lunmask(bfa, rp);4987		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);4988		break;4989 4990	case BFI_RPORT_I2H_QOS_SCN:4991		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);4992		rp->event_arg.fw_msg = msg.qos_scn_evt;4993		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);4994		break;4995 4996	case BFI_RPORT_I2H_LIP_SCN_ONLINE:4997		bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),4998				&msg.lip_scn->loop_info);4999		bfa_cb_rport_scn_online(bfa);5000		break;5001 5002	case BFI_RPORT_I2H_LIP_SCN_OFFLINE:5003		bfa_cb_rport_scn_offline(bfa);5004		break;5005 5006	case BFI_RPORT_I2H_NO_DEV:5007		rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);5008		bfa_cb_rport_scn_no_dev(rp->rport_drv);5009		break;5010 5011	default:5012		bfa_trc(bfa, m->mhdr.msg_id);5013		WARN_ON(1);5014	}5015}5016 5017void5018bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)5019{5020	struct bfa_rport_mod_s	*mod = BFA_RPORT_MOD(bfa);5021	struct list_head	*qe;5022	int	i;5023 5024	for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {5025		bfa_q_deq_tail(&mod->rp_free_q, &qe);5026		list_add_tail(qe, &mod->rp_unused_q);5027	}5028}5029 5030/*5031 *  bfa_rport_api5032 */5033 5034struct bfa_rport_s *5035bfa_rport_create(struct bfa_s *bfa, void *rport_drv)5036{5037	struct bfa_rport_s *rp;5038 5039	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));5040 5041	if (rp == NULL)5042		return NULL;5043 5044	rp->bfa = bfa;5045	rp->rport_drv = rport_drv;5046	memset(&rp->stats, 0, sizeof(rp->stats));5047 5048	WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));5049	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);5050 5051	return rp;5052}5053 5054void5055bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)5056{5057	WARN_ON(rport_info->max_frmsz == 0);5058 5059	/*5060	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI5061	 * responses. Default to minimum size.5062	 */5063	if (rport_info->max_frmsz == 0) {5064		bfa_trc(rport->bfa, rport->rport_tag);5065		rport_info->max_frmsz = FC_MIN_PDUSZ;5066	}5067 5068	rport->rport_info = *rport_info;5069	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);5070}5071 5072void5073bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)5074{5075	WARN_ON(speed == 0);5076	WARN_ON(speed == BFA_PORT_SPEED_AUTO);5077 5078	if (rport) {5079		rport->rport_info.speed = speed;5080		bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);5081	}5082}5083 5084/* Set Rport LUN Mask */5085void5086bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)5087{5088	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);5089	wwn_t	lp_wwn, rp_wwn;5090	u8 lp_tag = (u8)rp->rport_info.lp_tag;5091 5092	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;5093	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;5094 5095	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =5096					rp->lun_mask = BFA_TRUE;5097	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);5098}5099 5100/* Unset Rport LUN mask */5101void5102bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)5103{5104	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);5105	wwn_t	lp_wwn, rp_wwn;5106 5107	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;5108	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;5109 5110	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =5111				rp->lun_mask = BFA_FALSE;5112	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,5113			BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);5114}5115 5116/*5117 * SGPG related functions5118 */5119 5120/*5121 * Compute and return memory needed by FCP(im) module.5122 */5123void5124bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,5125		struct bfa_s *bfa)5126{5127	struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);5128	struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);5129	struct bfa_mem_dma_s *seg_ptr;5130	u16	nsegs, idx, per_seg_sgpg, num_sgpg;5131	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);5132 5133	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)5134		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;5135	else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)5136		cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;5137 5138	num_sgpg = cfg->drvcfg.num_sgpgs;5139 5140	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);5141	per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);5142 5143	bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {5144		if (num_sgpg >= per_seg_sgpg) {5145			num_sgpg -= per_seg_sgpg;5146			bfa_mem_dma_setup(minfo, seg_ptr,5147					per_seg_sgpg * sgpg_sz);5148		} else5149			bfa_mem_dma_setup(minfo, seg_ptr,5150					num_sgpg * sgpg_sz);5151	}5152 5153	/* kva memory */5154	bfa_mem_kva_setup(minfo, sgpg_kva,5155		cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));5156}5157 5158void5159bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,5160		struct bfa_pcidev_s *pcidev)5161{5162	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);5163	struct bfa_sgpg_s *hsgpg;5164	struct bfi_sgpg_s *sgpg;5165	u64 align_len;5166	struct bfa_mem_dma_s *seg_ptr;5167	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);5168	u16	i, idx, nsegs, per_seg_sgpg, num_sgpg;5169 5170	union {5171		u64 pa;5172		union bfi_addr_u addr;5173	} sgpg_pa, sgpg_pa_tmp;5174 5175	INIT_LIST_HEAD(&mod->sgpg_q);5176	INIT_LIST_HEAD(&mod->sgpg_wait_q);5177 5178	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);5179 5180	mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;5181 5182	num_sgpg = cfg->drvcfg.num_sgpgs;5183	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);5184 5185	/* dma/kva mem claim */5186	hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);5187 5188	bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {5189 5190		if (!bfa_mem_dma_virt(seg_ptr))5191			break;5192 5193		align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -5194					     bfa_mem_dma_phys(seg_ptr);5195 5196		sgpg = (struct bfi_sgpg_s *)5197			(((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);5198		sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;5199		WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));5200 5201		per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;5202 5203		for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {5204			memset(hsgpg, 0, sizeof(*hsgpg));5205			memset(sgpg, 0, sizeof(*sgpg));5206 5207			hsgpg->sgpg = sgpg;5208			sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);5209			hsgpg->sgpg_pa = sgpg_pa_tmp.addr;5210			list_add_tail(&hsgpg->qe, &mod->sgpg_q);5211 5212			sgpg++;5213			hsgpg++;5214			sgpg_pa.pa += sgpg_sz;5215		}5216	}5217 5218	bfa_mem_kva_curp(mod) = (u8 *) hsgpg;5219}5220 5221bfa_status_t5222bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)5223{5224	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);5225	struct bfa_sgpg_s *hsgpg;5226	int i;5227 5228	if (mod->free_sgpgs < nsgpgs)5229		return BFA_STATUS_ENOMEM;5230 5231	for (i = 0; i < nsgpgs; i++) {5232		bfa_q_deq(&mod->sgpg_q, &hsgpg);5233		WARN_ON(!hsgpg);5234		list_add_tail(&hsgpg->qe, sgpg_q);5235	}5236 5237	mod->free_sgpgs -= nsgpgs;5238	return BFA_STATUS_OK;5239}5240 5241void5242bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)5243{5244	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);5245	struct bfa_sgpg_wqe_s *wqe;5246 5247	mod->free_sgpgs += nsgpg;5248	WARN_ON(mod->free_sgpgs > mod->num_sgpgs);5249 5250	list_splice_tail_init(sgpg_q, &mod->sgpg_q);5251 5252	if (list_empty(&mod->sgpg_wait_q))5253		return;5254 5255	/*5256	 * satisfy as many waiting requests as possible5257	 */5258	do {5259		wqe = bfa_q_first(&mod->sgpg_wait_q);5260		if (mod->free_sgpgs < wqe->nsgpg)5261			nsgpg = mod->free_sgpgs;5262		else5263			nsgpg = wqe->nsgpg;5264		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);5265		wqe->nsgpg -= nsgpg;5266		if (wqe->nsgpg == 0) {5267			list_del(&wqe->qe);5268			wqe->cbfn(wqe->cbarg);5269		}5270	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));5271}5272 5273void5274bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)5275{5276	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);5277 5278	WARN_ON(nsgpg <= 0);5279	WARN_ON(nsgpg <= mod->free_sgpgs);5280 5281	wqe->nsgpg_total = wqe->nsgpg = nsgpg;5282 5283	/*5284	 * allocate any left to this one first5285	 */5286	if (mod->free_sgpgs) {5287		/*5288		 * no one else is waiting for SGPG5289		 */5290		WARN_ON(!list_empty(&mod->sgpg_wait_q));5291		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);5292		wqe->nsgpg -= mod->free_sgpgs;5293		mod->free_sgpgs = 0;5294	}5295 5296	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);5297}5298 5299void5300bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)5301{5302	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);5303 5304	WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));5305	list_del(&wqe->qe);5306 5307	if (wqe->nsgpg_total != wqe->nsgpg)5308		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,5309				   wqe->nsgpg_total - wqe->nsgpg);5310}5311 5312void5313bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),5314		   void *cbarg)5315{5316	INIT_LIST_HEAD(&wqe->sgpg_q);5317	wqe->cbfn = cbfn;5318	wqe->cbarg = cbarg;5319}5320 5321/*5322 *  UF related functions5323 */5324/*5325 *****************************************************************************5326 * Internal functions5327 *****************************************************************************5328 */5329static void5330__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)5331{5332	struct bfa_uf_s   *uf = cbarg;5333	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);5334 5335	if (complete)5336		ufm->ufrecv(ufm->cbarg, uf);5337}5338 5339static void5340claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)5341{5342	struct bfi_uf_buf_post_s *uf_bp_msg;5343	u16 i;5344	u16 buf_len;5345 5346	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);5347	uf_bp_msg = ufm->uf_buf_posts;5348 5349	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;5350	     i++, uf_bp_msg++) {5351		memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));5352 5353		uf_bp_msg->buf_tag = i;5354		buf_len = sizeof(struct bfa_uf_buf_s);5355		uf_bp_msg->buf_len = cpu_to_be16(buf_len);5356		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,5357			    bfa_fn_lpu(ufm->bfa));5358		bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));5359	}5360 5361	/*5362	 * advance pointer beyond consumed memory5363	 */5364	bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;5365}5366 5367static void5368claim_ufs(struct bfa_uf_mod_s *ufm)5369{5370	u16 i;5371	struct bfa_uf_s   *uf;5372 5373	/*5374	 * Claim block of memory for UF list5375	 */5376	ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);5377 5378	/*5379	 * Initialize UFs and queue it in UF free queue5380	 */5381	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {5382		memset(uf, 0, sizeof(struct bfa_uf_s));5383		uf->bfa = ufm->bfa;5384		uf->uf_tag = i;5385		uf->pb_len = BFA_PER_UF_DMA_SZ;5386		uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);5387		uf->buf_pa = ufm_pbs_pa(ufm, i);5388		list_add_tail(&uf->qe, &ufm->uf_free_q);5389	}5390 5391	/*5392	 * advance memory pointer5393	 */5394	bfa_mem_kva_curp(ufm) = (u8 *) uf;5395}5396 5397static void5398uf_mem_claim(struct bfa_uf_mod_s *ufm)5399{5400	claim_ufs(ufm);5401	claim_uf_post_msgs(ufm);5402}5403 5404void5405bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,5406		struct bfa_s *bfa)5407{5408	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);5409	struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);5410	u32	num_ufs = cfg->fwcfg.num_uf_bufs;5411	struct bfa_mem_dma_s *seg_ptr;5412	u16	nsegs, idx, per_seg_uf = 0;5413 5414	nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);5415	per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);5416 5417	bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {5418		if (num_ufs >= per_seg_uf) {5419			num_ufs -= per_seg_uf;5420			bfa_mem_dma_setup(minfo, seg_ptr,5421				per_seg_uf * BFA_PER_UF_DMA_SZ);5422		} else5423			bfa_mem_dma_setup(minfo, seg_ptr,5424				num_ufs * BFA_PER_UF_DMA_SZ);5425	}5426 5427	/* kva memory */5428	bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *5429		(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));5430}5431 5432void5433bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,5434		struct bfa_pcidev_s *pcidev)5435{5436	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);5437 5438	ufm->bfa = bfa;5439	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;5440	INIT_LIST_HEAD(&ufm->uf_free_q);5441	INIT_LIST_HEAD(&ufm->uf_posted_q);5442	INIT_LIST_HEAD(&ufm->uf_unused_q);5443 5444	uf_mem_claim(ufm);5445}5446 5447static struct bfa_uf_s *5448bfa_uf_get(struct bfa_uf_mod_s *uf_mod)5449{5450	struct bfa_uf_s   *uf;5451 5452	bfa_q_deq(&uf_mod->uf_free_q, &uf);5453	return uf;5454}5455 5456static void5457bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)5458{5459	list_add_tail(&uf->qe, &uf_mod->uf_free_q);5460}5461 5462static bfa_status_t5463bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)5464{5465	struct bfi_uf_buf_post_s *uf_post_msg;5466 5467	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);5468	if (!uf_post_msg)5469		return BFA_STATUS_FAILED;5470 5471	memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],5472		      sizeof(struct bfi_uf_buf_post_s));5473	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);5474 5475	bfa_trc(ufm->bfa, uf->uf_tag);5476 5477	list_add_tail(&uf->qe, &ufm->uf_posted_q);5478	return BFA_STATUS_OK;5479}5480 5481static void5482bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)5483{5484	struct bfa_uf_s   *uf;5485 5486	while ((uf = bfa_uf_get(uf_mod)) != NULL) {5487		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)5488			break;5489	}5490}5491 5492static void5493uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)5494{5495	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);5496	u16 uf_tag = m->buf_tag;5497	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];5498	struct bfa_uf_buf_s *uf_buf;5499	uint8_t *buf;5500 5501	uf_buf = (struct bfa_uf_buf_s *)5502			bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);5503	buf = &uf_buf->d[0];5504 5505	m->frm_len = be16_to_cpu(m->frm_len);5506	m->xfr_len = be16_to_cpu(m->xfr_len);5507 5508	list_del(&uf->qe);	/* dequeue from posted queue */5509 5510	uf->data_ptr = buf;5511	uf->data_len = m->xfr_len;5512 5513	WARN_ON(uf->data_len < sizeof(struct fchs_s));5514 5515	if (uf->data_len == sizeof(struct fchs_s)) {5516		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,5517			       uf->data_len, (struct fchs_s *)buf);5518	} else {5519		u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));5520		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,5521				      BFA_PL_EID_RX, uf->data_len,5522				      (struct fchs_s *)buf, pld_w0);5523	}5524 5525	if (bfa->fcs)5526		__bfa_cb_uf_recv(uf, BFA_TRUE);5527	else5528		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);5529}5530 5531void5532bfa_uf_iocdisable(struct bfa_s *bfa)5533{5534	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);5535	struct bfa_uf_s *uf;5536	struct list_head *qe, *qen;5537 5538	/* Enqueue unused uf resources to free_q */5539	list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);5540 5541	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {5542		uf = (struct bfa_uf_s *) qe;5543		list_del(&uf->qe);5544		bfa_uf_put(ufm, uf);5545	}5546}5547 5548void5549bfa_uf_start(struct bfa_s *bfa)5550{5551	bfa_uf_post_all(BFA_UF_MOD(bfa));5552}5553 5554/*5555 * Register handler for all unsolicted receive frames.5556 *5557 * @param[in]	bfa		BFA instance5558 * @param[in]	ufrecv	receive handler function5559 * @param[in]	cbarg	receive handler arg5560 */5561void5562bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)5563{5564	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);5565 5566	ufm->ufrecv = ufrecv;5567	ufm->cbarg = cbarg;5568}5569 5570/*5571 *	Free an unsolicited frame back to BFA.5572 *5573 * @param[in]		uf		unsolicited frame to be freed5574 *5575 * @return None5576 */5577void5578bfa_uf_free(struct bfa_uf_s *uf)5579{5580	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);5581	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));5582}5583 5584 5585 5586/*5587 *  uf_pub BFA uf module public functions5588 */5589void5590bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)5591{5592	bfa_trc(bfa, msg->mhdr.msg_id);5593 5594	switch (msg->mhdr.msg_id) {5595	case BFI_UF_I2H_FRM_RCVD:5596		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);5597		break;5598 5599	default:5600		bfa_trc(bfa, msg->mhdr.msg_id);5601		WARN_ON(1);5602	}5603}5604 5605void5606bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)5607{5608	struct bfa_uf_mod_s	*mod = BFA_UF_MOD(bfa);5609	struct list_head	*qe;5610	int	i;5611 5612	for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {5613		bfa_q_deq_tail(&mod->uf_free_q, &qe);5614		list_add_tail(qe, &mod->uf_unused_q);5615	}5616}5617 5618/*5619 *	Dport forward declaration5620 */5621 5622enum bfa_dport_test_state_e {5623	BFA_DPORT_ST_DISABLED	= 0,	/*!< dport is disabled */5624	BFA_DPORT_ST_INP	= 1,	/*!< test in progress */5625	BFA_DPORT_ST_COMP	= 2,	/*!< test complete successfully */5626	BFA_DPORT_ST_NO_SFP	= 3,	/*!< sfp is not present */5627	BFA_DPORT_ST_NOTSTART	= 4,	/*!< test not start dport is enabled */5628};5629 5630static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,5631				  enum bfa_dport_sm_event event);5632static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,5633				  enum bfa_dport_sm_event event);5634static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,5635				  enum bfa_dport_sm_event event);5636static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,5637				 enum bfa_dport_sm_event event);5638static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,5639				 enum bfa_dport_sm_event event);5640static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,5641				   enum bfa_dport_sm_event event);5642static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,5643					enum bfa_dport_sm_event event);5644static void bfa_dport_sm_starting(struct bfa_dport_s *dport,5645				  enum bfa_dport_sm_event event);5646static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,5647				   enum bfa_dport_sm_event event);5648static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,5649				   enum bfa_dport_sm_event event);5650static void bfa_dport_qresume(void *cbarg);5651static void bfa_dport_req_comp(struct bfa_dport_s *dport,5652				struct bfi_diag_dport_rsp_s *msg);5653static void bfa_dport_scn(struct bfa_dport_s *dport,5654				struct bfi_diag_dport_scn_s *msg);5655 5656/*5657 *	BFA fcdiag module5658 */5659#define BFA_DIAG_QTEST_TOV	1000    /* msec */5660 5661/*5662 *	Set port status to busy5663 */5664static void5665bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)5666{5667	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);5668 5669	if (fcdiag->lb.lock)5670		fcport->diag_busy = BFA_TRUE;5671	else5672		fcport->diag_busy = BFA_FALSE;5673}5674 5675void5676bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,5677		struct bfa_pcidev_s *pcidev)5678{5679	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);5680	struct bfa_dport_s  *dport = &fcdiag->dport;5681 5682	fcdiag->bfa             = bfa;5683	fcdiag->trcmod  = bfa->trcmod;5684	/* The common DIAG attach bfa_diag_attach() will do all memory claim */5685	dport->bfa = bfa;5686	bfa_sm_set_state(dport, bfa_dport_sm_disabled);5687	bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);5688	dport->cbfn = NULL;5689	dport->cbarg = NULL;5690	dport->test_state = BFA_DPORT_ST_DISABLED;5691	memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));5692}5693 5694void5695bfa_fcdiag_iocdisable(struct bfa_s *bfa)5696{5697	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);5698	struct bfa_dport_s *dport = &fcdiag->dport;5699 5700	bfa_trc(fcdiag, fcdiag->lb.lock);5701	if (fcdiag->lb.lock) {5702		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;5703		fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);5704		fcdiag->lb.lock = 0;5705		bfa_fcdiag_set_busy_status(fcdiag);5706	}5707 5708	bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);5709}5710 5711static void5712bfa_fcdiag_queuetest_timeout(void *cbarg)5713{5714	struct bfa_fcdiag_s       *fcdiag = cbarg;5715	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;5716 5717	bfa_trc(fcdiag, fcdiag->qtest.all);5718	bfa_trc(fcdiag, fcdiag->qtest.count);5719 5720	fcdiag->qtest.timer_active = 0;5721 5722	res->status = BFA_STATUS_ETIMER;5723	res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;5724	if (fcdiag->qtest.all)5725		res->queue  = fcdiag->qtest.all;5726 5727	bfa_trc(fcdiag, BFA_STATUS_ETIMER);5728	fcdiag->qtest.status = BFA_STATUS_ETIMER;5729	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);5730	fcdiag->qtest.lock = 0;5731}5732 5733static bfa_status_t5734bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)5735{5736	u32	i;5737	struct bfi_diag_qtest_req_s *req;5738 5739	req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);5740	if (!req)5741		return BFA_STATUS_DEVBUSY;5742 5743	/* build host command */5744	bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,5745		bfa_fn_lpu(fcdiag->bfa));5746 5747	for (i = 0; i < BFI_LMSG_PL_WSZ; i++)5748		req->data[i] = QTEST_PAT_DEFAULT;5749 5750	bfa_trc(fcdiag, fcdiag->qtest.queue);5751	/* ring door bell */5752	bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);5753	return BFA_STATUS_OK;5754}5755 5756static void5757bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,5758			bfi_diag_qtest_rsp_t *rsp)5759{5760	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;5761	bfa_status_t status = BFA_STATUS_OK;5762	int i;5763 5764	/* Check timer, should still be active   */5765	if (!fcdiag->qtest.timer_active) {5766		bfa_trc(fcdiag, fcdiag->qtest.timer_active);5767		return;5768	}5769 5770	/* update count */5771	fcdiag->qtest.count--;5772 5773	/* Check result */5774	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {5775		if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {5776			res->status = BFA_STATUS_DATACORRUPTED;5777			break;5778		}5779	}5780 5781	if (res->status == BFA_STATUS_OK) {5782		if (fcdiag->qtest.count > 0) {5783			status = bfa_fcdiag_queuetest_send(fcdiag);5784			if (status == BFA_STATUS_OK)5785				return;5786			else5787				res->status = status;5788		} else if (fcdiag->qtest.all > 0 &&5789			fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {5790			fcdiag->qtest.count = QTEST_CNT_DEFAULT;5791			fcdiag->qtest.queue++;5792			status = bfa_fcdiag_queuetest_send(fcdiag);5793			if (status == BFA_STATUS_OK)5794				return;5795			else5796				res->status = status;5797		}5798	}5799 5800	/* Stop timer when we comp all queue */5801	if (fcdiag->qtest.timer_active) {5802		bfa_timer_stop(&fcdiag->qtest.timer);5803		fcdiag->qtest.timer_active = 0;5804	}5805	res->queue = fcdiag->qtest.queue;5806	res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;5807	bfa_trc(fcdiag, res->count);5808	bfa_trc(fcdiag, res->status);5809	fcdiag->qtest.status = res->status;5810	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);5811	fcdiag->qtest.lock = 0;5812}5813 5814static void5815bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,5816			struct bfi_diag_lb_rsp_s *rsp)5817{5818	struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;5819 5820	res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);5821	res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);5822	res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);5823	res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);5824	res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);5825	res->status     = rsp->res.status;5826	fcdiag->lb.status = rsp->res.status;5827	bfa_trc(fcdiag, fcdiag->lb.status);5828	fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);5829	fcdiag->lb.lock = 0;5830	bfa_fcdiag_set_busy_status(fcdiag);5831}5832 5833static bfa_status_t5834bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,5835			struct bfa_diag_loopback_s *loopback)5836{5837	struct bfi_diag_lb_req_s *lb_req;5838 5839	lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);5840	if (!lb_req)5841		return BFA_STATUS_DEVBUSY;5842 5843	/* build host command */5844	bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,5845		bfa_fn_lpu(fcdiag->bfa));5846 5847	lb_req->lb_mode = loopback->lb_mode;5848	lb_req->speed = loopback->speed;5849	lb_req->loopcnt = loopback->loopcnt;5850	lb_req->pattern = loopback->pattern;5851 5852	/* ring door bell */5853	bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);5854 5855	bfa_trc(fcdiag, loopback->lb_mode);5856	bfa_trc(fcdiag, loopback->speed);5857	bfa_trc(fcdiag, loopback->loopcnt);5858	bfa_trc(fcdiag, loopback->pattern);5859	return BFA_STATUS_OK;5860}5861 5862/*5863 *	cpe/rme intr handler5864 */5865void5866bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)5867{5868	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);5869 5870	switch (msg->mhdr.msg_id) {5871	case BFI_DIAG_I2H_LOOPBACK:5872		bfa_fcdiag_loopback_comp(fcdiag,5873				(struct bfi_diag_lb_rsp_s *) msg);5874		break;5875	case BFI_DIAG_I2H_QTEST:5876		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);5877		break;5878	case BFI_DIAG_I2H_DPORT:5879		bfa_dport_req_comp(&fcdiag->dport,5880				(struct bfi_diag_dport_rsp_s *)msg);5881		break;5882	case BFI_DIAG_I2H_DPORT_SCN:5883		bfa_dport_scn(&fcdiag->dport,5884				(struct bfi_diag_dport_scn_s *)msg);5885		break;5886	default:5887		bfa_trc(fcdiag, msg->mhdr.msg_id);5888		WARN_ON(1);5889	}5890}5891 5892/*5893 *	Loopback test5894 *5895 *   @param[in] *bfa            - bfa data struct5896 *   @param[in] opmode          - port operation mode5897 *   @param[in] speed           - port speed5898 *   @param[in] lpcnt           - loop count5899 *   @param[in] pat                     - pattern to build packet5900 *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct5901 *   @param[in] cbfn            - callback function5902 *   @param[in] cbarg           - callback functioin arg5903 *5904 *   @param[out]5905 */5906bfa_status_t5907bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,5908		enum bfa_port_speed speed, u32 lpcnt, u32 pat,5909		struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,5910		void *cbarg)5911{5912	struct  bfa_diag_loopback_s loopback;5913	struct bfa_port_attr_s attr;5914	bfa_status_t status;5915	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);5916 5917	if (!bfa_iocfc_is_operational(bfa))5918		return BFA_STATUS_IOC_NON_OP;5919 5920	/* if port is PBC disabled, return error */5921	if (bfa_fcport_is_pbcdisabled(bfa)) {5922		bfa_trc(fcdiag, BFA_STATUS_PBC);5923		return BFA_STATUS_PBC;5924	}5925 5926	if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {5927		bfa_trc(fcdiag, opmode);5928		return BFA_STATUS_PORT_NOT_DISABLED;5929	}5930 5931	/*5932	 * Check if input speed is supported by the port mode5933	 */5934	if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {5935		if (!(speed == BFA_PORT_SPEED_1GBPS ||5936		      speed == BFA_PORT_SPEED_2GBPS ||5937		      speed == BFA_PORT_SPEED_4GBPS ||5938		      speed == BFA_PORT_SPEED_8GBPS ||5939		      speed == BFA_PORT_SPEED_16GBPS ||5940		      speed == BFA_PORT_SPEED_AUTO)) {5941			bfa_trc(fcdiag, speed);5942			return BFA_STATUS_UNSUPP_SPEED;5943		}5944		bfa_fcport_get_attr(bfa, &attr);5945		bfa_trc(fcdiag, attr.speed_supported);5946		if (speed > attr.speed_supported)5947			return BFA_STATUS_UNSUPP_SPEED;5948	} else {5949		if (speed != BFA_PORT_SPEED_10GBPS) {5950			bfa_trc(fcdiag, speed);5951			return BFA_STATUS_UNSUPP_SPEED;5952		}5953	}5954 5955	/*5956	 * For CT2, 1G is not supported5957	 */5958	if ((speed == BFA_PORT_SPEED_1GBPS) &&5959	    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {5960		bfa_trc(fcdiag, speed);5961		return BFA_STATUS_UNSUPP_SPEED;5962	}5963 5964	/* For Mezz card, port speed entered needs to be checked */5965	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {5966		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {5967			if (!(speed == BFA_PORT_SPEED_1GBPS ||5968			      speed == BFA_PORT_SPEED_2GBPS ||5969			      speed == BFA_PORT_SPEED_4GBPS ||5970			      speed == BFA_PORT_SPEED_8GBPS ||5971			      speed == BFA_PORT_SPEED_16GBPS ||5972			      speed == BFA_PORT_SPEED_AUTO))5973				return BFA_STATUS_UNSUPP_SPEED;5974		} else {5975			if (speed != BFA_PORT_SPEED_10GBPS)5976				return BFA_STATUS_UNSUPP_SPEED;5977		}5978	}5979	/* check to see if fcport is dport */5980	if (bfa_fcport_is_dport(bfa)) {5981		bfa_trc(fcdiag, fcdiag->lb.lock);5982		return BFA_STATUS_DPORT_ENABLED;5983	}5984	/* check to see if there is another destructive diag cmd running */5985	if (fcdiag->lb.lock) {5986		bfa_trc(fcdiag, fcdiag->lb.lock);5987		return BFA_STATUS_DEVBUSY;5988	}5989 5990	fcdiag->lb.lock = 1;5991	loopback.lb_mode = opmode;5992	loopback.speed = speed;5993	loopback.loopcnt = lpcnt;5994	loopback.pattern = pat;5995	fcdiag->lb.result = result;5996	fcdiag->lb.cbfn = cbfn;5997	fcdiag->lb.cbarg = cbarg;5998	memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));5999	bfa_fcdiag_set_busy_status(fcdiag);6000 6001	/* Send msg to fw */6002	status = bfa_fcdiag_loopback_send(fcdiag, &loopback);6003	return status;6004}6005 6006/*6007 *	DIAG queue test command6008 *6009 *   @param[in] *bfa            - bfa data struct6010 *   @param[in] force           - 1: don't do ioc op checking6011 *   @param[in] queue           - queue no. to test6012 *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct6013 *   @param[in] cbfn            - callback function6014 *   @param[in] *cbarg          - callback functioin arg6015 *6016 *   @param[out]6017 */6018bfa_status_t6019bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,6020		struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,6021		void *cbarg)6022{6023	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);6024	bfa_status_t status;6025	bfa_trc(fcdiag, force);6026	bfa_trc(fcdiag, queue);6027 6028	if (!force && !bfa_iocfc_is_operational(bfa))6029		return BFA_STATUS_IOC_NON_OP;6030 6031	/* check to see if there is another destructive diag cmd running */6032	if (fcdiag->qtest.lock) {6033		bfa_trc(fcdiag, fcdiag->qtest.lock);6034		return BFA_STATUS_DEVBUSY;6035	}6036 6037	/* Initialization */6038	fcdiag->qtest.lock = 1;6039	fcdiag->qtest.cbfn = cbfn;6040	fcdiag->qtest.cbarg = cbarg;6041	fcdiag->qtest.result = result;6042	fcdiag->qtest.count = QTEST_CNT_DEFAULT;6043 6044	/* Init test results */6045	fcdiag->qtest.result->status = BFA_STATUS_OK;6046	fcdiag->qtest.result->count  = 0;6047 6048	/* send */6049	if (queue < BFI_IOC_MAX_CQS) {6050		fcdiag->qtest.result->queue  = (u8)queue;6051		fcdiag->qtest.queue = (u8)queue;6052		fcdiag->qtest.all   = 0;6053	} else {6054		fcdiag->qtest.result->queue  = 0;6055		fcdiag->qtest.queue = 0;6056		fcdiag->qtest.all   = 1;6057	}6058	status = bfa_fcdiag_queuetest_send(fcdiag);6059 6060	/* Start a timer */6061	if (status == BFA_STATUS_OK) {6062		bfa_timer_start(bfa, &fcdiag->qtest.timer,6063				bfa_fcdiag_queuetest_timeout, fcdiag,6064				BFA_DIAG_QTEST_TOV);6065		fcdiag->qtest.timer_active = 1;6066	}6067	return status;6068}6069 6070/*6071 * DIAG PLB is running6072 *6073 *   @param[in] *bfa    - bfa data struct6074 *6075 *   @param[out]6076 */6077bfa_status_t6078bfa_fcdiag_lb_is_running(struct bfa_s *bfa)6079{6080	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);6081	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;6082}6083 6084/*6085 *	D-port6086 */6087#define bfa_dport_result_start(__dport, __mode) do {				\6088		(__dport)->result.start_time = ktime_get_real_seconds();	\6089		(__dport)->result.status = DPORT_TEST_ST_INPRG;			\6090		(__dport)->result.mode = (__mode);				\6091		(__dport)->result.rp_pwwn = (__dport)->rp_pwwn;			\6092		(__dport)->result.rp_nwwn = (__dport)->rp_nwwn;			\6093		(__dport)->result.lpcnt = (__dport)->lpcnt;			\6094} while (0)6095 6096static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,6097					enum bfi_dport_req req);6098static void6099bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)6100{6101	if (dport->cbfn != NULL) {6102		dport->cbfn(dport->cbarg, bfa_status);6103		dport->cbfn = NULL;6104		dport->cbarg = NULL;6105	}6106}6107 6108static void6109bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)6110{6111	bfa_trc(dport->bfa, event);6112 6113	switch (event) {6114	case BFA_DPORT_SM_ENABLE:6115		bfa_fcport_dportenable(dport->bfa);6116		if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))6117			bfa_sm_set_state(dport, bfa_dport_sm_enabling);6118		else6119			bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);6120		break;6121 6122	case BFA_DPORT_SM_DISABLE:6123		/* Already disabled */6124		break;6125 6126	case BFA_DPORT_SM_HWFAIL:6127		/* ignore */6128		break;6129 6130	case BFA_DPORT_SM_SCN:6131		if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) {6132			bfa_fcport_ddportenable(dport->bfa);6133			dport->dynamic = BFA_TRUE;6134			dport->test_state = BFA_DPORT_ST_NOTSTART;6135			bfa_sm_set_state(dport, bfa_dport_sm_enabled);6136		} else {6137			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);6138			WARN_ON(1);6139		}6140		break;6141 6142	default:6143		bfa_sm_fault(dport->bfa, event);6144	}6145}6146 6147static void6148bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,6149			    enum bfa_dport_sm_event event)6150{6151	bfa_trc(dport->bfa, event);6152 6153	switch (event) {6154	case BFA_DPORT_SM_QRESUME:6155		bfa_sm_set_state(dport, bfa_dport_sm_enabling);6156		bfa_dport_send_req(dport, BFI_DPORT_ENABLE);6157		break;6158 6159	case BFA_DPORT_SM_HWFAIL:6160		bfa_reqq_wcancel(&dport->reqq_wait);6161		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6162		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);6163		break;6164 6165	default:6166		bfa_sm_fault(dport->bfa, event);6167	}6168}6169 6170static void6171bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)6172{6173	bfa_trc(dport->bfa, event);6174 6175	switch (event) {6176	case BFA_DPORT_SM_FWRSP:6177		memset(&dport->result, 0,6178				sizeof(struct bfa_diag_dport_result_s));6179		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {6180			dport->test_state = BFA_DPORT_ST_NO_SFP;6181		} else {6182			dport->test_state = BFA_DPORT_ST_INP;6183			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);6184		}6185		bfa_sm_set_state(dport, bfa_dport_sm_enabled);6186		break;6187 6188	case BFA_DPORT_SM_REQFAIL:6189		dport->test_state = BFA_DPORT_ST_DISABLED;6190		bfa_fcport_dportdisable(dport->bfa);6191		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6192		break;6193 6194	case BFA_DPORT_SM_HWFAIL:6195		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6196		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);6197		break;6198 6199	default:6200		bfa_sm_fault(dport->bfa, event);6201	}6202}6203 6204static void6205bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)6206{6207	bfa_trc(dport->bfa, event);6208 6209	switch (event) {6210	case BFA_DPORT_SM_START:6211		if (bfa_dport_send_req(dport, BFI_DPORT_START))6212			bfa_sm_set_state(dport, bfa_dport_sm_starting);6213		else6214			bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);6215		break;6216 6217	case BFA_DPORT_SM_DISABLE:6218		bfa_fcport_dportdisable(dport->bfa);6219		if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))6220			bfa_sm_set_state(dport, bfa_dport_sm_disabling);6221		else6222			bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);6223		break;6224 6225	case BFA_DPORT_SM_HWFAIL:6226		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6227		break;6228 6229	case BFA_DPORT_SM_SCN:6230		switch (dport->i2hmsg.scn.state) {6231		case BFI_DPORT_SCN_TESTCOMP:6232			dport->test_state = BFA_DPORT_ST_COMP;6233			break;6234 6235		case BFI_DPORT_SCN_TESTSTART:6236			dport->test_state = BFA_DPORT_ST_INP;6237			break;6238 6239		case BFI_DPORT_SCN_TESTSKIP:6240		case BFI_DPORT_SCN_SUBTESTSTART:6241			/* no state change */6242			break;6243 6244		case BFI_DPORT_SCN_SFP_REMOVED:6245			dport->test_state = BFA_DPORT_ST_NO_SFP;6246			break;6247 6248		case BFI_DPORT_SCN_DDPORT_DISABLE:6249			bfa_fcport_ddportdisable(dport->bfa);6250 6251			if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))6252				bfa_sm_set_state(dport,6253					 bfa_dport_sm_dynamic_disabling);6254			else6255				bfa_sm_set_state(dport,6256					 bfa_dport_sm_dynamic_disabling_qwait);6257			break;6258 6259		case BFI_DPORT_SCN_FCPORT_DISABLE:6260			bfa_fcport_ddportdisable(dport->bfa);6261 6262			bfa_sm_set_state(dport, bfa_dport_sm_disabled);6263			dport->dynamic = BFA_FALSE;6264			break;6265 6266		default:6267			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);6268			bfa_sm_fault(dport->bfa, event);6269		}6270		break;6271	default:6272		bfa_sm_fault(dport->bfa, event);6273	}6274}6275 6276static void6277bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,6278			     enum bfa_dport_sm_event event)6279{6280	bfa_trc(dport->bfa, event);6281 6282	switch (event) {6283	case BFA_DPORT_SM_QRESUME:6284		bfa_sm_set_state(dport, bfa_dport_sm_disabling);6285		bfa_dport_send_req(dport, BFI_DPORT_DISABLE);6286		break;6287 6288	case BFA_DPORT_SM_HWFAIL:6289		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6290		bfa_reqq_wcancel(&dport->reqq_wait);6291		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);6292		break;6293 6294	case BFA_DPORT_SM_SCN:6295		/* ignore */6296		break;6297 6298	default:6299		bfa_sm_fault(dport->bfa, event);6300	}6301}6302 6303static void6304bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)6305{6306	bfa_trc(dport->bfa, event);6307 6308	switch (event) {6309	case BFA_DPORT_SM_FWRSP:6310		dport->test_state = BFA_DPORT_ST_DISABLED;6311		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6312		break;6313 6314	case BFA_DPORT_SM_HWFAIL:6315		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6316		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);6317		break;6318 6319	case BFA_DPORT_SM_SCN:6320		/* no state change */6321		break;6322 6323	default:6324		bfa_sm_fault(dport->bfa, event);6325	}6326}6327 6328static void6329bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,6330			    enum bfa_dport_sm_event event)6331{6332	bfa_trc(dport->bfa, event);6333 6334	switch (event) {6335	case BFA_DPORT_SM_QRESUME:6336		bfa_sm_set_state(dport, bfa_dport_sm_starting);6337		bfa_dport_send_req(dport, BFI_DPORT_START);6338		break;6339 6340	case BFA_DPORT_SM_HWFAIL:6341		bfa_reqq_wcancel(&dport->reqq_wait);6342		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6343		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);6344		break;6345 6346	default:6347		bfa_sm_fault(dport->bfa, event);6348	}6349}6350 6351static void6352bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)6353{6354	bfa_trc(dport->bfa, event);6355 6356	switch (event) {6357	case BFA_DPORT_SM_FWRSP:6358		memset(&dport->result, 0,6359				sizeof(struct bfa_diag_dport_result_s));6360		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {6361			dport->test_state = BFA_DPORT_ST_NO_SFP;6362		} else {6363			dport->test_state = BFA_DPORT_ST_INP;6364			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);6365		}6366		fallthrough;6367 6368	case BFA_DPORT_SM_REQFAIL:6369		bfa_sm_set_state(dport, bfa_dport_sm_enabled);6370		break;6371 6372	case BFA_DPORT_SM_HWFAIL:6373		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6374		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);6375		break;6376 6377	default:6378		bfa_sm_fault(dport->bfa, event);6379	}6380}6381 6382static void6383bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,6384			       enum bfa_dport_sm_event event)6385{6386	bfa_trc(dport->bfa, event);6387 6388	switch (event) {6389	case BFA_DPORT_SM_SCN:6390		switch (dport->i2hmsg.scn.state) {6391		case BFI_DPORT_SCN_DDPORT_DISABLED:6392			bfa_sm_set_state(dport, bfa_dport_sm_disabled);6393			dport->dynamic = BFA_FALSE;6394			bfa_fcport_enable(dport->bfa);6395			break;6396 6397		default:6398			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);6399			bfa_sm_fault(dport->bfa, event);6400 6401		}6402		break;6403 6404	case BFA_DPORT_SM_HWFAIL:6405		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6406		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);6407		break;6408 6409	default:6410		bfa_sm_fault(dport->bfa, event);6411	}6412}6413 6414static void6415bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,6416			    enum bfa_dport_sm_event event)6417{6418	bfa_trc(dport->bfa, event);6419 6420	switch (event) {6421	case BFA_DPORT_SM_QRESUME:6422		bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);6423		bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);6424		break;6425 6426	case BFA_DPORT_SM_HWFAIL:6427		bfa_sm_set_state(dport, bfa_dport_sm_disabled);6428		bfa_reqq_wcancel(&dport->reqq_wait);6429		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);6430		break;6431 6432	case BFA_DPORT_SM_SCN:6433		/* ignore */6434		break;6435 6436	default:6437		bfa_sm_fault(dport->bfa, event);6438	}6439}6440 6441static bfa_boolean_t6442bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)6443{6444	struct bfi_diag_dport_req_s *m;6445 6446	/*6447	 * check for room in queue to send request now6448	 */6449	m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);6450	if (!m) {6451		bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);6452		return BFA_FALSE;6453	}6454 6455	bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,6456		    bfa_fn_lpu(dport->bfa));6457	m->req  = req;6458	if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {6459		m->lpcnt = cpu_to_be32(dport->lpcnt);6460		m->payload = cpu_to_be32(dport->payload);6461	}6462 6463	/*6464	 * queue I/O message to firmware6465	 */6466	bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);6467 6468	return BFA_TRUE;6469}6470 6471static void6472bfa_dport_qresume(void *cbarg)6473{6474	struct bfa_dport_s *dport = cbarg;6475 6476	bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);6477}6478 6479static void6480bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)6481{6482	msg->status = cpu_to_be32(msg->status);6483	dport->i2hmsg.rsp.status = msg->status;6484	dport->rp_pwwn = msg->pwwn;6485	dport->rp_nwwn = msg->nwwn;6486 6487	if ((msg->status == BFA_STATUS_OK) ||6488	    (msg->status == BFA_STATUS_DPORT_NO_SFP)) {6489		bfa_trc(dport->bfa, msg->status);6490		bfa_trc(dport->bfa, dport->rp_pwwn);6491		bfa_trc(dport->bfa, dport->rp_nwwn);6492		bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);6493 6494	} else {6495		bfa_trc(dport->bfa, msg->status);6496		bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);6497	}6498	bfa_cb_fcdiag_dport(dport, msg->status);6499}6500 6501static bfa_boolean_t6502bfa_dport_is_sending_req(struct bfa_dport_s *dport)6503{6504	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)	||6505	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||6506	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)	||6507	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||6508	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting)	||6509	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {6510		return BFA_TRUE;6511	} else {6512		return BFA_FALSE;6513	}6514}6515 6516static void6517bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)6518{6519	int i;6520	uint8_t subtesttype;6521 6522	bfa_trc(dport->bfa, msg->state);6523	dport->i2hmsg.scn.state = msg->state;6524 6525	switch (dport->i2hmsg.scn.state) {6526	case BFI_DPORT_SCN_TESTCOMP:6527		dport->result.end_time = ktime_get_real_seconds();6528		bfa_trc(dport->bfa, dport->result.end_time);6529 6530		dport->result.status = msg->info.testcomp.status;6531		bfa_trc(dport->bfa, dport->result.status);6532 6533		dport->result.roundtrip_latency =6534			cpu_to_be32(msg->info.testcomp.latency);6535		dport->result.est_cable_distance =6536			cpu_to_be32(msg->info.testcomp.distance);6537		dport->result.buffer_required =6538			be16_to_cpu(msg->info.testcomp.numbuffer);6539 6540		dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);6541		dport->result.speed = msg->info.testcomp.speed;6542 6543		bfa_trc(dport->bfa, dport->result.roundtrip_latency);6544		bfa_trc(dport->bfa, dport->result.est_cable_distance);6545		bfa_trc(dport->bfa, dport->result.buffer_required);6546		bfa_trc(dport->bfa, dport->result.frmsz);6547		bfa_trc(dport->bfa, dport->result.speed);6548 6549		for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {6550			dport->result.subtest[i].status =6551				msg->info.testcomp.subtest_status[i];6552			bfa_trc(dport->bfa, dport->result.subtest[i].status);6553		}6554		break;6555 6556	case BFI_DPORT_SCN_TESTSKIP:6557	case BFI_DPORT_SCN_DDPORT_ENABLE:6558		memset(&dport->result, 0,6559				sizeof(struct bfa_diag_dport_result_s));6560		break;6561 6562	case BFI_DPORT_SCN_TESTSTART:6563		memset(&dport->result, 0,6564				sizeof(struct bfa_diag_dport_result_s));6565		dport->rp_pwwn = msg->info.teststart.pwwn;6566		dport->rp_nwwn = msg->info.teststart.nwwn;6567		dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);6568		bfa_dport_result_start(dport, msg->info.teststart.mode);6569		break;6570 6571	case BFI_DPORT_SCN_SUBTESTSTART:6572		subtesttype = msg->info.teststart.type;6573		dport->result.subtest[subtesttype].start_time =6574			ktime_get_real_seconds();6575		dport->result.subtest[subtesttype].status =6576			DPORT_TEST_ST_INPRG;6577 6578		bfa_trc(dport->bfa, subtesttype);6579		bfa_trc(dport->bfa,6580			dport->result.subtest[subtesttype].start_time);6581		break;6582 6583	case BFI_DPORT_SCN_SFP_REMOVED:6584	case BFI_DPORT_SCN_DDPORT_DISABLED:6585	case BFI_DPORT_SCN_DDPORT_DISABLE:6586	case BFI_DPORT_SCN_FCPORT_DISABLE:6587		dport->result.status = DPORT_TEST_ST_IDLE;6588		break;6589 6590	default:6591		bfa_sm_fault(dport->bfa, msg->state);6592	}6593 6594	bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);6595}6596 6597/*6598 * Dport enable6599 *6600 * @param[in] *bfa            - bfa data struct6601 */6602bfa_status_t6603bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,6604				bfa_cb_diag_t cbfn, void *cbarg)6605{6606	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);6607	struct bfa_dport_s  *dport = &fcdiag->dport;6608 6609	/*6610	 * Dport is not support in MEZZ card6611	 */6612	if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {6613		bfa_trc(dport->bfa, BFA_STATUS_PBC);6614		return BFA_STATUS_CMD_NOTSUPP_MEZZ;6615	}6616 6617	/*6618	 * Dport is supported in CT2 or above6619	 */6620	if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {6621		bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);6622		return BFA_STATUS_FEATURE_NOT_SUPPORTED;6623	}6624 6625	/*6626	 * Check to see if IOC is down6627	*/6628	if (!bfa_iocfc_is_operational(bfa))6629		return BFA_STATUS_IOC_NON_OP;6630 6631	/* if port is PBC disabled, return error */6632	if (bfa_fcport_is_pbcdisabled(bfa)) {6633		bfa_trc(dport->bfa, BFA_STATUS_PBC);6634		return BFA_STATUS_PBC;6635	}6636 6637	/*6638	 * Check if port mode is FC port6639	 */6640	if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {6641		bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));6642		return BFA_STATUS_CMD_NOTSUPP_CNA;6643	}6644 6645	/*6646	 * Check if port is in LOOP mode6647	 */6648	if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||6649	    (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {6650		bfa_trc(dport->bfa, 0);6651		return BFA_STATUS_TOPOLOGY_LOOP;6652	}6653 6654	/*6655	 * Check if port is TRUNK mode6656	 */6657	if (bfa_fcport_is_trunk_enabled(bfa)) {6658		bfa_trc(dport->bfa, 0);6659		return BFA_STATUS_ERROR_TRUNK_ENABLED;6660	}6661 6662	/*6663	 * Check if diag loopback is running6664	 */6665	if (bfa_fcdiag_lb_is_running(bfa)) {6666		bfa_trc(dport->bfa, 0);6667		return BFA_STATUS_DIAG_BUSY;6668	}6669 6670	/*6671	 * Check to see if port is disable or in dport state6672	 */6673	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&6674	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {6675		bfa_trc(dport->bfa, 0);6676		return BFA_STATUS_PORT_NOT_DISABLED;6677	}6678 6679	/*6680	 * Check if dport is in dynamic mode6681	 */6682	if (dport->dynamic)6683		return BFA_STATUS_DDPORT_ERR;6684 6685	/*6686	 * Check if dport is busy6687	 */6688	if (bfa_dport_is_sending_req(dport))6689		return BFA_STATUS_DEVBUSY;6690 6691	/*6692	 * Check if dport is already enabled6693	 */6694	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {6695		bfa_trc(dport->bfa, 0);6696		return BFA_STATUS_DPORT_ENABLED;6697	}6698 6699	bfa_trc(dport->bfa, lpcnt);6700	bfa_trc(dport->bfa, pat);6701	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;6702	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;6703	dport->cbfn = cbfn;6704	dport->cbarg = cbarg;6705 6706	bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);6707	return BFA_STATUS_OK;6708}6709 6710/*6711 *	Dport disable6712 *6713 *	@param[in] *bfa            - bfa data struct6714 */6715bfa_status_t6716bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)6717{6718	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);6719	struct bfa_dport_s *dport = &fcdiag->dport;6720 6721	if (bfa_ioc_is_disabled(&bfa->ioc))6722		return BFA_STATUS_IOC_DISABLED;6723 6724	/* if port is PBC disabled, return error */6725	if (bfa_fcport_is_pbcdisabled(bfa)) {6726		bfa_trc(dport->bfa, BFA_STATUS_PBC);6727		return BFA_STATUS_PBC;6728	}6729 6730	/*6731	 * Check if dport is in dynamic mode6732	 */6733	if (dport->dynamic) {6734		return BFA_STATUS_DDPORT_ERR;6735	}6736 6737	/*6738	 * Check to see if port is disable or in dport state6739	 */6740	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&6741	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {6742		bfa_trc(dport->bfa, 0);6743		return BFA_STATUS_PORT_NOT_DISABLED;6744	}6745 6746	/*6747	 * Check if dport is busy6748	 */6749	if (bfa_dport_is_sending_req(dport))6750		return BFA_STATUS_DEVBUSY;6751 6752	/*6753	 * Check if dport is already disabled6754	 */6755	if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {6756		bfa_trc(dport->bfa, 0);6757		return BFA_STATUS_DPORT_DISABLED;6758	}6759 6760	dport->cbfn = cbfn;6761	dport->cbarg = cbarg;6762 6763	bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);6764	return BFA_STATUS_OK;6765}6766 6767/*6768 * Dport start -- restart dport test6769 *6770 *   @param[in] *bfa		- bfa data struct6771 */6772bfa_status_t6773bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,6774			bfa_cb_diag_t cbfn, void *cbarg)6775{6776	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);6777	struct bfa_dport_s *dport = &fcdiag->dport;6778 6779	/*6780	 * Check to see if IOC is down6781	 */6782	if (!bfa_iocfc_is_operational(bfa))6783		return BFA_STATUS_IOC_NON_OP;6784 6785	/*6786	 * Check if dport is in dynamic mode6787	 */6788	if (dport->dynamic)6789		return BFA_STATUS_DDPORT_ERR;6790 6791	/*6792	 * Check if dport is busy6793	 */6794	if (bfa_dport_is_sending_req(dport))6795		return BFA_STATUS_DEVBUSY;6796 6797	/*6798	 * Check if dport is in enabled state.6799	 * Test can only be restart when previous test has completed6800	 */6801	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {6802		bfa_trc(dport->bfa, 0);6803		return BFA_STATUS_DPORT_DISABLED;6804 6805	} else {6806		if (dport->test_state == BFA_DPORT_ST_NO_SFP)6807			return BFA_STATUS_DPORT_INV_SFP;6808 6809		if (dport->test_state == BFA_DPORT_ST_INP)6810			return BFA_STATUS_DEVBUSY;6811 6812		WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);6813	}6814 6815	bfa_trc(dport->bfa, lpcnt);6816	bfa_trc(dport->bfa, pat);6817 6818	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;6819	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;6820 6821	dport->cbfn = cbfn;6822	dport->cbarg = cbarg;6823 6824	bfa_sm_send_event(dport, BFA_DPORT_SM_START);6825	return BFA_STATUS_OK;6826}6827 6828/*6829 * Dport show -- return dport test result6830 *6831 *   @param[in] *bfa		- bfa data struct6832 */6833bfa_status_t6834bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)6835{6836	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);6837	struct bfa_dport_s *dport = &fcdiag->dport;6838 6839	/*6840	 * Check to see if IOC is down6841	 */6842	if (!bfa_iocfc_is_operational(bfa))6843		return BFA_STATUS_IOC_NON_OP;6844 6845	/*6846	 * Check if dport is busy6847	 */6848	if (bfa_dport_is_sending_req(dport))6849		return BFA_STATUS_DEVBUSY;6850 6851	/*6852	 * Check if dport is in enabled state.6853	 */6854	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {6855		bfa_trc(dport->bfa, 0);6856		return BFA_STATUS_DPORT_DISABLED;6857 6858	}6859 6860	/*6861	 * Check if there is SFP6862	 */6863	if (dport->test_state == BFA_DPORT_ST_NO_SFP)6864		return BFA_STATUS_DPORT_INV_SFP;6865 6866	memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));6867 6868	return BFA_STATUS_OK;6869}6870