File Index
Files and directories
Sign in
FILE

bfa_svc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/scsi/bfa/bfa_svc.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
   4 * Copyright (c) 2014- QLogic Corporation.
   5 * All rights reserved
   6 * www.qlogic.com
   7 *
   8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
   9 */
  10
  11#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 definitions
  21 */
  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  255
  29#define BFA_LPS_MAX_VPORTS_SUPP_CT  190
  30
  31
  32/*
  33 * FC PORT related definitions
  34 */
  35/*
  36 * The port is considered disabled if corresponding physical port or IOC are
  37 * disabled explicitly
  38 */
  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 definitions
  45 */
  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 functions
  66 */
  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 functions
  78 */
  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 machine
  95 */
  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_event
  99					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_event
 105					event);
 106
 107/*
 108 * forward declaration for FC Port functions
 109 */
 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 machine
 127 */
 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_states
 181bfa_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 functions
 211 */
 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 machine
 224 */
 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 definitions
 254 */
 255static int
 256plkd_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 void
 270bfa_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
 296void
 297bfa_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
 306void
 307bfa_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
 326void
 327bfa_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
 353void
 354bfa_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
 370void
 371bfa_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 functions
 391 */
 392
 393static void
 394claim_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
 431void
 432bfa_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	else
 448		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		} else
 460			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
 469void
 470bfa_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
 491void
 492bfa_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	else
 524		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 void
 533bfa_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 sgpgs
 563		 */
 564		if (n_sgles > BFI_SGE_INLINE)
 565			WARN_ON(1);
 566	}
 567
 568}
 569
 570static void
 571bfa_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 void
 598bfa_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	else
 606		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	else
 626		list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
 627}
 628
 629static void
 630bfa_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 void
 638__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 void
 652hal_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 everything
 664	 *	 is received.
 665	 */
 666	if (fcxp_rsp->req_status == BFA_STATUS_OK)
 667		fcxp_rsp->residue_len = 0;
 668	else
 669		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 callback
 685			 */
 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 void
 702hal_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_id
 707	 */
 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 void
 730hal_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 void
 758bfa_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 void
 773bfa_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 sgles
 806	 */
 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 sgles
 823	 */
 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 request
 851 * that has a response. Request/response buffers are allocated by caller.
 852 *
 853 * @param[in]	bfa		BFA bfa instance
 854 * @param[in]	nreq_sgles	Number of SG elements required for request
 855 *				buffer. 0, if fcxp internal buffers are	used.
 856 *				Use bfa_fcxp_get_reqbuf() to get the
 857 *				internal req buffer.
 858 * @param[in]	req_sgles	SG elements describing request buffer. Will be
 859 *				copied in by BFA and hence can be freed on
 860 *				return from this function.
 861 * @param[in]	get_req_sga	function ptr to be called to get a request SG
 862 *				Address (given the sge index).
 863 * @param[in]	get_req_sglen	function ptr to be called to get a request SG
 864 *				len (given the sge index).
 865 * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
 866 *				Address (given the sge index).
 867 * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
 868 *				len (given the sge index).
 869 * @param[in]	req		Allocated FCXP is used to send req or rsp?
 870 *				request - BFA_TRUE, response - BFA_FALSE
 871 *
 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 pointer
 899 *
 900 * @param[in]	fcxp	BFA fcxp pointer
 901 *
 902 * @return		pointer to the internal request buffer
 903 */
 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
 916/*
 917 * Get the internal response buffer pointer
 918 *
 919 * @param[in]	fcxp	BFA fcxp pointer
 920 *
 921 * @return		pointer to the internal request buffer
 922 */
 923void *
 924bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
 925{
 926	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 927	void	*fcxp_buf;
 928
 929	WARN_ON(fcxp->use_irspbuf != 1);
 930
 931	fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
 932				mod->req_pld_sz + mod->rsp_pld_sz);
 933
 934	/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
 935	return ((u8 *) fcxp_buf) + mod->req_pld_sz;
 936}
 937
 938/*
 939 * Free the BFA FCXP
 940 *
 941 * @param[in]	fcxp			BFA fcxp pointer
 942 *
 943 * @return		void
 944 */
 945void
 946bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
 947{
 948	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
 949
 950	WARN_ON(fcxp == NULL);
 951	bfa_trc(mod->bfa, fcxp->fcxp_tag);
 952	bfa_fcxp_put(fcxp);
 953}
 954
 955/*
 956 * Send a FCXP request
 957 *
 958 * @param[in]	fcxp	BFA fcxp pointer
 959 * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
 960 * @param[in]	vf_id	virtual Fabric ID
 961 * @param[in]	lp_tag	lport tag
 962 * @param[in]	cts	use Continuous sequence
 963 * @param[in]	cos	fc Class of Service
 964 * @param[in]	reqlen	request length, does not include FCHS length
 965 * @param[in]	fchs	fc Header Pointer. The header content will be copied
 966 *			in by BFA.
 967 *
 968 * @param[in]	cbfn	call back function to be called on receiving
 969 *								the response
 970 * @param[in]	cbarg	arg for cbfn
 971 * @param[in]	rsp_timeout
 972 *			response timeout
 973 *
 974 * @return		bfa_status_t
 975 */
 976void
 977bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
 978	      u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
 979	      u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
 980	      void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
 981{
 982	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
 983	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
 984	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
 985	struct bfi_fcxp_send_req_s	*send_req;
 986
 987	bfa_trc(bfa, fcxp->fcxp_tag);
 988
 989	/*
 990	 * setup request/response info
 991	 */
 992	reqi->bfa_rport = rport;
 993	reqi->vf_id = vf_id;
 994	reqi->lp_tag = lp_tag;
 995	reqi->class = cos;
 996	rspi->rsp_timeout = rsp_timeout;
 997	reqi->cts = cts;
 998	reqi->fchs = *fchs;
 999	reqi->req_tot_len = reqlen;
1000	rspi->rsp_maxlen = rsp_maxlen;
1001	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1002	fcxp->send_cbarg = cbarg;
1003
1004	/*
1005	 * If no room in CPE queue, wait for space in request queue
1006	 */
1007	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1008	if (!send_req) {
1009		bfa_trc(bfa, fcxp->fcxp_tag);
1010		fcxp->reqq_waiting = BFA_TRUE;
1011		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1012		return;
1013	}
1014
1015	bfa_fcxp_queue(fcxp, send_req);
1016}
1017
1018void
1019bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1020	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1021	       void *caller, int nreq_sgles,
1022	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1023	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
1024	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1025	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1026{
1027	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1028
1029	if (req)
1030		WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1031	else
1032		WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1033
1034	wqe->alloc_cbfn = alloc_cbfn;
1035	wqe->alloc_cbarg = alloc_cbarg;
1036	wqe->caller = caller;
1037	wqe->bfa = bfa;
1038	wqe->nreq_sgles = nreq_sgles;
1039	wqe->nrsp_sgles = nrsp_sgles;
1040	wqe->req_sga_cbfn = req_sga_cbfn;
1041	wqe->req_sglen_cbfn = req_sglen_cbfn;
1042	wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1043	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1044
1045	if (req)
1046		list_add_tail(&wqe->qe, &mod->req_wait_q);
1047	else
1048		list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1049}
1050
1051void
1052bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1053{
1054	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1055
1056	WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1057		!bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1058	list_del(&wqe->qe);
1059}
1060
1061void
1062bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1063{
1064	/*
1065	 * If waiting for room in request queue, cancel reqq wait
1066	 * and free fcxp.
1067	 */
1068	if (fcxp->reqq_waiting) {
1069		fcxp->reqq_waiting = BFA_FALSE;
1070		bfa_reqq_wcancel(&fcxp->reqq_wqe);
1071		bfa_fcxp_free(fcxp);
1072		return;
1073	}
1074
1075	fcxp->send_cbfn = bfa_fcxp_null_comp;
1076}
1077
1078void
1079bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1080{
1081	switch (msg->mhdr.msg_id) {
1082	case BFI_FCXP_I2H_SEND_RSP:
1083		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1084		break;
1085
1086	default:
1087		bfa_trc(bfa, msg->mhdr.msg_id);
1088		WARN_ON(1);
1089	}
1090}
1091
1092u32
1093bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1094{
1095	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1096
1097	return mod->rsp_pld_sz;
1098}
1099
1100void
1101bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1102{
1103	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
1104	struct list_head	*qe;
1105	int	i;
1106
1107	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1108		if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1109			bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1110			list_add_tail(qe, &mod->fcxp_req_unused_q);
1111		} else {
1112			bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1113			list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1114		}
1115	}
1116}
1117
1118/*
1119 *  BFA LPS state machine functions
1120 */
1121
1122/*
1123 * Init state -- no login
1124 */
1125static void
1126bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1127{
1128	bfa_trc(lps->bfa, lps->bfa_tag);
1129	bfa_trc(lps->bfa, event);
1130
1131	switch (event) {
1132	case BFA_LPS_SM_LOGIN:
1133		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1134			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1135			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1136		} else {
1137			bfa_sm_set_state(lps, bfa_lps_sm_login);
1138			bfa_lps_send_login(lps);
1139		}
1140
1141		if (lps->fdisc)
1142			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1143				BFA_PL_EID_LOGIN, 0, "FDISC Request");
1144		else
1145			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1146				BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1147		break;
1148
1149	case BFA_LPS_SM_LOGOUT:
1150		bfa_lps_logout_comp(lps);
1151		break;
1152
1153	case BFA_LPS_SM_DELETE:
1154		bfa_lps_free(lps);
1155		break;
1156
1157	case BFA_LPS_SM_RX_CVL:
1158	case BFA_LPS_SM_OFFLINE:
1159		break;
1160
1161	case BFA_LPS_SM_FWRSP:
1162		/*
1163		 * Could happen when fabric detects loopback and discards
1164		 * the lps request. Fw will eventually sent out the timeout
1165		 * Just ignore
1166		 */
1167		break;
1168	case BFA_LPS_SM_SET_N2N_PID:
1169		/*
1170		 * When topology is set to loop, bfa_lps_set_n2n_pid() sends
1171		 * this event. Ignore this event.
1172		 */
1173		break;
1174
1175	default:
1176		bfa_sm_fault(lps->bfa, event);
1177	}
1178}
1179
1180/*
1181 * login is in progress -- awaiting response from firmware
1182 */
1183static void
1184bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1185{
1186	bfa_trc(lps->bfa, lps->bfa_tag);
1187	bfa_trc(lps->bfa, event);
1188
1189	switch (event) {
1190	case BFA_LPS_SM_FWRSP:
1191		if (lps->status == BFA_STATUS_OK) {
1192			bfa_sm_set_state(lps, bfa_lps_sm_online);
1193			if (lps->fdisc)
1194				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1195					BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1196			else
1197				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1198					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1199			/* If N2N, send the assigned PID to FW */
1200			bfa_trc(lps->bfa, lps->fport);
1201			bfa_trc(lps->bfa, lps->lp_pid);
1202
1203			if (!lps->fport && lps->lp_pid)
1204				bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1205		} else {
1206			bfa_sm_set_state(lps, bfa_lps_sm_init);
1207			if (lps->fdisc)
1208				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1209					BFA_PL_EID_LOGIN, 0,
1210					"FDISC Fail (RJT or timeout)");
1211			else
1212				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1213					BFA_PL_EID_LOGIN, 0,
1214					"FLOGI Fail (RJT or timeout)");
1215		}
1216		bfa_lps_login_comp(lps);
1217		break;
1218
1219	case BFA_LPS_SM_OFFLINE:
1220	case BFA_LPS_SM_DELETE:
1221		bfa_sm_set_state(lps, bfa_lps_sm_init);
1222		break;
1223
1224	case BFA_LPS_SM_SET_N2N_PID:
1225		bfa_trc(lps->bfa, lps->fport);
1226		bfa_trc(lps->bfa, lps->lp_pid);
1227		break;
1228
1229	default:
1230		bfa_sm_fault(lps->bfa, event);
1231	}
1232}
1233
1234/*
1235 * login pending - awaiting space in request queue
1236 */
1237static void
1238bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1239{
1240	bfa_trc(lps->bfa, lps->bfa_tag);
1241	bfa_trc(lps->bfa, event);
1242
1243	switch (event) {
1244	case BFA_LPS_SM_RESUME:
1245		bfa_sm_set_state(lps, bfa_lps_sm_login);
1246		bfa_lps_send_login(lps);
1247		break;
1248
1249	case BFA_LPS_SM_OFFLINE:
1250	case BFA_LPS_SM_DELETE:
1251		bfa_sm_set_state(lps, bfa_lps_sm_init);
1252		bfa_reqq_wcancel(&lps->wqe);
1253		break;
1254
1255	case BFA_LPS_SM_RX_CVL:
1256		/*
1257		 * Login was not even sent out; so when getting out
1258		 * of this state, it will appear like a login retry
1259		 * after Clear virtual link
1260		 */
1261		break;
1262
1263	default:
1264		bfa_sm_fault(lps->bfa, event);
1265	}
1266}
1267
1268/*
1269 * login complete
1270 */
1271static void
1272bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1273{
1274	bfa_trc(lps->bfa, lps->bfa_tag);
1275	bfa_trc(lps->bfa, event);
1276
1277	switch (event) {
1278	case BFA_LPS_SM_LOGOUT:
1279		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1280			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1281			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1282		} else {
1283			bfa_sm_set_state(lps, bfa_lps_sm_logout);
1284			bfa_lps_send_logout(lps);
1285		}
1286		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1287			BFA_PL_EID_LOGO, 0, "Logout");
1288		break;
1289
1290	case BFA_LPS_SM_RX_CVL:
1291		bfa_sm_set_state(lps, bfa_lps_sm_init);
1292
1293		/* Let the vport module know about this event */
1294		bfa_lps_cvl_event(lps);
1295		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1296			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1297		break;
1298
1299	case BFA_LPS_SM_SET_N2N_PID:
1300		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1301			bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1302			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1303		} else
1304			bfa_lps_send_set_n2n_pid(lps);
1305		break;
1306
1307	case BFA_LPS_SM_OFFLINE:
1308	case BFA_LPS_SM_DELETE:
1309		bfa_sm_set_state(lps, bfa_lps_sm_init);
1310		break;
1311
1312	default:
1313		bfa_sm_fault(lps->bfa, event);
1314	}
1315}
1316
1317/*
1318 * login complete
1319 */
1320static void
1321bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1322{
1323	bfa_trc(lps->bfa, lps->bfa_tag);
1324	bfa_trc(lps->bfa, event);
1325
1326	switch (event) {
1327	case BFA_LPS_SM_RESUME:
1328		bfa_sm_set_state(lps, bfa_lps_sm_online);
1329		bfa_lps_send_set_n2n_pid(lps);
1330		break;
1331
1332	case BFA_LPS_SM_LOGOUT:
1333		bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1334		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1335			BFA_PL_EID_LOGO, 0, "Logout");
1336		break;
1337
1338	case BFA_LPS_SM_RX_CVL:
1339		bfa_sm_set_state(lps, bfa_lps_sm_init);
1340		bfa_reqq_wcancel(&lps->wqe);
1341
1342		/* Let the vport module know about this event */
1343		bfa_lps_cvl_event(lps);
1344		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1345			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1346		break;
1347
1348	case BFA_LPS_SM_OFFLINE:
1349	case BFA_LPS_SM_DELETE:
1350		bfa_sm_set_state(lps, bfa_lps_sm_init);
1351		bfa_reqq_wcancel(&lps->wqe);
1352		break;
1353
1354	default:
1355		bfa_sm_fault(lps->bfa, event);
1356	}
1357}
1358
1359/*
1360 * logout in progress - awaiting firmware response
1361 */
1362static void
1363bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1364{
1365	bfa_trc(lps->bfa, lps->bfa_tag);
1366	bfa_trc(lps->bfa, event);
1367
1368	switch (event) {
1369	case BFA_LPS_SM_FWRSP:
1370	case BFA_LPS_SM_OFFLINE:
1371		bfa_sm_set_state(lps, bfa_lps_sm_init);
1372		bfa_lps_logout_comp(lps);
1373		break;
1374
1375	case BFA_LPS_SM_DELETE:
1376		bfa_sm_set_state(lps, bfa_lps_sm_init);
1377		break;
1378
1379	default:
1380		bfa_sm_fault(lps->bfa, event);
1381	}
1382}
1383
1384/*
1385 * logout pending -- awaiting space in request queue
1386 */
1387static void
1388bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1389{
1390	bfa_trc(lps->bfa, lps->bfa_tag);
1391	bfa_trc(lps->bfa, event);
1392
1393	switch (event) {
1394	case BFA_LPS_SM_RESUME:
1395		bfa_sm_set_state(lps, bfa_lps_sm_logout);
1396		bfa_lps_send_logout(lps);
1397		break;
1398
1399	case BFA_LPS_SM_OFFLINE:
1400	case BFA_LPS_SM_DELETE:
1401		bfa_sm_set_state(lps, bfa_lps_sm_init);
1402		bfa_reqq_wcancel(&lps->wqe);
1403		break;
1404
1405	default:
1406		bfa_sm_fault(lps->bfa, event);
1407	}
1408}
1409
1410
1411
1412/*
1413 *  lps_pvt BFA LPS private functions
1414 */
1415
1416/*
1417 * return memory requirement
1418 */
1419void
1420bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
1421		struct bfa_s *bfa)
1422{
1423	struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
1424
1425	if (cfg->drvcfg.min_cfg)
1426		bfa_mem_kva_setup(minfo, lps_kva,
1427			sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
1428	else
1429		bfa_mem_kva_setup(minfo, lps_kva,
1430			sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
1431}
1432
1433/*
1434 * bfa module attach at initialization time
1435 */
1436void
1437bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1438	struct bfa_pcidev_s *pcidev)
1439{
1440	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1441	struct bfa_lps_s	*lps;
1442	int			i;
1443
1444	mod->num_lps = BFA_LPS_MAX_LPORTS;
1445	if (cfg->drvcfg.min_cfg)
1446		mod->num_lps = BFA_LPS_MIN_LPORTS;
1447	else
1448		mod->num_lps = BFA_LPS_MAX_LPORTS;
1449	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
1450
1451	bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
1452
1453	INIT_LIST_HEAD(&mod->lps_free_q);
1454	INIT_LIST_HEAD(&mod->lps_active_q);
1455	INIT_LIST_HEAD(&mod->lps_login_q);
1456
1457	for (i = 0; i < mod->num_lps; i++, lps++) {
1458		lps->bfa	= bfa;
1459		lps->bfa_tag	= (u8) i;
1460		lps->reqq	= BFA_REQQ_LPS;
1461		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1462		list_add_tail(&lps->qe, &mod->lps_free_q);
1463	}
1464}
1465
1466/*
1467 * IOC in disabled state -- consider all lps offline
1468 */
1469void
1470bfa_lps_iocdisable(struct bfa_s *bfa)
1471{
1472	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1473	struct bfa_lps_s	*lps;
1474	struct list_head		*qe, *qen;
1475
1476	list_for_each_safe(qe, qen, &mod->lps_active_q) {
1477		lps = (struct bfa_lps_s *) qe;
1478		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1479	}
1480	list_for_each_safe(qe, qen, &mod->lps_login_q) {
1481		lps = (struct bfa_lps_s *) qe;
1482		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1483	}
1484	list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
1485}
1486
1487/*
1488 * Firmware login response
1489 */
1490static void
1491bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1492{
1493	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1494	struct bfa_lps_s	*lps;
1495
1496	WARN_ON(rsp->bfa_tag >= mod->num_lps);
1497	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1498
1499	lps->status = rsp->status;
1500	switch (rsp->status) {
1501	case BFA_STATUS_OK:
1502		lps->fw_tag	= rsp->fw_tag;
1503		lps->fport	= rsp->f_port;
1504		if (lps->fport)
1505			lps->lp_pid = rsp->lp_pid;
1506		lps->npiv_en	= rsp->npiv_en;
1507		lps->pr_bbcred	= be16_to_cpu(rsp->bb_credit);
1508		lps->pr_pwwn	= rsp->port_name;
1509		lps->pr_nwwn	= rsp->node_name;
1510		lps->auth_req	= rsp->auth_req;
1511		lps->lp_mac	= rsp->lp_mac;
1512		lps->brcd_switch = rsp->brcd_switch;
1513		lps->fcf_mac	= rsp->fcf_mac;
1514
1515		break;
1516
1517	case BFA_STATUS_FABRIC_RJT:
1518		lps->lsrjt_rsn = rsp->lsrjt_rsn;
1519		lps->lsrjt_expl = rsp->lsrjt_expl;
1520
1521		break;
1522
1523	case BFA_STATUS_EPROTOCOL:
1524		lps->ext_status = rsp->ext_status;
1525
1526		break;
1527
1528	case BFA_STATUS_VPORT_MAX:
1529		if (rsp->ext_status)
1530			bfa_lps_no_res(lps, rsp->ext_status);
1531		break;
1532
1533	default:
1534		/* Nothing to do with other status */
1535		break;
1536	}
1537
1538	list_del(&lps->qe);
1539	list_add_tail(&lps->qe, &mod->lps_active_q);
1540	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1541}
1542
1543static void
1544bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1545{
1546	struct bfa_s		*bfa = first_lps->bfa;
1547	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1548	struct list_head	*qe, *qe_next;
1549	struct bfa_lps_s	*lps;
1550
1551	bfa_trc(bfa, count);
1552
1553	qe = bfa_q_next(first_lps);
1554
1555	while (count && qe) {
1556		qe_next = bfa_q_next(qe);
1557		lps = (struct bfa_lps_s *)qe;
1558		bfa_trc(bfa, lps->bfa_tag);
1559		lps->status = first_lps->status;
1560		list_del(&lps->qe);
1561		list_add_tail(&lps->qe, &mod->lps_active_q);
1562		bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1563		qe = qe_next;
1564		count--;
1565	}
1566}
1567
1568/*
1569 * Firmware logout response
1570 */
1571static void
1572bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1573{
1574	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1575	struct bfa_lps_s	*lps;
1576
1577	WARN_ON(rsp->bfa_tag >= mod->num_lps);
1578	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1579
1580	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1581}
1582
1583/*
1584 * Firmware received a Clear virtual link request (for FCoE)
1585 */
1586static void
1587bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1588{
1589	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1590	struct bfa_lps_s	*lps;
1591
1592	lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
1593
1594	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1595}
1596
1597/*
1598 * Space is available in request queue, resume queueing request to firmware.
1599 */
1600static void
1601bfa_lps_reqq_resume(void *lps_arg)
1602{
1603	struct bfa_lps_s	*lps = lps_arg;
1604
1605	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1606}
1607
1608/*
1609 * lps is freed -- triggered by vport delete
1610 */
1611static void
1612bfa_lps_free(struct bfa_lps_s *lps)
1613{
1614	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
1615
1616	lps->lp_pid = 0;
1617	list_del(&lps->qe);
1618	list_add_tail(&lps->qe, &mod->lps_free_q);
1619}
1620
1621/*
1622 * send login request to firmware
1623 */
1624static void
1625bfa_lps_send_login(struct bfa_lps_s *lps)
1626{
1627	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
1628	struct bfi_lps_login_req_s	*m;
1629
1630	m = bfa_reqq_next(lps->bfa, lps->reqq);
1631	WARN_ON(!m);
1632
1633	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1634		bfa_fn_lpu(lps->bfa));
1635
1636	m->bfa_tag	= lps->bfa_tag;
1637	m->alpa		= lps->alpa;
1638	m->pdu_size	= cpu_to_be16(lps->pdusz);
1639	m->pwwn		= lps->pwwn;
1640	m->nwwn		= lps->nwwn;
1641	m->fdisc	= lps->fdisc;
1642	m->auth_en	= lps->auth_en;
1643
1644	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1645	list_del(&lps->qe);
1646	list_add_tail(&lps->qe, &mod->lps_login_q);
1647}
1648
1649/*
1650 * send logout request to firmware
1651 */
1652static void
1653bfa_lps_send_logout(struct bfa_lps_s *lps)
1654{
1655	struct bfi_lps_logout_req_s *m;
1656
1657	m = bfa_reqq_next(lps->bfa, lps->reqq);
1658	WARN_ON(!m);
1659
1660	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1661		bfa_fn_lpu(lps->bfa));
1662
1663	m->fw_tag = lps->fw_tag;
1664	m->port_name = lps->pwwn;
1665	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1666}
1667
1668/*
1669 * send n2n pid set request to firmware
1670 */
1671static void
1672bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1673{
1674	struct bfi_lps_n2n_pid_req_s *m;
1675
1676	m = bfa_reqq_next(lps->bfa, lps->reqq);
1677	WARN_ON(!m);
1678
1679	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1680		bfa_fn_lpu(lps->bfa));
1681
1682	m->fw_tag = lps->fw_tag;
1683	m->lp_pid = lps->lp_pid;
1684	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1685}
1686
1687/*
1688 * Indirect login completion handler for non-fcs
1689 */
1690static void
1691bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1692{
1693	struct bfa_lps_s *lps	= arg;
1694
1695	if (!complete)
1696		return;
1697
1698	if (lps->fdisc)
1699		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1700	else
1701		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1702}
1703
1704/*
1705 * Login completion handler -- direct call for fcs, queue for others
1706 */
1707static void
1708bfa_lps_login_comp(struct bfa_lps_s *lps)
1709{
1710	if (!lps->bfa->fcs) {
1711		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1712			lps);
1713		return;
1714	}
1715
1716	if (lps->fdisc)
1717		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1718	else
1719		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1720}
1721
1722/*
1723 * Indirect logout completion handler for non-fcs
1724 */
1725static void
1726bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1727{
1728	struct bfa_lps_s *lps	= arg;
1729
1730	if (!complete)
1731		return;
1732
1733	if (lps->fdisc)
1734		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1735	else
1736		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1737}
1738
1739/*
1740 * Logout completion handler -- direct call for fcs, queue for others
1741 */
1742static void
1743bfa_lps_logout_comp(struct bfa_lps_s *lps)
1744{
1745	if (!lps->bfa->fcs) {
1746		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1747			lps);
1748		return;
1749	}
1750	if (lps->fdisc)
1751		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1752}
1753
1754/*
1755 * Clear virtual link completion handler for non-fcs
1756 */
1757static void
1758bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1759{
1760	struct bfa_lps_s *lps	= arg;
1761
1762	if (!complete)
1763		return;
1764
1765	/* Clear virtual link to base port will result in link down */
1766	if (lps->fdisc)
1767		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1768}
1769
1770/*
1771 * Received Clear virtual link event --direct call for fcs,
1772 * queue for others
1773 */
1774static void
1775bfa_lps_cvl_event(struct bfa_lps_s *lps)
1776{
1777	if (!lps->bfa->fcs) {
1778		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1779			lps);
1780		return;
1781	}
1782
1783	/* Clear virtual link to base port will result in link down */
1784	if (lps->fdisc)
1785		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1786}
1787
1788
1789
1790/*
1791 *  lps_public BFA LPS public functions
1792 */
1793
1794u32
1795bfa_lps_get_max_vport(struct bfa_s *bfa)
1796{
1797	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1798		return BFA_LPS_MAX_VPORTS_SUPP_CT;
1799	else
1800		return BFA_LPS_MAX_VPORTS_SUPP_CB;
1801}
1802
1803/*
1804 * Allocate a lport srvice tag.
1805 */
1806struct bfa_lps_s  *
1807bfa_lps_alloc(struct bfa_s *bfa)
1808{
1809	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1810	struct bfa_lps_s	*lps = NULL;
1811
1812	bfa_q_deq(&mod->lps_free_q, &lps);
1813
1814	if (lps == NULL)
1815		return NULL;
1816
1817	list_add_tail(&lps->qe, &mod->lps_active_q);
1818
1819	bfa_sm_set_state(lps, bfa_lps_sm_init);
1820	return lps;
1821}
1822
1823/*
1824 * Free lport service tag. This can be called anytime after an alloc.
1825 * No need to wait for any pending login/logout completions.
1826 */
1827void
1828bfa_lps_delete(struct bfa_lps_s *lps)
1829{
1830	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1831}
1832
1833/*
1834 * Initiate a lport login.
1835 */
1836void
1837bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1838	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1839{
1840	lps->uarg	= uarg;
1841	lps->alpa	= alpa;
1842	lps->pdusz	= pdusz;
1843	lps->pwwn	= pwwn;
1844	lps->nwwn	= nwwn;
1845	lps->fdisc	= BFA_FALSE;
1846	lps->auth_en	= auth_en;
1847	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1848}
1849
1850/*
1851 * Initiate a lport fdisc login.
1852 */
1853void
1854bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1855	wwn_t nwwn)
1856{
1857	lps->uarg	= uarg;
1858	lps->alpa	= 0;
1859	lps->pdusz	= pdusz;
1860	lps->pwwn	= pwwn;
1861	lps->nwwn	= nwwn;
1862	lps->fdisc	= BFA_TRUE;
1863	lps->auth_en	= BFA_FALSE;
1864	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1865}
1866
1867
1868/*
1869 * Initiate a lport FDSIC logout.
1870 */
1871void
1872bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1873{
1874	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1875}
1876
1877u8
1878bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1879{
1880	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1881
1882	return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1883}
1884
1885/*
1886 * Return lport services tag given the pid
1887 */
1888u8
1889bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1890{
1891	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1892	struct bfa_lps_s	*lps;
1893	int			i;
1894
1895	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1896		if (lps->lp_pid == pid)
1897			return lps->bfa_tag;
1898	}
1899
1900	/* Return base port tag anyway */
1901	return 0;
1902}
1903
1904
1905/*
1906 * return port id assigned to the base lport
1907 */
1908u32
1909bfa_lps_get_base_pid(struct bfa_s *bfa)
1910{
1911	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1912
1913	return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1914}
1915
1916/*
1917 * Set PID in case of n2n (which is assigned during PLOGI)
1918 */
1919void
1920bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1921{
1922	bfa_trc(lps->bfa, lps->bfa_tag);
1923	bfa_trc(lps->bfa, n2n_pid);
1924
1925	lps->lp_pid = n2n_pid;
1926	bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1927}
1928
1929/*
1930 * LPS firmware message class handler.
1931 */
1932void
1933bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1934{
1935	union bfi_lps_i2h_msg_u	msg;
1936
1937	bfa_trc(bfa, m->mhdr.msg_id);
1938	msg.msg = m;
1939
1940	switch (m->mhdr.msg_id) {
1941	case BFI_LPS_I2H_LOGIN_RSP:
1942		bfa_lps_login_rsp(bfa, msg.login_rsp);
1943		break;
1944
1945	case BFI_LPS_I2H_LOGOUT_RSP:
1946		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
1947		break;
1948
1949	case BFI_LPS_I2H_CVL_EVENT:
1950		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
1951		break;
1952
1953	default:
1954		bfa_trc(bfa, m->mhdr.msg_id);
1955		WARN_ON(1);
1956	}
1957}
1958
1959static void
1960bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
1961{
1962	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
1963	struct bfa_aen_entry_s  *aen_entry;
1964
1965	bfad_get_aen_entry(bfad, aen_entry);
1966	if (!aen_entry)
1967		return;
1968
1969	aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
1970	aen_entry->aen_data.port.pwwn = fcport->pwwn;
1971
1972	/* Send the AEN notification */
1973	bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
1974				  BFA_AEN_CAT_PORT, event);
1975}
1976
1977/*
1978 * FC PORT state machine functions
1979 */
1980static void
1981bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
1982			enum bfa_fcport_sm_event event)
1983{
1984	bfa_trc(fcport->bfa, event);
1985
1986	switch (event) {
1987	case BFA_FCPORT_SM_START:
1988		/*
1989		 * Start event after IOC is configured and BFA is started.
1990		 */
1991		fcport->use_flash_cfg = BFA_TRUE;
1992
1993		if (bfa_fcport_send_enable(fcport)) {
1994			bfa_trc(fcport->bfa, BFA_TRUE);
1995			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
1996		} else {
1997			bfa_trc(fcport->bfa, BFA_FALSE);
1998			bfa_sm_set_state(fcport,
1999					bfa_fcport_sm_enabling_qwait);
2000		}
2001		break;
2002
2003	case BFA_FCPORT_SM_ENABLE:
2004		/*
2005		 * Port is persistently configured to be in enabled state. Do
2006		 * not change state. Port enabling is done when START event is
2007		 * received.
2008		 */
2009		break;
2010
2011	case BFA_FCPORT_SM_DISABLE:
2012		/*
2013		 * If a port is persistently configured to be disabled, the
2014		 * first event will a port disable request.
2015		 */
2016		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2017		break;
2018
2019	case BFA_FCPORT_SM_HWFAIL:
2020		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2021		break;
2022
2023	default:
2024		bfa_sm_fault(fcport->bfa, event);
2025	}
2026}
2027
2028static void
2029bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2030				enum bfa_fcport_sm_event event)
2031{
2032	char pwwn_buf[BFA_STRING_32];
2033	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2034	bfa_trc(fcport->bfa, event);
2035
2036	switch (event) {
2037	case BFA_FCPORT_SM_QRESUME:
2038		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2039		bfa_fcport_send_enable(fcport);
2040		break;
2041
2042	case BFA_FCPORT_SM_STOP:
2043		bfa_reqq_wcancel(&fcport->reqq_wait);
2044		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2045		break;
2046
2047	case BFA_FCPORT_SM_ENABLE:
2048		/*
2049		 * Already enable is in progress.
2050		 */
2051		break;
2052
2053	case BFA_FCPORT_SM_DISABLE:
2054		/*
2055		 * Just send disable request to firmware when room becomes
2056		 * available in request queue.
2057		 */
2058		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2059		bfa_reqq_wcancel(&fcport->reqq_wait);
2060		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2061				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2062		wwn2str(pwwn_buf, fcport->pwwn);
2063		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2064			"Base port disabled: WWN = %s\n", pwwn_buf);
2065		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2066		break;
2067
2068	case BFA_FCPORT_SM_LINKUP:
2069	case BFA_FCPORT_SM_LINKDOWN:
2070		/*
2071		 * Possible to get link events when doing back-to-back
2072		 * enable/disables.
2073		 */
2074		break;
2075
2076	case BFA_FCPORT_SM_HWFAIL:
2077		bfa_reqq_wcancel(&fcport->reqq_wait);
2078		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2079		break;
2080
2081	case BFA_FCPORT_SM_FAA_MISCONFIG:
2082		bfa_fcport_reset_linkinfo(fcport);
2083		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2084		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2085		break;
2086
2087	default:
2088		bfa_sm_fault(fcport->bfa, event);
2089	}
2090}
2091
2092static void
2093bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2094						enum bfa_fcport_sm_event event)
2095{
2096	char pwwn_buf[BFA_STRING_32];
2097	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2098	bfa_trc(fcport->bfa, event);
2099
2100	switch (event) {
2101	case BFA_FCPORT_SM_FWRSP:
2102	case BFA_FCPORT_SM_LINKDOWN:
2103		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2104		break;
2105
2106	case BFA_FCPORT_SM_LINKUP:
2107		bfa_fcport_update_linkinfo(fcport);
2108		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2109
2110		WARN_ON(!fcport->event_cbfn);
2111		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2112		break;
2113
2114	case BFA_FCPORT_SM_ENABLE:
2115		/*
2116		 * Already being enabled.
2117		 */
2118		break;
2119
2120	case BFA_FCPORT_SM_DISABLE:
2121		if (bfa_fcport_send_disable(fcport))
2122			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2123		else
2124			bfa_sm_set_state(fcport,
2125					 bfa_fcport_sm_disabling_qwait);
2126
2127		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2128				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2129		wwn2str(pwwn_buf, fcport->pwwn);
2130		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2131			"Base port disabled: WWN = %s\n", pwwn_buf);
2132		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2133		break;
2134
2135	case BFA_FCPORT_SM_STOP:
2136		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2137		break;
2138
2139	case BFA_FCPORT_SM_HWFAIL:
2140		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2141		break;
2142
2143	case BFA_FCPORT_SM_FAA_MISCONFIG:
2144		bfa_fcport_reset_linkinfo(fcport);
2145		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2146		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2147		break;
2148
2149	default:
2150		bfa_sm_fault(fcport->bfa, event);
2151	}
2152}
2153
2154static void
2155bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2156						enum bfa_fcport_sm_event event)
2157{
2158	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2159	char pwwn_buf[BFA_STRING_32];
2160	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2161
2162	bfa_trc(fcport->bfa, event);
2163
2164	switch (event) {
2165	case BFA_FCPORT_SM_LINKUP:
2166		bfa_fcport_update_linkinfo(fcport);
2167		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2168		WARN_ON(!fcport->event_cbfn);
2169		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2170				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2171		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2172
2173			bfa_trc(fcport->bfa,
2174				pevent->link_state.attr.vc_fcf.fcf.fipenabled);
2175			bfa_trc(fcport->bfa,
2176				pevent->link_state.attr.vc_fcf.fcf.fipfailed);
2177
2178			if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
2179				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2180					BFA_PL_EID_FIP_FCF_DISC, 0,
2181					"FIP FCF Discovery Failed");
2182			else
2183				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2184					BFA_PL_EID_FIP_FCF_DISC, 0,
2185					"FIP FCF Discovered");
2186		}
2187
2188		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2189		wwn2str(pwwn_buf, fcport->pwwn);
2190		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2191			"Base port online: WWN = %s\n", pwwn_buf);
2192		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
2193
2194		/* If QoS is enabled and it is not online, send AEN */
2195		if (fcport->cfg.qos_enabled &&
2196		    fcport->qos_attr.state != BFA_QOS_ONLINE)
2197			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
2198		break;
2199
2200	case BFA_FCPORT_SM_LINKDOWN:
2201		/*
2202		 * Possible to get link down event.
2203		 */
2204		break;
2205
2206	case BFA_FCPORT_SM_ENABLE:
2207		/*
2208		 * Already enabled.
2209		 */
2210		break;
2211
2212	case BFA_FCPORT_SM_DISABLE:
2213		if (bfa_fcport_send_disable(fcport))
2214			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2215		else
2216			bfa_sm_set_state(fcport,
2217					 bfa_fcport_sm_disabling_qwait);
2218
2219		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2220				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2221		wwn2str(pwwn_buf, fcport->pwwn);
2222		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2223			"Base port disabled: WWN = %s\n", pwwn_buf);
2224		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2225		break;
2226
2227	case BFA_FCPORT_SM_STOP:
2228		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2229		break;
2230
2231	case BFA_FCPORT_SM_HWFAIL:
2232		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2233		break;
2234
2235	case BFA_FCPORT_SM_FAA_MISCONFIG:
2236		bfa_fcport_reset_linkinfo(fcport);
2237		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2238		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2239		break;
2240
2241	default:
2242		bfa_sm_fault(fcport->bfa, event);
2243	}
2244}
2245
2246static void
2247bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2248	enum bfa_fcport_sm_event event)
2249{
2250	char pwwn_buf[BFA_STRING_32];
2251	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2252
2253	bfa_trc(fcport->bfa, event);
2254
2255	switch (event) {
2256	case BFA_FCPORT_SM_ENABLE:
2257		/*
2258		 * Already enabled.
2259		 */
2260		break;
2261
2262	case BFA_FCPORT_SM_DISABLE:
2263		if (bfa_fcport_send_disable(fcport))
2264			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2265		else
2266			bfa_sm_set_state(fcport,
2267					 bfa_fcport_sm_disabling_qwait);
2268
2269		bfa_fcport_reset_linkinfo(fcport);
2270		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2271		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2272				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2273		wwn2str(pwwn_buf, fcport->pwwn);
2274		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2275			"Base port offline: WWN = %s\n", pwwn_buf);
2276		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2277		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2278			"Base port disabled: WWN = %s\n", pwwn_buf);
2279		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2280		break;
2281
2282	case BFA_FCPORT_SM_LINKDOWN:
2283		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2284		bfa_fcport_reset_linkinfo(fcport);
2285		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2286		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2287				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2288		wwn2str(pwwn_buf, fcport->pwwn);
2289		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2290			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2291				"Base port offline: WWN = %s\n", pwwn_buf);
2292			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2293		} else {
2294			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2295				"Base port (WWN = %s) "
2296				"lost fabric connectivity\n", pwwn_buf);
2297			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2298		}
2299		break;
2300
2301	case BFA_FCPORT_SM_STOP:
2302		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2303		bfa_fcport_reset_linkinfo(fcport);
2304		wwn2str(pwwn_buf, fcport->pwwn);
2305		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2306			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2307				"Base port offline: WWN = %s\n", pwwn_buf);
2308			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2309		} else {
2310			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2311				"Base port (WWN = %s) "
2312				"lost fabric connectivity\n", pwwn_buf);
2313			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2314		}
2315		break;
2316
2317	case BFA_FCPORT_SM_HWFAIL:
2318		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2319		bfa_fcport_reset_linkinfo(fcport);
2320		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2321		wwn2str(pwwn_buf, fcport->pwwn);
2322		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2323			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2324				"Base port offline: WWN = %s\n", pwwn_buf);
2325			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2326		} else {
2327			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2328				"Base port (WWN = %s) "
2329				"lost fabric connectivity\n", pwwn_buf);
2330			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2331		}
2332		break;
2333
2334	case BFA_FCPORT_SM_FAA_MISCONFIG:
2335		bfa_fcport_reset_linkinfo(fcport);
2336		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2337		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2338		break;
2339
2340	default:
2341		bfa_sm_fault(fcport->bfa, event);
2342	}
2343}
2344
2345static void
2346bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2347				 enum bfa_fcport_sm_event event)
2348{
2349	bfa_trc(fcport->bfa, event);
2350
2351	switch (event) {
2352	case BFA_FCPORT_SM_QRESUME:
2353		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2354		bfa_fcport_send_disable(fcport);
2355		break;
2356
2357	case BFA_FCPORT_SM_STOP:
2358		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2359		bfa_reqq_wcancel(&fcport->reqq_wait);
2360		break;
2361
2362	case BFA_FCPORT_SM_ENABLE:
2363		bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2364		break;
2365
2366	case BFA_FCPORT_SM_DISABLE:
2367		/*
2368		 * Already being disabled.
2369		 */
2370		break;
2371
2372	case BFA_FCPORT_SM_LINKUP:
2373	case BFA_FCPORT_SM_LINKDOWN:
2374		/*
2375		 * Possible to get link events when doing back-to-back
2376		 * enable/disables.
2377		 */
2378		break;
2379
2380	case BFA_FCPORT_SM_HWFAIL:
2381		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2382		bfa_reqq_wcancel(&fcport->reqq_wait);
2383		break;
2384
2385	case BFA_FCPORT_SM_FAA_MISCONFIG:
2386		bfa_fcport_reset_linkinfo(fcport);
2387		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2388		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2389		break;
2390
2391	default:
2392		bfa_sm_fault(fcport->bfa, event);
2393	}
2394}
2395
2396static void
2397bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2398				 enum bfa_fcport_sm_event event)
2399{
2400	bfa_trc(fcport->bfa, event);
2401
2402	switch (event) {
2403	case BFA_FCPORT_SM_QRESUME:
2404		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2405		bfa_fcport_send_disable(fcport);
2406		if (bfa_fcport_send_enable(fcport))
2407			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2408		else
2409			bfa_sm_set_state(fcport,
2410					 bfa_fcport_sm_enabling_qwait);
2411		break;
2412
2413	case BFA_FCPORT_SM_STOP:
2414		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2415		bfa_reqq_wcancel(&fcport->reqq_wait);
2416		break;
2417
2418	case BFA_FCPORT_SM_ENABLE:
2419		break;
2420
2421	case BFA_FCPORT_SM_DISABLE:
2422		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2423		break;
2424
2425	case BFA_FCPORT_SM_LINKUP:
2426	case BFA_FCPORT_SM_LINKDOWN:
2427		/*
2428		 * Possible to get link events when doing back-to-back
2429		 * enable/disables.
2430		 */
2431		break;
2432
2433	case BFA_FCPORT_SM_HWFAIL:
2434		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2435		bfa_reqq_wcancel(&fcport->reqq_wait);
2436		break;
2437
2438	default:
2439		bfa_sm_fault(fcport->bfa, event);
2440	}
2441}
2442
2443static void
2444bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2445						enum bfa_fcport_sm_event event)
2446{
2447	char pwwn_buf[BFA_STRING_32];
2448	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2449	bfa_trc(fcport->bfa, event);
2450
2451	switch (event) {
2452	case BFA_FCPORT_SM_FWRSP:
2453		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2454		break;
2455
2456	case BFA_FCPORT_SM_DISABLE:
2457		/*
2458		 * Already being disabled.
2459		 */
2460		break;
2461
2462	case BFA_FCPORT_SM_ENABLE:
2463		if (bfa_fcport_send_enable(fcport))
2464			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2465		else
2466			bfa_sm_set_state(fcport,
2467					 bfa_fcport_sm_enabling_qwait);
2468
2469		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2470				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2471		wwn2str(pwwn_buf, fcport->pwwn);
2472		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2473			"Base port enabled: WWN = %s\n", pwwn_buf);
2474		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2475		break;
2476
2477	case BFA_FCPORT_SM_STOP:
2478		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2479		break;
2480
2481	case BFA_FCPORT_SM_LINKUP:
2482	case BFA_FCPORT_SM_LINKDOWN:
2483		/*
2484		 * Possible to get link events when doing back-to-back
2485		 * enable/disables.
2486		 */
2487		break;
2488
2489	case BFA_FCPORT_SM_HWFAIL:
2490		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2491		break;
2492
2493	default:
2494		bfa_sm_fault(fcport->bfa, event);
2495	}
2496}
2497
2498static void
2499bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2500						enum bfa_fcport_sm_event event)
2501{
2502	char pwwn_buf[BFA_STRING_32];
2503	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2504	bfa_trc(fcport->bfa, event);
2505
2506	switch (event) {
2507	case BFA_FCPORT_SM_START:
2508		/*
2509		 * Ignore start event for a port that is disabled.
2510		 */
2511		break;
2512
2513	case BFA_FCPORT_SM_STOP:
2514		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2515		break;
2516
2517	case BFA_FCPORT_SM_ENABLE:
2518		if (bfa_fcport_send_enable(fcport))
2519			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2520		else
2521			bfa_sm_set_state(fcport,
2522					 bfa_fcport_sm_enabling_qwait);
2523
2524		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2525				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2526		wwn2str(pwwn_buf, fcport->pwwn);
2527		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2528			"Base port enabled: WWN = %s\n", pwwn_buf);
2529		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2530		break;
2531
2532	case BFA_FCPORT_SM_DISABLE:
2533		/*
2534		 * Already disabled.
2535		 */
2536		break;
2537
2538	case BFA_FCPORT_SM_HWFAIL:
2539		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2540		break;
2541
2542	case BFA_FCPORT_SM_DPORTENABLE:
2543		bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
2544		break;
2545
2546	case BFA_FCPORT_SM_DDPORTENABLE:
2547		bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
2548		break;
2549
2550	default:
2551		bfa_sm_fault(fcport->bfa, event);
2552	}
2553}
2554
2555static void
2556bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2557			 enum bfa_fcport_sm_event event)
2558{
2559	bfa_trc(fcport->bfa, event);
2560
2561	switch (event) {
2562	case BFA_FCPORT_SM_START:
2563		if (bfa_fcport_send_enable(fcport))
2564			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2565		else
2566			bfa_sm_set_state(fcport,
2567					 bfa_fcport_sm_enabling_qwait);
2568		break;
2569
2570	default:
2571		/*
2572		 * Ignore all other events.
2573		 */
2574		;
2575	}
2576}
2577
2578/*
2579 * Port is enabled. IOC is down/failed.
2580 */
2581static void
2582bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2583			 enum bfa_fcport_sm_event event)
2584{
2585	bfa_trc(fcport->bfa, event);
2586
2587	switch (event) {
2588	case BFA_FCPORT_SM_START:
2589		if (bfa_fcport_send_enable(fcport))
2590			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2591		else
2592			bfa_sm_set_state(fcport,
2593					 bfa_fcport_sm_enabling_qwait);
2594		break;
2595
2596	default:
2597		/*
2598		 * Ignore all events.
2599		 */
2600		;
2601	}
2602}
2603
2604/*
2605 * Port is disabled. IOC is down/failed.
2606 */
2607static void
2608bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2609			 enum bfa_fcport_sm_event event)
2610{
2611	bfa_trc(fcport->bfa, event);
2612
2613	switch (event) {
2614	case BFA_FCPORT_SM_START:
2615		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2616		break;
2617
2618	case BFA_FCPORT_SM_ENABLE:
2619		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2620		break;
2621
2622	default:
2623		/*
2624		 * Ignore all events.
2625		 */
2626		;
2627	}
2628}
2629
2630static void
2631bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
2632{
2633	bfa_trc(fcport->bfa, event);
2634
2635	switch (event) {
2636	case BFA_FCPORT_SM_DPORTENABLE:
2637	case BFA_FCPORT_SM_DISABLE:
2638	case BFA_FCPORT_SM_ENABLE:
2639	case BFA_FCPORT_SM_START:
2640		/*
2641		 * Ignore event for a port that is dport
2642		 */
2643		break;
2644
2645	case BFA_FCPORT_SM_STOP:
2646		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2647		break;
2648
2649	case BFA_FCPORT_SM_HWFAIL:
2650		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2651		break;
2652
2653	case BFA_FCPORT_SM_DPORTDISABLE:
2654		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2655		break;
2656
2657	default:
2658		bfa_sm_fault(fcport->bfa, event);
2659	}
2660}
2661
2662static void
2663bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
2664			enum bfa_fcport_sm_event event)
2665{
2666	bfa_trc(fcport->bfa, event);
2667
2668	switch (event) {
2669	case BFA_FCPORT_SM_DISABLE:
2670	case BFA_FCPORT_SM_DDPORTDISABLE:
2671		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2672		break;
2673
2674	case BFA_FCPORT_SM_DPORTENABLE:
2675	case BFA_FCPORT_SM_DPORTDISABLE:
2676	case BFA_FCPORT_SM_ENABLE:
2677	case BFA_FCPORT_SM_START:
2678		/*
2679		 * Ignore event for a port that is ddport
2680		 */
2681		break;
2682
2683	case BFA_FCPORT_SM_STOP:
2684		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2685		break;
2686
2687	case BFA_FCPORT_SM_HWFAIL:
2688		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2689		break;
2690
2691	default:
2692		bfa_sm_fault(fcport->bfa, event);
2693	}
2694}
2695
2696static void
2697bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
2698			    enum bfa_fcport_sm_event event)
2699{
2700	bfa_trc(fcport->bfa, event);
2701
2702	switch (event) {
2703	case BFA_FCPORT_SM_DPORTENABLE:
2704	case BFA_FCPORT_SM_ENABLE:
2705	case BFA_FCPORT_SM_START:
2706		/*
2707		 * Ignore event for a port as there is FAA misconfig
2708		 */
2709		break;
2710
2711	case BFA_FCPORT_SM_DISABLE:
2712		if (bfa_fcport_send_disable(fcport))
2713			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2714		else
2715			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2716
2717		bfa_fcport_reset_linkinfo(fcport);
2718		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2719		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2720			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2721		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2722		break;
2723
2724	case BFA_FCPORT_SM_STOP:
2725		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2726		break;
2727
2728	case BFA_FCPORT_SM_HWFAIL:
2729		bfa_fcport_reset_linkinfo(fcport);
2730		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2731		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2732		break;
2733
2734	default:
2735		bfa_sm_fault(fcport->bfa, event);
2736	}
2737}
2738
2739/*
2740 * Link state is down
2741 */
2742static void
2743bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2744		enum bfa_fcport_ln_sm_event event)
2745{
2746	bfa_trc(ln->fcport->bfa, event);
2747
2748	switch (event) {
2749	case BFA_FCPORT_LN_SM_LINKUP:
2750		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2751		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2752		break;
2753
2754	default:
2755		bfa_sm_fault(ln->fcport->bfa, event);
2756	}
2757}
2758
2759/*
2760 * Link state is waiting for down notification
2761 */
2762static void
2763bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2764		enum bfa_fcport_ln_sm_event event)
2765{
2766	bfa_trc(ln->fcport->bfa, event);
2767
2768	switch (event) {
2769	case BFA_FCPORT_LN_SM_LINKUP:
2770		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2771		break;
2772
2773	case BFA_FCPORT_LN_SM_NOTIFICATION:
2774		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2775		break;
2776
2777	default:
2778		bfa_sm_fault(ln->fcport->bfa, event);
2779	}
2780}
2781
2782/*
2783 * Link state is waiting for down notification and there is a pending up
2784 */
2785static void
2786bfa_fcport_ln_sm_dn_up_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_LINKDOWN:
2793		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2794		break;
2795
2796	case BFA_FCPORT_LN_SM_NOTIFICATION:
2797		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2798		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2799		break;
2800
2801	default:
2802		bfa_sm_fault(ln->fcport->bfa, event);
2803	}
2804}
2805
2806/*
2807 * Link state is up
2808 */
2809static void
2810bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2811		enum bfa_fcport_ln_sm_event event)
2812{
2813	bfa_trc(ln->fcport->bfa, event);
2814
2815	switch (event) {
2816	case BFA_FCPORT_LN_SM_LINKDOWN:
2817		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2818		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2819		break;
2820
2821	default:
2822		bfa_sm_fault(ln->fcport->bfa, event);
2823	}
2824}
2825
2826/*
2827 * Link state is waiting for up notification
2828 */
2829static void
2830bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2831		enum bfa_fcport_ln_sm_event event)
2832{
2833	bfa_trc(ln->fcport->bfa, event);
2834
2835	switch (event) {
2836	case BFA_FCPORT_LN_SM_LINKDOWN:
2837		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2838		break;
2839
2840	case BFA_FCPORT_LN_SM_NOTIFICATION:
2841		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2842		break;
2843
2844	default:
2845		bfa_sm_fault(ln->fcport->bfa, event);
2846	}
2847}
2848
2849/*
2850 * Link state is waiting for up notification and there is a pending down
2851 */
2852static void
2853bfa_fcport_ln_sm_up_dn_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_LINKUP:
2860		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2861		break;
2862
2863	case BFA_FCPORT_LN_SM_NOTIFICATION:
2864		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2865		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2866		break;
2867
2868	default:
2869		bfa_sm_fault(ln->fcport->bfa, event);
2870	}
2871}
2872
2873/*
2874 * Link state is waiting for up notification and there are pending down and up
2875 */
2876static void
2877bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2878			enum bfa_fcport_ln_sm_event event)
2879{
2880	bfa_trc(ln->fcport->bfa, event);
2881
2882	switch (event) {
2883	case BFA_FCPORT_LN_SM_LINKDOWN:
2884		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2885		break;
2886
2887	case BFA_FCPORT_LN_SM_NOTIFICATION:
2888		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2889		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2890		break;
2891
2892	default:
2893		bfa_sm_fault(ln->fcport->bfa, event);
2894	}
2895}
2896
2897static void
2898__bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2899{
2900	struct bfa_fcport_ln_s *ln = cbarg;
2901
2902	if (complete)
2903		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2904	else
2905		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2906}
2907
2908/*
2909 * Send SCN notification to upper layers.
2910 * trunk - false if caller is fcport to ignore fcport event in trunked mode
2911 */
2912static void
2913bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2914	bfa_boolean_t trunk)
2915{
2916	if (fcport->cfg.trunked && !trunk)
2917		return;
2918
2919	switch (event) {
2920	case BFA_PORT_LINKUP:
2921		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2922		break;
2923	case BFA_PORT_LINKDOWN:
2924		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2925		break;
2926	default:
2927		WARN_ON(1);
2928	}
2929}
2930
2931static void
2932bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2933{
2934	struct bfa_fcport_s *fcport = ln->fcport;
2935
2936	if (fcport->bfa->fcs) {
2937		fcport->event_cbfn(fcport->event_cbarg, event);
2938		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2939	} else {
2940		ln->ln_event = event;
2941		bfa_cb_queue(fcport->bfa, &ln->ln_qe,
2942			__bfa_cb_fcport_event, ln);
2943	}
2944}
2945
2946#define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
2947							BFA_CACHELINE_SZ))
2948
2949void
2950bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
2951		   struct bfa_s *bfa)
2952{
2953	struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
2954
2955	bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
2956}
2957
2958static void
2959bfa_fcport_qresume(void *cbarg)
2960{
2961	struct bfa_fcport_s *fcport = cbarg;
2962
2963	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
2964}
2965
2966static void
2967bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
2968{
2969	struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
2970
2971	fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
2972	fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
2973	fcport->stats = (union bfa_fcport_stats_u *)
2974				bfa_mem_dma_virt(fcport_dma);
2975}
2976
2977/*
2978 * Memory initialization.
2979 */
2980void
2981bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
2982		struct bfa_pcidev_s *pcidev)
2983{
2984	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
2985	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
2986	struct bfa_fcport_ln_s *ln = &fcport->ln;
2987
2988	fcport->bfa = bfa;
2989	ln->fcport = fcport;
2990
2991	bfa_fcport_mem_claim(fcport);
2992
2993	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
2994	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2995
2996	/*
2997	 * initialize time stamp for stats reset
2998	 */
2999	fcport->stats_reset_time = ktime_get_seconds();
3000	fcport->stats_dma_ready = BFA_FALSE;
3001
3002	/*
3003	 * initialize and set default configuration
3004	 */
3005	port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
3006	port_cfg->speed = BFA_PORT_SPEED_AUTO;
3007	port_cfg->trunked = BFA_FALSE;
3008	port_cfg->maxfrsize = 0;
3009
3010	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
3011	port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
3012	port_cfg->qos_bw.med = BFA_QOS_BW_MED;
3013	port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
3014
3015	fcport->fec_state = BFA_FEC_OFFLINE;
3016
3017	INIT_LIST_HEAD(&fcport->stats_pending_q);
3018	INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3019
3020	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
3021}
3022
3023void
3024bfa_fcport_start(struct bfa_s *bfa)
3025{
3026	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
3027}
3028
3029/*
3030 * Called when IOC failure is detected.
3031 */
3032void
3033bfa_fcport_iocdisable(struct bfa_s *bfa)
3034{
3035	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3036
3037	bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
3038	bfa_trunk_iocdisable(bfa);
3039}
3040
3041/*
3042 * Update loop info in fcport for SCN online
3043 */
3044static void
3045bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
3046			struct bfa_fcport_loop_info_s *loop_info)
3047{
3048	fcport->myalpa = loop_info->myalpa;
3049	fcport->alpabm_valid =
3050			loop_info->alpabm_val;
3051	memcpy(fcport->alpabm.alpa_bm,
3052			loop_info->alpabm.alpa_bm,
3053			sizeof(struct fc_alpabm_s));
3054}
3055
3056static void
3057bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
3058{
3059	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
3060	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3061
3062	fcport->speed = pevent->link_state.speed;
3063	fcport->topology = pevent->link_state.topology;
3064
3065	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
3066		bfa_fcport_update_loop_info(fcport,
3067				&pevent->link_state.attr.loop_info);
3068		return;
3069	}
3070
3071	/* QoS Details */
3072	fcport->qos_attr = pevent->link_state.qos_attr;
3073	fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
3074
3075	if (fcport->cfg.bb_cr_enabled)
3076		fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
3077
3078	fcport->fec_state = pevent->link_state.fec_state;
3079
3080	/*
3081	 * update trunk state if applicable
3082	 */
3083	if (!fcport->cfg.trunked)
3084		trunk->attr.state = BFA_TRUNK_DISABLED;
3085
3086	/* update FCoE specific */
3087	fcport->fcoe_vlan =
3088		be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
3089
3090	bfa_trc(fcport->bfa, fcport->speed);
3091	bfa_trc(fcport->bfa, fcport->topology);
3092}
3093
3094static void
3095bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
3096{
3097	fcport->speed = BFA_PORT_SPEED_UNKNOWN;
3098	fcport->topology = BFA_PORT_TOPOLOGY_NONE;
3099	fcport->fec_state = BFA_FEC_OFFLINE;
3100}
3101
3102/*
3103 * Send port enable message to firmware.
3104 */
3105static bfa_boolean_t
3106bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
3107{
3108	struct bfi_fcport_enable_req_s *m;
3109
3110	/*
3111	 * Increment message tag before queue check, so that responses to old
3112	 * requests are discarded.
3113	 */
3114	fcport->msgtag++;
3115
3116	/*
3117	 * check for room in queue to send request now
3118	 */
3119	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3120	if (!m) {
3121		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3122							&fcport->reqq_wait);
3123		return BFA_FALSE;
3124	}
3125
3126	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
3127			bfa_fn_lpu(fcport->bfa));
3128	m->nwwn = fcport->nwwn;
3129	m->pwwn = fcport->pwwn;
3130	m->port_cfg = fcport->cfg;
3131	m->msgtag = fcport->msgtag;
3132	m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
3133	m->use_flash_cfg = fcport->use_flash_cfg;
3134	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3135	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3136	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3137
3138	/*
3139	 * queue I/O message to firmware
3140	 */
3141	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3142	return BFA_TRUE;
3143}
3144
3145/*
3146 * Send port disable message to firmware.
3147 */
3148static	bfa_boolean_t
3149bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3150{
3151	struct bfi_fcport_req_s *m;
3152
3153	/*
3154	 * Increment message tag before queue check, so that responses to old
3155	 * requests are discarded.
3156	 */
3157	fcport->msgtag++;
3158
3159	/*
3160	 * check for room in queue to send request now
3161	 */
3162	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3163	if (!m) {
3164		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3165							&fcport->reqq_wait);
3166		return BFA_FALSE;
3167	}
3168
3169	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
3170			bfa_fn_lpu(fcport->bfa));
3171	m->msgtag = fcport->msgtag;
3172
3173	/*
3174	 * queue I/O message to firmware
3175	 */
3176	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3177
3178	return BFA_TRUE;
3179}
3180
3181static void
3182bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3183{
3184	fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3185	fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3186
3187	bfa_trc(fcport->bfa, fcport->pwwn);
3188	bfa_trc(fcport->bfa, fcport->nwwn);
3189}
3190
3191static void
3192bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3193	struct bfa_qos_stats_s *s)
3194{
3195	u32	*dip = (u32 *) d;
3196	__be32	*sip = (__be32 *) s;
3197	int		i;
3198
3199	/* Now swap the 32 bit fields */
3200	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3201		dip[i] = be32_to_cpu(sip[i]);
3202}
3203
3204static void
3205bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3206	struct bfa_fcoe_stats_s *s)
3207{
3208	u32	*dip = (u32 *) d;
3209	__be32	*sip = (__be32 *) s;
3210	int		i;
3211
3212	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3213	     i = i + 2) {
3214#ifdef __BIG_ENDIAN
3215		dip[i] = be32_to_cpu(sip[i]);
3216		dip[i + 1] = be32_to_cpu(sip[i + 1]);
3217#else
3218		dip[i] = be32_to_cpu(sip[i + 1]);
3219		dip[i + 1] = be32_to_cpu(sip[i]);
3220#endif
3221	}
3222}
3223
3224static void
3225__bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3226{
3227	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3228	struct bfa_cb_pending_q_s *cb;
3229	struct list_head *qe, *qen;
3230	union bfa_fcport_stats_u *ret;
3231
3232	if (complete) {
3233		time64_t time = ktime_get_seconds();
3234
3235		list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3236			bfa_q_deq(&fcport->stats_pending_q, &qe);
3237			cb = (struct bfa_cb_pending_q_s *)qe;
3238			if (fcport->stats_status == BFA_STATUS_OK) {
3239				ret = (union bfa_fcport_stats_u *)cb->data;
3240				/* Swap FC QoS or FCoE stats */
3241				if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3242					bfa_fcport_qos_stats_swap(&ret->fcqos,
3243							&fcport->stats->fcqos);
3244				else {
3245					bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3246							&fcport->stats->fcoe);
3247					ret->fcoe.secs_reset =
3248						time - fcport->stats_reset_time;
3249				}
3250			}
3251			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3252					fcport->stats_status);
3253		}
3254		fcport->stats_status = BFA_STATUS_OK;
3255	} else {
3256		INIT_LIST_HEAD(&fcport->stats_pending_q);
3257		fcport->stats_status = BFA_STATUS_OK;
3258	}
3259}
3260
3261static void
3262bfa_fcport_stats_get_timeout(void *cbarg)
3263{
3264	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3265
3266	bfa_trc(fcport->bfa, fcport->stats_qfull);
3267
3268	if (fcport->stats_qfull) {
3269		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3270		fcport->stats_qfull = BFA_FALSE;
3271	}
3272
3273	fcport->stats_status = BFA_STATUS_ETIMER;
3274	__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3275}
3276
3277static void
3278bfa_fcport_send_stats_get(void *cbarg)
3279{
3280	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3281	struct bfi_fcport_req_s *msg;
3282
3283	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3284
3285	if (!msg) {
3286		fcport->stats_qfull = BFA_TRUE;
3287		bfa_reqq_winit(&fcport->stats_reqq_wait,
3288				bfa_fcport_send_stats_get, fcport);
3289		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3290				&fcport->stats_reqq_wait);
3291		return;
3292	}
3293	fcport->stats_qfull = BFA_FALSE;
3294
3295	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3296	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3297			bfa_fn_lpu(fcport->bfa));
3298	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3299}
3300
3301static void
3302__bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3303{
3304	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3305	struct bfa_cb_pending_q_s *cb;
3306	struct list_head *qe, *qen;
3307
3308	if (complete) {
3309		/*
3310		 * re-initialize time stamp for stats reset
3311		 */
3312		fcport->stats_reset_time = ktime_get_seconds();
3313		list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3314			bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3315			cb = (struct bfa_cb_pending_q_s *)qe;
3316			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3317						fcport->stats_status);
3318		}
3319		fcport->stats_status = BFA_STATUS_OK;
3320	} else {
3321		INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3322		fcport->stats_status = BFA_STATUS_OK;
3323	}
3324}
3325
3326static void
3327bfa_fcport_stats_clr_timeout(void *cbarg)
3328{
3329	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3330
3331	bfa_trc(fcport->bfa, fcport->stats_qfull);
3332
3333	if (fcport->stats_qfull) {
3334		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3335		fcport->stats_qfull = BFA_FALSE;
3336	}
3337
3338	fcport->stats_status = BFA_STATUS_ETIMER;
3339	__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3340}
3341
3342static void
3343bfa_fcport_send_stats_clear(void *cbarg)
3344{
3345	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3346	struct bfi_fcport_req_s *msg;
3347
3348	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3349
3350	if (!msg) {
3351		fcport->stats_qfull = BFA_TRUE;
3352		bfa_reqq_winit(&fcport->stats_reqq_wait,
3353				bfa_fcport_send_stats_clear, fcport);
3354		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3355						&fcport->stats_reqq_wait);
3356		return;
3357	}
3358	fcport->stats_qfull = BFA_FALSE;
3359
3360	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3361	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3362			bfa_fn_lpu(fcport->bfa));
3363	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3364}
3365
3366/*
3367 * Handle trunk SCN event from firmware.
3368 */
3369static void
3370bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3371{
3372	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3373	struct bfi_fcport_trunk_link_s *tlink;
3374	struct bfa_trunk_link_attr_s *lattr;
3375	enum bfa_trunk_state state_prev;
3376	int i;
3377	int link_bm = 0;
3378
3379	bfa_trc(fcport->bfa, fcport->cfg.trunked);
3380	WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3381		   scn->trunk_state != BFA_TRUNK_OFFLINE);
3382
3383	bfa_trc(fcport->bfa, trunk->attr.state);
3384	bfa_trc(fcport->bfa, scn->trunk_state);
3385	bfa_trc(fcport->bfa, scn->trunk_speed);
3386
3387	/*
3388	 * Save off new state for trunk attribute query
3389	 */
3390	state_prev = trunk->attr.state;
3391	if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3392		trunk->attr.state = scn->trunk_state;
3393	trunk->attr.speed = scn->trunk_speed;
3394	for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3395		lattr = &trunk->attr.link_attr[i];
3396		tlink = &scn->tlink[i];
3397
3398		lattr->link_state = tlink->state;
3399		lattr->trunk_wwn  = tlink->trunk_wwn;
3400		lattr->fctl	  = tlink->fctl;
3401		lattr->speed	  = tlink->speed;
3402		lattr->deskew	  = be32_to_cpu(tlink->deskew);
3403
3404		if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3405			fcport->speed	 = tlink->speed;
3406			fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3407			link_bm |= 1 << i;
3408		}
3409
3410		bfa_trc(fcport->bfa, lattr->link_state);
3411		bfa_trc(fcport->bfa, lattr->trunk_wwn);
3412		bfa_trc(fcport->bfa, lattr->fctl);
3413		bfa_trc(fcport->bfa, lattr->speed);
3414		bfa_trc(fcport->bfa, lattr->deskew);
3415	}
3416
3417	switch (link_bm) {
3418	case 3:
3419		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3420			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3421		break;
3422	case 2:
3423		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3424			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3425		break;
3426	case 1:
3427		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3428			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3429		break;
3430	default:
3431		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3432			BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3433	}
3434
3435	/*
3436	 * Notify upper layers if trunk state changed.
3437	 */
3438	if ((state_prev != trunk->attr.state) ||
3439		(scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3440		bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3441			BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3442	}
3443}
3444
3445static void
3446bfa_trunk_iocdisable(struct bfa_s *bfa)
3447{
3448	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3449	int i = 0;
3450
3451	/*
3452	 * In trunked mode, notify upper layers that link is down
3453	 */
3454	if (fcport->cfg.trunked) {
3455		if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3456			bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3457
3458		fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3459		fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3460		for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3461			fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3462			fcport->trunk.attr.link_attr[i].fctl =
3463						BFA_TRUNK_LINK_FCTL_NORMAL;
3464			fcport->trunk.attr.link_attr[i].link_state =
3465						BFA_TRUNK_LINK_STATE_DN_LINKDN;
3466			fcport->trunk.attr.link_attr[i].speed =
3467						BFA_PORT_SPEED_UNKNOWN;
3468			fcport->trunk.attr.link_attr[i].deskew = 0;
3469		}
3470	}
3471}
3472
3473/*
3474 * Called to initialize port attributes
3475 */
3476void
3477bfa_fcport_init(struct bfa_s *bfa)
3478{
3479	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3480
3481	/*
3482	 * Initialize port attributes from IOC hardware data.
3483	 */
3484	bfa_fcport_set_wwns(fcport);
3485	if (fcport->cfg.maxfrsize == 0)
3486		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3487	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3488	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3489
3490	if (bfa_fcport_is_pbcdisabled(bfa))
3491		bfa->modules.port.pbc_disabled = BFA_TRUE;
3492
3493	WARN_ON(!fcport->cfg.maxfrsize);
3494	WARN_ON(!fcport->cfg.rx_bbcredit);
3495	WARN_ON(!fcport->speed_sup);
3496}
3497
3498/*
3499 * Firmware message handler.
3500 */
3501void
3502bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3503{
3504	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3505	union bfi_fcport_i2h_msg_u i2hmsg;
3506
3507	i2hmsg.msg = msg;
3508	fcport->event_arg.i2hmsg = i2hmsg;
3509
3510	bfa_trc(bfa, msg->mhdr.msg_id);
3511	bfa_trc(bfa, bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm));
3512
3513	switch (msg->mhdr.msg_id) {
3514	case BFI_FCPORT_I2H_ENABLE_RSP:
3515		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3516
3517			fcport->stats_dma_ready = BFA_TRUE;
3518			if (fcport->use_flash_cfg) {
3519				fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3520				fcport->cfg.maxfrsize =
3521					cpu_to_be16(fcport->cfg.maxfrsize);
3522				fcport->cfg.path_tov =
3523					cpu_to_be16(fcport->cfg.path_tov);
3524				fcport->cfg.q_depth =
3525					cpu_to_be16(fcport->cfg.q_depth);
3526
3527				if (fcport->cfg.trunked)
3528					fcport->trunk.attr.state =
3529						BFA_TRUNK_OFFLINE;
3530				else
3531					fcport->trunk.attr.state =
3532						BFA_TRUNK_DISABLED;
3533				fcport->qos_attr.qos_bw =
3534					i2hmsg.penable_rsp->port_cfg.qos_bw;
3535				fcport->use_flash_cfg = BFA_FALSE;
3536			}
3537
3538			if (fcport->cfg.qos_enabled)
3539				fcport->qos_attr.state = BFA_QOS_OFFLINE;
3540			else
3541				fcport->qos_attr.state = BFA_QOS_DISABLED;
3542
3543			fcport->qos_attr.qos_bw_op =
3544					i2hmsg.penable_rsp->port_cfg.qos_bw;
3545
3546			if (fcport->cfg.bb_cr_enabled)
3547				fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3548			else
3549				fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3550
3551			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3552		}
3553		break;
3554
3555	case BFI_FCPORT_I2H_DISABLE_RSP:
3556		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3557			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3558		break;
3559
3560	case BFI_FCPORT_I2H_EVENT:
3561		if (fcport->cfg.bb_cr_enabled)
3562			fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3563		else
3564			fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3565
3566		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3567			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3568		else {
3569			if (i2hmsg.event->link_state.linkstate_rsn ==
3570			    BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
3571				bfa_sm_send_event(fcport,
3572						  BFA_FCPORT_SM_FAA_MISCONFIG);
3573			else
3574				bfa_sm_send_event(fcport,
3575						  BFA_FCPORT_SM_LINKDOWN);
3576		}
3577		fcport->qos_attr.qos_bw_op =
3578				i2hmsg.event->link_state.qos_attr.qos_bw_op;
3579		break;
3580
3581	case BFI_FCPORT_I2H_TRUNK_SCN:
3582		bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3583		break;
3584
3585	case BFI_FCPORT_I2H_STATS_GET_RSP:
3586		/*
3587		 * check for timer pop before processing the rsp
3588		 */
3589		if (list_empty(&fcport->stats_pending_q) ||
3590		    (fcport->stats_status == BFA_STATUS_ETIMER))
3591			break;
3592
3593		bfa_timer_stop(&fcport->timer);
3594		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3595		__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3596		break;
3597
3598	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3599		/*
3600		 * check for timer pop before processing the rsp
3601		 */
3602		if (list_empty(&fcport->statsclr_pending_q) ||
3603		    (fcport->stats_status == BFA_STATUS_ETIMER))
3604			break;
3605
3606		bfa_timer_stop(&fcport->timer);
3607		fcport->stats_status = BFA_STATUS_OK;
3608		__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3609		break;
3610
3611	case BFI_FCPORT_I2H_ENABLE_AEN:
3612		bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3613		break;
3614
3615	case BFI_FCPORT_I2H_DISABLE_AEN:
3616		bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3617		break;
3618
3619	default:
3620		WARN_ON(1);
3621	break;
3622	}
3623}
3624
3625/*
3626 * Registered callback for port events.
3627 */
3628void
3629bfa_fcport_event_register(struct bfa_s *bfa,
3630				void (*cbfn) (void *cbarg,
3631				enum bfa_port_linkstate event),
3632				void *cbarg)
3633{
3634	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3635
3636	fcport->event_cbfn = cbfn;
3637	fcport->event_cbarg = cbarg;
3638}
3639
3640bfa_status_t
3641bfa_fcport_enable(struct bfa_s *bfa)
3642{
3643	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3644
3645	if (bfa_fcport_is_pbcdisabled(bfa))
3646		return BFA_STATUS_PBC;
3647
3648	if (bfa_ioc_is_disabled(&bfa->ioc))
3649		return BFA_STATUS_IOC_DISABLED;
3650
3651	if (fcport->diag_busy)
3652		return BFA_STATUS_DIAG_BUSY;
3653
3654	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3655	return BFA_STATUS_OK;
3656}
3657
3658bfa_status_t
3659bfa_fcport_disable(struct bfa_s *bfa)
3660{
3661	if (bfa_fcport_is_pbcdisabled(bfa))
3662		return BFA_STATUS_PBC;
3663
3664	if (bfa_ioc_is_disabled(&bfa->ioc))
3665		return BFA_STATUS_IOC_DISABLED;
3666
3667	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3668	return BFA_STATUS_OK;
3669}
3670
3671/* If PBC is disabled on port, return error */
3672bfa_status_t
3673bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3674{
3675	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3676	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3677	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3678
3679	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3680		bfa_trc(bfa, fcport->pwwn);
3681		return BFA_STATUS_PBC;
3682	}
3683	return BFA_STATUS_OK;
3684}
3685
3686/*
3687 * Configure port speed.
3688 */
3689bfa_status_t
3690bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3691{
3692	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3693
3694	bfa_trc(bfa, speed);
3695
3696	if (fcport->cfg.trunked == BFA_TRUE)
3697		return BFA_STATUS_TRUNK_ENABLED;
3698	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
3699			(speed == BFA_PORT_SPEED_16GBPS))
3700		return BFA_STATUS_UNSUPP_SPEED;
3701	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3702		bfa_trc(bfa, fcport->speed_sup);
3703		return BFA_STATUS_UNSUPP_SPEED;
3704	}
3705
3706	/* Port speed entered needs to be checked */
3707	if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3708		/* For CT2, 1G is not supported */
3709		if ((speed == BFA_PORT_SPEED_1GBPS) &&
3710		    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3711			return BFA_STATUS_UNSUPP_SPEED;
3712
3713		/* Already checked for Auto Speed and Max Speed supp */
3714		if (!(speed == BFA_PORT_SPEED_1GBPS ||
3715		      speed == BFA_PORT_SPEED_2GBPS ||
3716		      speed == BFA_PORT_SPEED_4GBPS ||
3717		      speed == BFA_PORT_SPEED_8GBPS ||
3718		      speed == BFA_PORT_SPEED_16GBPS ||
3719		      speed == BFA_PORT_SPEED_AUTO))
3720			return BFA_STATUS_UNSUPP_SPEED;
3721	} else {
3722		if (speed != BFA_PORT_SPEED_10GBPS)
3723			return BFA_STATUS_UNSUPP_SPEED;
3724	}
3725
3726	fcport->cfg.speed = speed;
3727
3728	return BFA_STATUS_OK;
3729}
3730
3731/*
3732 * Get current speed.
3733 */
3734enum bfa_port_speed
3735bfa_fcport_get_speed(struct bfa_s *bfa)
3736{
3737	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3738
3739	return fcport->speed;
3740}
3741
3742/*
3743 * Configure port topology.
3744 */
3745bfa_status_t
3746bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3747{
3748	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3749
3750	bfa_trc(bfa, topology);
3751	bfa_trc(bfa, fcport->cfg.topology);
3752
3753	switch (topology) {
3754	case BFA_PORT_TOPOLOGY_P2P:
3755		break;
3756
3757	case BFA_PORT_TOPOLOGY_LOOP:
3758		if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
3759			(fcport->qos_attr.state != BFA_QOS_DISABLED))
3760			return BFA_STATUS_ERROR_QOS_ENABLED;
3761		if (fcport->cfg.ratelimit != BFA_FALSE)
3762			return BFA_STATUS_ERROR_TRL_ENABLED;
3763		if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
3764			(fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
3765			return BFA_STATUS_ERROR_TRUNK_ENABLED;
3766		if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
3767			(fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
3768			return BFA_STATUS_UNSUPP_SPEED;
3769		if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
3770			return BFA_STATUS_LOOP_UNSUPP_MEZZ;
3771		if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
3772			return BFA_STATUS_DPORT_ERR;
3773		if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
3774			return BFA_STATUS_DPORT_ERR;
3775		break;
3776
3777	case BFA_PORT_TOPOLOGY_AUTO:
3778		break;
3779
3780	default:
3781		return BFA_STATUS_EINVAL;
3782	}
3783
3784	fcport->cfg.topology = topology;
3785	return BFA_STATUS_OK;
3786}
3787
3788/*
3789 * Get current topology.
3790 */
3791enum bfa_port_topology
3792bfa_fcport_get_topology(struct bfa_s *bfa)
3793{
3794	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3795
3796	return fcport->topology;
3797}
3798
3799/*
3800 * Get config topology.
3801 */
3802enum bfa_port_topology
3803bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
3804{
3805	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3806
3807	return fcport->cfg.topology;
3808}
3809
3810bfa_status_t
3811bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3812{
3813	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3814
3815	bfa_trc(bfa, alpa);
3816	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3817	bfa_trc(bfa, fcport->cfg.hardalpa);
3818
3819	fcport->cfg.cfg_hardalpa = BFA_TRUE;
3820	fcport->cfg.hardalpa = alpa;
3821
3822	return BFA_STATUS_OK;
3823}
3824
3825bfa_status_t
3826bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3827{
3828	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3829
3830	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3831	bfa_trc(bfa, fcport->cfg.hardalpa);
3832
3833	fcport->cfg.cfg_hardalpa = BFA_FALSE;
3834	return BFA_STATUS_OK;
3835}
3836
3837u8
3838bfa_fcport_get_myalpa(struct bfa_s *bfa)
3839{
3840	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3841
3842	return fcport->myalpa;
3843}
3844
3845bfa_status_t
3846bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3847{
3848	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3849
3850	bfa_trc(bfa, maxfrsize);
3851	bfa_trc(bfa, fcport->cfg.maxfrsize);
3852
3853	/* with in range */
3854	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3855		return BFA_STATUS_INVLD_DFSZ;
3856
3857	/* power of 2, if not the max frame size of 2112 */
3858	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3859		return BFA_STATUS_INVLD_DFSZ;
3860
3861	fcport->cfg.maxfrsize = maxfrsize;
3862	return BFA_STATUS_OK;
3863}
3864
3865u16
3866bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3867{
3868	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3869
3870	return fcport->cfg.maxfrsize;
3871}
3872
3873u8
3874bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3875{
3876	if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
3877		return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
3878
3879	else
3880		return 0;
3881}
3882
3883void
3884bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3885{
3886	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3887
3888	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3889}
3890
3891/*
3892 * Get port attributes.
3893 */
3894void
3895bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3896{
3897	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3898
3899	memset(attr, 0, sizeof(struct bfa_port_attr_s));
3900
3901	attr->nwwn = fcport->nwwn;
3902	attr->pwwn = fcport->pwwn;
3903
3904	attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3905	attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3906
3907	memcpy(&attr->pport_cfg, &fcport->cfg,
3908		sizeof(struct bfa_port_cfg_s));
3909	/* speed attributes */
3910	attr->pport_cfg.speed = fcport->cfg.speed;
3911	attr->speed_supported = fcport->speed_sup;
3912	attr->speed = fcport->speed;
3913	attr->cos_supported = FC_CLASS_3;
3914
3915	/* topology attributes */
3916	attr->pport_cfg.topology = fcport->cfg.topology;
3917	attr->topology = fcport->topology;
3918	attr->pport_cfg.trunked = fcport->cfg.trunked;
3919
3920	/* beacon attributes */
3921	attr->beacon = fcport->beacon;
3922	attr->link_e2e_beacon = fcport->link_e2e_beacon;
3923
3924	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
3925	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
3926	attr->port_state = bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm);
3927
3928	attr->fec_state = fcport->fec_state;
3929
3930	/* PBC Disabled State */
3931	if (bfa_fcport_is_pbcdisabled(bfa))
3932		attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
3933	else {
3934		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
3935			attr->port_state = BFA_PORT_ST_IOCDIS;
3936		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
3937			attr->port_state = BFA_PORT_ST_FWMISMATCH;
3938	}
3939
3940	/* FCoE vlan */
3941	attr->fcoe_vlan = fcport->fcoe_vlan;
3942}
3943
3944#define BFA_FCPORT_STATS_TOV	1000
3945
3946/*
3947 * Fetch port statistics (FCQoS or FCoE).
3948 */
3949bfa_status_t
3950bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
3951{
3952	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3953
3954	if (!bfa_iocfc_is_operational(bfa) ||
3955	    !fcport->stats_dma_ready)
3956		return BFA_STATUS_IOC_NON_OP;
3957
3958	if (!list_empty(&fcport->statsclr_pending_q))
3959		return BFA_STATUS_DEVBUSY;
3960
3961	if (list_empty(&fcport->stats_pending_q)) {
3962		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
3963		bfa_fcport_send_stats_get(fcport);
3964		bfa_timer_start(bfa, &fcport->timer,
3965				bfa_fcport_stats_get_timeout,
3966				fcport, BFA_FCPORT_STATS_TOV);
3967	} else
3968		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
3969
3970	return BFA_STATUS_OK;
3971}
3972
3973/*
3974 * Reset port statistics (FCQoS or FCoE).
3975 */
3976bfa_status_t
3977bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
3978{
3979	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3980
3981	if (!bfa_iocfc_is_operational(bfa) ||
3982	    !fcport->stats_dma_ready)
3983		return BFA_STATUS_IOC_NON_OP;
3984
3985	if (!list_empty(&fcport->stats_pending_q))
3986		return BFA_STATUS_DEVBUSY;
3987
3988	if (list_empty(&fcport->statsclr_pending_q)) {
3989		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
3990		bfa_fcport_send_stats_clear(fcport);
3991		bfa_timer_start(bfa, &fcport->timer,
3992				bfa_fcport_stats_clr_timeout,
3993				fcport, BFA_FCPORT_STATS_TOV);
3994	} else
3995		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
3996
3997	return BFA_STATUS_OK;
3998}
3999
4000/*
4001 * Fetch port attributes.
4002 */
4003bfa_boolean_t
4004bfa_fcport_is_disabled(struct bfa_s *bfa)
4005{
4006	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4007
4008	return bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm) ==
4009		BFA_PORT_ST_DISABLED;
4010
4011}
4012
4013bfa_boolean_t
4014bfa_fcport_is_dport(struct bfa_s *bfa)
4015{
4016	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4017
4018	return (bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm) ==
4019		BFA_PORT_ST_DPORT);
4020}
4021
4022bfa_boolean_t
4023bfa_fcport_is_ddport(struct bfa_s *bfa)
4024{
4025	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4026
4027	return (bfa_fcport_sm_to_state(hal_port_sm_table, fcport->sm) ==
4028		BFA_PORT_ST_DDPORT);
4029}
4030
4031bfa_status_t
4032bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
4033{
4034	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4035	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
4036
4037	bfa_trc(bfa, ioc_type);
4038
4039	if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
4040		return BFA_STATUS_QOS_BW_INVALID;
4041
4042	if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
4043		return BFA_STATUS_QOS_BW_INVALID;
4044
4045	if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
4046	    (qos_bw->low > qos_bw->high))
4047		return BFA_STATUS_QOS_BW_INVALID;
4048
4049	if ((ioc_type == BFA_IOC_TYPE_FC) &&
4050	    (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
4051		fcport->cfg.qos_bw = *qos_bw;
4052
4053	return BFA_STATUS_OK;
4054}
4055
4056bfa_boolean_t
4057bfa_fcport_is_ratelim(struct bfa_s *bfa)
4058{
4059	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4060
4061	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
4062
4063}
4064
4065/*
4066 * Get default minimum ratelim speed
4067 */
4068enum bfa_port_speed
4069bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
4070{
4071	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4072
4073	bfa_trc(bfa, fcport->cfg.trl_def_speed);
4074	return fcport->cfg.trl_def_speed;
4075
4076}
4077
4078void
4079bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
4080		  bfa_boolean_t link_e2e_beacon)
4081{
4082	struct bfa_s *bfa = dev;
4083	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4084
4085	bfa_trc(bfa, beacon);
4086	bfa_trc(bfa, link_e2e_beacon);
4087	bfa_trc(bfa, fcport->beacon);
4088	bfa_trc(bfa, fcport->link_e2e_beacon);
4089
4090	fcport->beacon = beacon;
4091	fcport->link_e2e_beacon = link_e2e_beacon;
4092}
4093
4094bfa_boolean_t
4095bfa_fcport_is_linkup(struct bfa_s *bfa)
4096{
4097	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4098
4099	return	(!fcport->cfg.trunked &&
4100		 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
4101		(fcport->cfg.trunked &&
4102		 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
4103}
4104
4105bfa_boolean_t
4106bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
4107{
4108	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4109
4110	return fcport->cfg.qos_enabled;
4111}
4112
4113bfa_boolean_t
4114bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
4115{
4116	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4117
4118	return fcport->cfg.trunked;
4119}
4120
4121bfa_status_t
4122bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
4123{
4124	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4125
4126	bfa_trc(bfa, on_off);
4127
4128	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4129		return BFA_STATUS_BBCR_FC_ONLY;
4130
4131	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
4132		(bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
4133		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
4134
4135	if (on_off) {
4136		if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4137			return BFA_STATUS_TOPOLOGY_LOOP;
4138
4139		if (fcport->cfg.qos_enabled)
4140			return BFA_STATUS_ERROR_QOS_ENABLED;
4141
4142		if (fcport->cfg.trunked)
4143			return BFA_STATUS_TRUNK_ENABLED;
4144
4145		if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
4146			(fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
4147			return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
4148
4149		if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
4150			return BFA_STATUS_FEATURE_NOT_SUPPORTED;
4151
4152		if (fcport->cfg.bb_cr_enabled) {
4153			if (bb_scn != fcport->cfg.bb_scn)
4154				return BFA_STATUS_BBCR_CFG_NO_CHANGE;
4155			else
4156				return BFA_STATUS_NO_CHANGE;
4157		}
4158
4159		if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
4160			bb_scn = BFA_BB_SCN_DEF;
4161
4162		fcport->cfg.bb_cr_enabled = on_off;
4163		fcport->cfg.bb_scn = bb_scn;
4164	} else {
4165		if (!fcport->cfg.bb_cr_enabled)
4166			return BFA_STATUS_NO_CHANGE;
4167
4168		fcport->cfg.bb_cr_enabled = on_off;
4169		fcport->cfg.bb_scn = 0;
4170	}
4171
4172	return BFA_STATUS_OK;
4173}
4174
4175bfa_status_t
4176bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
4177		struct bfa_bbcr_attr_s *bbcr_attr)
4178{
4179	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4180
4181	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4182		return BFA_STATUS_BBCR_FC_ONLY;
4183
4184	if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4185		return BFA_STATUS_TOPOLOGY_LOOP;
4186
4187	*bbcr_attr = fcport->bbcr_attr;
4188
4189	return BFA_STATUS_OK;
4190}
4191
4192void
4193bfa_fcport_dportenable(struct bfa_s *bfa)
4194{
4195	/*
4196	 * Assume caller check for port is in disable state
4197	 */
4198	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
4199	bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
4200}
4201
4202void
4203bfa_fcport_dportdisable(struct bfa_s *bfa)
4204{
4205	/*
4206	 * Assume caller check for port is in disable state
4207	 */
4208	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
4209	bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
4210}
4211
4212static void
4213bfa_fcport_ddportenable(struct bfa_s *bfa)
4214{
4215	/*
4216	 * Assume caller check for port is in disable state
4217	 */
4218	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
4219}
4220
4221static void
4222bfa_fcport_ddportdisable(struct bfa_s *bfa)
4223{
4224	/*
4225	 * Assume caller check for port is in disable state
4226	 */
4227	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
4228}
4229
4230/*
4231 * Rport State machine functions
4232 */
4233/*
4234 * Beginning state, only online event expected.
4235 */
4236static void
4237bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
4238{
4239	bfa_trc(rp->bfa, rp->rport_tag);
4240	bfa_trc(rp->bfa, event);
4241
4242	switch (event) {
4243	case BFA_RPORT_SM_CREATE:
4244		bfa_stats(rp, sm_un_cr);
4245		bfa_sm_set_state(rp, bfa_rport_sm_created);
4246		break;
4247
4248	default:
4249		bfa_stats(rp, sm_un_unexp);
4250		bfa_sm_fault(rp->bfa, event);
4251	}
4252}
4253
4254static void
4255bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
4256{
4257	bfa_trc(rp->bfa, rp->rport_tag);
4258	bfa_trc(rp->bfa, event);
4259
4260	switch (event) {
4261	case BFA_RPORT_SM_ONLINE:
4262		bfa_stats(rp, sm_cr_on);
4263		if (bfa_rport_send_fwcreate(rp))
4264			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4265		else
4266			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4267		break;
4268
4269	case BFA_RPORT_SM_DELETE:
4270		bfa_stats(rp, sm_cr_del);
4271		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4272		bfa_rport_free(rp);
4273		break;
4274
4275	case BFA_RPORT_SM_HWFAIL:
4276		bfa_stats(rp, sm_cr_hwf);
4277		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4278		break;
4279
4280	default:
4281		bfa_stats(rp, sm_cr_unexp);
4282		bfa_sm_fault(rp->bfa, event);
4283	}
4284}
4285
4286/*
4287 * Waiting for rport create response from firmware.
4288 */
4289static void
4290bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
4291{
4292	bfa_trc(rp->bfa, rp->rport_tag);
4293	bfa_trc(rp->bfa, event);
4294
4295	switch (event) {
4296	case BFA_RPORT_SM_FWRSP:
4297		bfa_stats(rp, sm_fwc_rsp);
4298		bfa_sm_set_state(rp, bfa_rport_sm_online);
4299		bfa_rport_online_cb(rp);
4300		break;
4301
4302	case BFA_RPORT_SM_DELETE:
4303		bfa_stats(rp, sm_fwc_del);
4304		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4305		break;
4306
4307	case BFA_RPORT_SM_OFFLINE:
4308		bfa_stats(rp, sm_fwc_off);
4309		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4310		break;
4311
4312	case BFA_RPORT_SM_HWFAIL:
4313		bfa_stats(rp, sm_fwc_hwf);
4314		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4315		break;
4316
4317	default:
4318		bfa_stats(rp, sm_fwc_unexp);
4319		bfa_sm_fault(rp->bfa, event);
4320	}
4321}
4322
4323/*
4324 * Request queue is full, awaiting queue resume to send create request.
4325 */
4326static void
4327bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4328{
4329	bfa_trc(rp->bfa, rp->rport_tag);
4330	bfa_trc(rp->bfa, event);
4331
4332	switch (event) {
4333	case BFA_RPORT_SM_QRESUME:
4334		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4335		bfa_rport_send_fwcreate(rp);
4336		break;
4337
4338	case BFA_RPORT_SM_DELETE:
4339		bfa_stats(rp, sm_fwc_del);
4340		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4341		bfa_reqq_wcancel(&rp->reqq_wait);
4342		bfa_rport_free(rp);
4343		break;
4344
4345	case BFA_RPORT_SM_OFFLINE:
4346		bfa_stats(rp, sm_fwc_off);
4347		bfa_sm_set_state(rp, bfa_rport_sm_offline);
4348		bfa_reqq_wcancel(&rp->reqq_wait);
4349		bfa_rport_offline_cb(rp);
4350		break;
4351
4352	case BFA_RPORT_SM_HWFAIL:
4353		bfa_stats(rp, sm_fwc_hwf);
4354		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4355		bfa_reqq_wcancel(&rp->reqq_wait);
4356		break;
4357
4358	default:
4359		bfa_stats(rp, sm_fwc_unexp);
4360		bfa_sm_fault(rp->bfa, event);
4361	}
4362}
4363
4364/*
4365 * Online state - normal parking state.
4366 */
4367static void
4368bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
4369{
4370	struct bfi_rport_qos_scn_s *qos_scn;
4371
4372	bfa_trc(rp->bfa, rp->rport_tag);
4373	bfa_trc(rp->bfa, event);
4374
4375	switch (event) {
4376	case BFA_RPORT_SM_OFFLINE:
4377		bfa_stats(rp, sm_on_off);
4378		if (bfa_rport_send_fwdelete(rp))
4379			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4380		else
4381			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4382		break;
4383
4384	case BFA_RPORT_SM_DELETE:
4385		bfa_stats(rp, sm_on_del);
4386		if (bfa_rport_send_fwdelete(rp))
4387			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4388		else
4389			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4390		break;
4391
4392	case BFA_RPORT_SM_HWFAIL:
4393		bfa_stats(rp, sm_on_hwf);
4394		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4395		break;
4396
4397	case BFA_RPORT_SM_SET_SPEED:
4398		bfa_rport_send_fwspeed(rp);
4399		break;
4400
4401	case BFA_RPORT_SM_QOS_SCN:
4402		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
4403		rp->qos_attr = qos_scn->new_qos_attr;
4404		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
4405		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
4406		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
4407		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
4408
4409		qos_scn->old_qos_attr.qos_flow_id  =
4410			be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
4411		qos_scn->new_qos_attr.qos_flow_id  =
4412			be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
4413
4414		if (qos_scn->old_qos_attr.qos_flow_id !=
4415			qos_scn->new_qos_attr.qos_flow_id)
4416			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
4417						    qos_scn->old_qos_attr,
4418						    qos_scn->new_qos_attr);
4419		if (qos_scn->old_qos_attr.qos_priority !=
4420			qos_scn->new_qos_attr.qos_priority)
4421			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
4422						  qos_scn->old_qos_attr,
4423						  qos_scn->new_qos_attr);
4424		break;
4425
4426	default:
4427		bfa_stats(rp, sm_on_unexp);
4428		bfa_sm_fault(rp->bfa, event);
4429	}
4430}
4431
4432/*
4433 * Firmware rport is being deleted - awaiting f/w response.
4434 */
4435static void
4436bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4437{
4438	bfa_trc(rp->bfa, rp->rport_tag);
4439	bfa_trc(rp->bfa, event);
4440
4441	switch (event) {
4442	case BFA_RPORT_SM_FWRSP:
4443		bfa_stats(rp, sm_fwd_rsp);
4444		bfa_sm_set_state(rp, bfa_rport_sm_offline);
4445		bfa_rport_offline_cb(rp);
4446		break;
4447
4448	case BFA_RPORT_SM_DELETE:
4449		bfa_stats(rp, sm_fwd_del);
4450		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4451		break;
4452
4453	case BFA_RPORT_SM_HWFAIL:
4454		bfa_stats(rp, sm_fwd_hwf);
4455		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4456		bfa_rport_offline_cb(rp);
4457		break;
4458
4459	default:
4460		bfa_stats(rp, sm_fwd_unexp);
4461		bfa_sm_fault(rp->bfa, event);
4462	}
4463}
4464
4465static void
4466bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4467{
4468	bfa_trc(rp->bfa, rp->rport_tag);
4469	bfa_trc(rp->bfa, event);
4470
4471	switch (event) {
4472	case BFA_RPORT_SM_QRESUME:
4473		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4474		bfa_rport_send_fwdelete(rp);
4475		break;
4476
4477	case BFA_RPORT_SM_DELETE:
4478		bfa_stats(rp, sm_fwd_del);
4479		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4480		break;
4481
4482	case BFA_RPORT_SM_HWFAIL:
4483		bfa_stats(rp, sm_fwd_hwf);
4484		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4485		bfa_reqq_wcancel(&rp->reqq_wait);
4486		bfa_rport_offline_cb(rp);
4487		break;
4488
4489	default:
4490		bfa_stats(rp, sm_fwd_unexp);
4491		bfa_sm_fault(rp->bfa, event);
4492	}
4493}
4494
4495/*
4496 * Offline state.
4497 */
4498static void
4499bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4500{
4501	bfa_trc(rp->bfa, rp->rport_tag);
4502	bfa_trc(rp->bfa, event);
4503
4504	switch (event) {
4505	case BFA_RPORT_SM_DELETE:
4506		bfa_stats(rp, sm_off_del);
4507		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4508		bfa_rport_free(rp);
4509		break;
4510
4511	case BFA_RPORT_SM_ONLINE:
4512		bfa_stats(rp, sm_off_on);
4513		if (bfa_rport_send_fwcreate(rp))
4514			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4515		else
4516			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4517		break;
4518
4519	case BFA_RPORT_SM_HWFAIL:
4520		bfa_stats(rp, sm_off_hwf);
4521		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4522		break;
4523
4524	case BFA_RPORT_SM_OFFLINE:
4525		bfa_rport_offline_cb(rp);
4526		break;
4527
4528	default:
4529		bfa_stats(rp, sm_off_unexp);
4530		bfa_sm_fault(rp->bfa, event);
4531	}
4532}
4533
4534/*
4535 * Rport is deleted, waiting for firmware response to delete.
4536 */
4537static void
4538bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4539{
4540	bfa_trc(rp->bfa, rp->rport_tag);
4541	bfa_trc(rp->bfa, event);
4542
4543	switch (event) {
4544	case BFA_RPORT_SM_FWRSP:
4545		bfa_stats(rp, sm_del_fwrsp);
4546		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4547		bfa_rport_free(rp);
4548		break;
4549
4550	case BFA_RPORT_SM_HWFAIL:
4551		bfa_stats(rp, sm_del_hwf);
4552		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4553		bfa_rport_free(rp);
4554		break;
4555
4556	default:
4557		bfa_sm_fault(rp->bfa, event);
4558	}
4559}
4560
4561static void
4562bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4563{
4564	bfa_trc(rp->bfa, rp->rport_tag);
4565	bfa_trc(rp->bfa, event);
4566
4567	switch (event) {
4568	case BFA_RPORT_SM_QRESUME:
4569		bfa_stats(rp, sm_del_fwrsp);
4570		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4571		bfa_rport_send_fwdelete(rp);
4572		break;
4573
4574	case BFA_RPORT_SM_HWFAIL:
4575		bfa_stats(rp, sm_del_hwf);
4576		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4577		bfa_reqq_wcancel(&rp->reqq_wait);
4578		bfa_rport_free(rp);
4579		break;
4580
4581	default:
4582		bfa_sm_fault(rp->bfa, event);
4583	}
4584}
4585
4586/*
4587 * Waiting for rport create response from firmware. A delete is pending.
4588 */
4589static void
4590bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4591				enum bfa_rport_event event)
4592{
4593	bfa_trc(rp->bfa, rp->rport_tag);
4594	bfa_trc(rp->bfa, event);
4595
4596	switch (event) {
4597	case BFA_RPORT_SM_FWRSP:
4598		bfa_stats(rp, sm_delp_fwrsp);
4599		if (bfa_rport_send_fwdelete(rp))
4600			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4601		else
4602			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4603		break;
4604
4605	case BFA_RPORT_SM_HWFAIL:
4606		bfa_stats(rp, sm_delp_hwf);
4607		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4608		bfa_rport_free(rp);
4609		break;
4610
4611	default:
4612		bfa_stats(rp, sm_delp_unexp);
4613		bfa_sm_fault(rp->bfa, event);
4614	}
4615}
4616
4617/*
4618 * Waiting for rport create response from firmware. Rport offline is pending.
4619 */
4620static void
4621bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4622				 enum bfa_rport_event event)
4623{
4624	bfa_trc(rp->bfa, rp->rport_tag);
4625	bfa_trc(rp->bfa, event);
4626
4627	switch (event) {
4628	case BFA_RPORT_SM_FWRSP:
4629		bfa_stats(rp, sm_offp_fwrsp);
4630		if (bfa_rport_send_fwdelete(rp))
4631			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4632		else
4633			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4634		break;
4635
4636	case BFA_RPORT_SM_DELETE:
4637		bfa_stats(rp, sm_offp_del);
4638		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4639		break;
4640
4641	case BFA_RPORT_SM_HWFAIL:
4642		bfa_stats(rp, sm_offp_hwf);
4643		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4644		bfa_rport_offline_cb(rp);
4645		break;
4646
4647	default:
4648		bfa_stats(rp, sm_offp_unexp);
4649		bfa_sm_fault(rp->bfa, event);
4650	}
4651}
4652
4653/*
4654 * IOC h/w failed.
4655 */
4656static void
4657bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4658{
4659	bfa_trc(rp->bfa, rp->rport_tag);
4660	bfa_trc(rp->bfa, event);
4661
4662	switch (event) {
4663	case BFA_RPORT_SM_OFFLINE:
4664		bfa_stats(rp, sm_iocd_off);
4665		bfa_rport_offline_cb(rp);
4666		break;
4667
4668	case BFA_RPORT_SM_DELETE:
4669		bfa_stats(rp, sm_iocd_del);
4670		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4671		bfa_rport_free(rp);
4672		break;
4673
4674	case BFA_RPORT_SM_ONLINE:
4675		bfa_stats(rp, sm_iocd_on);
4676		if (bfa_rport_send_fwcreate(rp))
4677			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4678		else
4679			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4680		break;
4681
4682	case BFA_RPORT_SM_HWFAIL:
4683		break;
4684
4685	default:
4686		bfa_stats(rp, sm_iocd_unexp);
4687		bfa_sm_fault(rp->bfa, event);
4688	}
4689}
4690
4691
4692
4693/*
4694 *  bfa_rport_private BFA rport private functions
4695 */
4696
4697static void
4698__bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4699{
4700	struct bfa_rport_s *rp = cbarg;
4701
4702	if (complete)
4703		bfa_cb_rport_online(rp->rport_drv);
4704}
4705
4706static void
4707__bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4708{
4709	struct bfa_rport_s *rp = cbarg;
4710
4711	if (complete)
4712		bfa_cb_rport_offline(rp->rport_drv);
4713}
4714
4715static void
4716bfa_rport_qresume(void *cbarg)
4717{
4718	struct bfa_rport_s	*rp = cbarg;
4719
4720	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4721}
4722
4723void
4724bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
4725		struct bfa_s *bfa)
4726{
4727	struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
4728
4729	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4730		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4731
4732	/* kva memory */
4733	bfa_mem_kva_setup(minfo, rport_kva,
4734		cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
4735}
4736
4737void
4738bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4739		struct bfa_pcidev_s *pcidev)
4740{
4741	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4742	struct bfa_rport_s *rp;
4743	u16 i;
4744
4745	INIT_LIST_HEAD(&mod->rp_free_q);
4746	INIT_LIST_HEAD(&mod->rp_active_q);
4747	INIT_LIST_HEAD(&mod->rp_unused_q);
4748
4749	rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
4750	mod->rps_list = rp;
4751	mod->num_rports = cfg->fwcfg.num_rports;
4752
4753	WARN_ON(!mod->num_rports ||
4754		   (mod->num_rports & (mod->num_rports - 1)));
4755
4756	for (i = 0; i < mod->num_rports; i++, rp++) {
4757		memset(rp, 0, sizeof(struct bfa_rport_s));
4758		rp->bfa = bfa;
4759		rp->rport_tag = i;
4760		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4761
4762		/*
4763		 *  - is unused
4764		 */
4765		if (i)
4766			list_add_tail(&rp->qe, &mod->rp_free_q);
4767
4768		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4769	}
4770
4771	/*
4772	 * consume memory
4773	 */
4774	bfa_mem_kva_curp(mod) = (u8 *) rp;
4775}
4776
4777void
4778bfa_rport_iocdisable(struct bfa_s *bfa)
4779{
4780	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4781	struct bfa_rport_s *rport;
4782	struct list_head *qe, *qen;
4783
4784	/* Enqueue unused rport resources to free_q */
4785	list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
4786
4787	list_for_each_safe(qe, qen, &mod->rp_active_q) {
4788		rport = (struct bfa_rport_s *) qe;
4789		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4790	}
4791}
4792
4793static struct bfa_rport_s *
4794bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4795{
4796	struct bfa_rport_s *rport;
4797
4798	bfa_q_deq(&mod->rp_free_q, &rport);
4799	if (rport)
4800		list_add_tail(&rport->qe, &mod->rp_active_q);
4801
4802	return rport;
4803}
4804
4805static void
4806bfa_rport_free(struct bfa_rport_s *rport)
4807{
4808	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4809
4810	WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
4811	list_del(&rport->qe);
4812	list_add_tail(&rport->qe, &mod->rp_free_q);
4813}
4814
4815static bfa_boolean_t
4816bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4817{
4818	struct bfi_rport_create_req_s *m;
4819
4820	/*
4821	 * check for room in queue to send request now
4822	 */
4823	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4824	if (!m) {
4825		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4826		return BFA_FALSE;
4827	}
4828
4829	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
4830			bfa_fn_lpu(rp->bfa));
4831	m->bfa_handle = rp->rport_tag;
4832	m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
4833	m->pid = rp->rport_info.pid;
4834	m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
4835	m->local_pid = rp->rport_info.local_pid;
4836	m->fc_class = rp->rport_info.fc_class;
4837	m->vf_en = rp->rport_info.vf_en;
4838	m->vf_id = rp->rport_info.vf_id;
4839	m->cisc = rp->rport_info.cisc;
4840
4841	/*
4842	 * queue I/O message to firmware
4843	 */
4844	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4845	return BFA_TRUE;
4846}
4847
4848static bfa_boolean_t
4849bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4850{
4851	struct bfi_rport_delete_req_s *m;
4852
4853	/*
4854	 * check for room in queue to send request now
4855	 */
4856	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4857	if (!m) {
4858		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4859		return BFA_FALSE;
4860	}
4861
4862	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
4863			bfa_fn_lpu(rp->bfa));
4864	m->fw_handle = rp->fw_handle;
4865
4866	/*
4867	 * queue I/O message to firmware
4868	 */
4869	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4870	return BFA_TRUE;
4871}
4872
4873static bfa_boolean_t
4874bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4875{
4876	struct bfa_rport_speed_req_s *m;
4877
4878	/*
4879	 * check for room in queue to send request now
4880	 */
4881	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4882	if (!m) {
4883		bfa_trc(rp->bfa, rp->rport_info.speed);
4884		return BFA_FALSE;
4885	}
4886
4887	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
4888			bfa_fn_lpu(rp->bfa));
4889	m->fw_handle = rp->fw_handle;
4890	m->speed = (u8)rp->rport_info.speed;
4891
4892	/*
4893	 * queue I/O message to firmware
4894	 */
4895	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4896	return BFA_TRUE;
4897}
4898
4899
4900
4901/*
4902 *  bfa_rport_public
4903 */
4904
4905/*
4906 * Rport interrupt processing.
4907 */
4908void
4909bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
4910{
4911	union bfi_rport_i2h_msg_u msg;
4912	struct bfa_rport_s *rp;
4913
4914	bfa_trc(bfa, m->mhdr.msg_id);
4915
4916	msg.msg = m;
4917
4918	switch (m->mhdr.msg_id) {
4919	case BFI_RPORT_I2H_CREATE_RSP:
4920		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
4921		rp->fw_handle = msg.create_rsp->fw_handle;
4922		rp->qos_attr = msg.create_rsp->qos_attr;
4923		bfa_rport_set_lunmask(bfa, rp);
4924		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
4925		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
4926		break;
4927
4928	case BFI_RPORT_I2H_DELETE_RSP:
4929		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
4930		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
4931		bfa_rport_unset_lunmask(bfa, rp);
4932		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
4933		break;
4934
4935	case BFI_RPORT_I2H_QOS_SCN:
4936		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
4937		rp->event_arg.fw_msg = msg.qos_scn_evt;
4938		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
4939		break;
4940
4941	case BFI_RPORT_I2H_LIP_SCN_ONLINE:
4942		bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
4943				&msg.lip_scn->loop_info);
4944		bfa_cb_rport_scn_online(bfa);
4945		break;
4946
4947	case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
4948		bfa_cb_rport_scn_offline(bfa);
4949		break;
4950
4951	case BFI_RPORT_I2H_NO_DEV:
4952		rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
4953		bfa_cb_rport_scn_no_dev(rp->rport_drv);
4954		break;
4955
4956	default:
4957		bfa_trc(bfa, m->mhdr.msg_id);
4958		WARN_ON(1);
4959	}
4960}
4961
4962void
4963bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
4964{
4965	struct bfa_rport_mod_s	*mod = BFA_RPORT_MOD(bfa);
4966	struct list_head	*qe;
4967	int	i;
4968
4969	for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
4970		bfa_q_deq_tail(&mod->rp_free_q, &qe);
4971		list_add_tail(qe, &mod->rp_unused_q);
4972	}
4973}
4974
4975/*
4976 *  bfa_rport_api
4977 */
4978
4979struct bfa_rport_s *
4980bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
4981{
4982	struct bfa_rport_s *rp;
4983
4984	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
4985
4986	if (rp == NULL)
4987		return NULL;
4988
4989	rp->bfa = bfa;
4990	rp->rport_drv = rport_drv;
4991	memset(&rp->stats, 0, sizeof(rp->stats));
4992
4993	WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
4994	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
4995
4996	return rp;
4997}
4998
4999void
5000bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
5001{
5002	WARN_ON(rport_info->max_frmsz == 0);
5003
5004	/*
5005	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
5006	 * responses. Default to minimum size.
5007	 */
5008	if (rport_info->max_frmsz == 0) {
5009		bfa_trc(rport->bfa, rport->rport_tag);
5010		rport_info->max_frmsz = FC_MIN_PDUSZ;
5011	}
5012
5013	rport->rport_info = *rport_info;
5014	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
5015}
5016
5017void
5018bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
5019{
5020	WARN_ON(speed == 0);
5021	WARN_ON(speed == BFA_PORT_SPEED_AUTO);
5022
5023	if (rport) {
5024		rport->rport_info.speed = speed;
5025		bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
5026	}
5027}
5028
5029/* Set Rport LUN Mask */
5030void
5031bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5032{
5033	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);
5034	wwn_t	lp_wwn, rp_wwn;
5035	u8 lp_tag = (u8)rp->rport_info.lp_tag;
5036
5037	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5038	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5039
5040	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5041					rp->lun_mask = BFA_TRUE;
5042	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);
5043}
5044
5045/* Unset Rport LUN mask */
5046void
5047bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5048{
5049	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);
5050	wwn_t	lp_wwn, rp_wwn;
5051
5052	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5053	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5054
5055	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5056				rp->lun_mask = BFA_FALSE;
5057	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,
5058			BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);
5059}
5060
5061/*
5062 * SGPG related functions
5063 */
5064
5065/*
5066 * Compute and return memory needed by FCP(im) module.
5067 */
5068void
5069bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5070		struct bfa_s *bfa)
5071{
5072	struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
5073	struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
5074	struct bfa_mem_dma_s *seg_ptr;
5075	u16	nsegs, idx, per_seg_sgpg, num_sgpg;
5076	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
5077
5078	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
5079		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
5080	else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
5081		cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
5082
5083	num_sgpg = cfg->drvcfg.num_sgpgs;
5084
5085	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5086	per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
5087
5088	bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
5089		if (num_sgpg >= per_seg_sgpg) {
5090			num_sgpg -= per_seg_sgpg;
5091			bfa_mem_dma_setup(minfo, seg_ptr,
5092					per_seg_sgpg * sgpg_sz);
5093		} else
5094			bfa_mem_dma_setup(minfo, seg_ptr,
5095					num_sgpg * sgpg_sz);
5096	}
5097
5098	/* kva memory */
5099	bfa_mem_kva_setup(minfo, sgpg_kva,
5100		cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
5101}
5102
5103void
5104bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5105		struct bfa_pcidev_s *pcidev)
5106{
5107	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5108	struct bfa_sgpg_s *hsgpg;
5109	struct bfi_sgpg_s *sgpg;
5110	u64 align_len;
5111	struct bfa_mem_dma_s *seg_ptr;
5112	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
5113	u16	i, idx, nsegs, per_seg_sgpg, num_sgpg;
5114
5115	union {
5116		u64 pa;
5117		union bfi_addr_u addr;
5118	} sgpg_pa, sgpg_pa_tmp;
5119
5120	INIT_LIST_HEAD(&mod->sgpg_q);
5121	INIT_LIST_HEAD(&mod->sgpg_wait_q);
5122
5123	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
5124
5125	mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
5126
5127	num_sgpg = cfg->drvcfg.num_sgpgs;
5128	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5129
5130	/* dma/kva mem claim */
5131	hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
5132
5133	bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
5134
5135		if (!bfa_mem_dma_virt(seg_ptr))
5136			break;
5137
5138		align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
5139					     bfa_mem_dma_phys(seg_ptr);
5140
5141		sgpg = (struct bfi_sgpg_s *)
5142			(((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
5143		sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
5144		WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
5145
5146		per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
5147
5148		for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
5149			memset(hsgpg, 0, sizeof(*hsgpg));
5150			memset(sgpg, 0, sizeof(*sgpg));
5151
5152			hsgpg->sgpg = sgpg;
5153			sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
5154			hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
5155			list_add_tail(&hsgpg->qe, &mod->sgpg_q);
5156
5157			sgpg++;
5158			hsgpg++;
5159			sgpg_pa.pa += sgpg_sz;
5160		}
5161	}
5162
5163	bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
5164}
5165
5166bfa_status_t
5167bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
5168{
5169	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5170	struct bfa_sgpg_s *hsgpg;
5171	int i;
5172
5173	if (mod->free_sgpgs < nsgpgs)
5174		return BFA_STATUS_ENOMEM;
5175
5176	for (i = 0; i < nsgpgs; i++) {
5177		bfa_q_deq(&mod->sgpg_q, &hsgpg);
5178		WARN_ON(!hsgpg);
5179		list_add_tail(&hsgpg->qe, sgpg_q);
5180	}
5181
5182	mod->free_sgpgs -= nsgpgs;
5183	return BFA_STATUS_OK;
5184}
5185
5186void
5187bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
5188{
5189	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5190	struct bfa_sgpg_wqe_s *wqe;
5191
5192	mod->free_sgpgs += nsgpg;
5193	WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
5194
5195	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
5196
5197	if (list_empty(&mod->sgpg_wait_q))
5198		return;
5199
5200	/*
5201	 * satisfy as many waiting requests as possible
5202	 */
5203	do {
5204		wqe = bfa_q_first(&mod->sgpg_wait_q);
5205		if (mod->free_sgpgs < wqe->nsgpg)
5206			nsgpg = mod->free_sgpgs;
5207		else
5208			nsgpg = wqe->nsgpg;
5209		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
5210		wqe->nsgpg -= nsgpg;
5211		if (wqe->nsgpg == 0) {
5212			list_del(&wqe->qe);
5213			wqe->cbfn(wqe->cbarg);
5214		}
5215	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
5216}
5217
5218void
5219bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
5220{
5221	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5222
5223	WARN_ON(nsgpg <= 0);
5224	WARN_ON(nsgpg <= mod->free_sgpgs);
5225
5226	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
5227
5228	/*
5229	 * allocate any left to this one first
5230	 */
5231	if (mod->free_sgpgs) {
5232		/*
5233		 * no one else is waiting for SGPG
5234		 */
5235		WARN_ON(!list_empty(&mod->sgpg_wait_q));
5236		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
5237		wqe->nsgpg -= mod->free_sgpgs;
5238		mod->free_sgpgs = 0;
5239	}
5240
5241	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
5242}
5243
5244void
5245bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
5246{
5247	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5248
5249	WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
5250	list_del(&wqe->qe);
5251
5252	if (wqe->nsgpg_total != wqe->nsgpg)
5253		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
5254				   wqe->nsgpg_total - wqe->nsgpg);
5255}
5256
5257void
5258bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
5259		   void *cbarg)
5260{
5261	INIT_LIST_HEAD(&wqe->sgpg_q);
5262	wqe->cbfn = cbfn;
5263	wqe->cbarg = cbarg;
5264}
5265
5266/*
5267 *  UF related functions
5268 */
5269/*
5270 *****************************************************************************
5271 * Internal functions
5272 *****************************************************************************
5273 */
5274static void
5275__bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
5276{
5277	struct bfa_uf_s   *uf = cbarg;
5278	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
5279
5280	if (complete)
5281		ufm->ufrecv(ufm->cbarg, uf);
5282}
5283
5284static void
5285claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
5286{
5287	struct bfi_uf_buf_post_s *uf_bp_msg;
5288	u16 i;
5289	u16 buf_len;
5290
5291	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
5292	uf_bp_msg = ufm->uf_buf_posts;
5293
5294	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
5295	     i++, uf_bp_msg++) {
5296		memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
5297
5298		uf_bp_msg->buf_tag = i;
5299		buf_len = sizeof(struct bfa_uf_buf_s);
5300		uf_bp_msg->buf_len = cpu_to_be16(buf_len);
5301		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
5302			    bfa_fn_lpu(ufm->bfa));
5303		bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
5304	}
5305
5306	/*
5307	 * advance pointer beyond consumed memory
5308	 */
5309	bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
5310}
5311
5312static void
5313claim_ufs(struct bfa_uf_mod_s *ufm)
5314{
5315	u16 i;
5316	struct bfa_uf_s   *uf;
5317
5318	/*
5319	 * Claim block of memory for UF list
5320	 */
5321	ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
5322
5323	/*
5324	 * Initialize UFs and queue it in UF free queue
5325	 */
5326	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
5327		memset(uf, 0, sizeof(struct bfa_uf_s));
5328		uf->bfa = ufm->bfa;
5329		uf->uf_tag = i;
5330		uf->pb_len = BFA_PER_UF_DMA_SZ;
5331		uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
5332		uf->buf_pa = ufm_pbs_pa(ufm, i);
5333		list_add_tail(&uf->qe, &ufm->uf_free_q);
5334	}
5335
5336	/*
5337	 * advance memory pointer
5338	 */
5339	bfa_mem_kva_curp(ufm) = (u8 *) uf;
5340}
5341
5342static void
5343uf_mem_claim(struct bfa_uf_mod_s *ufm)
5344{
5345	claim_ufs(ufm);
5346	claim_uf_post_msgs(ufm);
5347}
5348
5349void
5350bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5351		struct bfa_s *bfa)
5352{
5353	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5354	struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
5355	u32	num_ufs = cfg->fwcfg.num_uf_bufs;
5356	struct bfa_mem_dma_s *seg_ptr;
5357	u16	nsegs, idx, per_seg_uf = 0;
5358
5359	nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
5360	per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
5361
5362	bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
5363		if (num_ufs >= per_seg_uf) {
5364			num_ufs -= per_seg_uf;
5365			bfa_mem_dma_setup(minfo, seg_ptr,
5366				per_seg_uf * BFA_PER_UF_DMA_SZ);
5367		} else
5368			bfa_mem_dma_setup(minfo, seg_ptr,
5369				num_ufs * BFA_PER_UF_DMA_SZ);
5370	}
5371
5372	/* kva memory */
5373	bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
5374		(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
5375}
5376
5377void
5378bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5379		struct bfa_pcidev_s *pcidev)
5380{
5381	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5382
5383	ufm->bfa = bfa;
5384	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
5385	INIT_LIST_HEAD(&ufm->uf_free_q);
5386	INIT_LIST_HEAD(&ufm->uf_posted_q);
5387	INIT_LIST_HEAD(&ufm->uf_unused_q);
5388
5389	uf_mem_claim(ufm);
5390}
5391
5392static struct bfa_uf_s *
5393bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
5394{
5395	struct bfa_uf_s   *uf;
5396
5397	bfa_q_deq(&uf_mod->uf_free_q, &uf);
5398	return uf;
5399}
5400
5401static void
5402bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
5403{
5404	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
5405}
5406
5407static bfa_status_t
5408bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
5409{
5410	struct bfi_uf_buf_post_s *uf_post_msg;
5411
5412	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
5413	if (!uf_post_msg)
5414		return BFA_STATUS_FAILED;
5415
5416	memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
5417		      sizeof(struct bfi_uf_buf_post_s));
5418	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
5419
5420	bfa_trc(ufm->bfa, uf->uf_tag);
5421
5422	list_add_tail(&uf->qe, &ufm->uf_posted_q);
5423	return BFA_STATUS_OK;
5424}
5425
5426static void
5427bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
5428{
5429	struct bfa_uf_s   *uf;
5430
5431	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
5432		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
5433			break;
5434	}
5435}
5436
5437static void
5438uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
5439{
5440	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5441	u16 uf_tag = m->buf_tag;
5442	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
5443	struct bfa_uf_buf_s *uf_buf;
5444	uint8_t *buf;
5445
5446	uf_buf = (struct bfa_uf_buf_s *)
5447			bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
5448	buf = &uf_buf->d[0];
5449
5450	m->frm_len = be16_to_cpu(m->frm_len);
5451	m->xfr_len = be16_to_cpu(m->xfr_len);
5452
5453	list_del(&uf->qe);	/* dequeue from posted queue */
5454
5455	uf->data_ptr = buf;
5456	uf->data_len = m->xfr_len;
5457
5458	WARN_ON(uf->data_len < sizeof(struct fchs_s));
5459
5460	if (uf->data_len == sizeof(struct fchs_s)) {
5461		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
5462			       uf->data_len, (struct fchs_s *)buf);
5463	} else {
5464		u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
5465		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
5466				      BFA_PL_EID_RX, uf->data_len,
5467				      (struct fchs_s *)buf, pld_w0);
5468	}
5469
5470	if (bfa->fcs)
5471		__bfa_cb_uf_recv(uf, BFA_TRUE);
5472	else
5473		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
5474}
5475
5476void
5477bfa_uf_start(struct bfa_s *bfa)
5478{
5479	bfa_uf_post_all(BFA_UF_MOD(bfa));
5480}
5481
5482/*
5483 * Register handler for all unsolicted receive frames.
5484 *
5485 * @param[in]	bfa		BFA instance
5486 * @param[in]	ufrecv	receive handler function
5487 * @param[in]	cbarg	receive handler arg
5488 */
5489void
5490bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5491{
5492	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5493
5494	ufm->ufrecv = ufrecv;
5495	ufm->cbarg = cbarg;
5496}
5497
5498/*
5499 *	Free an unsolicited frame back to BFA.
5500 *
5501 * @param[in]		uf		unsolicited frame to be freed
5502 *
5503 * @return None
5504 */
5505void
5506bfa_uf_free(struct bfa_uf_s *uf)
5507{
5508	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5509	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5510}
5511
5512
5513
5514/*
5515 *  uf_pub BFA uf module public functions
5516 */
5517void
5518bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5519{
5520	bfa_trc(bfa, msg->mhdr.msg_id);
5521
5522	switch (msg->mhdr.msg_id) {
5523	case BFI_UF_I2H_FRM_RCVD:
5524		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5525		break;
5526
5527	default:
5528		bfa_trc(bfa, msg->mhdr.msg_id);
5529		WARN_ON(1);
5530	}
5531}
5532
5533void
5534bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5535{
5536	struct bfa_uf_mod_s	*mod = BFA_UF_MOD(bfa);
5537	struct list_head	*qe;
5538	int	i;
5539
5540	for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
5541		bfa_q_deq_tail(&mod->uf_free_q, &qe);
5542		list_add_tail(qe, &mod->uf_unused_q);
5543	}
5544}
5545
5546/*
5547 *	Dport forward declaration
5548 */
5549
5550enum bfa_dport_test_state_e {
5551	BFA_DPORT_ST_DISABLED	= 0,	/*!< dport is disabled */
5552	BFA_DPORT_ST_INP	= 1,	/*!< test in progress */
5553	BFA_DPORT_ST_COMP	= 2,	/*!< test complete successfully */
5554	BFA_DPORT_ST_NO_SFP	= 3,	/*!< sfp is not present */
5555	BFA_DPORT_ST_NOTSTART	= 4,	/*!< test not start dport is enabled */
5556};
5557
5558static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
5559				  enum bfa_dport_sm_event event);
5560static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
5561				  enum bfa_dport_sm_event event);
5562static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
5563				  enum bfa_dport_sm_event event);
5564static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
5565				 enum bfa_dport_sm_event event);
5566static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
5567				 enum bfa_dport_sm_event event);
5568static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
5569				   enum bfa_dport_sm_event event);
5570static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
5571					enum bfa_dport_sm_event event);
5572static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
5573				  enum bfa_dport_sm_event event);
5574static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
5575				   enum bfa_dport_sm_event event);
5576static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
5577				   enum bfa_dport_sm_event event);
5578static void bfa_dport_qresume(void *cbarg);
5579static void bfa_dport_req_comp(struct bfa_dport_s *dport,
5580				struct bfi_diag_dport_rsp_s *msg);
5581static void bfa_dport_scn(struct bfa_dport_s *dport,
5582				struct bfi_diag_dport_scn_s *msg);
5583
5584/*
5585 *	BFA fcdiag module
5586 */
5587#define BFA_DIAG_QTEST_TOV	1000    /* msec */
5588
5589/*
5590 *	Set port status to busy
5591 */
5592static void
5593bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
5594{
5595	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
5596
5597	if (fcdiag->lb.lock)
5598		fcport->diag_busy = BFA_TRUE;
5599	else
5600		fcport->diag_busy = BFA_FALSE;
5601}
5602
5603void
5604bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5605		struct bfa_pcidev_s *pcidev)
5606{
5607	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5608	struct bfa_dport_s  *dport = &fcdiag->dport;
5609
5610	fcdiag->bfa             = bfa;
5611	fcdiag->trcmod  = bfa->trcmod;
5612	/* The common DIAG attach bfa_diag_attach() will do all memory claim */
5613	dport->bfa = bfa;
5614	bfa_sm_set_state(dport, bfa_dport_sm_disabled);
5615	bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
5616	dport->cbfn = NULL;
5617	dport->cbarg = NULL;
5618	dport->test_state = BFA_DPORT_ST_DISABLED;
5619	memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
5620}
5621
5622void
5623bfa_fcdiag_iocdisable(struct bfa_s *bfa)
5624{
5625	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5626	struct bfa_dport_s *dport = &fcdiag->dport;
5627
5628	bfa_trc(fcdiag, fcdiag->lb.lock);
5629	if (fcdiag->lb.lock) {
5630		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
5631		fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5632		fcdiag->lb.lock = 0;
5633		bfa_fcdiag_set_busy_status(fcdiag);
5634	}
5635
5636	bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
5637}
5638
5639static void
5640bfa_fcdiag_queuetest_timeout(void *cbarg)
5641{
5642	struct bfa_fcdiag_s       *fcdiag = cbarg;
5643	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5644
5645	bfa_trc(fcdiag, fcdiag->qtest.all);
5646	bfa_trc(fcdiag, fcdiag->qtest.count);
5647
5648	fcdiag->qtest.timer_active = 0;
5649
5650	res->status = BFA_STATUS_ETIMER;
5651	res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5652	if (fcdiag->qtest.all)
5653		res->queue  = fcdiag->qtest.all;
5654
5655	bfa_trc(fcdiag, BFA_STATUS_ETIMER);
5656	fcdiag->qtest.status = BFA_STATUS_ETIMER;
5657	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5658	fcdiag->qtest.lock = 0;
5659}
5660
5661static bfa_status_t
5662bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
5663{
5664	u32	i;
5665	struct bfi_diag_qtest_req_s *req;
5666
5667	req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
5668	if (!req)
5669		return BFA_STATUS_DEVBUSY;
5670
5671	/* build host command */
5672	bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
5673		bfa_fn_lpu(fcdiag->bfa));
5674
5675	for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
5676		req->data[i] = QTEST_PAT_DEFAULT;
5677
5678	bfa_trc(fcdiag, fcdiag->qtest.queue);
5679	/* ring door bell */
5680	bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
5681	return BFA_STATUS_OK;
5682}
5683
5684static void
5685bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
5686			bfi_diag_qtest_rsp_t *rsp)
5687{
5688	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5689	bfa_status_t status = BFA_STATUS_OK;
5690	int i;
5691
5692	/* Check timer, should still be active   */
5693	if (!fcdiag->qtest.timer_active) {
5694		bfa_trc(fcdiag, fcdiag->qtest.timer_active);
5695		return;
5696	}
5697
5698	/* update count */
5699	fcdiag->qtest.count--;
5700
5701	/* Check result */
5702	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
5703		if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
5704			res->status = BFA_STATUS_DATACORRUPTED;
5705			break;
5706		}
5707	}
5708
5709	if (res->status == BFA_STATUS_OK) {
5710		if (fcdiag->qtest.count > 0) {
5711			status = bfa_fcdiag_queuetest_send(fcdiag);
5712			if (status == BFA_STATUS_OK)
5713				return;
5714			else
5715				res->status = status;
5716		} else if (fcdiag->qtest.all > 0 &&
5717			fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
5718			fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5719			fcdiag->qtest.queue++;
5720			status = bfa_fcdiag_queuetest_send(fcdiag);
5721			if (status == BFA_STATUS_OK)
5722				return;
5723			else
5724				res->status = status;
5725		}
5726	}
5727
5728	/* Stop timer when we comp all queue */
5729	if (fcdiag->qtest.timer_active) {
5730		bfa_timer_stop(&fcdiag->qtest.timer);
5731		fcdiag->qtest.timer_active = 0;
5732	}
5733	res->queue = fcdiag->qtest.queue;
5734	res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5735	bfa_trc(fcdiag, res->count);
5736	bfa_trc(fcdiag, res->status);
5737	fcdiag->qtest.status = res->status;
5738	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5739	fcdiag->qtest.lock = 0;
5740}
5741
5742static void
5743bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
5744			struct bfi_diag_lb_rsp_s *rsp)
5745{
5746	struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
5747
5748	res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);
5749	res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);
5750	res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);
5751	res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);
5752	res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);
5753	res->status     = rsp->res.status;
5754	fcdiag->lb.status = rsp->res.status;
5755	bfa_trc(fcdiag, fcdiag->lb.status);
5756	fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5757	fcdiag->lb.lock = 0;
5758	bfa_fcdiag_set_busy_status(fcdiag);
5759}
5760
5761static bfa_status_t
5762bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
5763			struct bfa_diag_loopback_s *loopback)
5764{
5765	struct bfi_diag_lb_req_s *lb_req;
5766
5767	lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
5768	if (!lb_req)
5769		return BFA_STATUS_DEVBUSY;
5770
5771	/* build host command */
5772	bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
5773		bfa_fn_lpu(fcdiag->bfa));
5774
5775	lb_req->lb_mode = loopback->lb_mode;
5776	lb_req->speed = loopback->speed;
5777	lb_req->loopcnt = loopback->loopcnt;
5778	lb_req->pattern = loopback->pattern;
5779
5780	/* ring door bell */
5781	bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
5782
5783	bfa_trc(fcdiag, loopback->lb_mode);
5784	bfa_trc(fcdiag, loopback->speed);
5785	bfa_trc(fcdiag, loopback->loopcnt);
5786	bfa_trc(fcdiag, loopback->pattern);
5787	return BFA_STATUS_OK;
5788}
5789
5790/*
5791 *	cpe/rme intr handler
5792 */
5793void
5794bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5795{
5796	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5797
5798	switch (msg->mhdr.msg_id) {
5799	case BFI_DIAG_I2H_LOOPBACK:
5800		bfa_fcdiag_loopback_comp(fcdiag,
5801				(struct bfi_diag_lb_rsp_s *) msg);
5802		break;
5803	case BFI_DIAG_I2H_QTEST:
5804		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
5805		break;
5806	case BFI_DIAG_I2H_DPORT:
5807		bfa_dport_req_comp(&fcdiag->dport,
5808				(struct bfi_diag_dport_rsp_s *)msg);
5809		break;
5810	case BFI_DIAG_I2H_DPORT_SCN:
5811		bfa_dport_scn(&fcdiag->dport,
5812				(struct bfi_diag_dport_scn_s *)msg);
5813		break;
5814	default:
5815		bfa_trc(fcdiag, msg->mhdr.msg_id);
5816		WARN_ON(1);
5817	}
5818}
5819
5820/*
5821 *	Loopback test
5822 *
5823 *   @param[in] *bfa            - bfa data struct
5824 *   @param[in] opmode          - port operation mode
5825 *   @param[in] speed           - port speed
5826 *   @param[in] lpcnt           - loop count
5827 *   @param[in] pat                     - pattern to build packet
5828 *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct
5829 *   @param[in] cbfn            - callback function
5830 *   @param[in] cbarg           - callback functioin arg
5831 *
5832 *   @param[out]
5833 */
5834bfa_status_t
5835bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
5836		enum bfa_port_speed speed, u32 lpcnt, u32 pat,
5837		struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
5838		void *cbarg)
5839{
5840	struct  bfa_diag_loopback_s loopback;
5841	struct bfa_port_attr_s attr;
5842	bfa_status_t status;
5843	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5844
5845	if (!bfa_iocfc_is_operational(bfa))
5846		return BFA_STATUS_IOC_NON_OP;
5847
5848	/* if port is PBC disabled, return error */
5849	if (bfa_fcport_is_pbcdisabled(bfa)) {
5850		bfa_trc(fcdiag, BFA_STATUS_PBC);
5851		return BFA_STATUS_PBC;
5852	}
5853
5854	if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
5855		bfa_trc(fcdiag, opmode);
5856		return BFA_STATUS_PORT_NOT_DISABLED;
5857	}
5858
5859	/*
5860	 * Check if input speed is supported by the port mode
5861	 */
5862	if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5863		if (!(speed == BFA_PORT_SPEED_1GBPS ||
5864		      speed == BFA_PORT_SPEED_2GBPS ||
5865		      speed == BFA_PORT_SPEED_4GBPS ||
5866		      speed == BFA_PORT_SPEED_8GBPS ||
5867		      speed == BFA_PORT_SPEED_16GBPS ||
5868		      speed == BFA_PORT_SPEED_AUTO)) {
5869			bfa_trc(fcdiag, speed);
5870			return BFA_STATUS_UNSUPP_SPEED;
5871		}
5872		bfa_fcport_get_attr(bfa, &attr);
5873		bfa_trc(fcdiag, attr.speed_supported);
5874		if (speed > attr.speed_supported)
5875			return BFA_STATUS_UNSUPP_SPEED;
5876	} else {
5877		if (speed != BFA_PORT_SPEED_10GBPS) {
5878			bfa_trc(fcdiag, speed);
5879			return BFA_STATUS_UNSUPP_SPEED;
5880		}
5881	}
5882
5883	/*
5884	 * For CT2, 1G is not supported
5885	 */
5886	if ((speed == BFA_PORT_SPEED_1GBPS) &&
5887	    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
5888		bfa_trc(fcdiag, speed);
5889		return BFA_STATUS_UNSUPP_SPEED;
5890	}
5891
5892	/* For Mezz card, port speed entered needs to be checked */
5893	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
5894		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5895			if (!(speed == BFA_PORT_SPEED_1GBPS ||
5896			      speed == BFA_PORT_SPEED_2GBPS ||
5897			      speed == BFA_PORT_SPEED_4GBPS ||
5898			      speed == BFA_PORT_SPEED_8GBPS ||
5899			      speed == BFA_PORT_SPEED_16GBPS ||
5900			      speed == BFA_PORT_SPEED_AUTO))
5901				return BFA_STATUS_UNSUPP_SPEED;
5902		} else {
5903			if (speed != BFA_PORT_SPEED_10GBPS)
5904				return BFA_STATUS_UNSUPP_SPEED;
5905		}
5906	}
5907	/* check to see if fcport is dport */
5908	if (bfa_fcport_is_dport(bfa)) {
5909		bfa_trc(fcdiag, fcdiag->lb.lock);
5910		return BFA_STATUS_DPORT_ENABLED;
5911	}
5912	/* check to see if there is another destructive diag cmd running */
5913	if (fcdiag->lb.lock) {
5914		bfa_trc(fcdiag, fcdiag->lb.lock);
5915		return BFA_STATUS_DEVBUSY;
5916	}
5917
5918	fcdiag->lb.lock = 1;
5919	loopback.lb_mode = opmode;
5920	loopback.speed = speed;
5921	loopback.loopcnt = lpcnt;
5922	loopback.pattern = pat;
5923	fcdiag->lb.result = result;
5924	fcdiag->lb.cbfn = cbfn;
5925	fcdiag->lb.cbarg = cbarg;
5926	memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
5927	bfa_fcdiag_set_busy_status(fcdiag);
5928
5929	/* Send msg to fw */
5930	status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
5931	return status;
5932}
5933
5934/*
5935 *	DIAG queue test command
5936 *
5937 *   @param[in] *bfa            - bfa data struct
5938 *   @param[in] force           - 1: don't do ioc op checking
5939 *   @param[in] queue           - queue no. to test
5940 *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct
5941 *   @param[in] cbfn            - callback function
5942 *   @param[in] *cbarg          - callback functioin arg
5943 *
5944 *   @param[out]
5945 */
5946bfa_status_t
5947bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
5948		struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
5949		void *cbarg)
5950{
5951	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5952	bfa_status_t status;
5953	bfa_trc(fcdiag, force);
5954	bfa_trc(fcdiag, queue);
5955
5956	if (!force && !bfa_iocfc_is_operational(bfa))
5957		return BFA_STATUS_IOC_NON_OP;
5958
5959	/* check to see if there is another destructive diag cmd running */
5960	if (fcdiag->qtest.lock) {
5961		bfa_trc(fcdiag, fcdiag->qtest.lock);
5962		return BFA_STATUS_DEVBUSY;
5963	}
5964
5965	/* Initialization */
5966	fcdiag->qtest.lock = 1;
5967	fcdiag->qtest.cbfn = cbfn;
5968	fcdiag->qtest.cbarg = cbarg;
5969	fcdiag->qtest.result = result;
5970	fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5971
5972	/* Init test results */
5973	fcdiag->qtest.result->status = BFA_STATUS_OK;
5974	fcdiag->qtest.result->count  = 0;
5975
5976	/* send */
5977	if (queue < BFI_IOC_MAX_CQS) {
5978		fcdiag->qtest.result->queue  = (u8)queue;
5979		fcdiag->qtest.queue = (u8)queue;
5980		fcdiag->qtest.all   = 0;
5981	} else {
5982		fcdiag->qtest.result->queue  = 0;
5983		fcdiag->qtest.queue = 0;
5984		fcdiag->qtest.all   = 1;
5985	}
5986	status = bfa_fcdiag_queuetest_send(fcdiag);
5987
5988	/* Start a timer */
5989	if (status == BFA_STATUS_OK) {
5990		bfa_timer_start(bfa, &fcdiag->qtest.timer,
5991				bfa_fcdiag_queuetest_timeout, fcdiag,
5992				BFA_DIAG_QTEST_TOV);
5993		fcdiag->qtest.timer_active = 1;
5994	}
5995	return status;
5996}
5997
5998/*
5999 * DIAG PLB is running
6000 *
6001 *   @param[in] *bfa    - bfa data struct
6002 *
6003 *   @param[out]
6004 */
6005bfa_status_t
6006bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
6007{
6008	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6009	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
6010}
6011
6012/*
6013 *	D-port
6014 */
6015#define bfa_dport_result_start(__dport, __mode) do {				\
6016		(__dport)->result.start_time = ktime_get_real_seconds();	\
6017		(__dport)->result.status = DPORT_TEST_ST_INPRG;			\
6018		(__dport)->result.mode = (__mode);				\
6019		(__dport)->result.rp_pwwn = (__dport)->rp_pwwn;			\
6020		(__dport)->result.rp_nwwn = (__dport)->rp_nwwn;			\
6021		(__dport)->result.lpcnt = (__dport)->lpcnt;			\
6022} while (0)
6023
6024static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
6025					enum bfi_dport_req req);
6026static void
6027bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
6028{
6029	if (dport->cbfn != NULL) {
6030		dport->cbfn(dport->cbarg, bfa_status);
6031		dport->cbfn = NULL;
6032		dport->cbarg = NULL;
6033	}
6034}
6035
6036static void
6037bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6038{
6039	bfa_trc(dport->bfa, event);
6040
6041	switch (event) {
6042	case BFA_DPORT_SM_ENABLE:
6043		bfa_fcport_dportenable(dport->bfa);
6044		if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
6045			bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6046		else
6047			bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
6048		break;
6049
6050	case BFA_DPORT_SM_DISABLE:
6051		/* Already disabled */
6052		break;
6053
6054	case BFA_DPORT_SM_HWFAIL:
6055		/* ignore */
6056		break;
6057
6058	case BFA_DPORT_SM_SCN:
6059		if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) {
6060			bfa_fcport_ddportenable(dport->bfa);
6061			dport->dynamic = BFA_TRUE;
6062			dport->test_state = BFA_DPORT_ST_NOTSTART;
6063			bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6064		} else {
6065			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6066			WARN_ON(1);
6067		}
6068		break;
6069
6070	default:
6071		bfa_sm_fault(dport->bfa, event);
6072	}
6073}
6074
6075static void
6076bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
6077			    enum bfa_dport_sm_event event)
6078{
6079	bfa_trc(dport->bfa, event);
6080
6081	switch (event) {
6082	case BFA_DPORT_SM_QRESUME:
6083		bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6084		bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
6085		break;
6086
6087	case BFA_DPORT_SM_HWFAIL:
6088		bfa_reqq_wcancel(&dport->reqq_wait);
6089		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6090		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6091		break;
6092
6093	default:
6094		bfa_sm_fault(dport->bfa, event);
6095	}
6096}
6097
6098static void
6099bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6100{
6101	bfa_trc(dport->bfa, event);
6102
6103	switch (event) {
6104	case BFA_DPORT_SM_FWRSP:
6105		memset(&dport->result, 0,
6106				sizeof(struct bfa_diag_dport_result_s));
6107		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6108			dport->test_state = BFA_DPORT_ST_NO_SFP;
6109		} else {
6110			dport->test_state = BFA_DPORT_ST_INP;
6111			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
6112		}
6113		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6114		break;
6115
6116	case BFA_DPORT_SM_REQFAIL:
6117		dport->test_state = BFA_DPORT_ST_DISABLED;
6118		bfa_fcport_dportdisable(dport->bfa);
6119		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6120		break;
6121
6122	case BFA_DPORT_SM_HWFAIL:
6123		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6124		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6125		break;
6126
6127	default:
6128		bfa_sm_fault(dport->bfa, event);
6129	}
6130}
6131
6132static void
6133bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6134{
6135	bfa_trc(dport->bfa, event);
6136
6137	switch (event) {
6138	case BFA_DPORT_SM_START:
6139		if (bfa_dport_send_req(dport, BFI_DPORT_START))
6140			bfa_sm_set_state(dport, bfa_dport_sm_starting);
6141		else
6142			bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
6143		break;
6144
6145	case BFA_DPORT_SM_DISABLE:
6146		bfa_fcport_dportdisable(dport->bfa);
6147		if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
6148			bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6149		else
6150			bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
6151		break;
6152
6153	case BFA_DPORT_SM_HWFAIL:
6154		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6155		break;
6156
6157	case BFA_DPORT_SM_SCN:
6158		switch (dport->i2hmsg.scn.state) {
6159		case BFI_DPORT_SCN_TESTCOMP:
6160			dport->test_state = BFA_DPORT_ST_COMP;
6161			break;
6162
6163		case BFI_DPORT_SCN_TESTSTART:
6164			dport->test_state = BFA_DPORT_ST_INP;
6165			break;
6166
6167		case BFI_DPORT_SCN_TESTSKIP:
6168		case BFI_DPORT_SCN_SUBTESTSTART:
6169			/* no state change */
6170			break;
6171
6172		case BFI_DPORT_SCN_SFP_REMOVED:
6173			dport->test_state = BFA_DPORT_ST_NO_SFP;
6174			break;
6175
6176		case BFI_DPORT_SCN_DDPORT_DISABLE:
6177			bfa_fcport_ddportdisable(dport->bfa);
6178
6179			if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
6180				bfa_sm_set_state(dport,
6181					 bfa_dport_sm_dynamic_disabling);
6182			else
6183				bfa_sm_set_state(dport,
6184					 bfa_dport_sm_dynamic_disabling_qwait);
6185			break;
6186
6187		case BFI_DPORT_SCN_FCPORT_DISABLE:
6188			bfa_fcport_ddportdisable(dport->bfa);
6189
6190			bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6191			dport->dynamic = BFA_FALSE;
6192			break;
6193
6194		default:
6195			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6196			bfa_sm_fault(dport->bfa, event);
6197		}
6198		break;
6199	default:
6200		bfa_sm_fault(dport->bfa, event);
6201	}
6202}
6203
6204static void
6205bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
6206			     enum bfa_dport_sm_event event)
6207{
6208	bfa_trc(dport->bfa, event);
6209
6210	switch (event) {
6211	case BFA_DPORT_SM_QRESUME:
6212		bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6213		bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
6214		break;
6215
6216	case BFA_DPORT_SM_HWFAIL:
6217		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6218		bfa_reqq_wcancel(&dport->reqq_wait);
6219		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6220		break;
6221
6222	case BFA_DPORT_SM_SCN:
6223		/* ignore */
6224		break;
6225
6226	default:
6227		bfa_sm_fault(dport->bfa, event);
6228	}
6229}
6230
6231static void
6232bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6233{
6234	bfa_trc(dport->bfa, event);
6235
6236	switch (event) {
6237	case BFA_DPORT_SM_FWRSP:
6238		dport->test_state = BFA_DPORT_ST_DISABLED;
6239		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6240		break;
6241
6242	case BFA_DPORT_SM_HWFAIL:
6243		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6244		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6245		break;
6246
6247	case BFA_DPORT_SM_SCN:
6248		/* no state change */
6249		break;
6250
6251	default:
6252		bfa_sm_fault(dport->bfa, event);
6253	}
6254}
6255
6256static void
6257bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
6258			    enum bfa_dport_sm_event event)
6259{
6260	bfa_trc(dport->bfa, event);
6261
6262	switch (event) {
6263	case BFA_DPORT_SM_QRESUME:
6264		bfa_sm_set_state(dport, bfa_dport_sm_starting);
6265		bfa_dport_send_req(dport, BFI_DPORT_START);
6266		break;
6267
6268	case BFA_DPORT_SM_HWFAIL:
6269		bfa_reqq_wcancel(&dport->reqq_wait);
6270		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6271		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6272		break;
6273
6274	default:
6275		bfa_sm_fault(dport->bfa, event);
6276	}
6277}
6278
6279static void
6280bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6281{
6282	bfa_trc(dport->bfa, event);
6283
6284	switch (event) {
6285	case BFA_DPORT_SM_FWRSP:
6286		memset(&dport->result, 0,
6287				sizeof(struct bfa_diag_dport_result_s));
6288		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6289			dport->test_state = BFA_DPORT_ST_NO_SFP;
6290		} else {
6291			dport->test_state = BFA_DPORT_ST_INP;
6292			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
6293		}
6294		fallthrough;
6295
6296	case BFA_DPORT_SM_REQFAIL:
6297		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6298		break;
6299
6300	case BFA_DPORT_SM_HWFAIL:
6301		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6302		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6303		break;
6304
6305	default:
6306		bfa_sm_fault(dport->bfa, event);
6307	}
6308}
6309
6310static void
6311bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
6312			       enum bfa_dport_sm_event event)
6313{
6314	bfa_trc(dport->bfa, event);
6315
6316	switch (event) {
6317	case BFA_DPORT_SM_SCN:
6318		switch (dport->i2hmsg.scn.state) {
6319		case BFI_DPORT_SCN_DDPORT_DISABLED:
6320			bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6321			dport->dynamic = BFA_FALSE;
6322			bfa_fcport_enable(dport->bfa);
6323			break;
6324
6325		default:
6326			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6327			bfa_sm_fault(dport->bfa, event);
6328
6329		}
6330		break;
6331
6332	case BFA_DPORT_SM_HWFAIL:
6333		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6334		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6335		break;
6336
6337	default:
6338		bfa_sm_fault(dport->bfa, event);
6339	}
6340}
6341
6342static void
6343bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
6344			    enum bfa_dport_sm_event event)
6345{
6346	bfa_trc(dport->bfa, event);
6347
6348	switch (event) {
6349	case BFA_DPORT_SM_QRESUME:
6350		bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
6351		bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
6352		break;
6353
6354	case BFA_DPORT_SM_HWFAIL:
6355		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6356		bfa_reqq_wcancel(&dport->reqq_wait);
6357		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6358		break;
6359
6360	case BFA_DPORT_SM_SCN:
6361		/* ignore */
6362		break;
6363
6364	default:
6365		bfa_sm_fault(dport->bfa, event);
6366	}
6367}
6368
6369static bfa_boolean_t
6370bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
6371{
6372	struct bfi_diag_dport_req_s *m;
6373
6374	/*
6375	 * check for room in queue to send request now
6376	 */
6377	m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
6378	if (!m) {
6379		bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
6380		return BFA_FALSE;
6381	}
6382
6383	bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
6384		    bfa_fn_lpu(dport->bfa));
6385	m->req  = req;
6386	if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
6387		m->lpcnt = cpu_to_be32(dport->lpcnt);
6388		m->payload = cpu_to_be32(dport->payload);
6389	}
6390
6391	/*
6392	 * queue I/O message to firmware
6393	 */
6394	bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
6395
6396	return BFA_TRUE;
6397}
6398
6399static void
6400bfa_dport_qresume(void *cbarg)
6401{
6402	struct bfa_dport_s *dport = cbarg;
6403
6404	bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
6405}
6406
6407static void
6408bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
6409{
6410	msg->status = cpu_to_be32(msg->status);
6411	dport->i2hmsg.rsp.status = msg->status;
6412	dport->rp_pwwn = msg->pwwn;
6413	dport->rp_nwwn = msg->nwwn;
6414
6415	if ((msg->status == BFA_STATUS_OK) ||
6416	    (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
6417		bfa_trc(dport->bfa, msg->status);
6418		bfa_trc(dport->bfa, dport->rp_pwwn);
6419		bfa_trc(dport->bfa, dport->rp_nwwn);
6420		bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
6421
6422	} else {
6423		bfa_trc(dport->bfa, msg->status);
6424		bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
6425	}
6426	bfa_cb_fcdiag_dport(dport, msg->status);
6427}
6428
6429static bfa_boolean_t
6430bfa_dport_is_sending_req(struct bfa_dport_s *dport)
6431{
6432	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)	||
6433	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
6434	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)	||
6435	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
6436	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting)	||
6437	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
6438		return BFA_TRUE;
6439	} else {
6440		return BFA_FALSE;
6441	}
6442}
6443
6444static void
6445bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
6446{
6447	int i;
6448	uint8_t subtesttype;
6449
6450	bfa_trc(dport->bfa, msg->state);
6451	dport->i2hmsg.scn.state = msg->state;
6452
6453	switch (dport->i2hmsg.scn.state) {
6454	case BFI_DPORT_SCN_TESTCOMP:
6455		dport->result.end_time = ktime_get_real_seconds();
6456		bfa_trc(dport->bfa, dport->result.end_time);
6457
6458		dport->result.status = msg->info.testcomp.status;
6459		bfa_trc(dport->bfa, dport->result.status);
6460
6461		dport->result.roundtrip_latency =
6462			cpu_to_be32(msg->info.testcomp.latency);
6463		dport->result.est_cable_distance =
6464			cpu_to_be32(msg->info.testcomp.distance);
6465		dport->result.buffer_required =
6466			be16_to_cpu(msg->info.testcomp.numbuffer);
6467
6468		dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
6469		dport->result.speed = msg->info.testcomp.speed;
6470
6471		bfa_trc(dport->bfa, dport->result.roundtrip_latency);
6472		bfa_trc(dport->bfa, dport->result.est_cable_distance);
6473		bfa_trc(dport->bfa, dport->result.buffer_required);
6474		bfa_trc(dport->bfa, dport->result.frmsz);
6475		bfa_trc(dport->bfa, dport->result.speed);
6476
6477		for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
6478			dport->result.subtest[i].status =
6479				msg->info.testcomp.subtest_status[i];
6480			bfa_trc(dport->bfa, dport->result.subtest[i].status);
6481		}
6482		break;
6483
6484	case BFI_DPORT_SCN_TESTSKIP:
6485	case BFI_DPORT_SCN_DDPORT_ENABLE:
6486		memset(&dport->result, 0,
6487				sizeof(struct bfa_diag_dport_result_s));
6488		break;
6489
6490	case BFI_DPORT_SCN_TESTSTART:
6491		memset(&dport->result, 0,
6492				sizeof(struct bfa_diag_dport_result_s));
6493		dport->rp_pwwn = msg->info.teststart.pwwn;
6494		dport->rp_nwwn = msg->info.teststart.nwwn;
6495		dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
6496		bfa_dport_result_start(dport, msg->info.teststart.mode);
6497		break;
6498
6499	case BFI_DPORT_SCN_SUBTESTSTART:
6500		subtesttype = msg->info.teststart.type;
6501		dport->result.subtest[subtesttype].start_time =
6502			ktime_get_real_seconds();
6503		dport->result.subtest[subtesttype].status =
6504			DPORT_TEST_ST_INPRG;
6505
6506		bfa_trc(dport->bfa, subtesttype);
6507		bfa_trc(dport->bfa,
6508			dport->result.subtest[subtesttype].start_time);
6509		break;
6510
6511	case BFI_DPORT_SCN_SFP_REMOVED:
6512	case BFI_DPORT_SCN_DDPORT_DISABLED:
6513	case BFI_DPORT_SCN_DDPORT_DISABLE:
6514	case BFI_DPORT_SCN_FCPORT_DISABLE:
6515		dport->result.status = DPORT_TEST_ST_IDLE;
6516		break;
6517
6518	default:
6519		bfa_sm_fault(dport->bfa, msg->state);
6520	}
6521
6522	bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
6523}
6524
6525/*
6526 * Dport enable
6527 *
6528 * @param[in] *bfa            - bfa data struct
6529 */
6530bfa_status_t
6531bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6532				bfa_cb_diag_t cbfn, void *cbarg)
6533{
6534	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6535	struct bfa_dport_s  *dport = &fcdiag->dport;
6536
6537	/*
6538	 * Dport is not support in MEZZ card
6539	 */
6540	if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
6541		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6542		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
6543	}
6544
6545	/*
6546	 * Dport is supported in CT2 or above
6547	 */
6548	if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
6549		bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
6550		return BFA_STATUS_FEATURE_NOT_SUPPORTED;
6551	}
6552
6553	/*
6554	 * Check to see if IOC is down
6555	*/
6556	if (!bfa_iocfc_is_operational(bfa))
6557		return BFA_STATUS_IOC_NON_OP;
6558
6559	/* if port is PBC disabled, return error */
6560	if (bfa_fcport_is_pbcdisabled(bfa)) {
6561		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6562		return BFA_STATUS_PBC;
6563	}
6564
6565	/*
6566	 * Check if port mode is FC port
6567	 */
6568	if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
6569		bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
6570		return BFA_STATUS_CMD_NOTSUPP_CNA;
6571	}
6572
6573	/*
6574	 * Check if port is in LOOP mode
6575	 */
6576	if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
6577	    (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
6578		bfa_trc(dport->bfa, 0);
6579		return BFA_STATUS_TOPOLOGY_LOOP;
6580	}
6581
6582	/*
6583	 * Check if port is TRUNK mode
6584	 */
6585	if (bfa_fcport_is_trunk_enabled(bfa)) {
6586		bfa_trc(dport->bfa, 0);
6587		return BFA_STATUS_ERROR_TRUNK_ENABLED;
6588	}
6589
6590	/*
6591	 * Check if diag loopback is running
6592	 */
6593	if (bfa_fcdiag_lb_is_running(bfa)) {
6594		bfa_trc(dport->bfa, 0);
6595		return BFA_STATUS_DIAG_BUSY;
6596	}
6597
6598	/*
6599	 * Check to see if port is disable or in dport state
6600	 */
6601	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6602	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6603		bfa_trc(dport->bfa, 0);
6604		return BFA_STATUS_PORT_NOT_DISABLED;
6605	}
6606
6607	/*
6608	 * Check if dport is in dynamic mode
6609	 */
6610	if (dport->dynamic)
6611		return BFA_STATUS_DDPORT_ERR;
6612
6613	/*
6614	 * Check if dport is busy
6615	 */
6616	if (bfa_dport_is_sending_req(dport))
6617		return BFA_STATUS_DEVBUSY;
6618
6619	/*
6620	 * Check if dport is already enabled
6621	 */
6622	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6623		bfa_trc(dport->bfa, 0);
6624		return BFA_STATUS_DPORT_ENABLED;
6625	}
6626
6627	bfa_trc(dport->bfa, lpcnt);
6628	bfa_trc(dport->bfa, pat);
6629	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6630	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6631	dport->cbfn = cbfn;
6632	dport->cbarg = cbarg;
6633
6634	bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
6635	return BFA_STATUS_OK;
6636}
6637
6638/*
6639 *	Dport disable
6640 *
6641 *	@param[in] *bfa            - bfa data struct
6642 */
6643bfa_status_t
6644bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
6645{
6646	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6647	struct bfa_dport_s *dport = &fcdiag->dport;
6648
6649	if (bfa_ioc_is_disabled(&bfa->ioc))
6650		return BFA_STATUS_IOC_DISABLED;
6651
6652	/* if port is PBC disabled, return error */
6653	if (bfa_fcport_is_pbcdisabled(bfa)) {
6654		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6655		return BFA_STATUS_PBC;
6656	}
6657
6658	/*
6659	 * Check if dport is in dynamic mode
6660	 */
6661	if (dport->dynamic) {
6662		return BFA_STATUS_DDPORT_ERR;
6663	}
6664
6665	/*
6666	 * Check to see if port is disable or in dport state
6667	 */
6668	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6669	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6670		bfa_trc(dport->bfa, 0);
6671		return BFA_STATUS_PORT_NOT_DISABLED;
6672	}
6673
6674	/*
6675	 * Check if dport is busy
6676	 */
6677	if (bfa_dport_is_sending_req(dport))
6678		return BFA_STATUS_DEVBUSY;
6679
6680	/*
6681	 * Check if dport is already disabled
6682	 */
6683	if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
6684		bfa_trc(dport->bfa, 0);
6685		return BFA_STATUS_DPORT_DISABLED;
6686	}
6687
6688	dport->cbfn = cbfn;
6689	dport->cbarg = cbarg;
6690
6691	bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
6692	return BFA_STATUS_OK;
6693}
6694
6695/*
6696 * Dport start -- restart dport test
6697 *
6698 *   @param[in] *bfa		- bfa data struct
6699 */
6700bfa_status_t
6701bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6702			bfa_cb_diag_t cbfn, void *cbarg)
6703{
6704	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6705	struct bfa_dport_s *dport = &fcdiag->dport;
6706
6707	/*
6708	 * Check to see if IOC is down
6709	 */
6710	if (!bfa_iocfc_is_operational(bfa))
6711		return BFA_STATUS_IOC_NON_OP;
6712
6713	/*
6714	 * Check if dport is in dynamic mode
6715	 */
6716	if (dport->dynamic)
6717		return BFA_STATUS_DDPORT_ERR;
6718
6719	/*
6720	 * Check if dport is busy
6721	 */
6722	if (bfa_dport_is_sending_req(dport))
6723		return BFA_STATUS_DEVBUSY;
6724
6725	/*
6726	 * Check if dport is in enabled state.
6727	 * Test can only be restart when previous test has completed
6728	 */
6729	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6730		bfa_trc(dport->bfa, 0);
6731		return BFA_STATUS_DPORT_DISABLED;
6732
6733	} else {
6734		if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6735			return BFA_STATUS_DPORT_INV_SFP;
6736
6737		if (dport->test_state == BFA_DPORT_ST_INP)
6738			return BFA_STATUS_DEVBUSY;
6739
6740		WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
6741	}
6742
6743	bfa_trc(dport->bfa, lpcnt);
6744	bfa_trc(dport->bfa, pat);
6745
6746	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6747	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6748
6749	dport->cbfn = cbfn;
6750	dport->cbarg = cbarg;
6751
6752	bfa_sm_send_event(dport, BFA_DPORT_SM_START);
6753	return BFA_STATUS_OK;
6754}
6755
6756/*
6757 * Dport show -- return dport test result
6758 *
6759 *   @param[in] *bfa		- bfa data struct
6760 */
6761bfa_status_t
6762bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
6763{
6764	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6765	struct bfa_dport_s *dport = &fcdiag->dport;
6766
6767	/*
6768	 * Check to see if IOC is down
6769	 */
6770	if (!bfa_iocfc_is_operational(bfa))
6771		return BFA_STATUS_IOC_NON_OP;
6772
6773	/*
6774	 * Check if dport is busy
6775	 */
6776	if (bfa_dport_is_sending_req(dport))
6777		return BFA_STATUS_DEVBUSY;
6778
6779	/*
6780	 * Check if dport is in enabled state.
6781	 */
6782	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6783		bfa_trc(dport->bfa, 0);
6784		return BFA_STATUS_DPORT_DISABLED;
6785
6786	}
6787
6788	/*
6789	 * Check if there is SFP
6790	 */
6791	if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6792		return BFA_STATUS_DPORT_INV_SFP;
6793
6794	memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
6795
6796	return BFA_STATUS_OK;
6797}
~/ Read-only file preview.