brintos

brintos / linux-shallow public Read only

0
0
Text · 159.1 KiB · ea2f107 Raw
7020 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.4 * Copyright (c) 2014- QLogic Corporation.5 * All rights reserved6 * www.qlogic.com7 *8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.9 */10 11#include "bfad_drv.h"12#include "bfad_im.h"13#include "bfa_ioc.h"14#include "bfi_reg.h"15#include "bfa_defs.h"16#include "bfa_defs_svc.h"17#include "bfi.h"18 19BFA_TRC_FILE(CNA, IOC);20 21/*22 * IOC local definitions23 */24#define BFA_IOC_TOV		3000	/* msecs */25#define BFA_IOC_HWSEM_TOV	500	/* msecs */26#define BFA_IOC_HB_TOV		500	/* msecs */27#define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV28#define BFA_IOC_POLL_TOV	BFA_TIMER_FREQ29 30#define bfa_ioc_timer_start(__ioc)					\31	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\32			bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)33#define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)34 35#define bfa_hb_timer_start(__ioc)					\36	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer,		\37			bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)38#define bfa_hb_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->hb_timer)39 40#define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))41 42#define bfa_ioc_state_disabled(__sm)		\43	(((__sm) == BFI_IOC_UNINIT) ||		\44	((__sm) == BFI_IOC_INITING) ||		\45	((__sm) == BFI_IOC_HWINIT) ||		\46	((__sm) == BFI_IOC_DISABLED) ||		\47	((__sm) == BFI_IOC_FAIL) ||		\48	((__sm) == BFI_IOC_CFG_DISABLED))49 50/*51 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.52 */53 54#define bfa_ioc_firmware_lock(__ioc)			\55			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))56#define bfa_ioc_firmware_unlock(__ioc)			\57			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))58#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))59#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))60#define bfa_ioc_notify_fail(__ioc)              \61			((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))62#define bfa_ioc_sync_start(__ioc)               \63			((__ioc)->ioc_hwif->ioc_sync_start(__ioc))64#define bfa_ioc_sync_join(__ioc)                \65			((__ioc)->ioc_hwif->ioc_sync_join(__ioc))66#define bfa_ioc_sync_leave(__ioc)               \67			((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))68#define bfa_ioc_sync_ack(__ioc)                 \69			((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))70#define bfa_ioc_sync_complete(__ioc)            \71			((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))72#define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate)		\73			((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate))74#define bfa_ioc_get_cur_ioc_fwstate(__ioc)		\75			((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc))76#define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate)		\77		((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate))78#define bfa_ioc_get_alt_ioc_fwstate(__ioc)		\79			((__ioc)->ioc_hwif->ioc_get_alt_fwstate(__ioc))80 81#define bfa_ioc_mbox_cmd_pending(__ioc)		\82			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \83			readl((__ioc)->ioc_regs.hfn_mbox_cmd))84 85bfa_boolean_t bfa_auto_recover = BFA_TRUE;86 87/*88 * forward declarations89 */90static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);91static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);92static void bfa_ioc_timeout(void *ioc);93static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);94static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);95static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);96static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);97static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);98static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);99static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);100static void bfa_ioc_recover(struct bfa_ioc_s *ioc);101static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,102				enum bfa_ioc_event_e event);103static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);104static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);105static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);106static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);107static enum bfi_ioc_img_ver_cmp_e bfa_ioc_fw_ver_patch_cmp(108				struct bfi_ioc_image_hdr_s *base_fwhdr,109				struct bfi_ioc_image_hdr_s *fwhdr_to_cmp);110static enum bfi_ioc_img_ver_cmp_e bfa_ioc_flash_fwver_cmp(111				struct bfa_ioc_s *ioc,112				struct bfi_ioc_image_hdr_s *base_fwhdr);113 114/*115 * IOC state machine definitions/declarations116 */117bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);118bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);119bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);120bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);121bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);122bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);123bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);124bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);125bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);126bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);127 128struct bfa_ioc_sm_table {129	bfa_ioc_sm_t	sm;		/*  state machine function	*/130	enum bfa_ioc_state state;	/*  state machine encoding	*/131	char		*name;		/*  state name for display	*/132};133 134static struct bfa_ioc_sm_table ioc_sm_table[] = {135	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},136	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},137	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},138	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},139	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},140	{BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},141	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},142	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},143	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},144	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},145};146 147static inline enum bfa_ioc_state148bfa_ioc_sm_to_state(struct bfa_ioc_sm_table *smt, bfa_ioc_sm_t sm)149{150	int	i = 0;151 152	while (smt[i].sm && smt[i].sm != sm)153		i++;154	return smt[i].state;155}156 157/*158 * IOCPF state machine definitions/declarations159 */160 161#define bfa_iocpf_timer_start(__ioc)					\162	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\163			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)164#define bfa_iocpf_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->ioc_timer)165 166#define bfa_iocpf_poll_timer_start(__ioc)				\167	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\168			bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)169 170#define bfa_sem_timer_start(__ioc)					\171	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,	\172			bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)173#define bfa_sem_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->sem_timer)174 175/*176 * Forward declareations for iocpf state machine177 */178static void bfa_iocpf_timeout(void *ioc_arg);179static void bfa_iocpf_sem_timeout(void *ioc_arg);180static void bfa_iocpf_poll_timeout(void *ioc_arg);181 182/*183 * IOCPF states184 */185enum bfa_iocpf_state {186	BFA_IOCPF_RESET		= 1,	/*  IOC is in reset state */187	BFA_IOCPF_SEMWAIT	= 2,	/*  Waiting for IOC h/w semaphore */188	BFA_IOCPF_HWINIT	= 3,	/*  IOC h/w is being initialized */189	BFA_IOCPF_READY		= 4,	/*  IOCPF is initialized */190	BFA_IOCPF_INITFAIL	= 5,	/*  IOCPF failed */191	BFA_IOCPF_FAIL		= 6,	/*  IOCPF failed */192	BFA_IOCPF_DISABLING	= 7,	/*  IOCPF is being disabled */193	BFA_IOCPF_DISABLED	= 8,	/*  IOCPF is disabled */194	BFA_IOCPF_FWMISMATCH	= 9,	/*  IOC f/w different from drivers */195};196 197bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);198bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);199bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);200bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);201bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);202bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);203bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);204bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s,205						enum iocpf_event);206bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);207bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);208bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);209bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);210bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s,211						enum iocpf_event);212bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);213 214struct bfa_iocpf_sm_table {215	bfa_iocpf_sm_t	sm;		/*  state machine function	*/216	enum bfa_iocpf_state state;	/*  state machine encoding	*/217	char		*name;		/*  state name for display	*/218};219 220static inline enum bfa_iocpf_state221bfa_iocpf_sm_to_state(struct bfa_iocpf_sm_table *smt, bfa_iocpf_sm_t sm)222{223	int	i = 0;224 225	while (smt[i].sm && smt[i].sm != sm)226		i++;227	return smt[i].state;228}229 230static struct bfa_iocpf_sm_table iocpf_sm_table[] = {231	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},232	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},233	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},234	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},235	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},236	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},237	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},238	{BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},239	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},240	{BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},241	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},242	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},243	{BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},244	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},245};246 247/*248 * IOC State Machine249 */250 251/*252 * Beginning state. IOC uninit state.253 */254 255static void256bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)257{258}259 260/*261 * IOC is in uninit state.262 */263static void264bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)265{266	bfa_trc(ioc, event);267 268	switch (event) {269	case IOC_E_RESET:270		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);271		break;272 273	default:274		bfa_sm_fault(ioc, event);275	}276}277/*278 * Reset entry actions -- initialize state machine279 */280static void281bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)282{283	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);284}285 286/*287 * IOC is in reset state.288 */289static void290bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)291{292	bfa_trc(ioc, event);293 294	switch (event) {295	case IOC_E_ENABLE:296		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);297		break;298 299	case IOC_E_DISABLE:300		bfa_ioc_disable_comp(ioc);301		break;302 303	case IOC_E_DETACH:304		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);305		break;306 307	default:308		bfa_sm_fault(ioc, event);309	}310}311 312 313static void314bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)315{316	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);317}318 319/*320 * Host IOC function is being enabled, awaiting response from firmware.321 * Semaphore is acquired.322 */323static void324bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)325{326	bfa_trc(ioc, event);327 328	switch (event) {329	case IOC_E_ENABLED:330		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);331		break;332 333	case IOC_E_PFFAILED:334		/* !!! fall through !!! */335	case IOC_E_HWERROR:336		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);337		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);338		if (event != IOC_E_PFFAILED)339			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);340		break;341 342	case IOC_E_HWFAILED:343		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);344		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);345		break;346 347	case IOC_E_DISABLE:348		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);349		break;350 351	case IOC_E_DETACH:352		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);353		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);354		break;355 356	case IOC_E_ENABLE:357		break;358 359	default:360		bfa_sm_fault(ioc, event);361	}362}363 364 365static void366bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)367{368	bfa_ioc_timer_start(ioc);369	bfa_ioc_send_getattr(ioc);370}371 372/*373 * IOC configuration in progress. Timer is active.374 */375static void376bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)377{378	bfa_trc(ioc, event);379 380	switch (event) {381	case IOC_E_FWRSP_GETATTR:382		bfa_ioc_timer_stop(ioc);383		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);384		break;385 386	case IOC_E_PFFAILED:387	case IOC_E_HWERROR:388		bfa_ioc_timer_stop(ioc);389		fallthrough;390	case IOC_E_TIMEOUT:391		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);392		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);393		if (event != IOC_E_PFFAILED)394			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);395		break;396 397	case IOC_E_DISABLE:398		bfa_ioc_timer_stop(ioc);399		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);400		break;401 402	case IOC_E_ENABLE:403		break;404 405	default:406		bfa_sm_fault(ioc, event);407	}408}409 410static void411bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)412{413	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;414 415	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);416	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);417	bfa_ioc_hb_monitor(ioc);418	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");419	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);420}421 422static void423bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)424{425	bfa_trc(ioc, event);426 427	switch (event) {428	case IOC_E_ENABLE:429		break;430 431	case IOC_E_DISABLE:432		bfa_hb_timer_stop(ioc);433		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);434		break;435 436	case IOC_E_PFFAILED:437	case IOC_E_HWERROR:438		bfa_hb_timer_stop(ioc);439		fallthrough;440	case IOC_E_HBFAIL:441		if (ioc->iocpf.auto_recover)442			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);443		else444			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);445 446		bfa_ioc_fail_notify(ioc);447 448		if (event != IOC_E_PFFAILED)449			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);450		break;451 452	default:453		bfa_sm_fault(ioc, event);454	}455}456 457 458static void459bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)460{461	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;462	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);463	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");464	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);465}466 467/*468 * IOC is being disabled469 */470static void471bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)472{473	bfa_trc(ioc, event);474 475	switch (event) {476	case IOC_E_DISABLED:477		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);478		break;479 480	case IOC_E_HWERROR:481		/*482		 * No state change.  Will move to disabled state483		 * after iocpf sm completes failure processing and484		 * moves to disabled state.485		 */486		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);487		break;488 489	case IOC_E_HWFAILED:490		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);491		bfa_ioc_disable_comp(ioc);492		break;493 494	default:495		bfa_sm_fault(ioc, event);496	}497}498 499/*500 * IOC disable completion entry.501 */502static void503bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)504{505	bfa_ioc_disable_comp(ioc);506}507 508static void509bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)510{511	bfa_trc(ioc, event);512 513	switch (event) {514	case IOC_E_ENABLE:515		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);516		break;517 518	case IOC_E_DISABLE:519		ioc->cbfn->disable_cbfn(ioc->bfa);520		break;521 522	case IOC_E_DETACH:523		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);524		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);525		break;526 527	default:528		bfa_sm_fault(ioc, event);529	}530}531 532 533static void534bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)535{536	bfa_trc(ioc, 0);537}538 539/*540 * Hardware initialization retry.541 */542static void543bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)544{545	bfa_trc(ioc, event);546 547	switch (event) {548	case IOC_E_ENABLED:549		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);550		break;551 552	case IOC_E_PFFAILED:553	case IOC_E_HWERROR:554		/*555		 * Initialization retry failed.556		 */557		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);558		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);559		if (event != IOC_E_PFFAILED)560			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);561		break;562 563	case IOC_E_HWFAILED:564		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);565		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);566		break;567 568	case IOC_E_ENABLE:569		break;570 571	case IOC_E_DISABLE:572		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);573		break;574 575	case IOC_E_DETACH:576		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);577		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);578		break;579 580	default:581		bfa_sm_fault(ioc, event);582	}583}584 585 586static void587bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)588{589	bfa_trc(ioc, 0);590}591 592/*593 * IOC failure.594 */595static void596bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)597{598	bfa_trc(ioc, event);599 600	switch (event) {601 602	case IOC_E_ENABLE:603		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);604		break;605 606	case IOC_E_DISABLE:607		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);608		break;609 610	case IOC_E_DETACH:611		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);612		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);613		break;614 615	case IOC_E_HWERROR:616	case IOC_E_HWFAILED:617		/*618		 * HB failure / HW error notification, ignore.619		 */620		break;621	default:622		bfa_sm_fault(ioc, event);623	}624}625 626static void627bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc)628{629	bfa_trc(ioc, 0);630}631 632static void633bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)634{635	bfa_trc(ioc, event);636 637	switch (event) {638	case IOC_E_ENABLE:639		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);640		break;641 642	case IOC_E_DISABLE:643		ioc->cbfn->disable_cbfn(ioc->bfa);644		break;645 646	case IOC_E_DETACH:647		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);648		break;649 650	case IOC_E_HWERROR:651		/* Ignore - already in hwfail state */652		break;653 654	default:655		bfa_sm_fault(ioc, event);656	}657}658 659/*660 * IOCPF State Machine661 */662 663/*664 * Reset entry actions -- initialize state machine665 */666static void667bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)668{669	iocpf->fw_mismatch_notified = BFA_FALSE;670	iocpf->auto_recover = bfa_auto_recover;671}672 673/*674 * Beginning state. IOC is in reset state.675 */676static void677bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)678{679	struct bfa_ioc_s *ioc = iocpf->ioc;680 681	bfa_trc(ioc, event);682 683	switch (event) {684	case IOCPF_E_ENABLE:685		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);686		break;687 688	case IOCPF_E_STOP:689		break;690 691	default:692		bfa_sm_fault(ioc, event);693	}694}695 696/*697 * Semaphore should be acquired for version check.698 */699static void700bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)701{702	struct bfi_ioc_image_hdr_s	fwhdr;703	u32	r32, fwstate, pgnum, loff = 0;704	int	i;705 706	/*707	 * Spin on init semaphore to serialize.708	 */709	r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg);710	while (r32 & 0x1) {711		udelay(20);712		r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg);713	}714 715	/* h/w sem init */716	fwstate = bfa_ioc_get_cur_ioc_fwstate(iocpf->ioc);717	if (fwstate == BFI_IOC_UNINIT) {718		writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);719		goto sem_get;720	}721 722	bfa_ioc_fwver_get(iocpf->ioc, &fwhdr);723 724	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {725		writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);726		goto sem_get;727	}728 729	/*730	 * Clear fwver hdr731	 */732	pgnum = PSS_SMEM_PGNUM(iocpf->ioc->ioc_regs.smem_pg0, loff);733	writel(pgnum, iocpf->ioc->ioc_regs.host_page_num_fn);734 735	for (i = 0; i < sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32); i++) {736		bfa_mem_write(iocpf->ioc->ioc_regs.smem_page_start, loff, 0);737		loff += sizeof(u32);738	}739 740	bfa_trc(iocpf->ioc, fwstate);741	bfa_trc(iocpf->ioc, swab32(fwhdr.exec));742	bfa_ioc_set_cur_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT);743	bfa_ioc_set_alt_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT);744 745	/*746	 * Unlock the hw semaphore. Should be here only once per boot.747	 */748	bfa_ioc_ownership_reset(iocpf->ioc);749 750	/*751	 * unlock init semaphore.752	 */753	writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);754 755sem_get:756	bfa_ioc_hw_sem_get(iocpf->ioc);757}758 759/*760 * Awaiting h/w semaphore to continue with version check.761 */762static void763bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)764{765	struct bfa_ioc_s *ioc = iocpf->ioc;766 767	bfa_trc(ioc, event);768 769	switch (event) {770	case IOCPF_E_SEMLOCKED:771		if (bfa_ioc_firmware_lock(ioc)) {772			if (bfa_ioc_sync_start(ioc)) {773				bfa_ioc_sync_join(ioc);774				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);775			} else {776				bfa_ioc_firmware_unlock(ioc);777				writel(1, ioc->ioc_regs.ioc_sem_reg);778				bfa_sem_timer_start(ioc);779			}780		} else {781			writel(1, ioc->ioc_regs.ioc_sem_reg);782			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);783		}784		break;785 786	case IOCPF_E_SEM_ERROR:787		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);788		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);789		break;790 791	case IOCPF_E_DISABLE:792		bfa_sem_timer_stop(ioc);793		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);794		bfa_fsm_send_event(ioc, IOC_E_DISABLED);795		break;796 797	case IOCPF_E_STOP:798		bfa_sem_timer_stop(ioc);799		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);800		break;801 802	default:803		bfa_sm_fault(ioc, event);804	}805}806 807/*808 * Notify enable completion callback.809 */810static void811bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)812{813	/*814	 * Call only the first time sm enters fwmismatch state.815	 */816	if (iocpf->fw_mismatch_notified == BFA_FALSE)817		bfa_ioc_pf_fwmismatch(iocpf->ioc);818 819	iocpf->fw_mismatch_notified = BFA_TRUE;820	bfa_iocpf_timer_start(iocpf->ioc);821}822 823/*824 * Awaiting firmware version match.825 */826static void827bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)828{829	struct bfa_ioc_s *ioc = iocpf->ioc;830 831	bfa_trc(ioc, event);832 833	switch (event) {834	case IOCPF_E_TIMEOUT:835		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);836		break;837 838	case IOCPF_E_DISABLE:839		bfa_iocpf_timer_stop(ioc);840		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);841		bfa_fsm_send_event(ioc, IOC_E_DISABLED);842		break;843 844	case IOCPF_E_STOP:845		bfa_iocpf_timer_stop(ioc);846		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);847		break;848 849	default:850		bfa_sm_fault(ioc, event);851	}852}853 854/*855 * Request for semaphore.856 */857static void858bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)859{860	bfa_ioc_hw_sem_get(iocpf->ioc);861}862 863/*864 * Awaiting semaphore for h/w initialzation.865 */866static void867bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)868{869	struct bfa_ioc_s *ioc = iocpf->ioc;870 871	bfa_trc(ioc, event);872 873	switch (event) {874	case IOCPF_E_SEMLOCKED:875		if (bfa_ioc_sync_complete(ioc)) {876			bfa_ioc_sync_join(ioc);877			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);878		} else {879			writel(1, ioc->ioc_regs.ioc_sem_reg);880			bfa_sem_timer_start(ioc);881		}882		break;883 884	case IOCPF_E_SEM_ERROR:885		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);886		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);887		break;888 889	case IOCPF_E_DISABLE:890		bfa_sem_timer_stop(ioc);891		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);892		break;893 894	default:895		bfa_sm_fault(ioc, event);896	}897}898 899static void900bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)901{902	iocpf->poll_time = 0;903	bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);904}905 906/*907 * Hardware is being initialized. Interrupts are enabled.908 * Holding hardware semaphore lock.909 */910static void911bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)912{913	struct bfa_ioc_s *ioc = iocpf->ioc;914 915	bfa_trc(ioc, event);916 917	switch (event) {918	case IOCPF_E_FWREADY:919		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);920		break;921 922	case IOCPF_E_TIMEOUT:923		writel(1, ioc->ioc_regs.ioc_sem_reg);924		bfa_fsm_send_event(ioc, IOC_E_PFFAILED);925		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);926		break;927 928	case IOCPF_E_DISABLE:929		bfa_iocpf_timer_stop(ioc);930		bfa_ioc_sync_leave(ioc);931		writel(1, ioc->ioc_regs.ioc_sem_reg);932		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);933		break;934 935	default:936		bfa_sm_fault(ioc, event);937	}938}939 940static void941bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)942{943	bfa_iocpf_timer_start(iocpf->ioc);944	/*945	 * Enable Interrupts before sending fw IOC ENABLE cmd.946	 */947	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);948	bfa_ioc_send_enable(iocpf->ioc);949}950 951/*952 * Host IOC function is being enabled, awaiting response from firmware.953 * Semaphore is acquired.954 */955static void956bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)957{958	struct bfa_ioc_s *ioc = iocpf->ioc;959 960	bfa_trc(ioc, event);961 962	switch (event) {963	case IOCPF_E_FWRSP_ENABLE:964		bfa_iocpf_timer_stop(ioc);965		writel(1, ioc->ioc_regs.ioc_sem_reg);966		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);967		break;968 969	case IOCPF_E_INITFAIL:970		bfa_iocpf_timer_stop(ioc);971		fallthrough;972 973	case IOCPF_E_TIMEOUT:974		writel(1, ioc->ioc_regs.ioc_sem_reg);975		if (event == IOCPF_E_TIMEOUT)976			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);977		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);978		break;979 980	case IOCPF_E_DISABLE:981		bfa_iocpf_timer_stop(ioc);982		writel(1, ioc->ioc_regs.ioc_sem_reg);983		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);984		break;985 986	default:987		bfa_sm_fault(ioc, event);988	}989}990 991static void992bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)993{994	bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);995}996 997static void998bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)999{1000	struct bfa_ioc_s *ioc = iocpf->ioc;1001 1002	bfa_trc(ioc, event);1003 1004	switch (event) {1005	case IOCPF_E_DISABLE:1006		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);1007		break;1008 1009	case IOCPF_E_GETATTRFAIL:1010		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);1011		break;1012 1013	case IOCPF_E_FAIL:1014		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);1015		break;1016 1017	default:1018		bfa_sm_fault(ioc, event);1019	}1020}1021 1022static void1023bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)1024{1025	bfa_iocpf_timer_start(iocpf->ioc);1026	bfa_ioc_send_disable(iocpf->ioc);1027}1028 1029/*1030 * IOC is being disabled1031 */1032static void1033bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1034{1035	struct bfa_ioc_s *ioc = iocpf->ioc;1036 1037	bfa_trc(ioc, event);1038 1039	switch (event) {1040	case IOCPF_E_FWRSP_DISABLE:1041		bfa_iocpf_timer_stop(ioc);1042		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);1043		break;1044 1045	case IOCPF_E_FAIL:1046		bfa_iocpf_timer_stop(ioc);1047		fallthrough;1048 1049	case IOCPF_E_TIMEOUT:1050		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);1051		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);1052		break;1053 1054	case IOCPF_E_FWRSP_ENABLE:1055		break;1056 1057	default:1058		bfa_sm_fault(ioc, event);1059	}1060}1061 1062static void1063bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf)1064{1065	bfa_ioc_hw_sem_get(iocpf->ioc);1066}1067 1068/*1069 * IOC hb ack request is being removed.1070 */1071static void1072bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1073{1074	struct bfa_ioc_s *ioc = iocpf->ioc;1075 1076	bfa_trc(ioc, event);1077 1078	switch (event) {1079	case IOCPF_E_SEMLOCKED:1080		bfa_ioc_sync_leave(ioc);1081		writel(1, ioc->ioc_regs.ioc_sem_reg);1082		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);1083		break;1084 1085	case IOCPF_E_SEM_ERROR:1086		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);1087		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);1088		break;1089 1090	case IOCPF_E_FAIL:1091		break;1092 1093	default:1094		bfa_sm_fault(ioc, event);1095	}1096}1097 1098/*1099 * IOC disable completion entry.1100 */1101static void1102bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)1103{1104	bfa_ioc_mbox_flush(iocpf->ioc);1105	bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);1106}1107 1108static void1109bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1110{1111	struct bfa_ioc_s *ioc = iocpf->ioc;1112 1113	bfa_trc(ioc, event);1114 1115	switch (event) {1116	case IOCPF_E_ENABLE:1117		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);1118		break;1119 1120	case IOCPF_E_STOP:1121		bfa_ioc_firmware_unlock(ioc);1122		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);1123		break;1124 1125	default:1126		bfa_sm_fault(ioc, event);1127	}1128}1129 1130static void1131bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)1132{1133	bfa_ioc_debug_save_ftrc(iocpf->ioc);1134	bfa_ioc_hw_sem_get(iocpf->ioc);1135}1136 1137/*1138 * Hardware initialization failed.1139 */1140static void1141bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1142{1143	struct bfa_ioc_s *ioc = iocpf->ioc;1144 1145	bfa_trc(ioc, event);1146 1147	switch (event) {1148	case IOCPF_E_SEMLOCKED:1149		bfa_ioc_notify_fail(ioc);1150		bfa_ioc_sync_leave(ioc);1151		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);1152		writel(1, ioc->ioc_regs.ioc_sem_reg);1153		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);1154		break;1155 1156	case IOCPF_E_SEM_ERROR:1157		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);1158		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);1159		break;1160 1161	case IOCPF_E_DISABLE:1162		bfa_sem_timer_stop(ioc);1163		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);1164		break;1165 1166	case IOCPF_E_STOP:1167		bfa_sem_timer_stop(ioc);1168		bfa_ioc_firmware_unlock(ioc);1169		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);1170		break;1171 1172	case IOCPF_E_FAIL:1173		break;1174 1175	default:1176		bfa_sm_fault(ioc, event);1177	}1178}1179 1180static void1181bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)1182{1183	bfa_trc(iocpf->ioc, 0);1184}1185 1186/*1187 * Hardware initialization failed.1188 */1189static void1190bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1191{1192	struct bfa_ioc_s *ioc = iocpf->ioc;1193 1194	bfa_trc(ioc, event);1195 1196	switch (event) {1197	case IOCPF_E_DISABLE:1198		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);1199		break;1200 1201	case IOCPF_E_STOP:1202		bfa_ioc_firmware_unlock(ioc);1203		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);1204		break;1205 1206	default:1207		bfa_sm_fault(ioc, event);1208	}1209}1210 1211static void1212bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)1213{1214	/*1215	 * Mark IOC as failed in hardware and stop firmware.1216	 */1217	bfa_ioc_lpu_stop(iocpf->ioc);1218 1219	/*1220	 * Flush any queued up mailbox requests.1221	 */1222	bfa_ioc_mbox_flush(iocpf->ioc);1223 1224	bfa_ioc_hw_sem_get(iocpf->ioc);1225}1226 1227static void1228bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1229{1230	struct bfa_ioc_s *ioc = iocpf->ioc;1231 1232	bfa_trc(ioc, event);1233 1234	switch (event) {1235	case IOCPF_E_SEMLOCKED:1236		bfa_ioc_sync_ack(ioc);1237		bfa_ioc_notify_fail(ioc);1238		if (!iocpf->auto_recover) {1239			bfa_ioc_sync_leave(ioc);1240			bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);1241			writel(1, ioc->ioc_regs.ioc_sem_reg);1242			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);1243		} else {1244			if (bfa_ioc_sync_complete(ioc))1245				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);1246			else {1247				writel(1, ioc->ioc_regs.ioc_sem_reg);1248				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);1249			}1250		}1251		break;1252 1253	case IOCPF_E_SEM_ERROR:1254		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);1255		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);1256		break;1257 1258	case IOCPF_E_DISABLE:1259		bfa_sem_timer_stop(ioc);1260		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);1261		break;1262 1263	case IOCPF_E_FAIL:1264		break;1265 1266	default:1267		bfa_sm_fault(ioc, event);1268	}1269}1270 1271static void1272bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)1273{1274	bfa_trc(iocpf->ioc, 0);1275}1276 1277/*1278 * IOC is in failed state.1279 */1280static void1281bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)1282{1283	struct bfa_ioc_s *ioc = iocpf->ioc;1284 1285	bfa_trc(ioc, event);1286 1287	switch (event) {1288	case IOCPF_E_DISABLE:1289		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);1290		break;1291 1292	default:1293		bfa_sm_fault(ioc, event);1294	}1295}1296 1297/*1298 *  BFA IOC private functions1299 */1300 1301/*1302 * Notify common modules registered for notification.1303 */1304static void1305bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)1306{1307	struct bfa_ioc_notify_s	*notify;1308	struct list_head	*qe;1309 1310	list_for_each(qe, &ioc->notify_q) {1311		notify = (struct bfa_ioc_notify_s *)qe;1312		notify->cbfn(notify->cbarg, event);1313	}1314}1315 1316static void1317bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)1318{1319	ioc->cbfn->disable_cbfn(ioc->bfa);1320	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);1321}1322 1323bfa_boolean_t1324bfa_ioc_sem_get(void __iomem *sem_reg)1325{1326	u32 r32;1327	int cnt = 0;1328#define BFA_SEM_SPINCNT	30001329 1330	r32 = readl(sem_reg);1331 1332	while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {1333		cnt++;1334		udelay(2);1335		r32 = readl(sem_reg);1336	}1337 1338	if (!(r32 & 1))1339		return BFA_TRUE;1340 1341	return BFA_FALSE;1342}1343 1344static void1345bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)1346{1347	u32	r32;1348 1349	/*1350	 * First read to the semaphore register will return 0, subsequent reads1351	 * will return 1. Semaphore is released by writing 1 to the register1352	 */1353	r32 = readl(ioc->ioc_regs.ioc_sem_reg);1354	if (r32 == ~0) {1355		WARN_ON(r32 == ~0);1356		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);1357		return;1358	}1359	if (!(r32 & 1)) {1360		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);1361		return;1362	}1363 1364	bfa_sem_timer_start(ioc);1365}1366 1367/*1368 * Initialize LPU local memory (aka secondary memory / SRAM)1369 */1370static void1371bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)1372{1373	u32	pss_ctl;1374	int		i;1375#define PSS_LMEM_INIT_TIME  100001376 1377	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1378	pss_ctl &= ~__PSS_LMEM_RESET;1379	pss_ctl |= __PSS_LMEM_INIT_EN;1380 1381	/*1382	 * i2c workaround 12.5khz clock1383	 */1384	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);1385	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1386 1387	/*1388	 * wait for memory initialization to be complete1389	 */1390	i = 0;1391	do {1392		pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1393		i++;1394	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));1395 1396	/*1397	 * If memory initialization is not successful, IOC timeout will catch1398	 * such failures.1399	 */1400	WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));1401	bfa_trc(ioc, pss_ctl);1402 1403	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);1404	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1405}1406 1407static void1408bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)1409{1410	u32	pss_ctl;1411 1412	/*1413	 * Take processor out of reset.1414	 */1415	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1416	pss_ctl &= ~__PSS_LPU0_RESET;1417 1418	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1419}1420 1421static void1422bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)1423{1424	u32	pss_ctl;1425 1426	/*1427	 * Put processors in reset.1428	 */1429	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1430	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);1431 1432	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1433}1434 1435/*1436 * Get driver and firmware versions.1437 */1438void1439bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)1440{1441	u32	pgnum;1442	u32	loff = 0;1443	int		i;1444	u32	*fwsig = (u32 *) fwhdr;1445 1446	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);1447	writel(pgnum, ioc->ioc_regs.host_page_num_fn);1448 1449	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));1450	     i++) {1451		fwsig[i] =1452			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);1453		loff += sizeof(u32);1454	}1455}1456 1457/*1458 * Returns TRUE if driver is willing to work with current smem f/w version.1459 */1460bfa_boolean_t1461bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,1462		struct bfi_ioc_image_hdr_s *smem_fwhdr)1463{1464	struct bfi_ioc_image_hdr_s *drv_fwhdr;1465	enum bfi_ioc_img_ver_cmp_e smem_flash_cmp, drv_smem_cmp;1466 1467	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)1468		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);1469 1470	/*1471	 * If smem is incompatible or old, driver should not work with it.1472	 */1473	drv_smem_cmp = bfa_ioc_fw_ver_patch_cmp(drv_fwhdr, smem_fwhdr);1474	if (drv_smem_cmp == BFI_IOC_IMG_VER_INCOMP ||1475		drv_smem_cmp == BFI_IOC_IMG_VER_OLD) {1476		return BFA_FALSE;1477	}1478 1479	/*1480	 * IF Flash has a better F/W than smem do not work with smem.1481	 * If smem f/w == flash f/w, as smem f/w not old | incmp, work with it.1482	 * If Flash is old or incomp work with smem iff smem f/w == drv f/w.1483	 */1484	smem_flash_cmp = bfa_ioc_flash_fwver_cmp(ioc, smem_fwhdr);1485 1486	if (smem_flash_cmp == BFI_IOC_IMG_VER_BETTER) {1487		return BFA_FALSE;1488	} else if (smem_flash_cmp == BFI_IOC_IMG_VER_SAME) {1489		return BFA_TRUE;1490	} else {1491		return (drv_smem_cmp == BFI_IOC_IMG_VER_SAME) ?1492			BFA_TRUE : BFA_FALSE;1493	}1494}1495 1496/*1497 * Return true if current running version is valid. Firmware signature and1498 * execution context (driver/bios) must match.1499 */1500static bfa_boolean_t1501bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)1502{1503	struct bfi_ioc_image_hdr_s fwhdr;1504 1505	bfa_ioc_fwver_get(ioc, &fwhdr);1506 1507	if (swab32(fwhdr.bootenv) != boot_env) {1508		bfa_trc(ioc, fwhdr.bootenv);1509		bfa_trc(ioc, boot_env);1510		return BFA_FALSE;1511	}1512 1513	return bfa_ioc_fwver_cmp(ioc, &fwhdr);1514}1515 1516static bfa_boolean_t1517bfa_ioc_fwver_md5_check(struct bfi_ioc_image_hdr_s *fwhdr_1,1518				struct bfi_ioc_image_hdr_s *fwhdr_2)1519{1520	int i;1521 1522	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++)1523		if (fwhdr_1->md5sum[i] != fwhdr_2->md5sum[i])1524			return BFA_FALSE;1525 1526	return BFA_TRUE;1527}1528 1529/*1530 * Returns TRUE if major minor and maintainence are same.1531 * If patch versions are same, check for MD5 Checksum to be same.1532 */1533static bfa_boolean_t1534bfa_ioc_fw_ver_compatible(struct bfi_ioc_image_hdr_s *drv_fwhdr,1535				struct bfi_ioc_image_hdr_s *fwhdr_to_cmp)1536{1537	if (drv_fwhdr->signature != fwhdr_to_cmp->signature)1538		return BFA_FALSE;1539 1540	if (drv_fwhdr->fwver.major != fwhdr_to_cmp->fwver.major)1541		return BFA_FALSE;1542 1543	if (drv_fwhdr->fwver.minor != fwhdr_to_cmp->fwver.minor)1544		return BFA_FALSE;1545 1546	if (drv_fwhdr->fwver.maint != fwhdr_to_cmp->fwver.maint)1547		return BFA_FALSE;1548 1549	if (drv_fwhdr->fwver.patch == fwhdr_to_cmp->fwver.patch &&1550		drv_fwhdr->fwver.phase == fwhdr_to_cmp->fwver.phase &&1551		drv_fwhdr->fwver.build == fwhdr_to_cmp->fwver.build) {1552		return bfa_ioc_fwver_md5_check(drv_fwhdr, fwhdr_to_cmp);1553	}1554 1555	return BFA_TRUE;1556}1557 1558static bfa_boolean_t1559bfa_ioc_flash_fwver_valid(struct bfi_ioc_image_hdr_s *flash_fwhdr)1560{1561	if (flash_fwhdr->fwver.major == 0 || flash_fwhdr->fwver.major == 0xFF)1562		return BFA_FALSE;1563 1564	return BFA_TRUE;1565}1566 1567static bfa_boolean_t fwhdr_is_ga(struct bfi_ioc_image_hdr_s *fwhdr)1568{1569	if (fwhdr->fwver.phase == 0 &&1570		fwhdr->fwver.build == 0)1571		return BFA_TRUE;1572 1573	return BFA_FALSE;1574}1575 1576/*1577 * Returns TRUE if both are compatible and patch of fwhdr_to_cmp is better.1578 */1579static enum bfi_ioc_img_ver_cmp_e1580bfa_ioc_fw_ver_patch_cmp(struct bfi_ioc_image_hdr_s *base_fwhdr,1581				struct bfi_ioc_image_hdr_s *fwhdr_to_cmp)1582{1583	if (bfa_ioc_fw_ver_compatible(base_fwhdr, fwhdr_to_cmp) == BFA_FALSE)1584		return BFI_IOC_IMG_VER_INCOMP;1585 1586	if (fwhdr_to_cmp->fwver.patch > base_fwhdr->fwver.patch)1587		return BFI_IOC_IMG_VER_BETTER;1588 1589	else if (fwhdr_to_cmp->fwver.patch < base_fwhdr->fwver.patch)1590		return BFI_IOC_IMG_VER_OLD;1591 1592	/*1593	 * GA takes priority over internal builds of the same patch stream.1594	 * At this point major minor maint and patch numbers are same.1595	 */1596 1597	if (fwhdr_is_ga(base_fwhdr) == BFA_TRUE) {1598		if (fwhdr_is_ga(fwhdr_to_cmp))1599			return BFI_IOC_IMG_VER_SAME;1600		else1601			return BFI_IOC_IMG_VER_OLD;1602	} else {1603		if (fwhdr_is_ga(fwhdr_to_cmp))1604			return BFI_IOC_IMG_VER_BETTER;1605	}1606 1607	if (fwhdr_to_cmp->fwver.phase > base_fwhdr->fwver.phase)1608		return BFI_IOC_IMG_VER_BETTER;1609	else if (fwhdr_to_cmp->fwver.phase < base_fwhdr->fwver.phase)1610		return BFI_IOC_IMG_VER_OLD;1611 1612	if (fwhdr_to_cmp->fwver.build > base_fwhdr->fwver.build)1613		return BFI_IOC_IMG_VER_BETTER;1614	else if (fwhdr_to_cmp->fwver.build < base_fwhdr->fwver.build)1615		return BFI_IOC_IMG_VER_OLD;1616 1617	/*1618	 * All Version Numbers are equal.1619	 * Md5 check to be done as a part of compatibility check.1620	 */1621	return BFI_IOC_IMG_VER_SAME;1622}1623 1624#define BFA_FLASH_PART_FWIMG_ADDR	0x100000 /* fw image address */1625 1626bfa_status_t1627bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off,1628				u32 *fwimg)1629{1630	return bfa_flash_raw_read(ioc->pcidev.pci_bar_kva,1631			BFA_FLASH_PART_FWIMG_ADDR + (off * sizeof(u32)),1632			(char *)fwimg, BFI_FLASH_CHUNK_SZ);1633}1634 1635static enum bfi_ioc_img_ver_cmp_e1636bfa_ioc_flash_fwver_cmp(struct bfa_ioc_s *ioc,1637			struct bfi_ioc_image_hdr_s *base_fwhdr)1638{1639	struct bfi_ioc_image_hdr_s *flash_fwhdr;1640	bfa_status_t status;1641	u32 fwimg[BFI_FLASH_CHUNK_SZ_WORDS];1642 1643	status = bfa_ioc_flash_img_get_chnk(ioc, 0, fwimg);1644	if (status != BFA_STATUS_OK)1645		return BFI_IOC_IMG_VER_INCOMP;1646 1647	flash_fwhdr = (struct bfi_ioc_image_hdr_s *) fwimg;1648	if (bfa_ioc_flash_fwver_valid(flash_fwhdr) == BFA_TRUE)1649		return bfa_ioc_fw_ver_patch_cmp(base_fwhdr, flash_fwhdr);1650	else1651		return BFI_IOC_IMG_VER_INCOMP;1652}1653 1654 1655/*1656 * Invalidate fwver signature1657 */1658bfa_status_t1659bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc)1660{1661 1662	u32	pgnum;1663	u32	loff = 0;1664	enum bfi_ioc_state ioc_fwstate;1665 1666	ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);1667	if (!bfa_ioc_state_disabled(ioc_fwstate))1668		return BFA_STATUS_ADAPTER_ENABLED;1669 1670	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);1671	writel(pgnum, ioc->ioc_regs.host_page_num_fn);1672	bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, BFA_IOC_FW_INV_SIGN);1673 1674	return BFA_STATUS_OK;1675}1676 1677/*1678 * Conditionally flush any pending message from firmware at start.1679 */1680static void1681bfa_ioc_msgflush(struct bfa_ioc_s *ioc)1682{1683	u32	r32;1684 1685	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);1686	if (r32)1687		writel(1, ioc->ioc_regs.lpu_mbox_cmd);1688}1689 1690static void1691bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)1692{1693	enum bfi_ioc_state ioc_fwstate;1694	bfa_boolean_t fwvalid;1695	u32 boot_type;1696	u32 boot_env;1697 1698	ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);1699 1700	if (force)1701		ioc_fwstate = BFI_IOC_UNINIT;1702 1703	bfa_trc(ioc, ioc_fwstate);1704 1705	boot_type = BFI_FWBOOT_TYPE_NORMAL;1706	boot_env = BFI_FWBOOT_ENV_OS;1707 1708	/*1709	 * check if firmware is valid1710	 */1711	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?1712		BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);1713 1714	if (!fwvalid) {1715		if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK)1716			bfa_ioc_poll_fwinit(ioc);1717		return;1718	}1719 1720	/*1721	 * If hardware initialization is in progress (initialized by other IOC),1722	 * just wait for an initialization completion interrupt.1723	 */1724	if (ioc_fwstate == BFI_IOC_INITING) {1725		bfa_ioc_poll_fwinit(ioc);1726		return;1727	}1728 1729	/*1730	 * If IOC function is disabled and firmware version is same,1731	 * just re-enable IOC.1732	 *1733	 * If option rom, IOC must not be in operational state. With1734	 * convergence, IOC will be in operational state when 2nd driver1735	 * is loaded.1736	 */1737	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {1738 1739		/*1740		 * When using MSI-X any pending firmware ready event should1741		 * be flushed. Otherwise MSI-X interrupts are not delivered.1742		 */1743		bfa_ioc_msgflush(ioc);1744		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);1745		return;1746	}1747 1748	/*1749	 * Initialize the h/w for any other states.1750	 */1751	if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK)1752		bfa_ioc_poll_fwinit(ioc);1753}1754 1755static void1756bfa_ioc_timeout(void *ioc_arg)1757{1758	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;1759 1760	bfa_trc(ioc, 0);1761	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);1762}1763 1764void1765bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)1766{1767	u32 *msgp = (u32 *) ioc_msg;1768	u32 i;1769 1770	bfa_trc(ioc, msgp[0]);1771	bfa_trc(ioc, len);1772 1773	WARN_ON(len > BFI_IOC_MSGLEN_MAX);1774 1775	/*1776	 * first write msg to mailbox registers1777	 */1778	for (i = 0; i < len / sizeof(u32); i++)1779		writel(cpu_to_le32(msgp[i]),1780			ioc->ioc_regs.hfn_mbox + i * sizeof(u32));1781 1782	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)1783		writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));1784 1785	/*1786	 * write 1 to mailbox CMD to trigger LPU event1787	 */1788	writel(1, ioc->ioc_regs.hfn_mbox_cmd);1789	(void) readl(ioc->ioc_regs.hfn_mbox_cmd);1790}1791 1792static void1793bfa_ioc_send_enable(struct bfa_ioc_s *ioc)1794{1795	struct bfi_ioc_ctrl_req_s enable_req;1796 1797	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,1798		    bfa_ioc_portid(ioc));1799	enable_req.clscode = cpu_to_be16(ioc->clscode);1800	/* unsigned 32-bit time_t overflow in y2106 */1801	enable_req.tv_sec = be32_to_cpu(ktime_get_real_seconds());1802	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));1803}1804 1805static void1806bfa_ioc_send_disable(struct bfa_ioc_s *ioc)1807{1808	struct bfi_ioc_ctrl_req_s disable_req;1809 1810	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,1811		    bfa_ioc_portid(ioc));1812	disable_req.clscode = cpu_to_be16(ioc->clscode);1813	/* unsigned 32-bit time_t overflow in y2106 */1814	disable_req.tv_sec = be32_to_cpu(ktime_get_real_seconds());1815	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));1816}1817 1818static void1819bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)1820{1821	struct bfi_ioc_getattr_req_s	attr_req;1822 1823	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,1824		    bfa_ioc_portid(ioc));1825	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);1826	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));1827}1828 1829static void1830bfa_ioc_hb_check(void *cbarg)1831{1832	struct bfa_ioc_s  *ioc = cbarg;1833	u32	hb_count;1834 1835	hb_count = readl(ioc->ioc_regs.heartbeat);1836	if (ioc->hb_count == hb_count) {1837		bfa_ioc_recover(ioc);1838		return;1839	} else {1840		ioc->hb_count = hb_count;1841	}1842 1843	bfa_ioc_mbox_poll(ioc);1844	bfa_hb_timer_start(ioc);1845}1846 1847static void1848bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)1849{1850	ioc->hb_count = readl(ioc->ioc_regs.heartbeat);1851	bfa_hb_timer_start(ioc);1852}1853 1854/*1855 *	Initiate a full firmware download.1856 */1857static bfa_status_t1858bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,1859		    u32 boot_env)1860{1861	u32 *fwimg;1862	u32 pgnum;1863	u32 loff = 0;1864	u32 chunkno = 0;1865	u32 i;1866	u32 asicmode;1867	u32 fwimg_size;1868	u32 fwimg_buf[BFI_FLASH_CHUNK_SZ_WORDS];1869	bfa_status_t status;1870 1871	if (boot_env == BFI_FWBOOT_ENV_OS &&1872		boot_type == BFI_FWBOOT_TYPE_FLASH) {1873		fwimg_size = BFI_FLASH_IMAGE_SZ/sizeof(u32);1874 1875		status = bfa_ioc_flash_img_get_chnk(ioc,1876			BFA_IOC_FLASH_CHUNK_ADDR(chunkno), fwimg_buf);1877		if (status != BFA_STATUS_OK)1878			return status;1879 1880		fwimg = fwimg_buf;1881	} else {1882		fwimg_size = bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc));1883		fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),1884					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));1885	}1886 1887	bfa_trc(ioc, fwimg_size);1888 1889 1890	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);1891	writel(pgnum, ioc->ioc_regs.host_page_num_fn);1892 1893	for (i = 0; i < fwimg_size; i++) {1894 1895		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {1896			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);1897 1898			if (boot_env == BFI_FWBOOT_ENV_OS &&1899				boot_type == BFI_FWBOOT_TYPE_FLASH) {1900				status = bfa_ioc_flash_img_get_chnk(ioc,1901					BFA_IOC_FLASH_CHUNK_ADDR(chunkno),1902					fwimg_buf);1903				if (status != BFA_STATUS_OK)1904					return status;1905 1906				fwimg = fwimg_buf;1907			} else {1908				fwimg = bfa_cb_image_get_chunk(1909					bfa_ioc_asic_gen(ioc),1910					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));1911			}1912		}1913 1914		/*1915		 * write smem1916		 */1917		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,1918			      fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);1919 1920		loff += sizeof(u32);1921 1922		/*1923		 * handle page offset wrap around1924		 */1925		loff = PSS_SMEM_PGOFF(loff);1926		if (loff == 0) {1927			pgnum++;1928			writel(pgnum, ioc->ioc_regs.host_page_num_fn);1929		}1930	}1931 1932	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),1933			ioc->ioc_regs.host_page_num_fn);1934 1935	/*1936	 * Set boot type, env and device mode at the end.1937	 */1938	if (boot_env == BFI_FWBOOT_ENV_OS &&1939		boot_type == BFI_FWBOOT_TYPE_FLASH) {1940		boot_type = BFI_FWBOOT_TYPE_NORMAL;1941	}1942	asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,1943				ioc->port0_mode, ioc->port1_mode);1944	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,1945			swab32(asicmode));1946	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,1947			swab32(boot_type));1948	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,1949			swab32(boot_env));1950	return BFA_STATUS_OK;1951}1952 1953 1954/*1955 * Update BFA configuration from firmware configuration.1956 */1957static void1958bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)1959{1960	struct bfi_ioc_attr_s	*attr = ioc->attr;1961 1962	attr->adapter_prop  = be32_to_cpu(attr->adapter_prop);1963	attr->card_type     = be32_to_cpu(attr->card_type);1964	attr->maxfrsize	    = be16_to_cpu(attr->maxfrsize);1965	ioc->fcmode	= (attr->port_mode == BFI_PORT_MODE_FC);1966	attr->mfg_year	= be16_to_cpu(attr->mfg_year);1967 1968	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);1969}1970 1971/*1972 * Attach time initialization of mbox logic.1973 */1974static void1975bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)1976{1977	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;1978	int	mc;1979 1980	INIT_LIST_HEAD(&mod->cmd_q);1981	for (mc = 0; mc < BFI_MC_MAX; mc++) {1982		mod->mbhdlr[mc].cbfn = NULL;1983		mod->mbhdlr[mc].cbarg = ioc->bfa;1984	}1985}1986 1987/*1988 * Mbox poll timer -- restarts any pending mailbox requests.1989 */1990static void1991bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)1992{1993	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;1994	struct bfa_mbox_cmd_s		*cmd;1995	u32			stat;1996 1997	/*1998	 * If no command pending, do nothing1999	 */2000	if (list_empty(&mod->cmd_q))2001		return;2002 2003	/*2004	 * If previous command is not yet fetched by firmware, do nothing2005	 */2006	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);2007	if (stat)2008		return;2009 2010	/*2011	 * Enqueue command to firmware.2012	 */2013	bfa_q_deq(&mod->cmd_q, &cmd);2014	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));2015}2016 2017/*2018 * Cleanup any pending requests.2019 */2020static void2021bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)2022{2023	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;2024	struct bfa_mbox_cmd_s		*cmd;2025 2026	while (!list_empty(&mod->cmd_q))2027		bfa_q_deq(&mod->cmd_q, &cmd);2028}2029 2030/*2031 * Read data from SMEM to host through PCI memmap2032 *2033 * @param[in]	ioc	memory for IOC2034 * @param[in]	tbuf	app memory to store data from smem2035 * @param[in]	soff	smem offset2036 * @param[in]	sz	size of smem in bytes2037 */2038static bfa_status_t2039bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)2040{2041	u32 pgnum, loff;2042	__be32 r32;2043	int i, len;2044	u32 *buf = tbuf;2045 2046	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);2047	loff = PSS_SMEM_PGOFF(soff);2048	bfa_trc(ioc, pgnum);2049	bfa_trc(ioc, loff);2050	bfa_trc(ioc, sz);2051 2052	/*2053	 *  Hold semaphore to serialize pll init and fwtrc.2054	 */2055	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {2056		bfa_trc(ioc, 0);2057		return BFA_STATUS_FAILED;2058	}2059 2060	writel(pgnum, ioc->ioc_regs.host_page_num_fn);2061 2062	len = sz/sizeof(u32);2063	bfa_trc(ioc, len);2064	for (i = 0; i < len; i++) {2065		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);2066		buf[i] = swab32(r32);2067		loff += sizeof(u32);2068 2069		/*2070		 * handle page offset wrap around2071		 */2072		loff = PSS_SMEM_PGOFF(loff);2073		if (loff == 0) {2074			pgnum++;2075			writel(pgnum, ioc->ioc_regs.host_page_num_fn);2076		}2077	}2078	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),2079			ioc->ioc_regs.host_page_num_fn);2080	/*2081	 *  release semaphore.2082	 */2083	readl(ioc->ioc_regs.ioc_init_sem_reg);2084	writel(1, ioc->ioc_regs.ioc_init_sem_reg);2085 2086	bfa_trc(ioc, pgnum);2087	return BFA_STATUS_OK;2088}2089 2090/*2091 * Clear SMEM data from host through PCI memmap2092 *2093 * @param[in]	ioc	memory for IOC2094 * @param[in]	soff	smem offset2095 * @param[in]	sz	size of smem in bytes2096 */2097static bfa_status_t2098bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)2099{2100	int i, len;2101	u32 pgnum, loff;2102 2103	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);2104	loff = PSS_SMEM_PGOFF(soff);2105	bfa_trc(ioc, pgnum);2106	bfa_trc(ioc, loff);2107	bfa_trc(ioc, sz);2108 2109	/*2110	 *  Hold semaphore to serialize pll init and fwtrc.2111	 */2112	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {2113		bfa_trc(ioc, 0);2114		return BFA_STATUS_FAILED;2115	}2116 2117	writel(pgnum, ioc->ioc_regs.host_page_num_fn);2118 2119	len = sz/sizeof(u32); /* len in words */2120	bfa_trc(ioc, len);2121	for (i = 0; i < len; i++) {2122		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);2123		loff += sizeof(u32);2124 2125		/*2126		 * handle page offset wrap around2127		 */2128		loff = PSS_SMEM_PGOFF(loff);2129		if (loff == 0) {2130			pgnum++;2131			writel(pgnum, ioc->ioc_regs.host_page_num_fn);2132		}2133	}2134	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),2135			ioc->ioc_regs.host_page_num_fn);2136 2137	/*2138	 *  release semaphore.2139	 */2140	readl(ioc->ioc_regs.ioc_init_sem_reg);2141	writel(1, ioc->ioc_regs.ioc_init_sem_reg);2142	bfa_trc(ioc, pgnum);2143	return BFA_STATUS_OK;2144}2145 2146static void2147bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)2148{2149	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;2150 2151	/*2152	 * Notify driver and common modules registered for notification.2153	 */2154	ioc->cbfn->hbfail_cbfn(ioc->bfa);2155	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);2156 2157	bfa_ioc_debug_save_ftrc(ioc);2158 2159	BFA_LOG(KERN_CRIT, bfad, bfa_log_level,2160		"Heart Beat of IOC has failed\n");2161	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);2162 2163}2164 2165static void2166bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)2167{2168	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;2169	/*2170	 * Provide enable completion callback.2171	 */2172	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);2173	BFA_LOG(KERN_WARNING, bfad, bfa_log_level,2174		"Running firmware version is incompatible "2175		"with the driver version\n");2176	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);2177}2178 2179bfa_status_t2180bfa_ioc_pll_init(struct bfa_ioc_s *ioc)2181{2182 2183	/*2184	 *  Hold semaphore so that nobody can access the chip during init.2185	 */2186	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);2187 2188	bfa_ioc_pll_init_asic(ioc);2189 2190	ioc->pllinit = BFA_TRUE;2191 2192	/*2193	 * Initialize LMEM2194	 */2195	bfa_ioc_lmem_init(ioc);2196 2197	/*2198	 *  release semaphore.2199	 */2200	readl(ioc->ioc_regs.ioc_init_sem_reg);2201	writel(1, ioc->ioc_regs.ioc_init_sem_reg);2202 2203	return BFA_STATUS_OK;2204}2205 2206/*2207 * Interface used by diag module to do firmware boot with memory test2208 * as the entry vector.2209 */2210bfa_status_t2211bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)2212{2213	struct bfi_ioc_image_hdr_s *drv_fwhdr;2214	bfa_status_t status;2215	bfa_ioc_stats(ioc, ioc_boots);2216 2217	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)2218		return BFA_STATUS_FAILED;2219 2220	if (boot_env == BFI_FWBOOT_ENV_OS &&2221		boot_type == BFI_FWBOOT_TYPE_NORMAL) {2222 2223		drv_fwhdr = (struct bfi_ioc_image_hdr_s *)2224			bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);2225 2226		/*2227		 * Work with Flash iff flash f/w is better than driver f/w.2228		 * Otherwise push drivers firmware.2229		 */2230		if (bfa_ioc_flash_fwver_cmp(ioc, drv_fwhdr) ==2231						BFI_IOC_IMG_VER_BETTER)2232			boot_type = BFI_FWBOOT_TYPE_FLASH;2233	}2234 2235	/*2236	 * Initialize IOC state of all functions on a chip reset.2237	 */2238	if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {2239		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST);2240		bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST);2241	} else {2242		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING);2243		bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING);2244	}2245 2246	bfa_ioc_msgflush(ioc);2247	status = bfa_ioc_download_fw(ioc, boot_type, boot_env);2248	if (status == BFA_STATUS_OK)2249		bfa_ioc_lpu_start(ioc);2250	else {2251		WARN_ON(boot_type == BFI_FWBOOT_TYPE_MEMTEST);2252		bfa_iocpf_timeout(ioc);2253	}2254	return status;2255}2256 2257/*2258 * Enable/disable IOC failure auto recovery.2259 */2260void2261bfa_ioc_auto_recover(bfa_boolean_t auto_recover)2262{2263	bfa_auto_recover = auto_recover;2264}2265 2266 2267 2268bfa_boolean_t2269bfa_ioc_is_operational(struct bfa_ioc_s *ioc)2270{2271	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);2272}2273 2274bfa_boolean_t2275bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)2276{2277	u32 r32 = bfa_ioc_get_cur_ioc_fwstate(ioc);2278 2279	return ((r32 != BFI_IOC_UNINIT) &&2280		(r32 != BFI_IOC_INITING) &&2281		(r32 != BFI_IOC_MEMTEST));2282}2283 2284bfa_boolean_t2285bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)2286{2287	__be32	*msgp = mbmsg;2288	u32	r32;2289	int		i;2290 2291	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);2292	if ((r32 & 1) == 0)2293		return BFA_FALSE;2294 2295	/*2296	 * read the MBOX msg2297	 */2298	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));2299	     i++) {2300		r32 = readl(ioc->ioc_regs.lpu_mbox +2301				   i * sizeof(u32));2302		msgp[i] = cpu_to_be32(r32);2303	}2304 2305	/*2306	 * turn off mailbox interrupt by clearing mailbox status2307	 */2308	writel(1, ioc->ioc_regs.lpu_mbox_cmd);2309	readl(ioc->ioc_regs.lpu_mbox_cmd);2310 2311	return BFA_TRUE;2312}2313 2314void2315bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)2316{2317	union bfi_ioc_i2h_msg_u	*msg;2318	struct bfa_iocpf_s *iocpf = &ioc->iocpf;2319 2320	msg = (union bfi_ioc_i2h_msg_u *) m;2321 2322	bfa_ioc_stats(ioc, ioc_isrs);2323 2324	switch (msg->mh.msg_id) {2325	case BFI_IOC_I2H_HBEAT:2326		break;2327 2328	case BFI_IOC_I2H_ENABLE_REPLY:2329		ioc->port_mode = ioc->port_mode_cfg =2330				(enum bfa_mode_s)msg->fw_event.port_mode;2331		ioc->ad_cap_bm = msg->fw_event.cap_bm;2332		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);2333		break;2334 2335	case BFI_IOC_I2H_DISABLE_REPLY:2336		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);2337		break;2338 2339	case BFI_IOC_I2H_GETATTR_REPLY:2340		bfa_ioc_getattr_reply(ioc);2341		break;2342 2343	default:2344		bfa_trc(ioc, msg->mh.msg_id);2345		WARN_ON(1);2346	}2347}2348 2349/*2350 * IOC attach time initialization and setup.2351 *2352 * @param[in]	ioc	memory for IOC2353 * @param[in]	bfa	driver instance structure2354 */2355void2356bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,2357	       struct bfa_timer_mod_s *timer_mod)2358{2359	ioc->bfa	= bfa;2360	ioc->cbfn	= cbfn;2361	ioc->timer_mod	= timer_mod;2362	ioc->fcmode	= BFA_FALSE;2363	ioc->pllinit	= BFA_FALSE;2364	ioc->dbg_fwsave_once = BFA_TRUE;2365	ioc->iocpf.ioc	= ioc;2366 2367	bfa_ioc_mbox_attach(ioc);2368	INIT_LIST_HEAD(&ioc->notify_q);2369 2370	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);2371	bfa_fsm_send_event(ioc, IOC_E_RESET);2372}2373 2374/*2375 * Driver detach time IOC cleanup.2376 */2377void2378bfa_ioc_detach(struct bfa_ioc_s *ioc)2379{2380	bfa_fsm_send_event(ioc, IOC_E_DETACH);2381	INIT_LIST_HEAD(&ioc->notify_q);2382}2383 2384/*2385 * Setup IOC PCI properties.2386 *2387 * @param[in]	pcidev	PCI device information for this IOC2388 */2389void2390bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,2391		enum bfi_pcifn_class clscode)2392{2393	ioc->clscode	= clscode;2394	ioc->pcidev	= *pcidev;2395 2396	/*2397	 * Initialize IOC and device personality2398	 */2399	ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;2400	ioc->asic_mode  = BFI_ASIC_MODE_FC;2401 2402	switch (pcidev->device_id) {2403	case BFA_PCI_DEVICE_ID_FC_8G1P:2404	case BFA_PCI_DEVICE_ID_FC_8G2P:2405		ioc->asic_gen = BFI_ASIC_GEN_CB;2406		ioc->fcmode = BFA_TRUE;2407		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;2408		ioc->ad_cap_bm = BFA_CM_HBA;2409		break;2410 2411	case BFA_PCI_DEVICE_ID_CT:2412		ioc->asic_gen = BFI_ASIC_GEN_CT;2413		ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;2414		ioc->asic_mode  = BFI_ASIC_MODE_ETH;2415		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;2416		ioc->ad_cap_bm = BFA_CM_CNA;2417		break;2418 2419	case BFA_PCI_DEVICE_ID_CT_FC:2420		ioc->asic_gen = BFI_ASIC_GEN_CT;2421		ioc->fcmode = BFA_TRUE;2422		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;2423		ioc->ad_cap_bm = BFA_CM_HBA;2424		break;2425 2426	case BFA_PCI_DEVICE_ID_CT2:2427	case BFA_PCI_DEVICE_ID_CT2_QUAD:2428		ioc->asic_gen = BFI_ASIC_GEN_CT2;2429		if (clscode == BFI_PCIFN_CLASS_FC &&2430		    pcidev->ssid == BFA_PCI_CT2_SSID_FC) {2431			ioc->asic_mode  = BFI_ASIC_MODE_FC16;2432			ioc->fcmode = BFA_TRUE;2433			ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;2434			ioc->ad_cap_bm = BFA_CM_HBA;2435		} else {2436			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;2437			ioc->asic_mode  = BFI_ASIC_MODE_ETH;2438			if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {2439				ioc->port_mode =2440				ioc->port_mode_cfg = BFA_MODE_CNA;2441				ioc->ad_cap_bm = BFA_CM_CNA;2442			} else {2443				ioc->port_mode =2444				ioc->port_mode_cfg = BFA_MODE_NIC;2445				ioc->ad_cap_bm = BFA_CM_NIC;2446			}2447		}2448		break;2449 2450	default:2451		WARN_ON(1);2452	}2453 2454	/*2455	 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c2456	 */2457	if (ioc->asic_gen == BFI_ASIC_GEN_CB)2458		bfa_ioc_set_cb_hwif(ioc);2459	else if (ioc->asic_gen == BFI_ASIC_GEN_CT)2460		bfa_ioc_set_ct_hwif(ioc);2461	else {2462		WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);2463		bfa_ioc_set_ct2_hwif(ioc);2464		bfa_ioc_ct2_poweron(ioc);2465	}2466 2467	bfa_ioc_map_port(ioc);2468	bfa_ioc_reg_init(ioc);2469}2470 2471/*2472 * Initialize IOC dma memory2473 *2474 * @param[in]	dm_kva	kernel virtual address of IOC dma memory2475 * @param[in]	dm_pa	physical address of IOC dma memory2476 */2477void2478bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa)2479{2480	/*2481	 * dma memory for firmware attribute2482	 */2483	ioc->attr_dma.kva = dm_kva;2484	ioc->attr_dma.pa = dm_pa;2485	ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;2486}2487 2488void2489bfa_ioc_enable(struct bfa_ioc_s *ioc)2490{2491	bfa_ioc_stats(ioc, ioc_enables);2492	ioc->dbg_fwsave_once = BFA_TRUE;2493 2494	bfa_fsm_send_event(ioc, IOC_E_ENABLE);2495}2496 2497void2498bfa_ioc_disable(struct bfa_ioc_s *ioc)2499{2500	bfa_ioc_stats(ioc, ioc_disables);2501	bfa_fsm_send_event(ioc, IOC_E_DISABLE);2502}2503 2504void2505bfa_ioc_suspend(struct bfa_ioc_s *ioc)2506{2507	ioc->dbg_fwsave_once = BFA_TRUE;2508	bfa_fsm_send_event(ioc, IOC_E_HWERROR);2509}2510 2511/*2512 * Initialize memory for saving firmware trace. Driver must initialize2513 * trace memory before call bfa_ioc_enable().2514 */2515void2516bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)2517{2518	ioc->dbg_fwsave	    = dbg_fwsave;2519	ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;2520}2521 2522/*2523 * Register mailbox message handler functions2524 *2525 * @param[in]	ioc		IOC instance2526 * @param[in]	mcfuncs		message class handler functions2527 */2528void2529bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)2530{2531	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;2532	int				mc;2533 2534	for (mc = 0; mc < BFI_MC_MAX; mc++)2535		mod->mbhdlr[mc].cbfn = mcfuncs[mc];2536}2537 2538/*2539 * Register mailbox message handler function, to be called by common modules2540 */2541void2542bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,2543		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)2544{2545	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;2546 2547	mod->mbhdlr[mc].cbfn	= cbfn;2548	mod->mbhdlr[mc].cbarg	= cbarg;2549}2550 2551/*2552 * Queue a mailbox command request to firmware. Waits if mailbox is busy.2553 * Responsibility of caller to serialize2554 *2555 * @param[in]	ioc	IOC instance2556 * @param[i]	cmd	Mailbox command2557 */2558void2559bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)2560{2561	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;2562	u32			stat;2563 2564	/*2565	 * If a previous command is pending, queue new command2566	 */2567	if (!list_empty(&mod->cmd_q)) {2568		list_add_tail(&cmd->qe, &mod->cmd_q);2569		return;2570	}2571 2572	/*2573	 * If mailbox is busy, queue command for poll timer2574	 */2575	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);2576	if (stat) {2577		list_add_tail(&cmd->qe, &mod->cmd_q);2578		return;2579	}2580 2581	/*2582	 * mailbox is free -- queue command to firmware2583	 */2584	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));2585}2586 2587/*2588 * Handle mailbox interrupts2589 */2590void2591bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)2592{2593	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;2594	struct bfi_mbmsg_s		m;2595	int				mc;2596 2597	if (bfa_ioc_msgget(ioc, &m)) {2598		/*2599		 * Treat IOC message class as special.2600		 */2601		mc = m.mh.msg_class;2602		if (mc == BFI_MC_IOC) {2603			bfa_ioc_isr(ioc, &m);2604			return;2605		}2606 2607		if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))2608			return;2609 2610		mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);2611	}2612 2613	bfa_ioc_lpu_read_stat(ioc);2614 2615	/*2616	 * Try to send pending mailbox commands2617	 */2618	bfa_ioc_mbox_poll(ioc);2619}2620 2621void2622bfa_ioc_error_isr(struct bfa_ioc_s *ioc)2623{2624	bfa_ioc_stats(ioc, ioc_hbfails);2625	ioc->stats.hb_count = ioc->hb_count;2626	bfa_fsm_send_event(ioc, IOC_E_HWERROR);2627}2628 2629/*2630 * return true if IOC is disabled2631 */2632bfa_boolean_t2633bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)2634{2635	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||2636		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);2637}2638 2639/*2640 * return true if IOC firmware is different.2641 */2642bfa_boolean_t2643bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)2644{2645	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||2646		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||2647		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);2648}2649 2650/*2651 * Check if adapter is disabled -- both IOCs should be in a disabled2652 * state.2653 */2654bfa_boolean_t2655bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)2656{2657	u32	ioc_state;2658 2659	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))2660		return BFA_FALSE;2661 2662	ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);2663	if (!bfa_ioc_state_disabled(ioc_state))2664		return BFA_FALSE;2665 2666	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {2667		ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc);2668		if (!bfa_ioc_state_disabled(ioc_state))2669			return BFA_FALSE;2670	}2671 2672	return BFA_TRUE;2673}2674 2675/*2676 * Reset IOC fwstate registers.2677 */2678void2679bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)2680{2681	bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT);2682	bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT);2683}2684 2685#define BFA_MFG_NAME "QLogic"2686void2687bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,2688			 struct bfa_adapter_attr_s *ad_attr)2689{2690	struct bfi_ioc_attr_s	*ioc_attr;2691 2692	ioc_attr = ioc->attr;2693 2694	bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);2695	bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);2696	bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);2697	bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);2698	memcpy(&ad_attr->vpd, &ioc_attr->vpd,2699		      sizeof(struct bfa_mfg_vpd_s));2700 2701	ad_attr->nports = bfa_ioc_get_nports(ioc);2702	ad_attr->max_speed = bfa_ioc_speed_sup(ioc);2703 2704	bfa_ioc_get_adapter_model(ioc, ad_attr->model);2705	/* For now, model descr uses same model string */2706	bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);2707 2708	ad_attr->card_type = ioc_attr->card_type;2709	ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);2710 2711	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))2712		ad_attr->prototype = 1;2713	else2714		ad_attr->prototype = 0;2715 2716	ad_attr->pwwn = ioc->attr->pwwn;2717	ad_attr->mac  = bfa_ioc_get_mac(ioc);2718 2719	ad_attr->pcie_gen = ioc_attr->pcie_gen;2720	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;2721	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;2722	ad_attr->asic_rev = ioc_attr->asic_rev;2723 2724	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);2725 2726	ad_attr->cna_capable = bfa_ioc_is_cna(ioc);2727	ad_attr->trunk_capable = (ad_attr->nports > 1) &&2728				  !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;2729	ad_attr->mfg_day = ioc_attr->mfg_day;2730	ad_attr->mfg_month = ioc_attr->mfg_month;2731	ad_attr->mfg_year = ioc_attr->mfg_year;2732	memcpy(ad_attr->uuid, ioc_attr->uuid, BFA_ADAPTER_UUID_LEN);2733}2734 2735enum bfa_ioc_type_e2736bfa_ioc_get_type(struct bfa_ioc_s *ioc)2737{2738	if (ioc->clscode == BFI_PCIFN_CLASS_ETH)2739		return BFA_IOC_TYPE_LL;2740 2741	WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC);2742 2743	return (ioc->attr->port_mode == BFI_PORT_MODE_FC)2744		? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;2745}2746 2747void2748bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)2749{2750	memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);2751	memcpy((void *)serial_num,2752			(void *)ioc->attr->brcd_serialnum,2753			BFA_ADAPTER_SERIAL_NUM_LEN);2754}2755 2756void2757bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)2758{2759	memset((void *)fw_ver, 0, BFA_VERSION_LEN);2760	memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);2761}2762 2763void2764bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)2765{2766	WARN_ON(!chip_rev);2767 2768	memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);2769 2770	chip_rev[0] = 'R';2771	chip_rev[1] = 'e';2772	chip_rev[2] = 'v';2773	chip_rev[3] = '-';2774	chip_rev[4] = ioc->attr->asic_rev;2775	chip_rev[5] = '\0';2776}2777 2778void2779bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)2780{2781	memset((void *)optrom_ver, 0, BFA_VERSION_LEN);2782	memcpy(optrom_ver, ioc->attr->optrom_version,2783		      BFA_VERSION_LEN);2784}2785 2786void2787bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)2788{2789	memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);2790	strscpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);2791}2792 2793void2794bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)2795{2796	struct bfi_ioc_attr_s	*ioc_attr;2797	u8 nports = bfa_ioc_get_nports(ioc);2798 2799	WARN_ON(!model);2800	memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);2801 2802	ioc_attr = ioc->attr;2803 2804	if (bfa_asic_id_ct2(ioc->pcidev.device_id) &&2805		(!bfa_mfg_is_mezz(ioc_attr->card_type)))2806		snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u-%u%s",2807			BFA_MFG_NAME, ioc_attr->card_type, nports, "p");2808	else2809		snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",2810			BFA_MFG_NAME, ioc_attr->card_type);2811}2812 2813enum bfa_ioc_state2814bfa_ioc_get_state(struct bfa_ioc_s *ioc)2815{2816	enum bfa_iocpf_state iocpf_st;2817	enum bfa_ioc_state ioc_st = bfa_ioc_sm_to_state(ioc_sm_table, ioc->fsm);2818 2819	if (ioc_st == BFA_IOC_ENABLING ||2820		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {2821 2822		iocpf_st = bfa_iocpf_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);2823 2824		switch (iocpf_st) {2825		case BFA_IOCPF_SEMWAIT:2826			ioc_st = BFA_IOC_SEMWAIT;2827			break;2828 2829		case BFA_IOCPF_HWINIT:2830			ioc_st = BFA_IOC_HWINIT;2831			break;2832 2833		case BFA_IOCPF_FWMISMATCH:2834			ioc_st = BFA_IOC_FWMISMATCH;2835			break;2836 2837		case BFA_IOCPF_FAIL:2838			ioc_st = BFA_IOC_FAIL;2839			break;2840 2841		case BFA_IOCPF_INITFAIL:2842			ioc_st = BFA_IOC_INITFAIL;2843			break;2844 2845		default:2846			break;2847		}2848	}2849 2850	return ioc_st;2851}2852 2853void2854bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)2855{2856	memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));2857 2858	ioc_attr->state = bfa_ioc_get_state(ioc);2859	ioc_attr->port_id = bfa_ioc_portid(ioc);2860	ioc_attr->port_mode = ioc->port_mode;2861	ioc_attr->port_mode_cfg = ioc->port_mode_cfg;2862	ioc_attr->cap_bm = ioc->ad_cap_bm;2863 2864	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);2865 2866	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);2867 2868	ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc);2869	ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc);2870	ioc_attr->def_fn = (bfa_ioc_pcifn(ioc) == bfa_ioc_portid(ioc));2871	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);2872}2873 2874mac_t2875bfa_ioc_get_mac(struct bfa_ioc_s *ioc)2876{2877	/*2878	 * Check the IOC type and return the appropriate MAC2879	 */2880	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)2881		return ioc->attr->fcoe_mac;2882	else2883		return ioc->attr->mac;2884}2885 2886mac_t2887bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)2888{2889	mac_t	m;2890 2891	m = ioc->attr->mfg_mac;2892	if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))2893		m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);2894	else2895		bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),2896			bfa_ioc_pcifn(ioc));2897 2898	return m;2899}2900 2901/*2902 * Send AEN notification2903 */2904void2905bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)2906{2907	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;2908	struct bfa_aen_entry_s	*aen_entry;2909	enum bfa_ioc_type_e ioc_type;2910 2911	bfad_get_aen_entry(bfad, aen_entry);2912	if (!aen_entry)2913		return;2914 2915	ioc_type = bfa_ioc_get_type(ioc);2916	switch (ioc_type) {2917	case BFA_IOC_TYPE_FC:2918		aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;2919		break;2920	case BFA_IOC_TYPE_FCoE:2921		aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;2922		aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);2923		break;2924	case BFA_IOC_TYPE_LL:2925		aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);2926		break;2927	default:2928		WARN_ON(ioc_type != BFA_IOC_TYPE_FC);2929		break;2930	}2931 2932	/* Send the AEN notification */2933	aen_entry->aen_data.ioc.ioc_type = ioc_type;2934	bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,2935				  BFA_AEN_CAT_IOC, event);2936}2937 2938/*2939 * Retrieve saved firmware trace from a prior IOC failure.2940 */2941bfa_status_t2942bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)2943{2944	int	tlen;2945 2946	if (ioc->dbg_fwsave_len == 0)2947		return BFA_STATUS_ENOFSAVE;2948 2949	tlen = *trclen;2950	if (tlen > ioc->dbg_fwsave_len)2951		tlen = ioc->dbg_fwsave_len;2952 2953	memcpy(trcdata, ioc->dbg_fwsave, tlen);2954	*trclen = tlen;2955	return BFA_STATUS_OK;2956}2957 2958 2959/*2960 * Retrieve saved firmware trace from a prior IOC failure.2961 */2962bfa_status_t2963bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)2964{2965	u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));2966	int tlen;2967	bfa_status_t status;2968 2969	bfa_trc(ioc, *trclen);2970 2971	tlen = *trclen;2972	if (tlen > BFA_DBG_FWTRC_LEN)2973		tlen = BFA_DBG_FWTRC_LEN;2974 2975	status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);2976	*trclen = tlen;2977	return status;2978}2979 2980static void2981bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)2982{2983	struct bfa_mbox_cmd_s cmd;2984	struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;2985 2986	bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,2987		    bfa_ioc_portid(ioc));2988	req->clscode = cpu_to_be16(ioc->clscode);2989	bfa_ioc_mbox_queue(ioc, &cmd);2990}2991 2992static void2993bfa_ioc_fwsync(struct bfa_ioc_s *ioc)2994{2995	u32 fwsync_iter = 1000;2996 2997	bfa_ioc_send_fwsync(ioc);2998 2999	/*3000	 * After sending a fw sync mbox command wait for it to3001	 * take effect.  We will not wait for a response because3002	 *    1. fw_sync mbox cmd doesn't have a response.3003	 *    2. Even if we implement that,  interrupts might not3004	 *	 be enabled when we call this function.3005	 * So, just keep checking if any mbox cmd is pending, and3006	 * after waiting for a reasonable amount of time, go ahead.3007	 * It is possible that fw has crashed and the mbox command3008	 * is never acknowledged.3009	 */3010	while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)3011		fwsync_iter--;3012}3013 3014/*3015 * Dump firmware smem3016 */3017bfa_status_t3018bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,3019				u32 *offset, int *buflen)3020{3021	u32 loff;3022	int dlen;3023	bfa_status_t status;3024	u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);3025 3026	if (*offset >= smem_len) {3027		*offset = *buflen = 0;3028		return BFA_STATUS_EINVAL;3029	}3030 3031	loff = *offset;3032	dlen = *buflen;3033 3034	/*3035	 * First smem read, sync smem before proceeding3036	 * No need to sync before reading every chunk.3037	 */3038	if (loff == 0)3039		bfa_ioc_fwsync(ioc);3040 3041	if ((loff + dlen) >= smem_len)3042		dlen = smem_len - loff;3043 3044	status = bfa_ioc_smem_read(ioc, buf, loff, dlen);3045 3046	if (status != BFA_STATUS_OK) {3047		*offset = *buflen = 0;3048		return status;3049	}3050 3051	*offset += dlen;3052 3053	if (*offset >= smem_len)3054		*offset = 0;3055 3056	*buflen = dlen;3057 3058	return status;3059}3060 3061/*3062 * Firmware statistics3063 */3064bfa_status_t3065bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)3066{3067	u32 loff = BFI_IOC_FWSTATS_OFF + \3068		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));3069	int tlen;3070	bfa_status_t status;3071 3072	if (ioc->stats_busy) {3073		bfa_trc(ioc, ioc->stats_busy);3074		return BFA_STATUS_DEVBUSY;3075	}3076	ioc->stats_busy = BFA_TRUE;3077 3078	tlen = sizeof(struct bfa_fw_stats_s);3079	status = bfa_ioc_smem_read(ioc, stats, loff, tlen);3080 3081	ioc->stats_busy = BFA_FALSE;3082	return status;3083}3084 3085bfa_status_t3086bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)3087{3088	u32 loff = BFI_IOC_FWSTATS_OFF + \3089		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));3090	int tlen;3091	bfa_status_t status;3092 3093	if (ioc->stats_busy) {3094		bfa_trc(ioc, ioc->stats_busy);3095		return BFA_STATUS_DEVBUSY;3096	}3097	ioc->stats_busy = BFA_TRUE;3098 3099	tlen = sizeof(struct bfa_fw_stats_s);3100	status = bfa_ioc_smem_clr(ioc, loff, tlen);3101 3102	ioc->stats_busy = BFA_FALSE;3103	return status;3104}3105 3106/*3107 * Save firmware trace if configured.3108 */3109void3110bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)3111{3112	int		tlen;3113 3114	if (ioc->dbg_fwsave_once) {3115		ioc->dbg_fwsave_once = BFA_FALSE;3116		if (ioc->dbg_fwsave_len) {3117			tlen = ioc->dbg_fwsave_len;3118			bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);3119		}3120	}3121}3122 3123/*3124 * Firmware failure detected. Start recovery actions.3125 */3126static void3127bfa_ioc_recover(struct bfa_ioc_s *ioc)3128{3129	bfa_ioc_stats(ioc, ioc_hbfails);3130	ioc->stats.hb_count = ioc->hb_count;3131	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);3132}3133 3134/*3135 *  BFA IOC PF private functions3136 */3137static void3138bfa_iocpf_timeout(void *ioc_arg)3139{3140	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;3141 3142	bfa_trc(ioc, 0);3143	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);3144}3145 3146static void3147bfa_iocpf_sem_timeout(void *ioc_arg)3148{3149	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;3150 3151	bfa_ioc_hw_sem_get(ioc);3152}3153 3154static void3155bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)3156{3157	u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);3158 3159	bfa_trc(ioc, fwstate);3160 3161	if (fwstate == BFI_IOC_DISABLED) {3162		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);3163		return;3164	}3165 3166	if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV))3167		bfa_iocpf_timeout(ioc);3168	else {3169		ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;3170		bfa_iocpf_poll_timer_start(ioc);3171	}3172}3173 3174static void3175bfa_iocpf_poll_timeout(void *ioc_arg)3176{3177	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;3178 3179	bfa_ioc_poll_fwinit(ioc);3180}3181 3182/*3183 *  bfa timer function3184 */3185void3186bfa_timer_beat(struct bfa_timer_mod_s *mod)3187{3188	struct list_head *qh = &mod->timer_q;3189	struct list_head *qe, *qe_next;3190	struct bfa_timer_s *elem;3191	struct list_head timedout_q;3192 3193	INIT_LIST_HEAD(&timedout_q);3194 3195	qe = bfa_q_next(qh);3196 3197	while (qe != qh) {3198		qe_next = bfa_q_next(qe);3199 3200		elem = (struct bfa_timer_s *) qe;3201		if (elem->timeout <= BFA_TIMER_FREQ) {3202			elem->timeout = 0;3203			list_del(&elem->qe);3204			list_add_tail(&elem->qe, &timedout_q);3205		} else {3206			elem->timeout -= BFA_TIMER_FREQ;3207		}3208 3209		qe = qe_next;	/* go to next elem */3210	}3211 3212	/*3213	 * Pop all the timeout entries3214	 */3215	while (!list_empty(&timedout_q)) {3216		bfa_q_deq(&timedout_q, &elem);3217		elem->timercb(elem->arg);3218	}3219}3220 3221/*3222 * Should be called with lock protection3223 */3224void3225bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,3226		    void (*timercb) (void *), void *arg, unsigned int timeout)3227{3228 3229	WARN_ON(timercb == NULL);3230	WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));3231 3232	timer->timeout = timeout;3233	timer->timercb = timercb;3234	timer->arg = arg;3235 3236	list_add_tail(&timer->qe, &mod->timer_q);3237}3238 3239/*3240 * Should be called with lock protection3241 */3242void3243bfa_timer_stop(struct bfa_timer_s *timer)3244{3245	WARN_ON(list_empty(&timer->qe));3246 3247	list_del(&timer->qe);3248}3249 3250/*3251 *	ASIC block related3252 */3253static void3254bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)3255{3256	struct bfa_ablk_cfg_inst_s *cfg_inst;3257	int i, j;3258	u16	be16;3259 3260	for (i = 0; i < BFA_ABLK_MAX; i++) {3261		cfg_inst = &cfg->inst[i];3262		for (j = 0; j < BFA_ABLK_MAX_PFS; j++) {3263			be16 = cfg_inst->pf_cfg[j].pers;3264			cfg_inst->pf_cfg[j].pers = be16_to_cpu(be16);3265			be16 = cfg_inst->pf_cfg[j].num_qpairs;3266			cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);3267			be16 = cfg_inst->pf_cfg[j].num_vectors;3268			cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);3269			be16 = cfg_inst->pf_cfg[j].bw_min;3270			cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16);3271			be16 = cfg_inst->pf_cfg[j].bw_max;3272			cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16);3273		}3274	}3275}3276 3277static void3278bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg)3279{3280	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;3281	struct bfi_ablk_i2h_rsp_s *rsp = (struct bfi_ablk_i2h_rsp_s *)msg;3282	bfa_ablk_cbfn_t cbfn;3283 3284	WARN_ON(msg->mh.msg_class != BFI_MC_ABLK);3285	bfa_trc(ablk->ioc, msg->mh.msg_id);3286 3287	switch (msg->mh.msg_id) {3288	case BFI_ABLK_I2H_QUERY:3289		if (rsp->status == BFA_STATUS_OK) {3290			memcpy(ablk->cfg, ablk->dma_addr.kva,3291				sizeof(struct bfa_ablk_cfg_s));3292			bfa_ablk_config_swap(ablk->cfg);3293			ablk->cfg = NULL;3294		}3295		break;3296 3297	case BFI_ABLK_I2H_ADPT_CONFIG:3298	case BFI_ABLK_I2H_PORT_CONFIG:3299		/* update config port mode */3300		ablk->ioc->port_mode_cfg = rsp->port_mode;3301		break;3302 3303	case BFI_ABLK_I2H_PF_DELETE:3304	case BFI_ABLK_I2H_PF_UPDATE:3305	case BFI_ABLK_I2H_OPTROM_ENABLE:3306	case BFI_ABLK_I2H_OPTROM_DISABLE:3307		/* No-op */3308		break;3309 3310	case BFI_ABLK_I2H_PF_CREATE:3311		*(ablk->pcifn) = rsp->pcifn;3312		ablk->pcifn = NULL;3313		break;3314 3315	default:3316		WARN_ON(1);3317	}3318 3319	ablk->busy = BFA_FALSE;3320	if (ablk->cbfn) {3321		cbfn = ablk->cbfn;3322		ablk->cbfn = NULL;3323		cbfn(ablk->cbarg, rsp->status);3324	}3325}3326 3327static void3328bfa_ablk_notify(void *cbarg, enum bfa_ioc_event_e event)3329{3330	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;3331 3332	bfa_trc(ablk->ioc, event);3333 3334	switch (event) {3335	case BFA_IOC_E_ENABLED:3336		WARN_ON(ablk->busy != BFA_FALSE);3337		break;3338 3339	case BFA_IOC_E_DISABLED:3340	case BFA_IOC_E_FAILED:3341		/* Fail any pending requests */3342		ablk->pcifn = NULL;3343		if (ablk->busy) {3344			if (ablk->cbfn)3345				ablk->cbfn(ablk->cbarg, BFA_STATUS_FAILED);3346			ablk->cbfn = NULL;3347			ablk->busy = BFA_FALSE;3348		}3349		break;3350 3351	default:3352		WARN_ON(1);3353		break;3354	}3355}3356 3357u323358bfa_ablk_meminfo(void)3359{3360	return BFA_ROUNDUP(sizeof(struct bfa_ablk_cfg_s), BFA_DMA_ALIGN_SZ);3361}3362 3363void3364bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa)3365{3366	ablk->dma_addr.kva = dma_kva;3367	ablk->dma_addr.pa  = dma_pa;3368}3369 3370void3371bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc)3372{3373	ablk->ioc = ioc;3374 3375	bfa_ioc_mbox_regisr(ablk->ioc, BFI_MC_ABLK, bfa_ablk_isr, ablk);3376	bfa_q_qe_init(&ablk->ioc_notify);3377	bfa_ioc_notify_init(&ablk->ioc_notify, bfa_ablk_notify, ablk);3378	list_add_tail(&ablk->ioc_notify.qe, &ablk->ioc->notify_q);3379}3380 3381bfa_status_t3382bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,3383		bfa_ablk_cbfn_t cbfn, void *cbarg)3384{3385	struct bfi_ablk_h2i_query_s *m;3386 3387	WARN_ON(!ablk_cfg);3388 3389	if (!bfa_ioc_is_operational(ablk->ioc)) {3390		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3391		return BFA_STATUS_IOC_FAILURE;3392	}3393 3394	if (ablk->busy) {3395		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3396		return  BFA_STATUS_DEVBUSY;3397	}3398 3399	ablk->cfg = ablk_cfg;3400	ablk->cbfn  = cbfn;3401	ablk->cbarg = cbarg;3402	ablk->busy  = BFA_TRUE;3403 3404	m = (struct bfi_ablk_h2i_query_s *)ablk->mb.msg;3405	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_QUERY,3406		    bfa_ioc_portid(ablk->ioc));3407	bfa_dma_be_addr_set(m->addr, ablk->dma_addr.pa);3408	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3409 3410	return BFA_STATUS_OK;3411}3412 3413bfa_status_t3414bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,3415		u8 port, enum bfi_pcifn_class personality,3416		u16 bw_min, u16 bw_max,3417		bfa_ablk_cbfn_t cbfn, void *cbarg)3418{3419	struct bfi_ablk_h2i_pf_req_s *m;3420 3421	if (!bfa_ioc_is_operational(ablk->ioc)) {3422		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3423		return BFA_STATUS_IOC_FAILURE;3424	}3425 3426	if (ablk->busy) {3427		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3428		return  BFA_STATUS_DEVBUSY;3429	}3430 3431	ablk->pcifn = pcifn;3432	ablk->cbfn = cbfn;3433	ablk->cbarg = cbarg;3434	ablk->busy  = BFA_TRUE;3435 3436	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;3437	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,3438		    bfa_ioc_portid(ablk->ioc));3439	m->pers = cpu_to_be16((u16)personality);3440	m->bw_min = cpu_to_be16(bw_min);3441	m->bw_max = cpu_to_be16(bw_max);3442	m->port = port;3443	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3444 3445	return BFA_STATUS_OK;3446}3447 3448bfa_status_t3449bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,3450		bfa_ablk_cbfn_t cbfn, void *cbarg)3451{3452	struct bfi_ablk_h2i_pf_req_s *m;3453 3454	if (!bfa_ioc_is_operational(ablk->ioc)) {3455		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3456		return BFA_STATUS_IOC_FAILURE;3457	}3458 3459	if (ablk->busy) {3460		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3461		return  BFA_STATUS_DEVBUSY;3462	}3463 3464	ablk->cbfn  = cbfn;3465	ablk->cbarg = cbarg;3466	ablk->busy  = BFA_TRUE;3467 3468	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;3469	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_DELETE,3470		    bfa_ioc_portid(ablk->ioc));3471	m->pcifn = (u8)pcifn;3472	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3473 3474	return BFA_STATUS_OK;3475}3476 3477bfa_status_t3478bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, enum bfa_mode_s mode,3479		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)3480{3481	struct bfi_ablk_h2i_cfg_req_s *m;3482 3483	if (!bfa_ioc_is_operational(ablk->ioc)) {3484		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3485		return BFA_STATUS_IOC_FAILURE;3486	}3487 3488	if (ablk->busy) {3489		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3490		return  BFA_STATUS_DEVBUSY;3491	}3492 3493	ablk->cbfn  = cbfn;3494	ablk->cbarg = cbarg;3495	ablk->busy  = BFA_TRUE;3496 3497	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;3498	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_ADPT_CONFIG,3499		    bfa_ioc_portid(ablk->ioc));3500	m->mode = (u8)mode;3501	m->max_pf = (u8)max_pf;3502	m->max_vf = (u8)max_vf;3503	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3504 3505	return BFA_STATUS_OK;3506}3507 3508bfa_status_t3509bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,3510		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)3511{3512	struct bfi_ablk_h2i_cfg_req_s *m;3513 3514	if (!bfa_ioc_is_operational(ablk->ioc)) {3515		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3516		return BFA_STATUS_IOC_FAILURE;3517	}3518 3519	if (ablk->busy) {3520		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3521		return  BFA_STATUS_DEVBUSY;3522	}3523 3524	ablk->cbfn  = cbfn;3525	ablk->cbarg = cbarg;3526	ablk->busy  = BFA_TRUE;3527 3528	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;3529	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PORT_CONFIG,3530		bfa_ioc_portid(ablk->ioc));3531	m->port = (u8)port;3532	m->mode = (u8)mode;3533	m->max_pf = (u8)max_pf;3534	m->max_vf = (u8)max_vf;3535	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3536 3537	return BFA_STATUS_OK;3538}3539 3540bfa_status_t3541bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min,3542		   u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg)3543{3544	struct bfi_ablk_h2i_pf_req_s *m;3545 3546	if (!bfa_ioc_is_operational(ablk->ioc)) {3547		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3548		return BFA_STATUS_IOC_FAILURE;3549	}3550 3551	if (ablk->busy) {3552		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3553		return  BFA_STATUS_DEVBUSY;3554	}3555 3556	ablk->cbfn  = cbfn;3557	ablk->cbarg = cbarg;3558	ablk->busy  = BFA_TRUE;3559 3560	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;3561	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,3562		bfa_ioc_portid(ablk->ioc));3563	m->pcifn = (u8)pcifn;3564	m->bw_min = cpu_to_be16(bw_min);3565	m->bw_max = cpu_to_be16(bw_max);3566	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3567 3568	return BFA_STATUS_OK;3569}3570 3571bfa_status_t3572bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)3573{3574	struct bfi_ablk_h2i_optrom_s *m;3575 3576	if (!bfa_ioc_is_operational(ablk->ioc)) {3577		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3578		return BFA_STATUS_IOC_FAILURE;3579	}3580 3581	if (ablk->busy) {3582		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3583		return  BFA_STATUS_DEVBUSY;3584	}3585 3586	ablk->cbfn  = cbfn;3587	ablk->cbarg = cbarg;3588	ablk->busy  = BFA_TRUE;3589 3590	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;3591	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_ENABLE,3592		bfa_ioc_portid(ablk->ioc));3593	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3594 3595	return BFA_STATUS_OK;3596}3597 3598bfa_status_t3599bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)3600{3601	struct bfi_ablk_h2i_optrom_s *m;3602 3603	if (!bfa_ioc_is_operational(ablk->ioc)) {3604		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);3605		return BFA_STATUS_IOC_FAILURE;3606	}3607 3608	if (ablk->busy) {3609		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);3610		return  BFA_STATUS_DEVBUSY;3611	}3612 3613	ablk->cbfn  = cbfn;3614	ablk->cbarg = cbarg;3615	ablk->busy  = BFA_TRUE;3616 3617	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;3618	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_DISABLE,3619		bfa_ioc_portid(ablk->ioc));3620	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);3621 3622	return BFA_STATUS_OK;3623}3624 3625/*3626 *	SFP module specific3627 */3628 3629/* forward declarations */3630static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp);3631static void bfa_sfp_media_get(struct bfa_sfp_s *sfp);3632static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp,3633				enum bfa_port_speed portspeed);3634 3635static void3636bfa_cb_sfp_show(struct bfa_sfp_s *sfp)3637{3638	bfa_trc(sfp, sfp->lock);3639	if (sfp->cbfn)3640		sfp->cbfn(sfp->cbarg, sfp->status);3641	sfp->lock = 0;3642	sfp->cbfn = NULL;3643}3644 3645static void3646bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp)3647{3648	bfa_trc(sfp, sfp->portspeed);3649	if (sfp->media) {3650		bfa_sfp_media_get(sfp);3651		if (sfp->state_query_cbfn)3652			sfp->state_query_cbfn(sfp->state_query_cbarg,3653					sfp->status);3654		sfp->media = NULL;3655	}3656 3657	if (sfp->portspeed) {3658		sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed);3659		if (sfp->state_query_cbfn)3660			sfp->state_query_cbfn(sfp->state_query_cbarg,3661					sfp->status);3662		sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;3663	}3664 3665	sfp->state_query_lock = 0;3666	sfp->state_query_cbfn = NULL;3667}3668 3669/*3670 *	IOC event handler.3671 */3672static void3673bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event)3674{3675	struct bfa_sfp_s *sfp = sfp_arg;3676 3677	bfa_trc(sfp, event);3678	bfa_trc(sfp, sfp->lock);3679	bfa_trc(sfp, sfp->state_query_lock);3680 3681	switch (event) {3682	case BFA_IOC_E_DISABLED:3683	case BFA_IOC_E_FAILED:3684		if (sfp->lock) {3685			sfp->status = BFA_STATUS_IOC_FAILURE;3686			bfa_cb_sfp_show(sfp);3687		}3688 3689		if (sfp->state_query_lock) {3690			sfp->status = BFA_STATUS_IOC_FAILURE;3691			bfa_cb_sfp_state_query(sfp);3692		}3693		break;3694 3695	default:3696		break;3697	}3698}3699 3700/*3701 * SFP's State Change Notification post to AEN3702 */3703static void3704bfa_sfp_scn_aen_post(struct bfa_sfp_s *sfp, struct bfi_sfp_scn_s *rsp)3705{3706	struct bfad_s *bfad = (struct bfad_s *)sfp->ioc->bfa->bfad;3707	struct bfa_aen_entry_s  *aen_entry;3708	enum bfa_port_aen_event aen_evt = 0;3709 3710	bfa_trc(sfp, (((u64)rsp->pomlvl) << 16) | (((u64)rsp->sfpid) << 8) |3711		      ((u64)rsp->event));3712 3713	bfad_get_aen_entry(bfad, aen_entry);3714	if (!aen_entry)3715		return;3716 3717	aen_entry->aen_data.port.ioc_type = bfa_ioc_get_type(sfp->ioc);3718	aen_entry->aen_data.port.pwwn = sfp->ioc->attr->pwwn;3719	aen_entry->aen_data.port.mac = bfa_ioc_get_mac(sfp->ioc);3720 3721	switch (rsp->event) {3722	case BFA_SFP_SCN_INSERTED:3723		aen_evt = BFA_PORT_AEN_SFP_INSERT;3724		break;3725	case BFA_SFP_SCN_REMOVED:3726		aen_evt = BFA_PORT_AEN_SFP_REMOVE;3727		break;3728	case BFA_SFP_SCN_FAILED:3729		aen_evt = BFA_PORT_AEN_SFP_ACCESS_ERROR;3730		break;3731	case BFA_SFP_SCN_UNSUPPORT:3732		aen_evt = BFA_PORT_AEN_SFP_UNSUPPORT;3733		break;3734	case BFA_SFP_SCN_POM:3735		aen_evt = BFA_PORT_AEN_SFP_POM;3736		aen_entry->aen_data.port.level = rsp->pomlvl;3737		break;3738	default:3739		bfa_trc(sfp, rsp->event);3740		WARN_ON(1);3741	}3742 3743	/* Send the AEN notification */3744	bfad_im_post_vendor_event(aen_entry, bfad, ++sfp->ioc->ioc_aen_seq,3745				  BFA_AEN_CAT_PORT, aen_evt);3746}3747 3748/*3749 *	SFP get data send3750 */3751static void3752bfa_sfp_getdata_send(struct bfa_sfp_s *sfp)3753{3754	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;3755 3756	bfa_trc(sfp, req->memtype);3757 3758	/* build host command */3759	bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW,3760			bfa_ioc_portid(sfp->ioc));3761 3762	/* send mbox cmd */3763	bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd);3764}3765 3766/*3767 *	SFP is valid, read sfp data3768 */3769static void3770bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype)3771{3772	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;3773 3774	WARN_ON(sfp->lock != 0);3775	bfa_trc(sfp, sfp->state);3776 3777	sfp->lock = 1;3778	sfp->memtype = memtype;3779	req->memtype = memtype;3780 3781	/* Setup SG list */3782	bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa);3783 3784	bfa_sfp_getdata_send(sfp);3785}3786 3787/*3788 *	SFP scn handler3789 */3790static void3791bfa_sfp_scn(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)3792{3793	struct bfi_sfp_scn_s *rsp = (struct bfi_sfp_scn_s *) msg;3794 3795	switch (rsp->event) {3796	case BFA_SFP_SCN_INSERTED:3797		sfp->state = BFA_SFP_STATE_INSERTED;3798		sfp->data_valid = 0;3799		bfa_sfp_scn_aen_post(sfp, rsp);3800		break;3801	case BFA_SFP_SCN_REMOVED:3802		sfp->state = BFA_SFP_STATE_REMOVED;3803		sfp->data_valid = 0;3804		bfa_sfp_scn_aen_post(sfp, rsp);3805		break;3806	case BFA_SFP_SCN_FAILED:3807		sfp->state = BFA_SFP_STATE_FAILED;3808		sfp->data_valid = 0;3809		bfa_sfp_scn_aen_post(sfp, rsp);3810		break;3811	case BFA_SFP_SCN_UNSUPPORT:3812		sfp->state = BFA_SFP_STATE_UNSUPPORT;3813		bfa_sfp_scn_aen_post(sfp, rsp);3814		if (!sfp->lock)3815			bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);3816		break;3817	case BFA_SFP_SCN_POM:3818		bfa_sfp_scn_aen_post(sfp, rsp);3819		break;3820	case BFA_SFP_SCN_VALID:3821		sfp->state = BFA_SFP_STATE_VALID;3822		if (!sfp->lock)3823			bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);3824		break;3825	default:3826		bfa_trc(sfp, rsp->event);3827		WARN_ON(1);3828	}3829}3830 3831/*3832 * SFP show complete3833 */3834static void3835bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)3836{3837	struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg;3838 3839	if (!sfp->lock) {3840		/*3841		 * receiving response after ioc failure3842		 */3843		bfa_trc(sfp, sfp->lock);3844		return;3845	}3846 3847	bfa_trc(sfp, rsp->status);3848	if (rsp->status == BFA_STATUS_OK) {3849		sfp->data_valid = 1;3850		if (sfp->state == BFA_SFP_STATE_VALID)3851			sfp->status = BFA_STATUS_OK;3852		else if (sfp->state == BFA_SFP_STATE_UNSUPPORT)3853			sfp->status = BFA_STATUS_SFP_UNSUPP;3854		else3855			bfa_trc(sfp, sfp->state);3856	} else {3857		sfp->data_valid = 0;3858		sfp->status = rsp->status;3859		/* sfpshow shouldn't change sfp state */3860	}3861 3862	bfa_trc(sfp, sfp->memtype);3863	if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) {3864		bfa_trc(sfp, sfp->data_valid);3865		if (sfp->data_valid) {3866			u32	size = sizeof(struct sfp_mem_s);3867			u8 *des = (u8 *)(sfp->sfpmem);3868			memcpy(des, sfp->dbuf_kva, size);3869		}3870		/*3871		 * Queue completion callback.3872		 */3873		bfa_cb_sfp_show(sfp);3874	} else3875		sfp->lock = 0;3876 3877	bfa_trc(sfp, sfp->state_query_lock);3878	if (sfp->state_query_lock) {3879		sfp->state = rsp->state;3880		/* Complete callback */3881		bfa_cb_sfp_state_query(sfp);3882	}3883}3884 3885/*3886 *	SFP query fw sfp state3887 */3888static void3889bfa_sfp_state_query(struct bfa_sfp_s *sfp)3890{3891	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;3892 3893	/* Should not be doing query if not in _INIT state */3894	WARN_ON(sfp->state != BFA_SFP_STATE_INIT);3895	WARN_ON(sfp->state_query_lock != 0);3896	bfa_trc(sfp, sfp->state);3897 3898	sfp->state_query_lock = 1;3899	req->memtype = 0;3900 3901	if (!sfp->lock)3902		bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);3903}3904 3905static void3906bfa_sfp_media_get(struct bfa_sfp_s *sfp)3907{3908	enum bfa_defs_sfp_media_e *media = sfp->media;3909 3910	*media = BFA_SFP_MEDIA_UNKNOWN;3911 3912	if (sfp->state == BFA_SFP_STATE_UNSUPPORT)3913		*media = BFA_SFP_MEDIA_UNSUPPORT;3914	else if (sfp->state == BFA_SFP_STATE_VALID) {3915		union sfp_xcvr_e10g_code_u e10g;3916		struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;3917		u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 |3918				(sfpmem->srlid_base.xcvr[5] >> 1);3919 3920		e10g.b = sfpmem->srlid_base.xcvr[0];3921		bfa_trc(sfp, e10g.b);3922		bfa_trc(sfp, xmtr_tech);3923		/* check fc transmitter tech */3924		if ((xmtr_tech & SFP_XMTR_TECH_CU) ||3925		    (xmtr_tech & SFP_XMTR_TECH_CP) ||3926		    (xmtr_tech & SFP_XMTR_TECH_CA))3927			*media = BFA_SFP_MEDIA_CU;3928		else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) ||3929			 (xmtr_tech & SFP_XMTR_TECH_EL_INTER))3930			*media = BFA_SFP_MEDIA_EL;3931		else if ((xmtr_tech & SFP_XMTR_TECH_LL) ||3932			 (xmtr_tech & SFP_XMTR_TECH_LC))3933			*media = BFA_SFP_MEDIA_LW;3934		else if ((xmtr_tech & SFP_XMTR_TECH_SL) ||3935			 (xmtr_tech & SFP_XMTR_TECH_SN) ||3936			 (xmtr_tech & SFP_XMTR_TECH_SA))3937			*media = BFA_SFP_MEDIA_SW;3938		/* Check 10G Ethernet Compilance code */3939		else if (e10g.r.e10g_sr)3940			*media = BFA_SFP_MEDIA_SW;3941		else if (e10g.r.e10g_lrm && e10g.r.e10g_lr)3942			*media = BFA_SFP_MEDIA_LW;3943		else if (e10g.r.e10g_unall)3944			*media = BFA_SFP_MEDIA_UNKNOWN;3945		else3946			bfa_trc(sfp, 0);3947	} else3948		bfa_trc(sfp, sfp->state);3949}3950 3951static bfa_status_t3952bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed)3953{3954	struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;3955	struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr;3956	union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3;3957	union sfp_xcvr_e10g_code_u e10g = xcvr->e10g;3958 3959	if (portspeed == BFA_PORT_SPEED_10GBPS) {3960		if (e10g.r.e10g_sr || e10g.r.e10g_lr)3961			return BFA_STATUS_OK;3962		else {3963			bfa_trc(sfp, e10g.b);3964			return BFA_STATUS_UNSUPP_SPEED;3965		}3966	}3967	if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) ||3968	    ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) ||3969	    ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) ||3970	    ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) ||3971	    ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100))3972		return BFA_STATUS_OK;3973	else {3974		bfa_trc(sfp, portspeed);3975		bfa_trc(sfp, fc3.b);3976		bfa_trc(sfp, e10g.b);3977		return BFA_STATUS_UNSUPP_SPEED;3978	}3979}3980 3981/*3982 *	SFP hmbox handler3983 */3984void3985bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg)3986{3987	struct bfa_sfp_s *sfp = sfparg;3988 3989	switch (msg->mh.msg_id) {3990	case BFI_SFP_I2H_SHOW:3991		bfa_sfp_show_comp(sfp, msg);3992		break;3993 3994	case BFI_SFP_I2H_SCN:3995		bfa_sfp_scn(sfp, msg);3996		break;3997 3998	default:3999		bfa_trc(sfp, msg->mh.msg_id);4000		WARN_ON(1);4001	}4002}4003 4004/*4005 *	Return DMA memory needed by sfp module.4006 */4007u324008bfa_sfp_meminfo(void)4009{4010	return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);4011}4012 4013/*4014 *	Attach virtual and physical memory for SFP.4015 */4016void4017bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev,4018		struct bfa_trc_mod_s *trcmod)4019{4020	sfp->dev = dev;4021	sfp->ioc = ioc;4022	sfp->trcmod = trcmod;4023 4024	sfp->cbfn = NULL;4025	sfp->cbarg = NULL;4026	sfp->sfpmem = NULL;4027	sfp->lock = 0;4028	sfp->data_valid = 0;4029	sfp->state = BFA_SFP_STATE_INIT;4030	sfp->state_query_lock = 0;4031	sfp->state_query_cbfn = NULL;4032	sfp->state_query_cbarg = NULL;4033	sfp->media = NULL;4034	sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;4035	sfp->is_elb = BFA_FALSE;4036 4037	bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp);4038	bfa_q_qe_init(&sfp->ioc_notify);4039	bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp);4040	list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q);4041}4042 4043/*4044 *	Claim Memory for SFP4045 */4046void4047bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa)4048{4049	sfp->dbuf_kva   = dm_kva;4050	sfp->dbuf_pa    = dm_pa;4051	memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s));4052 4053	dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);4054	dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);4055}4056 4057/*4058 * Show SFP eeprom content4059 *4060 * @param[in] sfp   - bfa sfp module4061 *4062 * @param[out] sfpmem - sfp eeprom data4063 *4064 */4065bfa_status_t4066bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,4067		bfa_cb_sfp_t cbfn, void *cbarg)4068{4069 4070	if (!bfa_ioc_is_operational(sfp->ioc)) {4071		bfa_trc(sfp, 0);4072		return BFA_STATUS_IOC_NON_OP;4073	}4074 4075	if (sfp->lock) {4076		bfa_trc(sfp, 0);4077		return BFA_STATUS_DEVBUSY;4078	}4079 4080	sfp->cbfn = cbfn;4081	sfp->cbarg = cbarg;4082	sfp->sfpmem = sfpmem;4083 4084	bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT);4085	return BFA_STATUS_OK;4086}4087 4088/*4089 * Return SFP Media type4090 *4091 * @param[in] sfp   - bfa sfp module4092 *4093 * @param[out] media - port speed from user4094 *4095 */4096bfa_status_t4097bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media,4098		bfa_cb_sfp_t cbfn, void *cbarg)4099{4100	if (!bfa_ioc_is_operational(sfp->ioc)) {4101		bfa_trc(sfp, 0);4102		return BFA_STATUS_IOC_NON_OP;4103	}4104 4105	sfp->media = media;4106	if (sfp->state == BFA_SFP_STATE_INIT) {4107		if (sfp->state_query_lock) {4108			bfa_trc(sfp, 0);4109			return BFA_STATUS_DEVBUSY;4110		} else {4111			sfp->state_query_cbfn = cbfn;4112			sfp->state_query_cbarg = cbarg;4113			bfa_sfp_state_query(sfp);4114			return BFA_STATUS_SFP_NOT_READY;4115		}4116	}4117 4118	bfa_sfp_media_get(sfp);4119	return BFA_STATUS_OK;4120}4121 4122/*4123 * Check if user set port speed is allowed by the SFP4124 *4125 * @param[in] sfp   - bfa sfp module4126 * @param[in] portspeed - port speed from user4127 *4128 */4129bfa_status_t4130bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,4131		bfa_cb_sfp_t cbfn, void *cbarg)4132{4133	WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN);4134 4135	if (!bfa_ioc_is_operational(sfp->ioc))4136		return BFA_STATUS_IOC_NON_OP;4137 4138	/* For Mezz card, all speed is allowed */4139	if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type))4140		return BFA_STATUS_OK;4141 4142	/* Check SFP state */4143	sfp->portspeed = portspeed;4144	if (sfp->state == BFA_SFP_STATE_INIT) {4145		if (sfp->state_query_lock) {4146			bfa_trc(sfp, 0);4147			return BFA_STATUS_DEVBUSY;4148		} else {4149			sfp->state_query_cbfn = cbfn;4150			sfp->state_query_cbarg = cbarg;4151			bfa_sfp_state_query(sfp);4152			return BFA_STATUS_SFP_NOT_READY;4153		}4154	}4155 4156	if (sfp->state == BFA_SFP_STATE_REMOVED ||4157	    sfp->state == BFA_SFP_STATE_FAILED) {4158		bfa_trc(sfp, sfp->state);4159		return BFA_STATUS_NO_SFP_DEV;4160	}4161 4162	if (sfp->state == BFA_SFP_STATE_INSERTED) {4163		bfa_trc(sfp, sfp->state);4164		return BFA_STATUS_DEVBUSY;  /* sfp is reading data */4165	}4166 4167	/* For eloopback, all speed is allowed */4168	if (sfp->is_elb)4169		return BFA_STATUS_OK;4170 4171	return bfa_sfp_speed_valid(sfp, portspeed);4172}4173 4174/*4175 *	Flash module specific4176 */4177 4178/*4179 * FLASH DMA buffer should be big enough to hold both MFG block and4180 * asic block(64k) at the same time and also should be 2k aligned to4181 * avoid write segement to cross sector boundary.4182 */4183#define BFA_FLASH_SEG_SZ	20484184#define BFA_FLASH_DMA_BUF_SZ	\4185	BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)4186 4187static void4188bfa_flash_aen_audit_post(struct bfa_ioc_s *ioc, enum bfa_audit_aen_event event,4189			int inst, int type)4190{4191	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;4192	struct bfa_aen_entry_s  *aen_entry;4193 4194	bfad_get_aen_entry(bfad, aen_entry);4195	if (!aen_entry)4196		return;4197 4198	aen_entry->aen_data.audit.pwwn = ioc->attr->pwwn;4199	aen_entry->aen_data.audit.partition_inst = inst;4200	aen_entry->aen_data.audit.partition_type = type;4201 4202	/* Send the AEN notification */4203	bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,4204				  BFA_AEN_CAT_AUDIT, event);4205}4206 4207static void4208bfa_flash_cb(struct bfa_flash_s *flash)4209{4210	flash->op_busy = 0;4211	if (flash->cbfn)4212		flash->cbfn(flash->cbarg, flash->status);4213}4214 4215static void4216bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event)4217{4218	struct bfa_flash_s	*flash = cbarg;4219 4220	bfa_trc(flash, event);4221	switch (event) {4222	case BFA_IOC_E_DISABLED:4223	case BFA_IOC_E_FAILED:4224		if (flash->op_busy) {4225			flash->status = BFA_STATUS_IOC_FAILURE;4226			flash->cbfn(flash->cbarg, flash->status);4227			flash->op_busy = 0;4228		}4229		break;4230 4231	default:4232		break;4233	}4234}4235 4236/*4237 * Send flash attribute query request.4238 *4239 * @param[in] cbarg - callback argument4240 */4241static void4242bfa_flash_query_send(void *cbarg)4243{4244	struct bfa_flash_s *flash = cbarg;4245	struct bfi_flash_query_req_s *msg =4246			(struct bfi_flash_query_req_s *) flash->mb.msg;4247 4248	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,4249		bfa_ioc_portid(flash->ioc));4250	bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s),4251		flash->dbuf_pa);4252	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);4253}4254 4255/*4256 * Send flash write request.4257 *4258 * @param[in] cbarg - callback argument4259 */4260static void4261bfa_flash_write_send(struct bfa_flash_s *flash)4262{4263	struct bfi_flash_write_req_s *msg =4264			(struct bfi_flash_write_req_s *) flash->mb.msg;4265	u32	len;4266 4267	msg->type = be32_to_cpu(flash->type);4268	msg->instance = flash->instance;4269	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);4270	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?4271		flash->residue : BFA_FLASH_DMA_BUF_SZ;4272	msg->length = be32_to_cpu(len);4273 4274	/* indicate if it's the last msg of the whole write operation */4275	msg->last = (len == flash->residue) ? 1 : 0;4276 4277	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,4278			bfa_ioc_portid(flash->ioc));4279	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);4280	memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);4281	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);4282 4283	flash->residue -= len;4284	flash->offset += len;4285}4286 4287/*4288 * Send flash read request.4289 *4290 * @param[in] cbarg - callback argument4291 */4292static void4293bfa_flash_read_send(void *cbarg)4294{4295	struct bfa_flash_s *flash = cbarg;4296	struct bfi_flash_read_req_s *msg =4297			(struct bfi_flash_read_req_s *) flash->mb.msg;4298	u32	len;4299 4300	msg->type = be32_to_cpu(flash->type);4301	msg->instance = flash->instance;4302	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);4303	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?4304			flash->residue : BFA_FLASH_DMA_BUF_SZ;4305	msg->length = be32_to_cpu(len);4306	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,4307		bfa_ioc_portid(flash->ioc));4308	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);4309	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);4310}4311 4312/*4313 * Send flash erase request.4314 *4315 * @param[in] cbarg - callback argument4316 */4317static void4318bfa_flash_erase_send(void *cbarg)4319{4320	struct bfa_flash_s *flash = cbarg;4321	struct bfi_flash_erase_req_s *msg =4322			(struct bfi_flash_erase_req_s *) flash->mb.msg;4323 4324	msg->type = be32_to_cpu(flash->type);4325	msg->instance = flash->instance;4326	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ,4327			bfa_ioc_portid(flash->ioc));4328	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);4329}4330 4331/*4332 * Process flash response messages upon receiving interrupts.4333 *4334 * @param[in] flasharg - flash structure4335 * @param[in] msg - message structure4336 */4337static void4338bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)4339{4340	struct bfa_flash_s *flash = flasharg;4341	u32	status;4342 4343	union {4344		struct bfi_flash_query_rsp_s *query;4345		struct bfi_flash_erase_rsp_s *erase;4346		struct bfi_flash_write_rsp_s *write;4347		struct bfi_flash_read_rsp_s *read;4348		struct bfi_flash_event_s *event;4349		struct bfi_mbmsg_s   *msg;4350	} m;4351 4352	m.msg = msg;4353	bfa_trc(flash, msg->mh.msg_id);4354 4355	if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) {4356		/* receiving response after ioc failure */4357		bfa_trc(flash, 0x9999);4358		return;4359	}4360 4361	switch (msg->mh.msg_id) {4362	case BFI_FLASH_I2H_QUERY_RSP:4363		status = be32_to_cpu(m.query->status);4364		bfa_trc(flash, status);4365		if (status == BFA_STATUS_OK) {4366			u32	i;4367			struct bfa_flash_attr_s *attr, *f;4368 4369			attr = (struct bfa_flash_attr_s *) flash->ubuf;4370			f = (struct bfa_flash_attr_s *) flash->dbuf_kva;4371			attr->status = be32_to_cpu(f->status);4372			attr->npart = be32_to_cpu(f->npart);4373			bfa_trc(flash, attr->status);4374			bfa_trc(flash, attr->npart);4375			for (i = 0; i < attr->npart; i++) {4376				attr->part[i].part_type =4377					be32_to_cpu(f->part[i].part_type);4378				attr->part[i].part_instance =4379					be32_to_cpu(f->part[i].part_instance);4380				attr->part[i].part_off =4381					be32_to_cpu(f->part[i].part_off);4382				attr->part[i].part_size =4383					be32_to_cpu(f->part[i].part_size);4384				attr->part[i].part_len =4385					be32_to_cpu(f->part[i].part_len);4386				attr->part[i].part_status =4387					be32_to_cpu(f->part[i].part_status);4388			}4389		}4390		flash->status = status;4391		bfa_flash_cb(flash);4392		break;4393	case BFI_FLASH_I2H_ERASE_RSP:4394		status = be32_to_cpu(m.erase->status);4395		bfa_trc(flash, status);4396		flash->status = status;4397		bfa_flash_cb(flash);4398		break;4399	case BFI_FLASH_I2H_WRITE_RSP:4400		status = be32_to_cpu(m.write->status);4401		bfa_trc(flash, status);4402		if (status != BFA_STATUS_OK || flash->residue == 0) {4403			flash->status = status;4404			bfa_flash_cb(flash);4405		} else {4406			bfa_trc(flash, flash->offset);4407			bfa_flash_write_send(flash);4408		}4409		break;4410	case BFI_FLASH_I2H_READ_RSP:4411		status = be32_to_cpu(m.read->status);4412		bfa_trc(flash, status);4413		if (status != BFA_STATUS_OK) {4414			flash->status = status;4415			bfa_flash_cb(flash);4416		} else {4417			u32 len = be32_to_cpu(m.read->length);4418			bfa_trc(flash, flash->offset);4419			bfa_trc(flash, len);4420			memcpy(flash->ubuf + flash->offset,4421				flash->dbuf_kva, len);4422			flash->residue -= len;4423			flash->offset += len;4424			if (flash->residue == 0) {4425				flash->status = status;4426				bfa_flash_cb(flash);4427			} else4428				bfa_flash_read_send(flash);4429		}4430		break;4431	case BFI_FLASH_I2H_BOOT_VER_RSP:4432		break;4433	case BFI_FLASH_I2H_EVENT:4434		status = be32_to_cpu(m.event->status);4435		bfa_trc(flash, status);4436		if (status == BFA_STATUS_BAD_FWCFG)4437			bfa_ioc_aen_post(flash->ioc, BFA_IOC_AEN_FWCFG_ERROR);4438		else if (status == BFA_STATUS_INVALID_VENDOR) {4439			u32 param;4440			param = be32_to_cpu(m.event->param);4441			bfa_trc(flash, param);4442			bfa_ioc_aen_post(flash->ioc,4443				BFA_IOC_AEN_INVALID_VENDOR);4444		}4445		break;4446 4447	default:4448		WARN_ON(1);4449	}4450}4451 4452/*4453 * Flash memory info API.4454 *4455 * @param[in] mincfg - minimal cfg variable4456 */4457u324458bfa_flash_meminfo(bfa_boolean_t mincfg)4459{4460	/* min driver doesn't need flash */4461	if (mincfg)4462		return 0;4463	return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);4464}4465 4466/*4467 * Flash attach API.4468 *4469 * @param[in] flash - flash structure4470 * @param[in] ioc  - ioc structure4471 * @param[in] dev  - device structure4472 * @param[in] trcmod - trace module4473 * @param[in] logmod - log module4474 */4475void4476bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev,4477		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)4478{4479	flash->ioc = ioc;4480	flash->trcmod = trcmod;4481	flash->cbfn = NULL;4482	flash->cbarg = NULL;4483	flash->op_busy = 0;4484 4485	bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);4486	bfa_q_qe_init(&flash->ioc_notify);4487	bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);4488	list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);4489 4490	/* min driver doesn't need flash */4491	if (mincfg) {4492		flash->dbuf_kva = NULL;4493		flash->dbuf_pa = 0;4494	}4495}4496 4497/*4498 * Claim memory for flash4499 *4500 * @param[in] flash - flash structure4501 * @param[in] dm_kva - pointer to virtual memory address4502 * @param[in] dm_pa - physical memory address4503 * @param[in] mincfg - minimal cfg variable4504 */4505void4506bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa,4507		bfa_boolean_t mincfg)4508{4509	if (mincfg)4510		return;4511 4512	flash->dbuf_kva = dm_kva;4513	flash->dbuf_pa = dm_pa;4514	memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);4515	dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);4516	dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);4517}4518 4519/*4520 * Get flash attribute.4521 *4522 * @param[in] flash - flash structure4523 * @param[in] attr - flash attribute structure4524 * @param[in] cbfn - callback function4525 * @param[in] cbarg - callback argument4526 *4527 * Return status.4528 */4529bfa_status_t4530bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr,4531		bfa_cb_flash_t cbfn, void *cbarg)4532{4533	bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ);4534 4535	if (!bfa_ioc_is_operational(flash->ioc))4536		return BFA_STATUS_IOC_NON_OP;4537 4538	if (flash->op_busy) {4539		bfa_trc(flash, flash->op_busy);4540		return BFA_STATUS_DEVBUSY;4541	}4542 4543	flash->op_busy = 1;4544	flash->cbfn = cbfn;4545	flash->cbarg = cbarg;4546	flash->ubuf = (u8 *) attr;4547	bfa_flash_query_send(flash);4548 4549	return BFA_STATUS_OK;4550}4551 4552/*4553 * Erase flash partition.4554 *4555 * @param[in] flash - flash structure4556 * @param[in] type - flash partition type4557 * @param[in] instance - flash partition instance4558 * @param[in] cbfn - callback function4559 * @param[in] cbarg - callback argument4560 *4561 * Return status.4562 */4563bfa_status_t4564bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,4565		u8 instance, bfa_cb_flash_t cbfn, void *cbarg)4566{4567	bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ);4568	bfa_trc(flash, type);4569	bfa_trc(flash, instance);4570 4571	if (!bfa_ioc_is_operational(flash->ioc))4572		return BFA_STATUS_IOC_NON_OP;4573 4574	if (flash->op_busy) {4575		bfa_trc(flash, flash->op_busy);4576		return BFA_STATUS_DEVBUSY;4577	}4578 4579	flash->op_busy = 1;4580	flash->cbfn = cbfn;4581	flash->cbarg = cbarg;4582	flash->type = type;4583	flash->instance = instance;4584 4585	bfa_flash_erase_send(flash);4586	bfa_flash_aen_audit_post(flash->ioc, BFA_AUDIT_AEN_FLASH_ERASE,4587				instance, type);4588	return BFA_STATUS_OK;4589}4590 4591/*4592 * Update flash partition.4593 *4594 * @param[in] flash - flash structure4595 * @param[in] type - flash partition type4596 * @param[in] instance - flash partition instance4597 * @param[in] buf - update data buffer4598 * @param[in] len - data buffer length4599 * @param[in] offset - offset relative to the partition starting address4600 * @param[in] cbfn - callback function4601 * @param[in] cbarg - callback argument4602 *4603 * Return status.4604 */4605bfa_status_t4606bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,4607		u8 instance, void *buf, u32 len, u32 offset,4608		bfa_cb_flash_t cbfn, void *cbarg)4609{4610	bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ);4611	bfa_trc(flash, type);4612	bfa_trc(flash, instance);4613	bfa_trc(flash, len);4614	bfa_trc(flash, offset);4615 4616	if (!bfa_ioc_is_operational(flash->ioc))4617		return BFA_STATUS_IOC_NON_OP;4618 4619	/*4620	 * 'len' must be in word (4-byte) boundary4621	 * 'offset' must be in sector (16kb) boundary4622	 */4623	if (!len || (len & 0x03) || (offset & 0x00003FFF))4624		return BFA_STATUS_FLASH_BAD_LEN;4625 4626	if (type == BFA_FLASH_PART_MFG)4627		return BFA_STATUS_EINVAL;4628 4629	if (flash->op_busy) {4630		bfa_trc(flash, flash->op_busy);4631		return BFA_STATUS_DEVBUSY;4632	}4633 4634	flash->op_busy = 1;4635	flash->cbfn = cbfn;4636	flash->cbarg = cbarg;4637	flash->type = type;4638	flash->instance = instance;4639	flash->residue = len;4640	flash->offset = 0;4641	flash->addr_off = offset;4642	flash->ubuf = buf;4643 4644	bfa_flash_write_send(flash);4645	return BFA_STATUS_OK;4646}4647 4648/*4649 * Read flash partition.4650 *4651 * @param[in] flash - flash structure4652 * @param[in] type - flash partition type4653 * @param[in] instance - flash partition instance4654 * @param[in] buf - read data buffer4655 * @param[in] len - data buffer length4656 * @param[in] offset - offset relative to the partition starting address4657 * @param[in] cbfn - callback function4658 * @param[in] cbarg - callback argument4659 *4660 * Return status.4661 */4662bfa_status_t4663bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,4664		u8 instance, void *buf, u32 len, u32 offset,4665		bfa_cb_flash_t cbfn, void *cbarg)4666{4667	bfa_trc(flash, BFI_FLASH_H2I_READ_REQ);4668	bfa_trc(flash, type);4669	bfa_trc(flash, instance);4670	bfa_trc(flash, len);4671	bfa_trc(flash, offset);4672 4673	if (!bfa_ioc_is_operational(flash->ioc))4674		return BFA_STATUS_IOC_NON_OP;4675 4676	/*4677	 * 'len' must be in word (4-byte) boundary4678	 * 'offset' must be in sector (16kb) boundary4679	 */4680	if (!len || (len & 0x03) || (offset & 0x00003FFF))4681		return BFA_STATUS_FLASH_BAD_LEN;4682 4683	if (flash->op_busy) {4684		bfa_trc(flash, flash->op_busy);4685		return BFA_STATUS_DEVBUSY;4686	}4687 4688	flash->op_busy = 1;4689	flash->cbfn = cbfn;4690	flash->cbarg = cbarg;4691	flash->type = type;4692	flash->instance = instance;4693	flash->residue = len;4694	flash->offset = 0;4695	flash->addr_off = offset;4696	flash->ubuf = buf;4697	bfa_flash_read_send(flash);4698 4699	return BFA_STATUS_OK;4700}4701 4702/*4703 *	DIAG module specific4704 */4705 4706#define BFA_DIAG_MEMTEST_TOV	50000	/* memtest timeout in msec */4707#define CT2_BFA_DIAG_MEMTEST_TOV	(9*30*1000)  /* 4.5 min */4708 4709/* IOC event handler */4710static void4711bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event)4712{4713	struct bfa_diag_s *diag = diag_arg;4714 4715	bfa_trc(diag, event);4716	bfa_trc(diag, diag->block);4717	bfa_trc(diag, diag->fwping.lock);4718	bfa_trc(diag, diag->tsensor.lock);4719 4720	switch (event) {4721	case BFA_IOC_E_DISABLED:4722	case BFA_IOC_E_FAILED:4723		if (diag->fwping.lock) {4724			diag->fwping.status = BFA_STATUS_IOC_FAILURE;4725			diag->fwping.cbfn(diag->fwping.cbarg,4726					diag->fwping.status);4727			diag->fwping.lock = 0;4728		}4729 4730		if (diag->tsensor.lock) {4731			diag->tsensor.status = BFA_STATUS_IOC_FAILURE;4732			diag->tsensor.cbfn(diag->tsensor.cbarg,4733					   diag->tsensor.status);4734			diag->tsensor.lock = 0;4735		}4736 4737		if (diag->block) {4738			if (diag->timer_active) {4739				bfa_timer_stop(&diag->timer);4740				diag->timer_active = 0;4741			}4742 4743			diag->status = BFA_STATUS_IOC_FAILURE;4744			diag->cbfn(diag->cbarg, diag->status);4745			diag->block = 0;4746		}4747		break;4748 4749	default:4750		break;4751	}4752}4753 4754static void4755bfa_diag_memtest_done(void *cbarg)4756{4757	struct bfa_diag_s *diag = cbarg;4758	struct bfa_ioc_s  *ioc = diag->ioc;4759	struct bfa_diag_memtest_result *res = diag->result;4760	u32	loff = BFI_BOOT_MEMTEST_RES_ADDR;4761	u32	pgnum, i;4762 4763	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);4764	writel(pgnum, ioc->ioc_regs.host_page_num_fn);4765 4766	for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /4767			 sizeof(u32)); i++) {4768		/* read test result from smem */4769		*((u32 *) res + i) =4770			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);4771		loff += sizeof(u32);4772	}4773 4774	/* Reset IOC fwstates to BFI_IOC_UNINIT */4775	bfa_ioc_reset_fwstate(ioc);4776 4777	res->status = swab32(res->status);4778	bfa_trc(diag, res->status);4779 4780	if (res->status == BFI_BOOT_MEMTEST_RES_SIG)4781		diag->status = BFA_STATUS_OK;4782	else {4783		diag->status = BFA_STATUS_MEMTEST_FAILED;4784		res->addr = swab32(res->addr);4785		res->exp = swab32(res->exp);4786		res->act = swab32(res->act);4787		res->err_status = swab32(res->err_status);4788		res->err_status1 = swab32(res->err_status1);4789		res->err_addr = swab32(res->err_addr);4790		bfa_trc(diag, res->addr);4791		bfa_trc(diag, res->exp);4792		bfa_trc(diag, res->act);4793		bfa_trc(diag, res->err_status);4794		bfa_trc(diag, res->err_status1);4795		bfa_trc(diag, res->err_addr);4796	}4797	diag->timer_active = 0;4798	diag->cbfn(diag->cbarg, diag->status);4799	diag->block = 0;4800}4801 4802/*4803 * Firmware ping4804 */4805 4806/*4807 * Perform DMA test directly4808 */4809static void4810diag_fwping_send(struct bfa_diag_s *diag)4811{4812	struct bfi_diag_fwping_req_s *fwping_req;4813	u32	i;4814 4815	bfa_trc(diag, diag->fwping.dbuf_pa);4816 4817	/* fill DMA area with pattern */4818	for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++)4819		*((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data;4820 4821	/* Fill mbox msg */4822	fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg;4823 4824	/* Setup SG list */4825	bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ,4826			diag->fwping.dbuf_pa);4827	/* Set up dma count */4828	fwping_req->count = cpu_to_be32(diag->fwping.count);4829	/* Set up data pattern */4830	fwping_req->data = diag->fwping.data;4831 4832	/* build host command */4833	bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING,4834		bfa_ioc_portid(diag->ioc));4835 4836	/* send mbox cmd */4837	bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd);4838}4839 4840static void4841diag_fwping_comp(struct bfa_diag_s *diag,4842		 struct bfi_diag_fwping_rsp_s *diag_rsp)4843{4844	u32	rsp_data = diag_rsp->data;4845	u8	rsp_dma_status = diag_rsp->dma_status;4846 4847	bfa_trc(diag, rsp_data);4848	bfa_trc(diag, rsp_dma_status);4849 4850	if (rsp_dma_status == BFA_STATUS_OK) {4851		u32	i, pat;4852		pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) :4853			diag->fwping.data;4854		/* Check mbox data */4855		if (diag->fwping.data != rsp_data) {4856			bfa_trc(diag, rsp_data);4857			diag->fwping.result->dmastatus =4858					BFA_STATUS_DATACORRUPTED;4859			diag->fwping.status = BFA_STATUS_DATACORRUPTED;4860			diag->fwping.cbfn(diag->fwping.cbarg,4861					diag->fwping.status);4862			diag->fwping.lock = 0;4863			return;4864		}4865		/* Check dma pattern */4866		for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) {4867			if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) {4868				bfa_trc(diag, i);4869				bfa_trc(diag, pat);4870				bfa_trc(diag,4871					*((u32 *)diag->fwping.dbuf_kva + i));4872				diag->fwping.result->dmastatus =4873						BFA_STATUS_DATACORRUPTED;4874				diag->fwping.status = BFA_STATUS_DATACORRUPTED;4875				diag->fwping.cbfn(diag->fwping.cbarg,4876						diag->fwping.status);4877				diag->fwping.lock = 0;4878				return;4879			}4880		}4881		diag->fwping.result->dmastatus = BFA_STATUS_OK;4882		diag->fwping.status = BFA_STATUS_OK;4883		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);4884		diag->fwping.lock = 0;4885	} else {4886		diag->fwping.status = BFA_STATUS_HDMA_FAILED;4887		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);4888		diag->fwping.lock = 0;4889	}4890}4891 4892/*4893 * Temperature Sensor4894 */4895 4896static void4897diag_tempsensor_send(struct bfa_diag_s *diag)4898{4899	struct bfi_diag_ts_req_s *msg;4900 4901	msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg;4902	bfa_trc(diag, msg->temp);4903	/* build host command */4904	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR,4905		bfa_ioc_portid(diag->ioc));4906	/* send mbox cmd */4907	bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd);4908}4909 4910static void4911diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)4912{4913	if (!diag->tsensor.lock) {4914		/* receiving response after ioc failure */4915		bfa_trc(diag, diag->tsensor.lock);4916		return;4917	}4918 4919	/*4920	 * ASIC junction tempsensor is a reg read operation4921	 * it will always return OK4922	 */4923	diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);4924	diag->tsensor.temp->ts_junc = rsp->ts_junc;4925	diag->tsensor.temp->ts_brd = rsp->ts_brd;4926 4927	if (rsp->ts_brd) {4928		/* tsensor.temp->status is brd_temp status */4929		diag->tsensor.temp->status = rsp->status;4930		if (rsp->status == BFA_STATUS_OK) {4931			diag->tsensor.temp->brd_temp =4932				be16_to_cpu(rsp->brd_temp);4933		} else4934			diag->tsensor.temp->brd_temp = 0;4935	}4936 4937	bfa_trc(diag, rsp->status);4938	bfa_trc(diag, rsp->ts_junc);4939	bfa_trc(diag, rsp->temp);4940	bfa_trc(diag, rsp->ts_brd);4941	bfa_trc(diag, rsp->brd_temp);4942 4943	/* tsensor status is always good bcos we always have junction temp */4944	diag->tsensor.status = BFA_STATUS_OK;4945	diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);4946	diag->tsensor.lock = 0;4947}4948 4949/*4950 *	LED Test command4951 */4952static void4953diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)4954{4955	struct bfi_diag_ledtest_req_s  *msg;4956 4957	msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg;4958	/* build host command */4959	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST,4960			bfa_ioc_portid(diag->ioc));4961 4962	/*4963	 * convert the freq from N blinks per 10 sec to4964	 * crossbow ontime value. We do it here because division is need4965	 */4966	if (ledtest->freq)4967		ledtest->freq = 500 / ledtest->freq;4968 4969	if (ledtest->freq == 0)4970		ledtest->freq = 1;4971 4972	bfa_trc(diag, ledtest->freq);4973	/* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */4974	msg->cmd = (u8) ledtest->cmd;4975	msg->color = (u8) ledtest->color;4976	msg->portid = bfa_ioc_portid(diag->ioc);4977	msg->led = ledtest->led;4978	msg->freq = cpu_to_be16(ledtest->freq);4979 4980	/* send mbox cmd */4981	bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd);4982}4983 4984static void4985diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s *msg)4986{4987	bfa_trc(diag, diag->ledtest.lock);4988	diag->ledtest.lock = BFA_FALSE;4989	/* no bfa_cb_queue is needed because driver is not waiting */4990}4991 4992/*4993 * Port beaconing4994 */4995static void4996diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec)4997{4998	struct bfi_diag_portbeacon_req_s *msg;4999 5000	msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg;5001	/* build host command */5002	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON,5003		bfa_ioc_portid(diag->ioc));5004	msg->beacon = beacon;5005	msg->period = cpu_to_be32(sec);5006	/* send mbox cmd */5007	bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd);5008}5009 5010static void5011diag_portbeacon_comp(struct bfa_diag_s *diag)5012{5013	bfa_trc(diag, diag->beacon.state);5014	diag->beacon.state = BFA_FALSE;5015	if (diag->cbfn_beacon)5016		diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e);5017}5018 5019/*5020 *	Diag hmbox handler5021 */5022static void5023bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)5024{5025	struct bfa_diag_s *diag = diagarg;5026 5027	switch (msg->mh.msg_id) {5028	case BFI_DIAG_I2H_PORTBEACON:5029		diag_portbeacon_comp(diag);5030		break;5031	case BFI_DIAG_I2H_FWPING:5032		diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg);5033		break;5034	case BFI_DIAG_I2H_TEMPSENSOR:5035		diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg);5036		break;5037	case BFI_DIAG_I2H_LEDTEST:5038		diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg);5039		break;5040	default:5041		bfa_trc(diag, msg->mh.msg_id);5042		WARN_ON(1);5043	}5044}5045 5046/*5047 * Gen RAM Test5048 *5049 *   @param[in] *diag           - diag data struct5050 *   @param[in] *memtest        - mem test params input from upper layer,5051 *   @param[in] pattern         - mem test pattern5052 *   @param[in] *result         - mem test result5053 *   @param[in] cbfn            - mem test callback functioin5054 *   @param[in] cbarg           - callback functioin arg5055 *5056 *   @param[out]5057 */5058bfa_status_t5059bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest,5060		u32 pattern, struct bfa_diag_memtest_result *result,5061		bfa_cb_diag_t cbfn, void *cbarg)5062{5063	u32	memtest_tov;5064 5065	bfa_trc(diag, pattern);5066 5067	if (!bfa_ioc_adapter_is_disabled(diag->ioc))5068		return BFA_STATUS_ADAPTER_ENABLED;5069 5070	/* check to see if there is another destructive diag cmd running */5071	if (diag->block) {5072		bfa_trc(diag, diag->block);5073		return BFA_STATUS_DEVBUSY;5074	} else5075		diag->block = 1;5076 5077	diag->result = result;5078	diag->cbfn = cbfn;5079	diag->cbarg = cbarg;5080 5081	/* download memtest code and take LPU0 out of reset */5082	bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS);5083 5084	memtest_tov = (bfa_ioc_asic_gen(diag->ioc) == BFI_ASIC_GEN_CT2) ?5085		       CT2_BFA_DIAG_MEMTEST_TOV : BFA_DIAG_MEMTEST_TOV;5086	bfa_timer_begin(diag->ioc->timer_mod, &diag->timer,5087			bfa_diag_memtest_done, diag, memtest_tov);5088	diag->timer_active = 1;5089	return BFA_STATUS_OK;5090}5091 5092/*5093 * DIAG firmware ping command5094 *5095 *   @param[in] *diag           - diag data struct5096 *   @param[in] cnt             - dma loop count for testing PCIE5097 *   @param[in] data            - data pattern to pass in fw5098 *   @param[in] *result         - pt to bfa_diag_fwping_result_t data struct5099 *   @param[in] cbfn            - callback function5100 *   @param[in] *cbarg          - callback functioin arg5101 *5102 *   @param[out]5103 */5104bfa_status_t5105bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data,5106		struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn,5107		void *cbarg)5108{5109	bfa_trc(diag, cnt);5110	bfa_trc(diag, data);5111 5112	if (!bfa_ioc_is_operational(diag->ioc))5113		return BFA_STATUS_IOC_NON_OP;5114 5115	if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) &&5116	    ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH))5117		return BFA_STATUS_CMD_NOTSUPP;5118 5119	/* check to see if there is another destructive diag cmd running */5120	if (diag->block || diag->fwping.lock) {5121		bfa_trc(diag, diag->block);5122		bfa_trc(diag, diag->fwping.lock);5123		return BFA_STATUS_DEVBUSY;5124	}5125 5126	/* Initialization */5127	diag->fwping.lock = 1;5128	diag->fwping.cbfn = cbfn;5129	diag->fwping.cbarg = cbarg;5130	diag->fwping.result = result;5131	diag->fwping.data = data;5132	diag->fwping.count = cnt;5133 5134	/* Init test results */5135	diag->fwping.result->data = 0;5136	diag->fwping.result->status = BFA_STATUS_OK;5137 5138	/* kick off the first ping */5139	diag_fwping_send(diag);5140	return BFA_STATUS_OK;5141}5142 5143/*5144 * Read Temperature Sensor5145 *5146 *   @param[in] *diag           - diag data struct5147 *   @param[in] *result         - pt to bfa_diag_temp_t data struct5148 *   @param[in] cbfn            - callback function5149 *   @param[in] *cbarg          - callback functioin arg5150 *5151 *   @param[out]5152 */5153bfa_status_t5154bfa_diag_tsensor_query(struct bfa_diag_s *diag,5155		struct bfa_diag_results_tempsensor_s *result,5156		bfa_cb_diag_t cbfn, void *cbarg)5157{5158	/* check to see if there is a destructive diag cmd running */5159	if (diag->block || diag->tsensor.lock) {5160		bfa_trc(diag, diag->block);5161		bfa_trc(diag, diag->tsensor.lock);5162		return BFA_STATUS_DEVBUSY;5163	}5164 5165	if (!bfa_ioc_is_operational(diag->ioc))5166		return BFA_STATUS_IOC_NON_OP;5167 5168	/* Init diag mod params */5169	diag->tsensor.lock = 1;5170	diag->tsensor.temp = result;5171	diag->tsensor.cbfn = cbfn;5172	diag->tsensor.cbarg = cbarg;5173	diag->tsensor.status = BFA_STATUS_OK;5174 5175	/* Send msg to fw */5176	diag_tempsensor_send(diag);5177 5178	return BFA_STATUS_OK;5179}5180 5181/*5182 * LED Test command5183 *5184 *   @param[in] *diag           - diag data struct5185 *   @param[in] *ledtest        - pt to ledtest data structure5186 *5187 *   @param[out]5188 */5189bfa_status_t5190bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)5191{5192	bfa_trc(diag, ledtest->cmd);5193 5194	if (!bfa_ioc_is_operational(diag->ioc))5195		return BFA_STATUS_IOC_NON_OP;5196 5197	if (diag->beacon.state)5198		return BFA_STATUS_BEACON_ON;5199 5200	if (diag->ledtest.lock)5201		return BFA_STATUS_LEDTEST_OP;5202 5203	/* Send msg to fw */5204	diag->ledtest.lock = BFA_TRUE;5205	diag_ledtest_send(diag, ledtest);5206 5207	return BFA_STATUS_OK;5208}5209 5210/*5211 * Port beaconing command5212 *5213 *   @param[in] *diag           - diag data struct5214 *   @param[in] beacon          - port beaconing 1:ON   0:OFF5215 *   @param[in] link_e2e_beacon - link beaconing 1:ON   0:OFF5216 *   @param[in] sec             - beaconing duration in seconds5217 *5218 *   @param[out]5219 */5220bfa_status_t5221bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon,5222		bfa_boolean_t link_e2e_beacon, uint32_t sec)5223{5224	bfa_trc(diag, beacon);5225	bfa_trc(diag, link_e2e_beacon);5226	bfa_trc(diag, sec);5227 5228	if (!bfa_ioc_is_operational(diag->ioc))5229		return BFA_STATUS_IOC_NON_OP;5230 5231	if (diag->ledtest.lock)5232		return BFA_STATUS_LEDTEST_OP;5233 5234	if (diag->beacon.state && beacon)       /* beacon alread on */5235		return BFA_STATUS_BEACON_ON;5236 5237	diag->beacon.state	= beacon;5238	diag->beacon.link_e2e	= link_e2e_beacon;5239	if (diag->cbfn_beacon)5240		diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon);5241 5242	/* Send msg to fw */5243	diag_portbeacon_send(diag, beacon, sec);5244 5245	return BFA_STATUS_OK;5246}5247 5248/*5249 * Return DMA memory needed by diag module.5250 */5251u325252bfa_diag_meminfo(void)5253{5254	return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);5255}5256 5257/*5258 *	Attach virtual and physical memory for Diag.5259 */5260void5261bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,5262	bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod)5263{5264	diag->dev = dev;5265	diag->ioc = ioc;5266	diag->trcmod = trcmod;5267 5268	diag->block = 0;5269	diag->cbfn = NULL;5270	diag->cbarg = NULL;5271	diag->result = NULL;5272	diag->cbfn_beacon = cbfn_beacon;5273 5274	bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag);5275	bfa_q_qe_init(&diag->ioc_notify);5276	bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag);5277	list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q);5278}5279 5280void5281bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa)5282{5283	diag->fwping.dbuf_kva = dm_kva;5284	diag->fwping.dbuf_pa = dm_pa;5285	memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ);5286}5287 5288/*5289 *	PHY module specific5290 */5291#define BFA_PHY_DMA_BUF_SZ	0x02000         /* 8k dma buffer */5292#define BFA_PHY_LOCK_STATUS	0x018878        /* phy semaphore status reg */5293 5294static void5295bfa_phy_ntoh32(u32 *obuf, u32 *ibuf, int sz)5296{5297	int i, m = sz >> 2;5298 5299	for (i = 0; i < m; i++)5300		obuf[i] = be32_to_cpu(ibuf[i]);5301}5302 5303static bfa_boolean_t5304bfa_phy_present(struct bfa_phy_s *phy)5305{5306	return (phy->ioc->attr->card_type == BFA_MFG_TYPE_LIGHTNING);5307}5308 5309static void5310bfa_phy_notify(void *cbarg, enum bfa_ioc_event_e event)5311{5312	struct bfa_phy_s *phy = cbarg;5313 5314	bfa_trc(phy, event);5315 5316	switch (event) {5317	case BFA_IOC_E_DISABLED:5318	case BFA_IOC_E_FAILED:5319		if (phy->op_busy) {5320			phy->status = BFA_STATUS_IOC_FAILURE;5321			phy->cbfn(phy->cbarg, phy->status);5322			phy->op_busy = 0;5323		}5324		break;5325 5326	default:5327		break;5328	}5329}5330 5331/*5332 * Send phy attribute query request.5333 *5334 * @param[in] cbarg - callback argument5335 */5336static void5337bfa_phy_query_send(void *cbarg)5338{5339	struct bfa_phy_s *phy = cbarg;5340	struct bfi_phy_query_req_s *msg =5341			(struct bfi_phy_query_req_s *) phy->mb.msg;5342 5343	msg->instance = phy->instance;5344	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_QUERY_REQ,5345		bfa_ioc_portid(phy->ioc));5346	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_attr_s), phy->dbuf_pa);5347	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);5348}5349 5350/*5351 * Send phy write request.5352 *5353 * @param[in] cbarg - callback argument5354 */5355static void5356bfa_phy_write_send(void *cbarg)5357{5358	struct bfa_phy_s *phy = cbarg;5359	struct bfi_phy_write_req_s *msg =5360			(struct bfi_phy_write_req_s *) phy->mb.msg;5361	u32	len;5362	u16	*buf, *dbuf;5363	int	i, sz;5364 5365	msg->instance = phy->instance;5366	msg->offset = cpu_to_be32(phy->addr_off + phy->offset);5367	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?5368			phy->residue : BFA_PHY_DMA_BUF_SZ;5369	msg->length = cpu_to_be32(len);5370 5371	/* indicate if it's the last msg of the whole write operation */5372	msg->last = (len == phy->residue) ? 1 : 0;5373 5374	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_WRITE_REQ,5375		bfa_ioc_portid(phy->ioc));5376	bfa_alen_set(&msg->alen, len, phy->dbuf_pa);5377 5378	buf = (u16 *) (phy->ubuf + phy->offset);5379	dbuf = (u16 *)phy->dbuf_kva;5380	sz = len >> 1;5381	for (i = 0; i < sz; i++)5382		buf[i] = cpu_to_be16(dbuf[i]);5383 5384	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);5385 5386	phy->residue -= len;5387	phy->offset += len;5388}5389 5390/*5391 * Send phy read request.5392 *5393 * @param[in] cbarg - callback argument5394 */5395static void5396bfa_phy_read_send(void *cbarg)5397{5398	struct bfa_phy_s *phy = cbarg;5399	struct bfi_phy_read_req_s *msg =5400			(struct bfi_phy_read_req_s *) phy->mb.msg;5401	u32	len;5402 5403	msg->instance = phy->instance;5404	msg->offset = cpu_to_be32(phy->addr_off + phy->offset);5405	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?5406			phy->residue : BFA_PHY_DMA_BUF_SZ;5407	msg->length = cpu_to_be32(len);5408	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_READ_REQ,5409		bfa_ioc_portid(phy->ioc));5410	bfa_alen_set(&msg->alen, len, phy->dbuf_pa);5411	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);5412}5413 5414/*5415 * Send phy stats request.5416 *5417 * @param[in] cbarg - callback argument5418 */5419static void5420bfa_phy_stats_send(void *cbarg)5421{5422	struct bfa_phy_s *phy = cbarg;5423	struct bfi_phy_stats_req_s *msg =5424			(struct bfi_phy_stats_req_s *) phy->mb.msg;5425 5426	msg->instance = phy->instance;5427	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_STATS_REQ,5428		bfa_ioc_portid(phy->ioc));5429	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_stats_s), phy->dbuf_pa);5430	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);5431}5432 5433/*5434 * Flash memory info API.5435 *5436 * @param[in] mincfg - minimal cfg variable5437 */5438u325439bfa_phy_meminfo(bfa_boolean_t mincfg)5440{5441	/* min driver doesn't need phy */5442	if (mincfg)5443		return 0;5444 5445	return BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);5446}5447 5448/*5449 * Flash attach API.5450 *5451 * @param[in] phy - phy structure5452 * @param[in] ioc  - ioc structure5453 * @param[in] dev  - device structure5454 * @param[in] trcmod - trace module5455 * @param[in] logmod - log module5456 */5457void5458bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, void *dev,5459		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)5460{5461	phy->ioc = ioc;5462	phy->trcmod = trcmod;5463	phy->cbfn = NULL;5464	phy->cbarg = NULL;5465	phy->op_busy = 0;5466 5467	bfa_ioc_mbox_regisr(phy->ioc, BFI_MC_PHY, bfa_phy_intr, phy);5468	bfa_q_qe_init(&phy->ioc_notify);5469	bfa_ioc_notify_init(&phy->ioc_notify, bfa_phy_notify, phy);5470	list_add_tail(&phy->ioc_notify.qe, &phy->ioc->notify_q);5471 5472	/* min driver doesn't need phy */5473	if (mincfg) {5474		phy->dbuf_kva = NULL;5475		phy->dbuf_pa = 0;5476	}5477}5478 5479/*5480 * Claim memory for phy5481 *5482 * @param[in] phy - phy structure5483 * @param[in] dm_kva - pointer to virtual memory address5484 * @param[in] dm_pa - physical memory address5485 * @param[in] mincfg - minimal cfg variable5486 */5487void5488bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa,5489		bfa_boolean_t mincfg)5490{5491	if (mincfg)5492		return;5493 5494	phy->dbuf_kva = dm_kva;5495	phy->dbuf_pa = dm_pa;5496	memset(phy->dbuf_kva, 0, BFA_PHY_DMA_BUF_SZ);5497	dm_kva += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);5498	dm_pa += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);5499}5500 5501bfa_boolean_t5502bfa_phy_busy(struct bfa_ioc_s *ioc)5503{5504	void __iomem	*rb;5505 5506	rb = bfa_ioc_bar0(ioc);5507	return readl(rb + BFA_PHY_LOCK_STATUS);5508}5509 5510/*5511 * Get phy attribute.5512 *5513 * @param[in] phy - phy structure5514 * @param[in] attr - phy attribute structure5515 * @param[in] cbfn - callback function5516 * @param[in] cbarg - callback argument5517 *5518 * Return status.5519 */5520bfa_status_t5521bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,5522		struct bfa_phy_attr_s *attr, bfa_cb_phy_t cbfn, void *cbarg)5523{5524	bfa_trc(phy, BFI_PHY_H2I_QUERY_REQ);5525	bfa_trc(phy, instance);5526 5527	if (!bfa_phy_present(phy))5528		return BFA_STATUS_PHY_NOT_PRESENT;5529 5530	if (!bfa_ioc_is_operational(phy->ioc))5531		return BFA_STATUS_IOC_NON_OP;5532 5533	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {5534		bfa_trc(phy, phy->op_busy);5535		return BFA_STATUS_DEVBUSY;5536	}5537 5538	phy->op_busy = 1;5539	phy->cbfn = cbfn;5540	phy->cbarg = cbarg;5541	phy->instance = instance;5542	phy->ubuf = (uint8_t *) attr;5543	bfa_phy_query_send(phy);5544 5545	return BFA_STATUS_OK;5546}5547 5548/*5549 * Get phy stats.5550 *5551 * @param[in] phy - phy structure5552 * @param[in] instance - phy image instance5553 * @param[in] stats - pointer to phy stats5554 * @param[in] cbfn - callback function5555 * @param[in] cbarg - callback argument5556 *5557 * Return status.5558 */5559bfa_status_t5560bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,5561		struct bfa_phy_stats_s *stats,5562		bfa_cb_phy_t cbfn, void *cbarg)5563{5564	bfa_trc(phy, BFI_PHY_H2I_STATS_REQ);5565	bfa_trc(phy, instance);5566 5567	if (!bfa_phy_present(phy))5568		return BFA_STATUS_PHY_NOT_PRESENT;5569 5570	if (!bfa_ioc_is_operational(phy->ioc))5571		return BFA_STATUS_IOC_NON_OP;5572 5573	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {5574		bfa_trc(phy, phy->op_busy);5575		return BFA_STATUS_DEVBUSY;5576	}5577 5578	phy->op_busy = 1;5579	phy->cbfn = cbfn;5580	phy->cbarg = cbarg;5581	phy->instance = instance;5582	phy->ubuf = (u8 *) stats;5583	bfa_phy_stats_send(phy);5584 5585	return BFA_STATUS_OK;5586}5587 5588/*5589 * Update phy image.5590 *5591 * @param[in] phy - phy structure5592 * @param[in] instance - phy image instance5593 * @param[in] buf - update data buffer5594 * @param[in] len - data buffer length5595 * @param[in] offset - offset relative to starting address5596 * @param[in] cbfn - callback function5597 * @param[in] cbarg - callback argument5598 *5599 * Return status.5600 */5601bfa_status_t5602bfa_phy_update(struct bfa_phy_s *phy, u8 instance,5603		void *buf, u32 len, u32 offset,5604		bfa_cb_phy_t cbfn, void *cbarg)5605{5606	bfa_trc(phy, BFI_PHY_H2I_WRITE_REQ);5607	bfa_trc(phy, instance);5608	bfa_trc(phy, len);5609	bfa_trc(phy, offset);5610 5611	if (!bfa_phy_present(phy))5612		return BFA_STATUS_PHY_NOT_PRESENT;5613 5614	if (!bfa_ioc_is_operational(phy->ioc))5615		return BFA_STATUS_IOC_NON_OP;5616 5617	/* 'len' must be in word (4-byte) boundary */5618	if (!len || (len & 0x03))5619		return BFA_STATUS_FAILED;5620 5621	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {5622		bfa_trc(phy, phy->op_busy);5623		return BFA_STATUS_DEVBUSY;5624	}5625 5626	phy->op_busy = 1;5627	phy->cbfn = cbfn;5628	phy->cbarg = cbarg;5629	phy->instance = instance;5630	phy->residue = len;5631	phy->offset = 0;5632	phy->addr_off = offset;5633	phy->ubuf = buf;5634 5635	bfa_phy_write_send(phy);5636	return BFA_STATUS_OK;5637}5638 5639/*5640 * Read phy image.5641 *5642 * @param[in] phy - phy structure5643 * @param[in] instance - phy image instance5644 * @param[in] buf - read data buffer5645 * @param[in] len - data buffer length5646 * @param[in] offset - offset relative to starting address5647 * @param[in] cbfn - callback function5648 * @param[in] cbarg - callback argument5649 *5650 * Return status.5651 */5652bfa_status_t5653bfa_phy_read(struct bfa_phy_s *phy, u8 instance,5654		void *buf, u32 len, u32 offset,5655		bfa_cb_phy_t cbfn, void *cbarg)5656{5657	bfa_trc(phy, BFI_PHY_H2I_READ_REQ);5658	bfa_trc(phy, instance);5659	bfa_trc(phy, len);5660	bfa_trc(phy, offset);5661 5662	if (!bfa_phy_present(phy))5663		return BFA_STATUS_PHY_NOT_PRESENT;5664 5665	if (!bfa_ioc_is_operational(phy->ioc))5666		return BFA_STATUS_IOC_NON_OP;5667 5668	/* 'len' must be in word (4-byte) boundary */5669	if (!len || (len & 0x03))5670		return BFA_STATUS_FAILED;5671 5672	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {5673		bfa_trc(phy, phy->op_busy);5674		return BFA_STATUS_DEVBUSY;5675	}5676 5677	phy->op_busy = 1;5678	phy->cbfn = cbfn;5679	phy->cbarg = cbarg;5680	phy->instance = instance;5681	phy->residue = len;5682	phy->offset = 0;5683	phy->addr_off = offset;5684	phy->ubuf = buf;5685	bfa_phy_read_send(phy);5686 5687	return BFA_STATUS_OK;5688}5689 5690/*5691 * Process phy response messages upon receiving interrupts.5692 *5693 * @param[in] phyarg - phy structure5694 * @param[in] msg - message structure5695 */5696void5697bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)5698{5699	struct bfa_phy_s *phy = phyarg;5700	u32	status;5701 5702	union {5703		struct bfi_phy_query_rsp_s *query;5704		struct bfi_phy_stats_rsp_s *stats;5705		struct bfi_phy_write_rsp_s *write;5706		struct bfi_phy_read_rsp_s *read;5707		struct bfi_mbmsg_s   *msg;5708	} m;5709 5710	m.msg = msg;5711	bfa_trc(phy, msg->mh.msg_id);5712 5713	if (!phy->op_busy) {5714		/* receiving response after ioc failure */5715		bfa_trc(phy, 0x9999);5716		return;5717	}5718 5719	switch (msg->mh.msg_id) {5720	case BFI_PHY_I2H_QUERY_RSP:5721		status = be32_to_cpu(m.query->status);5722		bfa_trc(phy, status);5723 5724		if (status == BFA_STATUS_OK) {5725			struct bfa_phy_attr_s *attr =5726				(struct bfa_phy_attr_s *) phy->ubuf;5727			bfa_phy_ntoh32((u32 *)attr, (u32 *)phy->dbuf_kva,5728					sizeof(struct bfa_phy_attr_s));5729			bfa_trc(phy, attr->status);5730			bfa_trc(phy, attr->length);5731		}5732 5733		phy->status = status;5734		phy->op_busy = 0;5735		if (phy->cbfn)5736			phy->cbfn(phy->cbarg, phy->status);5737		break;5738	case BFI_PHY_I2H_STATS_RSP:5739		status = be32_to_cpu(m.stats->status);5740		bfa_trc(phy, status);5741 5742		if (status == BFA_STATUS_OK) {5743			struct bfa_phy_stats_s *stats =5744				(struct bfa_phy_stats_s *) phy->ubuf;5745			bfa_phy_ntoh32((u32 *)stats, (u32 *)phy->dbuf_kva,5746				sizeof(struct bfa_phy_stats_s));5747			bfa_trc(phy, stats->status);5748		}5749 5750		phy->status = status;5751		phy->op_busy = 0;5752		if (phy->cbfn)5753			phy->cbfn(phy->cbarg, phy->status);5754		break;5755	case BFI_PHY_I2H_WRITE_RSP:5756		status = be32_to_cpu(m.write->status);5757		bfa_trc(phy, status);5758 5759		if (status != BFA_STATUS_OK || phy->residue == 0) {5760			phy->status = status;5761			phy->op_busy = 0;5762			if (phy->cbfn)5763				phy->cbfn(phy->cbarg, phy->status);5764		} else {5765			bfa_trc(phy, phy->offset);5766			bfa_phy_write_send(phy);5767		}5768		break;5769	case BFI_PHY_I2H_READ_RSP:5770		status = be32_to_cpu(m.read->status);5771		bfa_trc(phy, status);5772 5773		if (status != BFA_STATUS_OK) {5774			phy->status = status;5775			phy->op_busy = 0;5776			if (phy->cbfn)5777				phy->cbfn(phy->cbarg, phy->status);5778		} else {5779			u32 len = be32_to_cpu(m.read->length);5780			u16 *buf = (u16 *)(phy->ubuf + phy->offset);5781			u16 *dbuf = (u16 *)phy->dbuf_kva;5782			int i, sz = len >> 1;5783 5784			bfa_trc(phy, phy->offset);5785			bfa_trc(phy, len);5786 5787			for (i = 0; i < sz; i++)5788				buf[i] = be16_to_cpu(dbuf[i]);5789 5790			phy->residue -= len;5791			phy->offset += len;5792 5793			if (phy->residue == 0) {5794				phy->status = status;5795				phy->op_busy = 0;5796				if (phy->cbfn)5797					phy->cbfn(phy->cbarg, phy->status);5798			} else5799				bfa_phy_read_send(phy);5800		}5801		break;5802	default:5803		WARN_ON(1);5804	}5805}5806 5807/* forward declaration of DCONF state machine */5808static void bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf,5809				enum bfa_dconf_event event);5810static void bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,5811				enum bfa_dconf_event event);5812static void bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf,5813				enum bfa_dconf_event event);5814static void bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf,5815				enum bfa_dconf_event event);5816static void bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf,5817				enum bfa_dconf_event event);5818static void bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,5819				enum bfa_dconf_event event);5820static void bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,5821				enum bfa_dconf_event event);5822 5823static void bfa_dconf_cbfn(void *dconf, bfa_status_t status);5824static void bfa_dconf_timer(void *cbarg);5825static bfa_status_t bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf);5826static void bfa_dconf_init_cb(void *arg, bfa_status_t status);5827 5828/*5829 * Beginning state of dconf module. Waiting for an event to start.5830 */5831static void5832bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)5833{5834	bfa_status_t bfa_status;5835	bfa_trc(dconf->bfa, event);5836 5837	switch (event) {5838	case BFA_DCONF_SM_INIT:5839		if (dconf->min_cfg) {5840			bfa_trc(dconf->bfa, dconf->min_cfg);5841			bfa_fsm_send_event(&dconf->bfa->iocfc,5842					IOCFC_E_DCONF_DONE);5843			return;5844		}5845		bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);5846		bfa_timer_start(dconf->bfa, &dconf->timer,5847			bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV);5848		bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),5849					BFA_FLASH_PART_DRV, dconf->instance,5850					dconf->dconf,5851					sizeof(struct bfa_dconf_s), 0,5852					bfa_dconf_init_cb, dconf->bfa);5853		if (bfa_status != BFA_STATUS_OK) {5854			bfa_timer_stop(&dconf->timer);5855			bfa_dconf_init_cb(dconf->bfa, BFA_STATUS_FAILED);5856			bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);5857			return;5858		}5859		break;5860	case BFA_DCONF_SM_EXIT:5861		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);5862		break;5863	case BFA_DCONF_SM_IOCDISABLE:5864	case BFA_DCONF_SM_WR:5865	case BFA_DCONF_SM_FLASH_COMP:5866		break;5867	default:5868		bfa_sm_fault(dconf->bfa, event);5869	}5870}5871 5872/*5873 * Read flash for dconf entries and make a call back to the driver once done.5874 */5875static void5876bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,5877			enum bfa_dconf_event event)5878{5879	bfa_trc(dconf->bfa, event);5880 5881	switch (event) {5882	case BFA_DCONF_SM_FLASH_COMP:5883		bfa_timer_stop(&dconf->timer);5884		bfa_sm_set_state(dconf, bfa_dconf_sm_ready);5885		break;5886	case BFA_DCONF_SM_TIMEOUT:5887		bfa_sm_set_state(dconf, bfa_dconf_sm_ready);5888		bfa_ioc_suspend(&dconf->bfa->ioc);5889		break;5890	case BFA_DCONF_SM_EXIT:5891		bfa_timer_stop(&dconf->timer);5892		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);5893		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);5894		break;5895	case BFA_DCONF_SM_IOCDISABLE:5896		bfa_timer_stop(&dconf->timer);5897		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);5898		break;5899	default:5900		bfa_sm_fault(dconf->bfa, event);5901	}5902}5903 5904/*5905 * DCONF Module is in ready state. Has completed the initialization.5906 */5907static void5908bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)5909{5910	bfa_trc(dconf->bfa, event);5911 5912	switch (event) {5913	case BFA_DCONF_SM_WR:5914		bfa_timer_start(dconf->bfa, &dconf->timer,5915			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);5916		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);5917		break;5918	case BFA_DCONF_SM_EXIT:5919		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);5920		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);5921		break;5922	case BFA_DCONF_SM_INIT:5923	case BFA_DCONF_SM_IOCDISABLE:5924		break;5925	default:5926		bfa_sm_fault(dconf->bfa, event);5927	}5928}5929 5930/*5931 * entries are dirty, write back to the flash.5932 */5933 5934static void5935bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)5936{5937	bfa_trc(dconf->bfa, event);5938 5939	switch (event) {5940	case BFA_DCONF_SM_TIMEOUT:5941		bfa_sm_set_state(dconf, bfa_dconf_sm_sync);5942		bfa_dconf_flash_write(dconf);5943		break;5944	case BFA_DCONF_SM_WR:5945		bfa_timer_stop(&dconf->timer);5946		bfa_timer_start(dconf->bfa, &dconf->timer,5947			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);5948		break;5949	case BFA_DCONF_SM_EXIT:5950		bfa_timer_stop(&dconf->timer);5951		bfa_timer_start(dconf->bfa, &dconf->timer,5952			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);5953		bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);5954		bfa_dconf_flash_write(dconf);5955		break;5956	case BFA_DCONF_SM_FLASH_COMP:5957		break;5958	case BFA_DCONF_SM_IOCDISABLE:5959		bfa_timer_stop(&dconf->timer);5960		bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);5961		break;5962	default:5963		bfa_sm_fault(dconf->bfa, event);5964	}5965}5966 5967/*5968 * Sync the dconf entries to the flash.5969 */5970static void5971bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,5972			enum bfa_dconf_event event)5973{5974	bfa_trc(dconf->bfa, event);5975 5976	switch (event) {5977	case BFA_DCONF_SM_IOCDISABLE:5978	case BFA_DCONF_SM_FLASH_COMP:5979		bfa_timer_stop(&dconf->timer);5980		fallthrough;5981	case BFA_DCONF_SM_TIMEOUT:5982		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);5983		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);5984		break;5985	default:5986		bfa_sm_fault(dconf->bfa, event);5987	}5988}5989 5990static void5991bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)5992{5993	bfa_trc(dconf->bfa, event);5994 5995	switch (event) {5996	case BFA_DCONF_SM_FLASH_COMP:5997		bfa_sm_set_state(dconf, bfa_dconf_sm_ready);5998		break;5999	case BFA_DCONF_SM_WR:6000		bfa_timer_start(dconf->bfa, &dconf->timer,6001			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);6002		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);6003		break;6004	case BFA_DCONF_SM_EXIT:6005		bfa_timer_start(dconf->bfa, &dconf->timer,6006			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);6007		bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);6008		break;6009	case BFA_DCONF_SM_IOCDISABLE:6010		bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);6011		break;6012	default:6013		bfa_sm_fault(dconf->bfa, event);6014	}6015}6016 6017static void6018bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,6019			enum bfa_dconf_event event)6020{6021	bfa_trc(dconf->bfa, event);6022 6023	switch (event) {6024	case BFA_DCONF_SM_INIT:6025		bfa_timer_start(dconf->bfa, &dconf->timer,6026			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);6027		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);6028		break;6029	case BFA_DCONF_SM_EXIT:6030		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);6031		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);6032		break;6033	case BFA_DCONF_SM_IOCDISABLE:6034		break;6035	default:6036		bfa_sm_fault(dconf->bfa, event);6037	}6038}6039 6040/*6041 * Compute and return memory needed by DRV_CFG module.6042 */6043void6044bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,6045		  struct bfa_s *bfa)6046{6047	struct bfa_mem_kva_s *dconf_kva = BFA_MEM_DCONF_KVA(bfa);6048 6049	if (cfg->drvcfg.min_cfg)6050		bfa_mem_kva_setup(meminfo, dconf_kva,6051				sizeof(struct bfa_dconf_hdr_s));6052	else6053		bfa_mem_kva_setup(meminfo, dconf_kva,6054				sizeof(struct bfa_dconf_s));6055}6056 6057void6058bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg)6059{6060	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);6061 6062	dconf->bfad = bfad;6063	dconf->bfa = bfa;6064	dconf->instance = bfa->ioc.port_id;6065	bfa_trc(bfa, dconf->instance);6066 6067	dconf->dconf = (struct bfa_dconf_s *) bfa_mem_kva_curp(dconf);6068	if (cfg->drvcfg.min_cfg) {6069		bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_hdr_s);6070		dconf->min_cfg = BFA_TRUE;6071	} else {6072		dconf->min_cfg = BFA_FALSE;6073		bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_s);6074	}6075 6076	bfa_dconf_read_data_valid(bfa) = BFA_FALSE;6077	bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);6078}6079 6080static void6081bfa_dconf_init_cb(void *arg, bfa_status_t status)6082{6083	struct bfa_s *bfa = arg;6084	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);6085 6086	if (status == BFA_STATUS_OK) {6087		bfa_dconf_read_data_valid(bfa) = BFA_TRUE;6088		if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)6089			dconf->dconf->hdr.signature = BFI_DCONF_SIGNATURE;6090		if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)6091			dconf->dconf->hdr.version = BFI_DCONF_VERSION;6092	}6093	bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);6094	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE);6095}6096 6097void6098bfa_dconf_modinit(struct bfa_s *bfa)6099{6100	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);6101	bfa_sm_send_event(dconf, BFA_DCONF_SM_INIT);6102}6103 6104static void bfa_dconf_timer(void *cbarg)6105{6106	struct bfa_dconf_mod_s *dconf = cbarg;6107	bfa_sm_send_event(dconf, BFA_DCONF_SM_TIMEOUT);6108}6109 6110void6111bfa_dconf_iocdisable(struct bfa_s *bfa)6112{6113	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);6114	bfa_sm_send_event(dconf, BFA_DCONF_SM_IOCDISABLE);6115}6116 6117static bfa_status_t6118bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf)6119{6120	bfa_status_t bfa_status;6121	bfa_trc(dconf->bfa, 0);6122 6123	bfa_status = bfa_flash_update_part(BFA_FLASH(dconf->bfa),6124				BFA_FLASH_PART_DRV, dconf->instance,6125				dconf->dconf,  sizeof(struct bfa_dconf_s), 0,6126				bfa_dconf_cbfn, dconf);6127	if (bfa_status != BFA_STATUS_OK)6128		WARN_ON(bfa_status);6129	bfa_trc(dconf->bfa, bfa_status);6130 6131	return bfa_status;6132}6133 6134bfa_status_t6135bfa_dconf_update(struct bfa_s *bfa)6136{6137	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);6138	bfa_trc(dconf->bfa, 0);6139	if (bfa_sm_cmp_state(dconf, bfa_dconf_sm_iocdown_dirty))6140		return BFA_STATUS_FAILED;6141 6142	if (dconf->min_cfg) {6143		bfa_trc(dconf->bfa, dconf->min_cfg);6144		return BFA_STATUS_FAILED;6145	}6146 6147	bfa_sm_send_event(dconf, BFA_DCONF_SM_WR);6148	return BFA_STATUS_OK;6149}6150 6151static void6152bfa_dconf_cbfn(void *arg, bfa_status_t status)6153{6154	struct bfa_dconf_mod_s *dconf = arg;6155	WARN_ON(status);6156	bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);6157}6158 6159void6160bfa_dconf_modexit(struct bfa_s *bfa)6161{6162	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);6163	bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);6164}6165 6166/*6167 * FRU specific functions6168 */6169 6170#define BFA_FRU_DMA_BUF_SZ	0x02000		/* 8k dma buffer */6171#define BFA_FRU_CHINOOK_MAX_SIZE 0x100006172#define BFA_FRU_LIGHTNING_MAX_SIZE 0x2006173 6174static void6175bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event)6176{6177	struct bfa_fru_s *fru = cbarg;6178 6179	bfa_trc(fru, event);6180 6181	switch (event) {6182	case BFA_IOC_E_DISABLED:6183	case BFA_IOC_E_FAILED:6184		if (fru->op_busy) {6185			fru->status = BFA_STATUS_IOC_FAILURE;6186			fru->cbfn(fru->cbarg, fru->status);6187			fru->op_busy = 0;6188		}6189		break;6190 6191	default:6192		break;6193	}6194}6195 6196/*6197 * Send fru write request.6198 *6199 * @param[in] cbarg - callback argument6200 */6201static void6202bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)6203{6204	struct bfa_fru_s *fru = cbarg;6205	struct bfi_fru_write_req_s *msg =6206			(struct bfi_fru_write_req_s *) fru->mb.msg;6207	u32 len;6208 6209	msg->offset = cpu_to_be32(fru->addr_off + fru->offset);6210	len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?6211				fru->residue : BFA_FRU_DMA_BUF_SZ;6212	msg->length = cpu_to_be32(len);6213 6214	/*6215	 * indicate if it's the last msg of the whole write operation6216	 */6217	msg->last = (len == fru->residue) ? 1 : 0;6218 6219	msg->trfr_cmpl = (len == fru->residue) ? fru->trfr_cmpl : 0;6220	bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));6221	bfa_alen_set(&msg->alen, len, fru->dbuf_pa);6222 6223	memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len);6224	bfa_ioc_mbox_queue(fru->ioc, &fru->mb);6225 6226	fru->residue -= len;6227	fru->offset += len;6228}6229 6230/*6231 * Send fru read request.6232 *6233 * @param[in] cbarg - callback argument6234 */6235static void6236bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)6237{6238	struct bfa_fru_s *fru = cbarg;6239	struct bfi_fru_read_req_s *msg =6240			(struct bfi_fru_read_req_s *) fru->mb.msg;6241	u32 len;6242 6243	msg->offset = cpu_to_be32(fru->addr_off + fru->offset);6244	len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?6245				fru->residue : BFA_FRU_DMA_BUF_SZ;6246	msg->length = cpu_to_be32(len);6247	bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));6248	bfa_alen_set(&msg->alen, len, fru->dbuf_pa);6249	bfa_ioc_mbox_queue(fru->ioc, &fru->mb);6250}6251 6252/*6253 * Flash memory info API.6254 *6255 * @param[in] mincfg - minimal cfg variable6256 */6257u326258bfa_fru_meminfo(bfa_boolean_t mincfg)6259{6260	/* min driver doesn't need fru */6261	if (mincfg)6262		return 0;6263 6264	return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);6265}6266 6267/*6268 * Flash attach API.6269 *6270 * @param[in] fru - fru structure6271 * @param[in] ioc  - ioc structure6272 * @param[in] dev  - device structure6273 * @param[in] trcmod - trace module6274 * @param[in] logmod - log module6275 */6276void6277bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev,6278	struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)6279{6280	fru->ioc = ioc;6281	fru->trcmod = trcmod;6282	fru->cbfn = NULL;6283	fru->cbarg = NULL;6284	fru->op_busy = 0;6285 6286	bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru);6287	bfa_q_qe_init(&fru->ioc_notify);6288	bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru);6289	list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q);6290 6291	/* min driver doesn't need fru */6292	if (mincfg) {6293		fru->dbuf_kva = NULL;6294		fru->dbuf_pa = 0;6295	}6296}6297 6298/*6299 * Claim memory for fru6300 *6301 * @param[in] fru - fru structure6302 * @param[in] dm_kva - pointer to virtual memory address6303 * @param[in] dm_pa - frusical memory address6304 * @param[in] mincfg - minimal cfg variable6305 */6306void6307bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,6308	bfa_boolean_t mincfg)6309{6310	if (mincfg)6311		return;6312 6313	fru->dbuf_kva = dm_kva;6314	fru->dbuf_pa = dm_pa;6315	memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ);6316	dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);6317	dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);6318}6319 6320/*6321 * Update fru vpd image.6322 *6323 * @param[in] fru - fru structure6324 * @param[in] buf - update data buffer6325 * @param[in] len - data buffer length6326 * @param[in] offset - offset relative to starting address6327 * @param[in] cbfn - callback function6328 * @param[in] cbarg - callback argument6329 *6330 * Return status.6331 */6332bfa_status_t6333bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,6334		  bfa_cb_fru_t cbfn, void *cbarg, u8 trfr_cmpl)6335{6336	bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);6337	bfa_trc(fru, len);6338	bfa_trc(fru, offset);6339 6340	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2 &&6341		fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2)6342		return BFA_STATUS_FRU_NOT_PRESENT;6343 6344	if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)6345		return BFA_STATUS_CMD_NOTSUPP;6346 6347	if (!bfa_ioc_is_operational(fru->ioc))6348		return BFA_STATUS_IOC_NON_OP;6349 6350	if (fru->op_busy) {6351		bfa_trc(fru, fru->op_busy);6352		return BFA_STATUS_DEVBUSY;6353	}6354 6355	fru->op_busy = 1;6356 6357	fru->cbfn = cbfn;6358	fru->cbarg = cbarg;6359	fru->residue = len;6360	fru->offset = 0;6361	fru->addr_off = offset;6362	fru->ubuf = buf;6363	fru->trfr_cmpl = trfr_cmpl;6364 6365	bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);6366 6367	return BFA_STATUS_OK;6368}6369 6370/*6371 * Read fru vpd image.6372 *6373 * @param[in] fru - fru structure6374 * @param[in] buf - read data buffer6375 * @param[in] len - data buffer length6376 * @param[in] offset - offset relative to starting address6377 * @param[in] cbfn - callback function6378 * @param[in] cbarg - callback argument6379 *6380 * Return status.6381 */6382bfa_status_t6383bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,6384		bfa_cb_fru_t cbfn, void *cbarg)6385{6386	bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ);6387	bfa_trc(fru, len);6388	bfa_trc(fru, offset);6389 6390	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)6391		return BFA_STATUS_FRU_NOT_PRESENT;6392 6393	if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK &&6394		fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK2)6395		return BFA_STATUS_CMD_NOTSUPP;6396 6397	if (!bfa_ioc_is_operational(fru->ioc))6398		return BFA_STATUS_IOC_NON_OP;6399 6400	if (fru->op_busy) {6401		bfa_trc(fru, fru->op_busy);6402		return BFA_STATUS_DEVBUSY;6403	}6404 6405	fru->op_busy = 1;6406 6407	fru->cbfn = cbfn;6408	fru->cbarg = cbarg;6409	fru->residue = len;6410	fru->offset = 0;6411	fru->addr_off = offset;6412	fru->ubuf = buf;6413	bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ);6414 6415	return BFA_STATUS_OK;6416}6417 6418/*6419 * Get maximum size fru vpd image.6420 *6421 * @param[in] fru - fru structure6422 * @param[out] size - maximum size of fru vpd data6423 *6424 * Return status.6425 */6426bfa_status_t6427bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)6428{6429	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)6430		return BFA_STATUS_FRU_NOT_PRESENT;6431 6432	if (!bfa_ioc_is_operational(fru->ioc))6433		return BFA_STATUS_IOC_NON_OP;6434 6435	if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK ||6436		fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK2)6437		*max_size = BFA_FRU_CHINOOK_MAX_SIZE;6438	else6439		return BFA_STATUS_CMD_NOTSUPP;6440	return BFA_STATUS_OK;6441}6442/*6443 * tfru write.6444 *6445 * @param[in] fru - fru structure6446 * @param[in] buf - update data buffer6447 * @param[in] len - data buffer length6448 * @param[in] offset - offset relative to starting address6449 * @param[in] cbfn - callback function6450 * @param[in] cbarg - callback argument6451 *6452 * Return status.6453 */6454bfa_status_t6455bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,6456	       bfa_cb_fru_t cbfn, void *cbarg)6457{6458	bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ);6459	bfa_trc(fru, len);6460	bfa_trc(fru, offset);6461	bfa_trc(fru, *((u8 *) buf));6462 6463	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)6464		return BFA_STATUS_FRU_NOT_PRESENT;6465 6466	if (!bfa_ioc_is_operational(fru->ioc))6467		return BFA_STATUS_IOC_NON_OP;6468 6469	if (fru->op_busy) {6470		bfa_trc(fru, fru->op_busy);6471		return BFA_STATUS_DEVBUSY;6472	}6473 6474	fru->op_busy = 1;6475 6476	fru->cbfn = cbfn;6477	fru->cbarg = cbarg;6478	fru->residue = len;6479	fru->offset = 0;6480	fru->addr_off = offset;6481	fru->ubuf = buf;6482 6483	bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ);6484 6485	return BFA_STATUS_OK;6486}6487 6488/*6489 * tfru read.6490 *6491 * @param[in] fru - fru structure6492 * @param[in] buf - read data buffer6493 * @param[in] len - data buffer length6494 * @param[in] offset - offset relative to starting address6495 * @param[in] cbfn - callback function6496 * @param[in] cbarg - callback argument6497 *6498 * Return status.6499 */6500bfa_status_t6501bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,6502	      bfa_cb_fru_t cbfn, void *cbarg)6503{6504	bfa_trc(fru, BFI_TFRU_H2I_READ_REQ);6505	bfa_trc(fru, len);6506	bfa_trc(fru, offset);6507 6508	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)6509		return BFA_STATUS_FRU_NOT_PRESENT;6510 6511	if (!bfa_ioc_is_operational(fru->ioc))6512		return BFA_STATUS_IOC_NON_OP;6513 6514	if (fru->op_busy) {6515		bfa_trc(fru, fru->op_busy);6516		return BFA_STATUS_DEVBUSY;6517	}6518 6519	fru->op_busy = 1;6520 6521	fru->cbfn = cbfn;6522	fru->cbarg = cbarg;6523	fru->residue = len;6524	fru->offset = 0;6525	fru->addr_off = offset;6526	fru->ubuf = buf;6527	bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ);6528 6529	return BFA_STATUS_OK;6530}6531 6532/*6533 * Process fru response messages upon receiving interrupts.6534 *6535 * @param[in] fruarg - fru structure6536 * @param[in] msg - message structure6537 */6538void6539bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)6540{6541	struct bfa_fru_s *fru = fruarg;6542	struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg;6543	u32 status;6544 6545	bfa_trc(fru, msg->mh.msg_id);6546 6547	if (!fru->op_busy) {6548		/*6549		 * receiving response after ioc failure6550		 */6551		bfa_trc(fru, 0x9999);6552		return;6553	}6554 6555	switch (msg->mh.msg_id) {6556	case BFI_FRUVPD_I2H_WRITE_RSP:6557	case BFI_TFRU_I2H_WRITE_RSP:6558		status = be32_to_cpu(rsp->status);6559		bfa_trc(fru, status);6560 6561		if (status != BFA_STATUS_OK || fru->residue == 0) {6562			fru->status = status;6563			fru->op_busy = 0;6564			if (fru->cbfn)6565				fru->cbfn(fru->cbarg, fru->status);6566		} else {6567			bfa_trc(fru, fru->offset);6568			if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP)6569				bfa_fru_write_send(fru,6570					BFI_FRUVPD_H2I_WRITE_REQ);6571			else6572				bfa_fru_write_send(fru,6573					BFI_TFRU_H2I_WRITE_REQ);6574		}6575		break;6576	case BFI_FRUVPD_I2H_READ_RSP:6577	case BFI_TFRU_I2H_READ_RSP:6578		status = be32_to_cpu(rsp->status);6579		bfa_trc(fru, status);6580 6581		if (status != BFA_STATUS_OK) {6582			fru->status = status;6583			fru->op_busy = 0;6584			if (fru->cbfn)6585				fru->cbfn(fru->cbarg, fru->status);6586		} else {6587			u32 len = be32_to_cpu(rsp->length);6588 6589			bfa_trc(fru, fru->offset);6590			bfa_trc(fru, len);6591 6592			memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len);6593			fru->residue -= len;6594			fru->offset += len;6595 6596			if (fru->residue == 0) {6597				fru->status = status;6598				fru->op_busy = 0;6599				if (fru->cbfn)6600					fru->cbfn(fru->cbarg, fru->status);6601			} else {6602				if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP)6603					bfa_fru_read_send(fru,6604						BFI_FRUVPD_H2I_READ_REQ);6605				else6606					bfa_fru_read_send(fru,6607						BFI_TFRU_H2I_READ_REQ);6608			}6609		}6610		break;6611	default:6612		WARN_ON(1);6613	}6614}6615 6616/*6617 * register definitions6618 */6619#define FLI_CMD_REG			0x0001d0006620#define FLI_RDDATA_REG			0x0001d0106621#define FLI_ADDR_REG			0x0001d0046622#define FLI_DEV_STATUS_REG		0x0001d0146623 6624#define BFA_FLASH_FIFO_SIZE		128	/* fifo size */6625#define BFA_FLASH_CHECK_MAX		10000	/* max # of status check */6626#define BFA_FLASH_BLOCKING_OP_MAX	1000000	/* max # of blocking op check */6627#define BFA_FLASH_WIP_MASK		0x01	/* write in progress bit mask */6628 6629enum bfa_flash_cmd {6630	BFA_FLASH_FAST_READ	= 0x0b,	/* fast read */6631	BFA_FLASH_READ_STATUS	= 0x05,	/* read status */6632};6633 6634/*6635 * Hardware error definition6636 */6637enum bfa_flash_err {6638	BFA_FLASH_NOT_PRESENT	= -1,	/*!< flash not present */6639	BFA_FLASH_UNINIT	= -2,	/*!< flash not initialized */6640	BFA_FLASH_BAD		= -3,	/*!< flash bad */6641	BFA_FLASH_BUSY		= -4,	/*!< flash busy */6642	BFA_FLASH_ERR_CMD_ACT	= -5,	/*!< command active never cleared */6643	BFA_FLASH_ERR_FIFO_CNT	= -6,	/*!< fifo count never cleared */6644	BFA_FLASH_ERR_WIP	= -7,	/*!< write-in-progress never cleared */6645	BFA_FLASH_ERR_TIMEOUT	= -8,	/*!< fli timeout */6646	BFA_FLASH_ERR_LEN	= -9,	/*!< invalid length */6647};6648 6649/*6650 * Flash command register data structure6651 */6652union bfa_flash_cmd_reg_u {6653	struct {6654#ifdef __BIG_ENDIAN6655		u32	act:1;6656		u32	rsv:1;6657		u32	write_cnt:9;6658		u32	read_cnt:9;6659		u32	addr_cnt:4;6660		u32	cmd:8;6661#else6662		u32	cmd:8;6663		u32	addr_cnt:4;6664		u32	read_cnt:9;6665		u32	write_cnt:9;6666		u32	rsv:1;6667		u32	act:1;6668#endif6669	} r;6670	u32	i;6671};6672 6673/*6674 * Flash device status register data structure6675 */6676union bfa_flash_dev_status_reg_u {6677	struct {6678#ifdef __BIG_ENDIAN6679		u32	rsv:21;6680		u32	fifo_cnt:6;6681		u32	busy:1;6682		u32	init_status:1;6683		u32	present:1;6684		u32	bad:1;6685		u32	good:1;6686#else6687		u32	good:1;6688		u32	bad:1;6689		u32	present:1;6690		u32	init_status:1;6691		u32	busy:1;6692		u32	fifo_cnt:6;6693		u32	rsv:21;6694#endif6695	} r;6696	u32	i;6697};6698 6699/*6700 * Flash address register data structure6701 */6702union bfa_flash_addr_reg_u {6703	struct {6704#ifdef __BIG_ENDIAN6705		u32	addr:24;6706		u32	dummy:8;6707#else6708		u32	dummy:8;6709		u32	addr:24;6710#endif6711	} r;6712	u32	i;6713};6714 6715/*6716 * dg flash_raw_private Flash raw private functions6717 */6718static void6719bfa_flash_set_cmd(void __iomem *pci_bar, u8 wr_cnt,6720		  u8 rd_cnt, u8 ad_cnt, u8 op)6721{6722	union bfa_flash_cmd_reg_u cmd;6723 6724	cmd.i = 0;6725	cmd.r.act = 1;6726	cmd.r.write_cnt = wr_cnt;6727	cmd.r.read_cnt = rd_cnt;6728	cmd.r.addr_cnt = ad_cnt;6729	cmd.r.cmd = op;6730	writel(cmd.i, (pci_bar + FLI_CMD_REG));6731}6732 6733static void6734bfa_flash_set_addr(void __iomem *pci_bar, u32 address)6735{6736	union bfa_flash_addr_reg_u addr;6737 6738	addr.r.addr = address & 0x00ffffff;6739	addr.r.dummy = 0;6740	writel(addr.i, (pci_bar + FLI_ADDR_REG));6741}6742 6743static int6744bfa_flash_cmd_act_check(void __iomem *pci_bar)6745{6746	union bfa_flash_cmd_reg_u cmd;6747 6748	cmd.i = readl(pci_bar + FLI_CMD_REG);6749 6750	if (cmd.r.act)6751		return BFA_FLASH_ERR_CMD_ACT;6752 6753	return 0;6754}6755 6756/*6757 * @brief6758 * Flush FLI data fifo.6759 *6760 * @param[in] pci_bar - pci bar address6761 * @param[in] dev_status - device status6762 *6763 * Return 0 on success, negative error number on error.6764 */6765static u326766bfa_flash_fifo_flush(void __iomem *pci_bar)6767{6768	u32 i;6769	union bfa_flash_dev_status_reg_u dev_status;6770 6771	dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);6772 6773	if (!dev_status.r.fifo_cnt)6774		return 0;6775 6776	/* fifo counter in terms of words */6777	for (i = 0; i < dev_status.r.fifo_cnt; i++)6778		readl(pci_bar + FLI_RDDATA_REG);6779 6780	/*6781	 * Check the device status. It may take some time.6782	 */6783	for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {6784		dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);6785		if (!dev_status.r.fifo_cnt)6786			break;6787	}6788 6789	if (dev_status.r.fifo_cnt)6790		return BFA_FLASH_ERR_FIFO_CNT;6791 6792	return 0;6793}6794 6795/*6796 * @brief6797 * Read flash status.6798 *6799 * @param[in] pci_bar - pci bar address6800 *6801 * Return 0 on success, negative error number on error.6802*/6803static u326804bfa_flash_status_read(void __iomem *pci_bar)6805{6806	union bfa_flash_dev_status_reg_u	dev_status;6807	int				status;6808	u32			ret_status;6809	int				i;6810 6811	status = bfa_flash_fifo_flush(pci_bar);6812	if (status < 0)6813		return status;6814 6815	bfa_flash_set_cmd(pci_bar, 0, 4, 0, BFA_FLASH_READ_STATUS);6816 6817	for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {6818		status = bfa_flash_cmd_act_check(pci_bar);6819		if (!status)6820			break;6821	}6822 6823	if (status)6824		return status;6825 6826	dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);6827	if (!dev_status.r.fifo_cnt)6828		return BFA_FLASH_BUSY;6829 6830	ret_status = readl(pci_bar + FLI_RDDATA_REG);6831	ret_status >>= 24;6832 6833	status = bfa_flash_fifo_flush(pci_bar);6834	if (status < 0)6835		return status;6836 6837	return ret_status;6838}6839 6840/*6841 * @brief6842 * Start flash read operation.6843 *6844 * @param[in] pci_bar - pci bar address6845 * @param[in] offset - flash address offset6846 * @param[in] len - read data length6847 * @param[in] buf - read data buffer6848 *6849 * Return 0 on success, negative error number on error.6850 */6851static u326852bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len,6853			 char *buf)6854{6855	int status;6856 6857	/*6858	 * len must be mutiple of 4 and not exceeding fifo size6859	 */6860	if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0)6861		return BFA_FLASH_ERR_LEN;6862 6863	/*6864	 * check status6865	 */6866	status = bfa_flash_status_read(pci_bar);6867	if (status == BFA_FLASH_BUSY)6868		status = bfa_flash_status_read(pci_bar);6869 6870	if (status < 0)6871		return status;6872 6873	/*6874	 * check if write-in-progress bit is cleared6875	 */6876	if (status & BFA_FLASH_WIP_MASK)6877		return BFA_FLASH_ERR_WIP;6878 6879	bfa_flash_set_addr(pci_bar, offset);6880 6881	bfa_flash_set_cmd(pci_bar, 0, (u8)len, 4, BFA_FLASH_FAST_READ);6882 6883	return 0;6884}6885 6886/*6887 * @brief6888 * Check flash read operation.6889 *6890 * @param[in] pci_bar - pci bar address6891 *6892 * Return flash device status, 1 if busy, 0 if not.6893 */6894static u326895bfa_flash_read_check(void __iomem *pci_bar)6896{6897	if (bfa_flash_cmd_act_check(pci_bar))6898		return 1;6899 6900	return 0;6901}6902 6903/*6904 * @brief6905 * End flash read operation.6906 *6907 * @param[in] pci_bar - pci bar address6908 * @param[in] len - read data length6909 * @param[in] buf - read data buffer6910 *6911 */6912static void6913bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf)6914{6915 6916	u32 i;6917 6918	/*6919	 * read data fifo up to 32 words6920	 */6921	for (i = 0; i < len; i += 4) {6922		u32 w = readl(pci_bar + FLI_RDDATA_REG);6923		*((u32 *) (buf + i)) = swab32(w);6924	}6925 6926	bfa_flash_fifo_flush(pci_bar);6927}6928 6929/*6930 * @brief6931 * Perform flash raw read.6932 *6933 * @param[in] pci_bar - pci bar address6934 * @param[in] offset - flash partition address offset6935 * @param[in] buf - read data buffer6936 * @param[in] len - read data length6937 *6938 * Return status.6939 */6940 6941 6942#define FLASH_BLOCKING_OP_MAX   5006943#define FLASH_SEM_LOCK_REG	0x188206944 6945static int6946bfa_raw_sem_get(void __iomem *bar)6947{6948	int	locked;6949 6950	locked = readl((bar + FLASH_SEM_LOCK_REG));6951	return !locked;6952 6953}6954 6955static bfa_status_t6956bfa_flash_sem_get(void __iomem *bar)6957{6958	u32 n = FLASH_BLOCKING_OP_MAX;6959 6960	while (!bfa_raw_sem_get(bar)) {6961		if (--n <= 0)6962			return BFA_STATUS_BADFLASH;6963		mdelay(10);6964	}6965	return BFA_STATUS_OK;6966}6967 6968static void6969bfa_flash_sem_put(void __iomem *bar)6970{6971	writel(0, (bar + FLASH_SEM_LOCK_REG));6972}6973 6974bfa_status_t6975bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf,6976		       u32 len)6977{6978	u32 n;6979	int status;6980	u32 off, l, s, residue, fifo_sz;6981 6982	residue = len;6983	off = 0;6984	fifo_sz = BFA_FLASH_FIFO_SIZE;6985	status = bfa_flash_sem_get(pci_bar);6986	if (status != BFA_STATUS_OK)6987		return status;6988 6989	while (residue) {6990		s = offset + off;6991		n = s / fifo_sz;6992		l = (n + 1) * fifo_sz - s;6993		if (l > residue)6994			l = residue;6995 6996		status = bfa_flash_read_start(pci_bar, offset + off, l,6997								&buf[off]);6998		if (status < 0) {6999			bfa_flash_sem_put(pci_bar);7000			return BFA_STATUS_FAILED;7001		}7002 7003		n = BFA_FLASH_BLOCKING_OP_MAX;7004		while (bfa_flash_read_check(pci_bar)) {7005			if (--n <= 0) {7006				bfa_flash_sem_put(pci_bar);7007				return BFA_STATUS_FAILED;7008			}7009		}7010 7011		bfa_flash_read_end(pci_bar, l, &buf[off]);7012 7013		residue -= l;7014		off += l;7015	}7016	bfa_flash_sem_put(pci_bar);7017 7018	return BFA_STATUS_OK;7019}7020