brintos

brintos / linux-shallow public Read only

0
0
Text · 77.3 KiB · 9c80ab0 Raw
3378 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Linux network driver for QLogic BR-series Converged Network Adapter.4 */5/*6 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.7 * Copyright (c) 2014-2015 QLogic Corporation8 * All rights reserved9 * www.qlogic.com10 */11 12#include "bfa_ioc.h"13#include "bfi_reg.h"14#include "bfa_defs.h"15 16/* IOC local definitions */17 18/* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. */19 20#define bfa_ioc_firmware_lock(__ioc)			\21			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))22#define bfa_ioc_firmware_unlock(__ioc)			\23			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))24#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))25#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))26#define bfa_ioc_notify_fail(__ioc)			\27			((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))28#define bfa_ioc_sync_start(__ioc)               \29			((__ioc)->ioc_hwif->ioc_sync_start(__ioc))30#define bfa_ioc_sync_join(__ioc)			\31			((__ioc)->ioc_hwif->ioc_sync_join(__ioc))32#define bfa_ioc_sync_leave(__ioc)			\33			((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))34#define bfa_ioc_sync_ack(__ioc)				\35			((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))36#define bfa_ioc_sync_complete(__ioc)			\37			((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))38#define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate)		\39			((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate))40#define bfa_ioc_get_cur_ioc_fwstate(__ioc)		\41			((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc))42#define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate)		\43		((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate))44 45static bool bfa_nw_auto_recover = true;46 47/*48 * forward declarations49 */50static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);51static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);52static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);53static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);54static void bfa_ioc_poll_fwinit(struct bfa_ioc *ioc);55static void bfa_ioc_send_enable(struct bfa_ioc *ioc);56static void bfa_ioc_send_disable(struct bfa_ioc *ioc);57static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);58static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);59static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);60static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);61static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);62static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);63static void bfa_ioc_recover(struct bfa_ioc *ioc);64static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);65static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);66static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);67static void bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc);68static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);69static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);70static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);71static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);72static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);73static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);74static enum bfa_status bfa_ioc_boot(struct bfa_ioc *ioc,75			enum bfi_fwboot_type boot_type, u32 boot_param);76static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);77static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,78						char *serial_num);79static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc,80						char *fw_ver);81static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc,82						char *chip_rev);83static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc,84						char *optrom_ver);85static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc,86						char *manufacturer);87static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);88static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);89 90/* IOC state machine definitions/declarations */91enum ioc_event {92	IOC_E_RESET		= 1,	/*!< IOC reset request		*/93	IOC_E_ENABLE		= 2,	/*!< IOC enable request		*/94	IOC_E_DISABLE		= 3,	/*!< IOC disable request	*/95	IOC_E_DETACH		= 4,	/*!< driver detach cleanup	*/96	IOC_E_ENABLED		= 5,	/*!< f/w enabled		*/97	IOC_E_FWRSP_GETATTR	= 6,	/*!< IOC get attribute response	*/98	IOC_E_DISABLED		= 7,	/*!< f/w disabled		*/99	IOC_E_PFFAILED		= 8,	/*!< failure notice by iocpf sm	*/100	IOC_E_HBFAIL		= 9,	/*!< heartbeat failure		*/101	IOC_E_HWERROR		= 10,	/*!< hardware error interrupt	*/102	IOC_E_TIMEOUT		= 11,	/*!< timeout			*/103	IOC_E_HWFAILED		= 12,	/*!< PCI mapping failure notice	*/104};105 106bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);107bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);108bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);109bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);110bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);111bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);112bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);113bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);114bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);115bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);116 117static struct ioc_sm_table_s ioc_sm_table[] = {118	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},119	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},120	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},121	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},122	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},123	{BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},124	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},125	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},126	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},127	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},128};129 130/*131 * Forward declareations for iocpf state machine132 */133static void bfa_iocpf_enable(struct bfa_ioc *ioc);134static void bfa_iocpf_disable(struct bfa_ioc *ioc);135static void bfa_iocpf_fail(struct bfa_ioc *ioc);136static void bfa_iocpf_initfail(struct bfa_ioc *ioc);137static void bfa_iocpf_getattrfail(struct bfa_ioc *ioc);138static void bfa_iocpf_stop(struct bfa_ioc *ioc);139 140/* IOCPF state machine events */141enum iocpf_event {142	IOCPF_E_ENABLE		= 1,	/*!< IOCPF enable request	*/143	IOCPF_E_DISABLE		= 2,	/*!< IOCPF disable request	*/144	IOCPF_E_STOP		= 3,	/*!< stop on driver detach	*/145	IOCPF_E_FWREADY		= 4,	/*!< f/w initialization done	*/146	IOCPF_E_FWRSP_ENABLE	= 5,	/*!< enable f/w response	*/147	IOCPF_E_FWRSP_DISABLE	= 6,	/*!< disable f/w response	*/148	IOCPF_E_FAIL		= 7,	/*!< failure notice by ioc sm	*/149	IOCPF_E_INITFAIL	= 8,	/*!< init fail notice by ioc sm	*/150	IOCPF_E_GETATTRFAIL	= 9,	/*!< init fail notice by ioc sm	*/151	IOCPF_E_SEMLOCKED	= 10,   /*!< h/w semaphore is locked	*/152	IOCPF_E_TIMEOUT		= 11,   /*!< f/w response timeout	*/153	IOCPF_E_SEM_ERROR	= 12,   /*!< h/w sem mapping error	*/154};155 156/* IOCPF states */157enum bfa_iocpf_state {158	BFA_IOCPF_RESET		= 1,	/*!< IOC is in reset state */159	BFA_IOCPF_SEMWAIT	= 2,	/*!< Waiting for IOC h/w semaphore */160	BFA_IOCPF_HWINIT	= 3,	/*!< IOC h/w is being initialized */161	BFA_IOCPF_READY		= 4,	/*!< IOCPF is initialized */162	BFA_IOCPF_INITFAIL	= 5,	/*!< IOCPF failed */163	BFA_IOCPF_FAIL		= 6,	/*!< IOCPF failed */164	BFA_IOCPF_DISABLING	= 7,	/*!< IOCPF is being disabled */165	BFA_IOCPF_DISABLED	= 8,	/*!< IOCPF is disabled */166	BFA_IOCPF_FWMISMATCH	= 9,	/*!< IOC f/w different from drivers */167};168 169bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf, enum iocpf_event);170bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf, enum iocpf_event);171bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf, enum iocpf_event);172bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf, enum iocpf_event);173bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf, enum iocpf_event);174bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf, enum iocpf_event);175bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf, enum iocpf_event);176bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf,177						enum iocpf_event);178bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf, enum iocpf_event);179bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf, enum iocpf_event);180bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf, enum iocpf_event);181bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf, enum iocpf_event);182bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf,183						enum iocpf_event);184bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf, enum iocpf_event);185 186static struct iocpf_sm_table_s iocpf_sm_table[] = {187	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},188	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},189	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},190	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},191	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},192	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},193	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},194	{BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},195	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},196	{BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},197	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},198	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},199	{BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},200	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},201};202 203/* IOC State Machine */204 205/* Beginning state. IOC uninit state. */206static void207bfa_ioc_sm_uninit_entry(struct bfa_ioc *ioc)208{209}210 211/* IOC is in uninit state. */212static void213bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)214{215	switch (event) {216	case IOC_E_RESET:217		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);218		break;219 220	default:221		bfa_sm_fault(event);222	}223}224 225/* Reset entry actions -- initialize state machine */226static void227bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)228{229	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);230}231 232/* IOC is in reset state. */233static void234bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)235{236	switch (event) {237	case IOC_E_ENABLE:238		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);239		break;240 241	case IOC_E_DISABLE:242		bfa_ioc_disable_comp(ioc);243		break;244 245	case IOC_E_DETACH:246		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);247		break;248 249	default:250		bfa_sm_fault(event);251	}252}253 254static void255bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)256{257	bfa_iocpf_enable(ioc);258}259 260/* Host IOC function is being enabled, awaiting response from firmware.261 * Semaphore is acquired.262 */263static void264bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)265{266	switch (event) {267	case IOC_E_ENABLED:268		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);269		break;270 271	case IOC_E_PFFAILED:272		fallthrough;273	case IOC_E_HWERROR:274		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);275		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);276		if (event != IOC_E_PFFAILED)277			bfa_iocpf_initfail(ioc);278		break;279 280	case IOC_E_HWFAILED:281		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);282		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);283		break;284 285	case IOC_E_DISABLE:286		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);287		break;288 289	case IOC_E_DETACH:290		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);291		bfa_iocpf_stop(ioc);292		break;293 294	case IOC_E_ENABLE:295		break;296 297	default:298		bfa_sm_fault(event);299	}300}301 302/* Semaphore should be acquired for version check. */303static void304bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)305{306	mod_timer(&ioc->ioc_timer, jiffies +307		msecs_to_jiffies(BFA_IOC_TOV));308	bfa_ioc_send_getattr(ioc);309}310 311/* IOC configuration in progress. Timer is active. */312static void313bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)314{315	switch (event) {316	case IOC_E_FWRSP_GETATTR:317		del_timer(&ioc->ioc_timer);318		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);319		break;320 321	case IOC_E_PFFAILED:322	case IOC_E_HWERROR:323		del_timer(&ioc->ioc_timer);324		fallthrough;325	case IOC_E_TIMEOUT:326		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);327		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);328		if (event != IOC_E_PFFAILED)329			bfa_iocpf_getattrfail(ioc);330		break;331 332	case IOC_E_DISABLE:333		del_timer(&ioc->ioc_timer);334		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);335		break;336 337	case IOC_E_ENABLE:338		break;339 340	default:341		bfa_sm_fault(event);342	}343}344 345static void346bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)347{348	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);349	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);350	bfa_ioc_hb_monitor(ioc);351}352 353static void354bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)355{356	switch (event) {357	case IOC_E_ENABLE:358		break;359 360	case IOC_E_DISABLE:361		bfa_ioc_hb_stop(ioc);362		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);363		break;364 365	case IOC_E_PFFAILED:366	case IOC_E_HWERROR:367		bfa_ioc_hb_stop(ioc);368		fallthrough;369 370	case IOC_E_HBFAIL:371		if (ioc->iocpf.auto_recover)372			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);373		else374			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);375 376		bfa_ioc_fail_notify(ioc);377 378		if (event != IOC_E_PFFAILED)379			bfa_iocpf_fail(ioc);380		break;381 382	default:383		bfa_sm_fault(event);384	}385}386 387static void388bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)389{390	bfa_iocpf_disable(ioc);391}392 393/* IOC is being disabled */394static void395bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)396{397	switch (event) {398	case IOC_E_DISABLED:399		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);400		break;401 402	case IOC_E_HWERROR:403		/*404		 * No state change.  Will move to disabled state405		 * after iocpf sm completes failure processing and406		 * moves to disabled state.407		 */408		bfa_iocpf_fail(ioc);409		break;410 411	case IOC_E_HWFAILED:412		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);413		bfa_ioc_disable_comp(ioc);414		break;415 416	default:417		bfa_sm_fault(event);418	}419}420 421/* IOC disable completion entry. */422static void423bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)424{425	bfa_ioc_disable_comp(ioc);426}427 428static void429bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)430{431	switch (event) {432	case IOC_E_ENABLE:433		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);434		break;435 436	case IOC_E_DISABLE:437		ioc->cbfn->disable_cbfn(ioc->bfa);438		break;439 440	case IOC_E_DETACH:441		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);442		bfa_iocpf_stop(ioc);443		break;444 445	default:446		bfa_sm_fault(event);447	}448}449 450static void451bfa_ioc_sm_fail_retry_entry(struct bfa_ioc *ioc)452{453}454 455/* Hardware initialization retry. */456static void457bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)458{459	switch (event) {460	case IOC_E_ENABLED:461		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);462		break;463 464	case IOC_E_PFFAILED:465	case IOC_E_HWERROR:466		/**467		 * Initialization retry failed.468		 */469		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);470		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);471		if (event != IOC_E_PFFAILED)472			bfa_iocpf_initfail(ioc);473		break;474 475	case IOC_E_HWFAILED:476		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);477		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);478		break;479 480	case IOC_E_ENABLE:481		break;482 483	case IOC_E_DISABLE:484		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);485		break;486 487	case IOC_E_DETACH:488		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);489		bfa_iocpf_stop(ioc);490		break;491 492	default:493		bfa_sm_fault(event);494	}495}496 497static void498bfa_ioc_sm_fail_entry(struct bfa_ioc *ioc)499{500}501 502/* IOC failure. */503static void504bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)505{506	switch (event) {507	case IOC_E_ENABLE:508		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);509		break;510 511	case IOC_E_DISABLE:512		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);513		break;514 515	case IOC_E_DETACH:516		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);517		bfa_iocpf_stop(ioc);518		break;519 520	case IOC_E_HWERROR:521		/* HB failure notification, ignore. */522		break;523 524	default:525		bfa_sm_fault(event);526	}527}528 529static void530bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc)531{532}533 534/* IOC failure. */535static void536bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event)537{538	switch (event) {539 540	case IOC_E_ENABLE:541		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);542		break;543 544	case IOC_E_DISABLE:545		ioc->cbfn->disable_cbfn(ioc->bfa);546		break;547 548	case IOC_E_DETACH:549		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);550		break;551 552	default:553		bfa_sm_fault(event);554	}555}556 557/* IOCPF State Machine */558 559/* Reset entry actions -- initialize state machine */560static void561bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)562{563	iocpf->fw_mismatch_notified = false;564	iocpf->auto_recover = bfa_nw_auto_recover;565}566 567/* Beginning state. IOC is in reset state. */568static void569bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event)570{571	switch (event) {572	case IOCPF_E_ENABLE:573		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);574		break;575 576	case IOCPF_E_STOP:577		break;578 579	default:580		bfa_sm_fault(event);581	}582}583 584/* Semaphore should be acquired for version check. */585static void586bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)587{588	bfa_ioc_hw_sem_init(iocpf->ioc);589	bfa_ioc_hw_sem_get(iocpf->ioc);590}591 592/* Awaiting h/w semaphore to continue with version check. */593static void594bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)595{596	struct bfa_ioc *ioc = iocpf->ioc;597 598	switch (event) {599	case IOCPF_E_SEMLOCKED:600		if (bfa_ioc_firmware_lock(ioc)) {601			if (bfa_ioc_sync_start(ioc)) {602				bfa_ioc_sync_join(ioc);603				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);604			} else {605				bfa_ioc_firmware_unlock(ioc);606				bfa_nw_ioc_hw_sem_release(ioc);607				mod_timer(&ioc->sem_timer, jiffies +608					msecs_to_jiffies(BFA_IOC_HWSEM_TOV));609			}610		} else {611			bfa_nw_ioc_hw_sem_release(ioc);612			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);613		}614		break;615 616	case IOCPF_E_SEM_ERROR:617		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);618		bfa_ioc_pf_hwfailed(ioc);619		break;620 621	case IOCPF_E_DISABLE:622		bfa_ioc_hw_sem_get_cancel(ioc);623		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);624		bfa_ioc_pf_disabled(ioc);625		break;626 627	case IOCPF_E_STOP:628		bfa_ioc_hw_sem_get_cancel(ioc);629		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);630		break;631 632	default:633		bfa_sm_fault(event);634	}635}636 637/* Notify enable completion callback */638static void639bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)640{641	/* Call only the first time sm enters fwmismatch state. */642	if (!iocpf->fw_mismatch_notified)643		bfa_ioc_pf_fwmismatch(iocpf->ioc);644 645	iocpf->fw_mismatch_notified = true;646	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +647		msecs_to_jiffies(BFA_IOC_TOV));648}649 650/* Awaiting firmware version match. */651static void652bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)653{654	struct bfa_ioc *ioc = iocpf->ioc;655 656	switch (event) {657	case IOCPF_E_TIMEOUT:658		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);659		break;660 661	case IOCPF_E_DISABLE:662		del_timer(&ioc->iocpf_timer);663		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);664		bfa_ioc_pf_disabled(ioc);665		break;666 667	case IOCPF_E_STOP:668		del_timer(&ioc->iocpf_timer);669		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);670		break;671 672	default:673		bfa_sm_fault(event);674	}675}676 677/* Request for semaphore. */678static void679bfa_iocpf_sm_semwait_entry(struct bfa_iocpf *iocpf)680{681	bfa_ioc_hw_sem_get(iocpf->ioc);682}683 684/* Awaiting semaphore for h/w initialzation. */685static void686bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)687{688	struct bfa_ioc *ioc = iocpf->ioc;689 690	switch (event) {691	case IOCPF_E_SEMLOCKED:692		if (bfa_ioc_sync_complete(ioc)) {693			bfa_ioc_sync_join(ioc);694			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);695		} else {696			bfa_nw_ioc_hw_sem_release(ioc);697			mod_timer(&ioc->sem_timer, jiffies +698				msecs_to_jiffies(BFA_IOC_HWSEM_TOV));699		}700		break;701 702	case IOCPF_E_SEM_ERROR:703		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);704		bfa_ioc_pf_hwfailed(ioc);705		break;706 707	case IOCPF_E_DISABLE:708		bfa_ioc_hw_sem_get_cancel(ioc);709		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);710		break;711 712	default:713		bfa_sm_fault(event);714	}715}716 717static void718bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)719{720	iocpf->poll_time = 0;721	bfa_ioc_reset(iocpf->ioc, false);722}723 724/* Hardware is being initialized. Interrupts are enabled.725 * Holding hardware semaphore lock.726 */727static void728bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)729{730	struct bfa_ioc *ioc = iocpf->ioc;731 732	switch (event) {733	case IOCPF_E_FWREADY:734		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);735		break;736 737	case IOCPF_E_TIMEOUT:738		bfa_nw_ioc_hw_sem_release(ioc);739		bfa_ioc_pf_failed(ioc);740		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);741		break;742 743	case IOCPF_E_DISABLE:744		del_timer(&ioc->iocpf_timer);745		bfa_ioc_sync_leave(ioc);746		bfa_nw_ioc_hw_sem_release(ioc);747		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);748		break;749 750	default:751		bfa_sm_fault(event);752	}753}754 755static void756bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)757{758	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +759		msecs_to_jiffies(BFA_IOC_TOV));760	/**761	 * Enable Interrupts before sending fw IOC ENABLE cmd.762	 */763	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);764	bfa_ioc_send_enable(iocpf->ioc);765}766 767/* Host IOC function is being enabled, awaiting response from firmware.768 * Semaphore is acquired.769 */770static void771bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)772{773	struct bfa_ioc *ioc = iocpf->ioc;774 775	switch (event) {776	case IOCPF_E_FWRSP_ENABLE:777		del_timer(&ioc->iocpf_timer);778		bfa_nw_ioc_hw_sem_release(ioc);779		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);780		break;781 782	case IOCPF_E_INITFAIL:783		del_timer(&ioc->iocpf_timer);784		fallthrough;785 786	case IOCPF_E_TIMEOUT:787		bfa_nw_ioc_hw_sem_release(ioc);788		if (event == IOCPF_E_TIMEOUT)789			bfa_ioc_pf_failed(ioc);790		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);791		break;792 793	case IOCPF_E_DISABLE:794		del_timer(&ioc->iocpf_timer);795		bfa_nw_ioc_hw_sem_release(ioc);796		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);797		break;798 799	default:800		bfa_sm_fault(event);801	}802}803 804static void805bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)806{807	bfa_ioc_pf_enabled(iocpf->ioc);808}809 810static void811bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)812{813	switch (event) {814	case IOCPF_E_DISABLE:815		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);816		break;817 818	case IOCPF_E_GETATTRFAIL:819		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);820		break;821 822	case IOCPF_E_FAIL:823		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);824		break;825 826	default:827		bfa_sm_fault(event);828	}829}830 831static void832bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf)833{834	mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +835		msecs_to_jiffies(BFA_IOC_TOV));836	bfa_ioc_send_disable(iocpf->ioc);837}838 839/* IOC is being disabled */840static void841bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)842{843	struct bfa_ioc *ioc = iocpf->ioc;844 845	switch (event) {846	case IOCPF_E_FWRSP_DISABLE:847		del_timer(&ioc->iocpf_timer);848		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);849		break;850 851	case IOCPF_E_FAIL:852		del_timer(&ioc->iocpf_timer);853		fallthrough;854 855	case IOCPF_E_TIMEOUT:856		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);857		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);858		break;859 860	case IOCPF_E_FWRSP_ENABLE:861		break;862 863	default:864		bfa_sm_fault(event);865	}866}867 868static void869bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf *iocpf)870{871	bfa_ioc_hw_sem_get(iocpf->ioc);872}873 874/* IOC hb ack request is being removed. */875static void876bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)877{878	struct bfa_ioc *ioc = iocpf->ioc;879 880	switch (event) {881	case IOCPF_E_SEMLOCKED:882		bfa_ioc_sync_leave(ioc);883		bfa_nw_ioc_hw_sem_release(ioc);884		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);885		break;886 887	case IOCPF_E_SEM_ERROR:888		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);889		bfa_ioc_pf_hwfailed(ioc);890		break;891 892	case IOCPF_E_FAIL:893		break;894 895	default:896		bfa_sm_fault(event);897	}898}899 900/* IOC disable completion entry. */901static void902bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)903{904	bfa_ioc_mbox_flush(iocpf->ioc);905	bfa_ioc_pf_disabled(iocpf->ioc);906}907 908static void909bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)910{911	struct bfa_ioc *ioc = iocpf->ioc;912 913	switch (event) {914	case IOCPF_E_ENABLE:915		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);916		break;917 918	case IOCPF_E_STOP:919		bfa_ioc_firmware_unlock(ioc);920		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);921		break;922 923	default:924		bfa_sm_fault(event);925	}926}927 928static void929bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)930{931	bfa_nw_ioc_debug_save_ftrc(iocpf->ioc);932	bfa_ioc_hw_sem_get(iocpf->ioc);933}934 935/* Hardware initialization failed. */936static void937bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)938{939	struct bfa_ioc *ioc = iocpf->ioc;940 941	switch (event) {942	case IOCPF_E_SEMLOCKED:943		bfa_ioc_notify_fail(ioc);944		bfa_ioc_sync_leave(ioc);945		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);946		bfa_nw_ioc_hw_sem_release(ioc);947		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);948		break;949 950	case IOCPF_E_SEM_ERROR:951		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);952		bfa_ioc_pf_hwfailed(ioc);953		break;954 955	case IOCPF_E_DISABLE:956		bfa_ioc_hw_sem_get_cancel(ioc);957		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);958		break;959 960	case IOCPF_E_STOP:961		bfa_ioc_hw_sem_get_cancel(ioc);962		bfa_ioc_firmware_unlock(ioc);963		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);964		break;965 966	case IOCPF_E_FAIL:967		break;968 969	default:970		bfa_sm_fault(event);971	}972}973 974static void975bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)976{977}978 979/* Hardware initialization failed. */980static void981bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)982{983	struct bfa_ioc *ioc = iocpf->ioc;984 985	switch (event) {986	case IOCPF_E_DISABLE:987		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);988		break;989 990	case IOCPF_E_STOP:991		bfa_ioc_firmware_unlock(ioc);992		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);993		break;994 995	default:996		bfa_sm_fault(event);997	}998}999 1000static void1001bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)1002{1003	/**1004	 * Mark IOC as failed in hardware and stop firmware.1005	 */1006	bfa_ioc_lpu_stop(iocpf->ioc);1007 1008	/**1009	 * Flush any queued up mailbox requests.1010	 */1011	bfa_ioc_mbox_flush(iocpf->ioc);1012	bfa_ioc_hw_sem_get(iocpf->ioc);1013}1014 1015/* IOC is in failed state. */1016static void1017bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)1018{1019	struct bfa_ioc *ioc = iocpf->ioc;1020 1021	switch (event) {1022	case IOCPF_E_SEMLOCKED:1023		bfa_ioc_sync_ack(ioc);1024		bfa_ioc_notify_fail(ioc);1025		if (!iocpf->auto_recover) {1026			bfa_ioc_sync_leave(ioc);1027			bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);1028			bfa_nw_ioc_hw_sem_release(ioc);1029			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);1030		} else {1031			if (bfa_ioc_sync_complete(ioc))1032				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);1033			else {1034				bfa_nw_ioc_hw_sem_release(ioc);1035				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);1036			}1037		}1038		break;1039 1040	case IOCPF_E_SEM_ERROR:1041		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);1042		bfa_ioc_pf_hwfailed(ioc);1043		break;1044 1045	case IOCPF_E_DISABLE:1046		bfa_ioc_hw_sem_get_cancel(ioc);1047		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);1048		break;1049 1050	case IOCPF_E_FAIL:1051		break;1052 1053	default:1054		bfa_sm_fault(event);1055	}1056}1057 1058static void1059bfa_iocpf_sm_fail_entry(struct bfa_iocpf *iocpf)1060{1061}1062 1063/* IOC is in failed state. */1064static void1065bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)1066{1067	switch (event) {1068	case IOCPF_E_DISABLE:1069		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);1070		break;1071 1072	default:1073		bfa_sm_fault(event);1074	}1075}1076 1077/* BFA IOC private functions */1078 1079/* Notify common modules registered for notification. */1080static void1081bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event)1082{1083	struct bfa_ioc_notify *notify;1084 1085	list_for_each_entry(notify, &ioc->notify_q, qe)1086		notify->cbfn(notify->cbarg, event);1087}1088 1089static void1090bfa_ioc_disable_comp(struct bfa_ioc *ioc)1091{1092	ioc->cbfn->disable_cbfn(ioc->bfa);1093	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);1094}1095 1096bool1097bfa_nw_ioc_sem_get(void __iomem *sem_reg)1098{1099	u32 r32;1100	int cnt = 0;1101#define BFA_SEM_SPINCNT	30001102 1103	r32 = readl(sem_reg);1104 1105	while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {1106		cnt++;1107		udelay(2);1108		r32 = readl(sem_reg);1109	}1110 1111	if (!(r32 & 1))1112		return true;1113 1114	return false;1115}1116 1117void1118bfa_nw_ioc_sem_release(void __iomem *sem_reg)1119{1120	readl(sem_reg);1121	writel(1, sem_reg);1122}1123 1124/* Clear fwver hdr */1125static void1126bfa_ioc_fwver_clear(struct bfa_ioc *ioc)1127{1128	u32 pgnum, loff = 0;1129	int i;1130 1131	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);1132	writel(pgnum, ioc->ioc_regs.host_page_num_fn);1133 1134	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32)); i++) {1135		writel(0, ioc->ioc_regs.smem_page_start + loff);1136		loff += sizeof(u32);1137	}1138}1139 1140 1141static void1142bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)1143{1144	struct bfi_ioc_image_hdr fwhdr;1145	u32 fwstate, r32;1146 1147	/* Spin on init semaphore to serialize. */1148	r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);1149	while (r32 & 0x1) {1150		udelay(20);1151		r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);1152	}1153 1154	fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);1155	if (fwstate == BFI_IOC_UNINIT) {1156		writel(1, ioc->ioc_regs.ioc_init_sem_reg);1157		return;1158	}1159 1160	bfa_nw_ioc_fwver_get(ioc, &fwhdr);1161 1162	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {1163		writel(1, ioc->ioc_regs.ioc_init_sem_reg);1164		return;1165	}1166 1167	bfa_ioc_fwver_clear(ioc);1168	bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT);1169	bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT);1170 1171	/*1172	 * Try to lock and then unlock the semaphore.1173	 */1174	readl(ioc->ioc_regs.ioc_sem_reg);1175	writel(1, ioc->ioc_regs.ioc_sem_reg);1176 1177	/* Unlock init semaphore */1178	writel(1, ioc->ioc_regs.ioc_init_sem_reg);1179}1180 1181static void1182bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)1183{1184	u32	r32;1185 1186	/**1187	 * First read to the semaphore register will return 0, subsequent reads1188	 * will return 1. Semaphore is released by writing 1 to the register1189	 */1190	r32 = readl(ioc->ioc_regs.ioc_sem_reg);1191	if (r32 == ~0) {1192		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);1193		return;1194	}1195	if (!(r32 & 1)) {1196		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);1197		return;1198	}1199 1200	mod_timer(&ioc->sem_timer, jiffies +1201		msecs_to_jiffies(BFA_IOC_HWSEM_TOV));1202}1203 1204void1205bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc)1206{1207	writel(1, ioc->ioc_regs.ioc_sem_reg);1208}1209 1210static void1211bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc)1212{1213	del_timer(&ioc->sem_timer);1214}1215 1216/* Initialize LPU local memory (aka secondary memory / SRAM) */1217static void1218bfa_ioc_lmem_init(struct bfa_ioc *ioc)1219{1220	u32	pss_ctl;1221	int		i;1222#define PSS_LMEM_INIT_TIME  100001223 1224	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1225	pss_ctl &= ~__PSS_LMEM_RESET;1226	pss_ctl |= __PSS_LMEM_INIT_EN;1227 1228	/*1229	 * i2c workaround 12.5khz clock1230	 */1231	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);1232	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1233 1234	/**1235	 * wait for memory initialization to be complete1236	 */1237	i = 0;1238	do {1239		pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1240		i++;1241	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));1242 1243	/**1244	 * If memory initialization is not successful, IOC timeout will catch1245	 * such failures.1246	 */1247	BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));1248 1249	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);1250	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1251}1252 1253static void1254bfa_ioc_lpu_start(struct bfa_ioc *ioc)1255{1256	u32	pss_ctl;1257 1258	/**1259	 * Take processor out of reset.1260	 */1261	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1262	pss_ctl &= ~__PSS_LPU0_RESET;1263 1264	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1265}1266 1267static void1268bfa_ioc_lpu_stop(struct bfa_ioc *ioc)1269{1270	u32	pss_ctl;1271 1272	/**1273	 * Put processors in reset.1274	 */1275	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);1276	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);1277 1278	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);1279}1280 1281/* Get driver and firmware versions. */1282void1283bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)1284{1285	u32	pgnum;1286	u32	loff = 0;1287	int		i;1288	u32	*fwsig = (u32 *) fwhdr;1289 1290	pgnum = bfa_ioc_smem_pgnum(ioc, loff);1291	writel(pgnum, ioc->ioc_regs.host_page_num_fn);1292 1293	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));1294	     i++) {1295		fwsig[i] =1296			swab32(readl(loff + ioc->ioc_regs.smem_page_start));1297		loff += sizeof(u32);1298	}1299}1300 1301static bool1302bfa_ioc_fwver_md5_check(struct bfi_ioc_image_hdr *fwhdr_1,1303			struct bfi_ioc_image_hdr *fwhdr_2)1304{1305	int i;1306 1307	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {1308		if (fwhdr_1->md5sum[i] != fwhdr_2->md5sum[i])1309			return false;1310	}1311 1312	return true;1313}1314 1315/* Returns TRUE if major minor and maintenance are same.1316 * If patch version are same, check for MD5 Checksum to be same.1317 */1318static bool1319bfa_ioc_fw_ver_compatible(struct bfi_ioc_image_hdr *drv_fwhdr,1320			  struct bfi_ioc_image_hdr *fwhdr_to_cmp)1321{1322	if (drv_fwhdr->signature != fwhdr_to_cmp->signature)1323		return false;1324	if (drv_fwhdr->fwver.major != fwhdr_to_cmp->fwver.major)1325		return false;1326	if (drv_fwhdr->fwver.minor != fwhdr_to_cmp->fwver.minor)1327		return false;1328	if (drv_fwhdr->fwver.maint != fwhdr_to_cmp->fwver.maint)1329		return false;1330	if (drv_fwhdr->fwver.patch == fwhdr_to_cmp->fwver.patch &&1331	    drv_fwhdr->fwver.phase == fwhdr_to_cmp->fwver.phase &&1332	    drv_fwhdr->fwver.build == fwhdr_to_cmp->fwver.build)1333		return bfa_ioc_fwver_md5_check(drv_fwhdr, fwhdr_to_cmp);1334 1335	return true;1336}1337 1338static bool1339bfa_ioc_flash_fwver_valid(struct bfi_ioc_image_hdr *flash_fwhdr)1340{1341	if (flash_fwhdr->fwver.major == 0 || flash_fwhdr->fwver.major == 0xFF)1342		return false;1343 1344	return true;1345}1346 1347static bool1348fwhdr_is_ga(struct bfi_ioc_image_hdr *fwhdr)1349{1350	if (fwhdr->fwver.phase == 0 &&1351	    fwhdr->fwver.build == 0)1352		return false;1353 1354	return true;1355}1356 1357/* Returns TRUE if both are compatible and patch of fwhdr_to_cmp is better. */1358static enum bfi_ioc_img_ver_cmp1359bfa_ioc_fw_ver_patch_cmp(struct bfi_ioc_image_hdr *base_fwhdr,1360			 struct bfi_ioc_image_hdr *fwhdr_to_cmp)1361{1362	if (!bfa_ioc_fw_ver_compatible(base_fwhdr, fwhdr_to_cmp))1363		return BFI_IOC_IMG_VER_INCOMP;1364 1365	if (fwhdr_to_cmp->fwver.patch > base_fwhdr->fwver.patch)1366		return BFI_IOC_IMG_VER_BETTER;1367	else if (fwhdr_to_cmp->fwver.patch < base_fwhdr->fwver.patch)1368		return BFI_IOC_IMG_VER_OLD;1369 1370	/* GA takes priority over internal builds of the same patch stream.1371	 * At this point major minor maint and patch numbers are same.1372	 */1373	if (fwhdr_is_ga(base_fwhdr))1374		if (fwhdr_is_ga(fwhdr_to_cmp))1375			return BFI_IOC_IMG_VER_SAME;1376		else1377			return BFI_IOC_IMG_VER_OLD;1378	else1379		if (fwhdr_is_ga(fwhdr_to_cmp))1380			return BFI_IOC_IMG_VER_BETTER;1381 1382	if (fwhdr_to_cmp->fwver.phase > base_fwhdr->fwver.phase)1383		return BFI_IOC_IMG_VER_BETTER;1384	else if (fwhdr_to_cmp->fwver.phase < base_fwhdr->fwver.phase)1385		return BFI_IOC_IMG_VER_OLD;1386 1387	if (fwhdr_to_cmp->fwver.build > base_fwhdr->fwver.build)1388		return BFI_IOC_IMG_VER_BETTER;1389	else if (fwhdr_to_cmp->fwver.build < base_fwhdr->fwver.build)1390		return BFI_IOC_IMG_VER_OLD;1391 1392	/* All Version Numbers are equal.1393	 * Md5 check to be done as a part of compatibility check.1394	 */1395	return BFI_IOC_IMG_VER_SAME;1396}1397 1398/* register definitions */1399#define FLI_CMD_REG			0x0001d0001400#define FLI_WRDATA_REG			0x0001d00c1401#define FLI_RDDATA_REG			0x0001d0101402#define FLI_ADDR_REG			0x0001d0041403#define FLI_DEV_STATUS_REG		0x0001d0141404 1405#define BFA_FLASH_FIFO_SIZE		128	/* fifo size */1406#define BFA_FLASH_CHECK_MAX		10000	/* max # of status check */1407#define BFA_FLASH_BLOCKING_OP_MAX	1000000	/* max # of blocking op check */1408#define BFA_FLASH_WIP_MASK		0x01	/* write in progress bit mask */1409 1410#define NFC_STATE_RUNNING		0x200000011411#define NFC_STATE_PAUSED		0x000045601412#define NFC_VER_VALID			0x1471413 1414enum bfa_flash_cmd {1415	BFA_FLASH_FAST_READ	= 0x0b,	/* fast read */1416	BFA_FLASH_WRITE_ENABLE	= 0x06,	/* write enable */1417	BFA_FLASH_SECTOR_ERASE	= 0xd8,	/* sector erase */1418	BFA_FLASH_WRITE		= 0x02,	/* write */1419	BFA_FLASH_READ_STATUS	= 0x05,	/* read status */1420};1421 1422/* hardware error definition */1423enum bfa_flash_err {1424	BFA_FLASH_NOT_PRESENT	= -1,	/*!< flash not present */1425	BFA_FLASH_UNINIT	= -2,	/*!< flash not initialized */1426	BFA_FLASH_BAD		= -3,	/*!< flash bad */1427	BFA_FLASH_BUSY		= -4,	/*!< flash busy */1428	BFA_FLASH_ERR_CMD_ACT	= -5,	/*!< command active never cleared */1429	BFA_FLASH_ERR_FIFO_CNT	= -6,	/*!< fifo count never cleared */1430	BFA_FLASH_ERR_WIP	= -7,	/*!< write-in-progress never cleared */1431	BFA_FLASH_ERR_TIMEOUT	= -8,	/*!< fli timeout */1432	BFA_FLASH_ERR_LEN	= -9,	/*!< invalid length */1433};1434 1435/* flash command register data structure */1436union bfa_flash_cmd_reg {1437	struct {1438#ifdef __BIG_ENDIAN1439		u32	act:1;1440		u32	rsv:1;1441		u32	write_cnt:9;1442		u32	read_cnt:9;1443		u32	addr_cnt:4;1444		u32	cmd:8;1445#else1446		u32	cmd:8;1447		u32	addr_cnt:4;1448		u32	read_cnt:9;1449		u32	write_cnt:9;1450		u32	rsv:1;1451		u32	act:1;1452#endif1453	} r;1454	u32	i;1455};1456 1457/* flash device status register data structure */1458union bfa_flash_dev_status_reg {1459	struct {1460#ifdef __BIG_ENDIAN1461		u32	rsv:21;1462		u32	fifo_cnt:6;1463		u32	busy:1;1464		u32	init_status:1;1465		u32	present:1;1466		u32	bad:1;1467		u32	good:1;1468#else1469		u32	good:1;1470		u32	bad:1;1471		u32	present:1;1472		u32	init_status:1;1473		u32	busy:1;1474		u32	fifo_cnt:6;1475		u32	rsv:21;1476#endif1477	} r;1478	u32	i;1479};1480 1481/* flash address register data structure */1482union bfa_flash_addr_reg {1483	struct {1484#ifdef __BIG_ENDIAN1485		u32	addr:24;1486		u32	dummy:8;1487#else1488		u32	dummy:8;1489		u32	addr:24;1490#endif1491	} r;1492	u32	i;1493};1494 1495/* Flash raw private functions */1496static void1497bfa_flash_set_cmd(void __iomem *pci_bar, u8 wr_cnt,1498		  u8 rd_cnt, u8 ad_cnt, u8 op)1499{1500	union bfa_flash_cmd_reg cmd;1501 1502	cmd.i = 0;1503	cmd.r.act = 1;1504	cmd.r.write_cnt = wr_cnt;1505	cmd.r.read_cnt = rd_cnt;1506	cmd.r.addr_cnt = ad_cnt;1507	cmd.r.cmd = op;1508	writel(cmd.i, (pci_bar + FLI_CMD_REG));1509}1510 1511static void1512bfa_flash_set_addr(void __iomem *pci_bar, u32 address)1513{1514	union bfa_flash_addr_reg addr;1515 1516	addr.r.addr = address & 0x00ffffff;1517	addr.r.dummy = 0;1518	writel(addr.i, (pci_bar + FLI_ADDR_REG));1519}1520 1521static int1522bfa_flash_cmd_act_check(void __iomem *pci_bar)1523{1524	union bfa_flash_cmd_reg cmd;1525 1526	cmd.i = readl(pci_bar + FLI_CMD_REG);1527 1528	if (cmd.r.act)1529		return BFA_FLASH_ERR_CMD_ACT;1530 1531	return 0;1532}1533 1534/* Flush FLI data fifo. */1535static int1536bfa_flash_fifo_flush(void __iomem *pci_bar)1537{1538	u32 i;1539	union bfa_flash_dev_status_reg dev_status;1540 1541	dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);1542 1543	if (!dev_status.r.fifo_cnt)1544		return 0;1545 1546	/* fifo counter in terms of words */1547	for (i = 0; i < dev_status.r.fifo_cnt; i++)1548		readl(pci_bar + FLI_RDDATA_REG);1549 1550	/* Check the device status. It may take some time. */1551	for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {1552		dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);1553		if (!dev_status.r.fifo_cnt)1554			break;1555	}1556 1557	if (dev_status.r.fifo_cnt)1558		return BFA_FLASH_ERR_FIFO_CNT;1559 1560	return 0;1561}1562 1563/* Read flash status. */1564static int1565bfa_flash_status_read(void __iomem *pci_bar)1566{1567	union bfa_flash_dev_status_reg	dev_status;1568	int				status;1569	u32			ret_status;1570	int				i;1571 1572	status = bfa_flash_fifo_flush(pci_bar);1573	if (status < 0)1574		return status;1575 1576	bfa_flash_set_cmd(pci_bar, 0, 4, 0, BFA_FLASH_READ_STATUS);1577 1578	for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {1579		status = bfa_flash_cmd_act_check(pci_bar);1580		if (!status)1581			break;1582	}1583 1584	if (status)1585		return status;1586 1587	dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);1588	if (!dev_status.r.fifo_cnt)1589		return BFA_FLASH_BUSY;1590 1591	ret_status = readl(pci_bar + FLI_RDDATA_REG);1592	ret_status >>= 24;1593 1594	status = bfa_flash_fifo_flush(pci_bar);1595	if (status < 0)1596		return status;1597 1598	return ret_status;1599}1600 1601/* Start flash read operation. */1602static int1603bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len,1604		     char *buf)1605{1606	int status;1607 1608	/* len must be mutiple of 4 and not exceeding fifo size */1609	if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0)1610		return BFA_FLASH_ERR_LEN;1611 1612	/* check status */1613	status = bfa_flash_status_read(pci_bar);1614	if (status == BFA_FLASH_BUSY)1615		status = bfa_flash_status_read(pci_bar);1616 1617	if (status < 0)1618		return status;1619 1620	/* check if write-in-progress bit is cleared */1621	if (status & BFA_FLASH_WIP_MASK)1622		return BFA_FLASH_ERR_WIP;1623 1624	bfa_flash_set_addr(pci_bar, offset);1625 1626	bfa_flash_set_cmd(pci_bar, 0, (u8)len, 4, BFA_FLASH_FAST_READ);1627 1628	return 0;1629}1630 1631/* Check flash read operation. */1632static u321633bfa_flash_read_check(void __iomem *pci_bar)1634{1635	if (bfa_flash_cmd_act_check(pci_bar))1636		return 1;1637 1638	return 0;1639}1640 1641/* End flash read operation. */1642static void1643bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf)1644{1645	u32 i;1646 1647	/* read data fifo up to 32 words */1648	for (i = 0; i < len; i += 4) {1649		u32 w = readl(pci_bar + FLI_RDDATA_REG);1650		*((u32 *)(buf + i)) = swab32(w);1651	}1652 1653	bfa_flash_fifo_flush(pci_bar);1654}1655 1656/* Perform flash raw read. */1657 1658#define FLASH_BLOCKING_OP_MAX   5001659#define FLASH_SEM_LOCK_REG	0x188201660 1661static int1662bfa_raw_sem_get(void __iomem *bar)1663{1664	int	locked;1665 1666	locked = readl(bar + FLASH_SEM_LOCK_REG);1667 1668	return !locked;1669}1670 1671static enum bfa_status1672bfa_flash_sem_get(void __iomem *bar)1673{1674	u32 n = FLASH_BLOCKING_OP_MAX;1675 1676	while (!bfa_raw_sem_get(bar)) {1677		if (--n <= 0)1678			return BFA_STATUS_BADFLASH;1679		mdelay(10);1680	}1681	return BFA_STATUS_OK;1682}1683 1684static void1685bfa_flash_sem_put(void __iomem *bar)1686{1687	writel(0, (bar + FLASH_SEM_LOCK_REG));1688}1689 1690static enum bfa_status1691bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf,1692		   u32 len)1693{1694	u32 n;1695	int status;1696	u32 off, l, s, residue, fifo_sz;1697 1698	residue = len;1699	off = 0;1700	fifo_sz = BFA_FLASH_FIFO_SIZE;1701	status = bfa_flash_sem_get(pci_bar);1702	if (status != BFA_STATUS_OK)1703		return status;1704 1705	while (residue) {1706		s = offset + off;1707		n = s / fifo_sz;1708		l = (n + 1) * fifo_sz - s;1709		if (l > residue)1710			l = residue;1711 1712		status = bfa_flash_read_start(pci_bar, offset + off, l,1713								&buf[off]);1714		if (status < 0) {1715			bfa_flash_sem_put(pci_bar);1716			return BFA_STATUS_FAILED;1717		}1718 1719		n = BFA_FLASH_BLOCKING_OP_MAX;1720		while (bfa_flash_read_check(pci_bar)) {1721			if (--n <= 0) {1722				bfa_flash_sem_put(pci_bar);1723				return BFA_STATUS_FAILED;1724			}1725		}1726 1727		bfa_flash_read_end(pci_bar, l, &buf[off]);1728 1729		residue -= l;1730		off += l;1731	}1732	bfa_flash_sem_put(pci_bar);1733 1734	return BFA_STATUS_OK;1735}1736 1737#define BFA_FLASH_PART_FWIMG_ADDR	0x100000 /* fw image address */1738 1739static enum bfa_status1740bfa_nw_ioc_flash_img_get_chnk(struct bfa_ioc *ioc, u32 off,1741			      u32 *fwimg)1742{1743	return bfa_flash_raw_read(ioc->pcidev.pci_bar_kva,1744			BFA_FLASH_PART_FWIMG_ADDR + (off * sizeof(u32)),1745			(char *)fwimg, BFI_FLASH_CHUNK_SZ);1746}1747 1748static enum bfi_ioc_img_ver_cmp1749bfa_ioc_flash_fwver_cmp(struct bfa_ioc *ioc,1750			struct bfi_ioc_image_hdr *base_fwhdr)1751{1752	struct bfi_ioc_image_hdr *flash_fwhdr;1753	enum bfa_status status;1754	u32 fwimg[BFI_FLASH_CHUNK_SZ_WORDS];1755 1756	status = bfa_nw_ioc_flash_img_get_chnk(ioc, 0, fwimg);1757	if (status != BFA_STATUS_OK)1758		return BFI_IOC_IMG_VER_INCOMP;1759 1760	flash_fwhdr = (struct bfi_ioc_image_hdr *)fwimg;1761	if (bfa_ioc_flash_fwver_valid(flash_fwhdr))1762		return bfa_ioc_fw_ver_patch_cmp(base_fwhdr, flash_fwhdr);1763	else1764		return BFI_IOC_IMG_VER_INCOMP;1765}1766 1767/*1768 * Returns TRUE if driver is willing to work with current smem f/w version.1769 */1770bool1771bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)1772{1773	struct bfi_ioc_image_hdr *drv_fwhdr;1774	enum bfi_ioc_img_ver_cmp smem_flash_cmp, drv_smem_cmp;1775 1776	drv_fwhdr = (struct bfi_ioc_image_hdr *)1777		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);1778 1779	/* If smem is incompatible or old, driver should not work with it. */1780	drv_smem_cmp = bfa_ioc_fw_ver_patch_cmp(drv_fwhdr, fwhdr);1781	if (drv_smem_cmp == BFI_IOC_IMG_VER_INCOMP ||1782	    drv_smem_cmp == BFI_IOC_IMG_VER_OLD) {1783		return false;1784	}1785 1786	/* IF Flash has a better F/W than smem do not work with smem.1787	 * If smem f/w == flash f/w, as smem f/w not old | incmp, work with it.1788	 * If Flash is old or incomp work with smem iff smem f/w == drv f/w.1789	 */1790	smem_flash_cmp = bfa_ioc_flash_fwver_cmp(ioc, fwhdr);1791 1792	if (smem_flash_cmp == BFI_IOC_IMG_VER_BETTER)1793		return false;1794	else if (smem_flash_cmp == BFI_IOC_IMG_VER_SAME)1795		return true;1796	else1797		return (drv_smem_cmp == BFI_IOC_IMG_VER_SAME) ?1798			true : false;1799}1800 1801/* Return true if current running version is valid. Firmware signature and1802 * execution context (driver/bios) must match.1803 */1804static bool1805bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)1806{1807	struct bfi_ioc_image_hdr fwhdr;1808 1809	bfa_nw_ioc_fwver_get(ioc, &fwhdr);1810	if (swab32(fwhdr.bootenv) != boot_env)1811		return false;1812 1813	return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);1814}1815 1816/* Conditionally flush any pending message from firmware at start. */1817static void1818bfa_ioc_msgflush(struct bfa_ioc *ioc)1819{1820	u32	r32;1821 1822	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);1823	if (r32)1824		writel(1, ioc->ioc_regs.lpu_mbox_cmd);1825}1826 1827static void1828bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)1829{1830	enum bfi_ioc_state ioc_fwstate;1831	bool fwvalid;1832	u32 boot_env;1833 1834	ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);1835 1836	if (force)1837		ioc_fwstate = BFI_IOC_UNINIT;1838 1839	boot_env = BFI_FWBOOT_ENV_OS;1840 1841	/**1842	 * check if firmware is valid1843	 */1844	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?1845		false : bfa_ioc_fwver_valid(ioc, boot_env);1846 1847	if (!fwvalid) {1848		if (bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env) ==1849								BFA_STATUS_OK)1850			bfa_ioc_poll_fwinit(ioc);1851 1852		return;1853	}1854 1855	/**1856	 * If hardware initialization is in progress (initialized by other IOC),1857	 * just wait for an initialization completion interrupt.1858	 */1859	if (ioc_fwstate == BFI_IOC_INITING) {1860		bfa_ioc_poll_fwinit(ioc);1861		return;1862	}1863 1864	/**1865	 * If IOC function is disabled and firmware version is same,1866	 * just re-enable IOC.1867	 */1868	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {1869		/**1870		 * When using MSI-X any pending firmware ready event should1871		 * be flushed. Otherwise MSI-X interrupts are not delivered.1872		 */1873		bfa_ioc_msgflush(ioc);1874		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);1875		return;1876	}1877 1878	/**1879	 * Initialize the h/w for any other states.1880	 */1881	if (bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env) ==1882							BFA_STATUS_OK)1883		bfa_ioc_poll_fwinit(ioc);1884}1885 1886void1887bfa_nw_ioc_timeout(struct bfa_ioc *ioc)1888{1889	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);1890}1891 1892static void1893bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len)1894{1895	u32 *msgp = (u32 *) ioc_msg;1896	u32 i;1897 1898	BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX));1899 1900	/*1901	 * first write msg to mailbox registers1902	 */1903	for (i = 0; i < len / sizeof(u32); i++)1904		writel(cpu_to_le32(msgp[i]),1905			      ioc->ioc_regs.hfn_mbox + i * sizeof(u32));1906 1907	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)1908		writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));1909 1910	/*1911	 * write 1 to mailbox CMD to trigger LPU event1912	 */1913	writel(1, ioc->ioc_regs.hfn_mbox_cmd);1914	(void) readl(ioc->ioc_regs.hfn_mbox_cmd);1915}1916 1917static void1918bfa_ioc_send_enable(struct bfa_ioc *ioc)1919{1920	struct bfi_ioc_ctrl_req enable_req;1921 1922	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,1923		    bfa_ioc_portid(ioc));1924	enable_req.clscode = htons(ioc->clscode);1925	enable_req.rsvd = htons(0);1926	/* overflow in 2106 */1927	enable_req.tv_sec = ntohl(ktime_get_real_seconds());1928	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));1929}1930 1931static void1932bfa_ioc_send_disable(struct bfa_ioc *ioc)1933{1934	struct bfi_ioc_ctrl_req disable_req;1935 1936	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,1937		    bfa_ioc_portid(ioc));1938	disable_req.clscode = htons(ioc->clscode);1939	disable_req.rsvd = htons(0);1940	/* overflow in 2106 */1941	disable_req.tv_sec = ntohl(ktime_get_real_seconds());1942	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req));1943}1944 1945static void1946bfa_ioc_send_getattr(struct bfa_ioc *ioc)1947{1948	struct bfi_ioc_getattr_req attr_req;1949 1950	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,1951		    bfa_ioc_portid(ioc));1952	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);1953	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));1954}1955 1956void1957bfa_nw_ioc_hb_check(struct bfa_ioc *ioc)1958{1959	u32 hb_count;1960 1961	hb_count = readl(ioc->ioc_regs.heartbeat);1962	if (ioc->hb_count == hb_count) {1963		bfa_ioc_recover(ioc);1964		return;1965	} else {1966		ioc->hb_count = hb_count;1967	}1968 1969	bfa_ioc_mbox_poll(ioc);1970	mod_timer(&ioc->hb_timer, jiffies +1971		msecs_to_jiffies(BFA_IOC_HB_TOV));1972}1973 1974static void1975bfa_ioc_hb_monitor(struct bfa_ioc *ioc)1976{1977	ioc->hb_count = readl(ioc->ioc_regs.heartbeat);1978	mod_timer(&ioc->hb_timer, jiffies +1979		msecs_to_jiffies(BFA_IOC_HB_TOV));1980}1981 1982static void1983bfa_ioc_hb_stop(struct bfa_ioc *ioc)1984{1985	del_timer(&ioc->hb_timer);1986}1987 1988/* Initiate a full firmware download. */1989static enum bfa_status1990bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,1991		    u32 boot_env)1992{1993	u32 *fwimg;1994	u32 pgnum;1995	u32 loff = 0;1996	u32 chunkno = 0;1997	u32 i;1998	u32 asicmode;1999	u32 fwimg_size;2000	u32 fwimg_buf[BFI_FLASH_CHUNK_SZ_WORDS];2001	enum bfa_status status;2002 2003	if (boot_env == BFI_FWBOOT_ENV_OS &&2004	    boot_type == BFI_FWBOOT_TYPE_FLASH) {2005		fwimg_size = BFI_FLASH_IMAGE_SZ/sizeof(u32);2006 2007		status = bfa_nw_ioc_flash_img_get_chnk(ioc,2008			BFA_IOC_FLASH_CHUNK_ADDR(chunkno), fwimg_buf);2009		if (status != BFA_STATUS_OK)2010			return status;2011 2012		fwimg = fwimg_buf;2013	} else {2014		fwimg_size = bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc));2015		fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),2016					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));2017	}2018 2019	pgnum = bfa_ioc_smem_pgnum(ioc, loff);2020 2021	writel(pgnum, ioc->ioc_regs.host_page_num_fn);2022 2023	for (i = 0; i < fwimg_size; i++) {2024		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {2025			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);2026			if (boot_env == BFI_FWBOOT_ENV_OS &&2027			    boot_type == BFI_FWBOOT_TYPE_FLASH) {2028				status = bfa_nw_ioc_flash_img_get_chnk(ioc,2029					BFA_IOC_FLASH_CHUNK_ADDR(chunkno),2030					fwimg_buf);2031				if (status != BFA_STATUS_OK)2032					return status;2033 2034				fwimg = fwimg_buf;2035			} else {2036				fwimg = bfa_cb_image_get_chunk(2037					bfa_ioc_asic_gen(ioc),2038					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));2039			}2040		}2041 2042		/**2043		 * write smem2044		 */2045		writel(swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]),2046		       ioc->ioc_regs.smem_page_start + loff);2047 2048		loff += sizeof(u32);2049 2050		/**2051		 * handle page offset wrap around2052		 */2053		loff = PSS_SMEM_PGOFF(loff);2054		if (loff == 0) {2055			pgnum++;2056			writel(pgnum,2057				      ioc->ioc_regs.host_page_num_fn);2058		}2059	}2060 2061	writel(bfa_ioc_smem_pgnum(ioc, 0),2062		      ioc->ioc_regs.host_page_num_fn);2063 2064	/*2065	 * Set boot type, env and device mode at the end.2066	*/2067	if (boot_env == BFI_FWBOOT_ENV_OS &&2068	    boot_type == BFI_FWBOOT_TYPE_FLASH) {2069		boot_type = BFI_FWBOOT_TYPE_NORMAL;2070	}2071	asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,2072					ioc->port0_mode, ioc->port1_mode);2073	writel(asicmode, ((ioc->ioc_regs.smem_page_start)2074			+ BFI_FWBOOT_DEVMODE_OFF));2075	writel(boot_type, ((ioc->ioc_regs.smem_page_start)2076			+ (BFI_FWBOOT_TYPE_OFF)));2077	writel(boot_env, ((ioc->ioc_regs.smem_page_start)2078			+ (BFI_FWBOOT_ENV_OFF)));2079	return BFA_STATUS_OK;2080}2081 2082static void2083bfa_ioc_reset(struct bfa_ioc *ioc, bool force)2084{2085	bfa_ioc_hwinit(ioc, force);2086}2087 2088/* BFA ioc enable reply by firmware */2089static void2090bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode,2091			u8 cap_bm)2092{2093	struct bfa_iocpf *iocpf = &ioc->iocpf;2094 2095	ioc->port_mode = ioc->port_mode_cfg = port_mode;2096	ioc->ad_cap_bm = cap_bm;2097	bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);2098}2099 2100/* Update BFA configuration from firmware configuration. */2101static void2102bfa_ioc_getattr_reply(struct bfa_ioc *ioc)2103{2104	struct bfi_ioc_attr *attr = ioc->attr;2105 2106	attr->adapter_prop  = ntohl(attr->adapter_prop);2107	attr->card_type     = ntohl(attr->card_type);2108	attr->maxfrsize	    = ntohs(attr->maxfrsize);2109 2110	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);2111}2112 2113/* Attach time initialization of mbox logic. */2114static void2115bfa_ioc_mbox_attach(struct bfa_ioc *ioc)2116{2117	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;2118	int	mc;2119 2120	INIT_LIST_HEAD(&mod->cmd_q);2121	for (mc = 0; mc < BFI_MC_MAX; mc++) {2122		mod->mbhdlr[mc].cbfn = NULL;2123		mod->mbhdlr[mc].cbarg = ioc->bfa;2124	}2125}2126 2127/* Mbox poll timer -- restarts any pending mailbox requests. */2128static void2129bfa_ioc_mbox_poll(struct bfa_ioc *ioc)2130{2131	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;2132	struct bfa_mbox_cmd *cmd;2133	bfa_mbox_cmd_cbfn_t cbfn;2134	void *cbarg;2135	u32 stat;2136 2137	/**2138	 * If no command pending, do nothing2139	 */2140	if (list_empty(&mod->cmd_q))2141		return;2142 2143	/**2144	 * If previous command is not yet fetched by firmware, do nothing2145	 */2146	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);2147	if (stat)2148		return;2149 2150	/**2151	 * Enqueue command to firmware.2152	 */2153	cmd = list_first_entry(&mod->cmd_q, struct bfa_mbox_cmd, qe);2154	list_del(&cmd->qe);2155	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));2156 2157	/**2158	 * Give a callback to the client, indicating that the command is sent2159	 */2160	if (cmd->cbfn) {2161		cbfn = cmd->cbfn;2162		cbarg = cmd->cbarg;2163		cmd->cbfn = NULL;2164		cbfn(cbarg);2165	}2166}2167 2168/* Cleanup any pending requests. */2169static void2170bfa_ioc_mbox_flush(struct bfa_ioc *ioc)2171{2172	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;2173	struct bfa_mbox_cmd *cmd;2174 2175	while (!list_empty(&mod->cmd_q)) {2176		cmd = list_first_entry(&mod->cmd_q, struct bfa_mbox_cmd, qe);2177		list_del(&cmd->qe);2178	}2179}2180 2181/**2182 * bfa_nw_ioc_smem_read - Read data from SMEM to host through PCI memmap2183 *2184 * @ioc:     memory for IOC2185 * @tbuf:    app memory to store data from smem2186 * @soff:    smem offset2187 * @sz:      size of smem in bytes2188 */2189static int2190bfa_nw_ioc_smem_read(struct bfa_ioc *ioc, void *tbuf, u32 soff, u32 sz)2191{2192	u32 pgnum, loff, r32;2193	int i, len;2194	u32 *buf = tbuf;2195 2196	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);2197	loff = PSS_SMEM_PGOFF(soff);2198 2199	/*2200	 *  Hold semaphore to serialize pll init and fwtrc.2201	*/2202	if (!bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg))2203		return 1;2204 2205	writel(pgnum, ioc->ioc_regs.host_page_num_fn);2206 2207	len = sz/sizeof(u32);2208	for (i = 0; i < len; i++) {2209		r32 = swab32(readl(loff + ioc->ioc_regs.smem_page_start));2210		buf[i] = be32_to_cpu(r32);2211		loff += sizeof(u32);2212 2213		/**2214		 * handle page offset wrap around2215		 */2216		loff = PSS_SMEM_PGOFF(loff);2217		if (loff == 0) {2218			pgnum++;2219			writel(pgnum, ioc->ioc_regs.host_page_num_fn);2220		}2221	}2222 2223	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),2224	       ioc->ioc_regs.host_page_num_fn);2225 2226	/*2227	 * release semaphore2228	 */2229	readl(ioc->ioc_regs.ioc_init_sem_reg);2230	writel(1, ioc->ioc_regs.ioc_init_sem_reg);2231	return 0;2232}2233 2234/* Retrieve saved firmware trace from a prior IOC failure. */2235int2236bfa_nw_ioc_debug_fwtrc(struct bfa_ioc *ioc, void *trcdata, int *trclen)2237{2238	u32 loff = BFI_IOC_TRC_OFF + BNA_DBG_FWTRC_LEN * ioc->port_id;2239	int tlen, status = 0;2240 2241	tlen = *trclen;2242	if (tlen > BNA_DBG_FWTRC_LEN)2243		tlen = BNA_DBG_FWTRC_LEN;2244 2245	status = bfa_nw_ioc_smem_read(ioc, trcdata, loff, tlen);2246	*trclen = tlen;2247	return status;2248}2249 2250/* Save firmware trace if configured. */2251static void2252bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc)2253{2254	int tlen;2255 2256	if (ioc->dbg_fwsave_once) {2257		ioc->dbg_fwsave_once = false;2258		if (ioc->dbg_fwsave_len) {2259			tlen = ioc->dbg_fwsave_len;2260			bfa_nw_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);2261		}2262	}2263}2264 2265/* Retrieve saved firmware trace from a prior IOC failure. */2266int2267bfa_nw_ioc_debug_fwsave(struct bfa_ioc *ioc, void *trcdata, int *trclen)2268{2269	int tlen;2270 2271	if (ioc->dbg_fwsave_len == 0)2272		return BFA_STATUS_ENOFSAVE;2273 2274	tlen = *trclen;2275	if (tlen > ioc->dbg_fwsave_len)2276		tlen = ioc->dbg_fwsave_len;2277 2278	memcpy(trcdata, ioc->dbg_fwsave, tlen);2279	*trclen = tlen;2280	return BFA_STATUS_OK;2281}2282 2283static void2284bfa_ioc_fail_notify(struct bfa_ioc *ioc)2285{2286	/**2287	 * Notify driver and common modules registered for notification.2288	 */2289	ioc->cbfn->hbfail_cbfn(ioc->bfa);2290	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);2291	bfa_nw_ioc_debug_save_ftrc(ioc);2292}2293 2294/* IOCPF to IOC interface */2295static void2296bfa_ioc_pf_enabled(struct bfa_ioc *ioc)2297{2298	bfa_fsm_send_event(ioc, IOC_E_ENABLED);2299}2300 2301static void2302bfa_ioc_pf_disabled(struct bfa_ioc *ioc)2303{2304	bfa_fsm_send_event(ioc, IOC_E_DISABLED);2305}2306 2307static void2308bfa_ioc_pf_failed(struct bfa_ioc *ioc)2309{2310	bfa_fsm_send_event(ioc, IOC_E_PFFAILED);2311}2312 2313static void2314bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc)2315{2316	bfa_fsm_send_event(ioc, IOC_E_HWFAILED);2317}2318 2319static void2320bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)2321{2322	/**2323	 * Provide enable completion callback and AEN notification.2324	 */2325	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);2326}2327 2328/* IOC public */2329static enum bfa_status2330bfa_ioc_pll_init(struct bfa_ioc *ioc)2331{2332	/*2333	 *  Hold semaphore so that nobody can access the chip during init.2334	 */2335	bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);2336 2337	bfa_ioc_pll_init_asic(ioc);2338 2339	ioc->pllinit = true;2340 2341	/* Initialize LMEM */2342	bfa_ioc_lmem_init(ioc);2343 2344	/*2345	 *  release semaphore.2346	 */2347	bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);2348 2349	return BFA_STATUS_OK;2350}2351 2352/* Interface used by diag module to do firmware boot with memory test2353 * as the entry vector.2354 */2355static enum bfa_status2356bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,2357		u32 boot_env)2358{2359	struct bfi_ioc_image_hdr *drv_fwhdr;2360	enum bfa_status status;2361	bfa_ioc_stats(ioc, ioc_boots);2362 2363	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)2364		return BFA_STATUS_FAILED;2365	if (boot_env == BFI_FWBOOT_ENV_OS &&2366	    boot_type == BFI_FWBOOT_TYPE_NORMAL) {2367		drv_fwhdr = (struct bfi_ioc_image_hdr *)2368			bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);2369		/* Work with Flash iff flash f/w is better than driver f/w.2370		 * Otherwise push drivers firmware.2371		 */2372		if (bfa_ioc_flash_fwver_cmp(ioc, drv_fwhdr) ==2373			BFI_IOC_IMG_VER_BETTER)2374			boot_type = BFI_FWBOOT_TYPE_FLASH;2375	}2376 2377	/**2378	 * Initialize IOC state of all functions on a chip reset.2379	 */2380	if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {2381		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST);2382		bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST);2383	} else {2384		bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING);2385		bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING);2386	}2387 2388	bfa_ioc_msgflush(ioc);2389	status = bfa_ioc_download_fw(ioc, boot_type, boot_env);2390	if (status == BFA_STATUS_OK)2391		bfa_ioc_lpu_start(ioc);2392	else2393		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);2394 2395	return status;2396}2397 2398/* Enable/disable IOC failure auto recovery. */2399void2400bfa_nw_ioc_auto_recover(bool auto_recover)2401{2402	bfa_nw_auto_recover = auto_recover;2403}2404 2405static bool2406bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)2407{2408	u32	*msgp = mbmsg;2409	u32	r32;2410	int		i;2411 2412	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);2413	if ((r32 & 1) == 0)2414		return false;2415 2416	/**2417	 * read the MBOX msg2418	 */2419	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));2420	     i++) {2421		r32 = readl(ioc->ioc_regs.lpu_mbox +2422				   i * sizeof(u32));2423		msgp[i] = htonl(r32);2424	}2425 2426	/**2427	 * turn off mailbox interrupt by clearing mailbox status2428	 */2429	writel(1, ioc->ioc_regs.lpu_mbox_cmd);2430	readl(ioc->ioc_regs.lpu_mbox_cmd);2431 2432	return true;2433}2434 2435static void2436bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)2437{2438	union bfi_ioc_i2h_msg_u	*msg;2439	struct bfa_iocpf *iocpf = &ioc->iocpf;2440 2441	msg = (union bfi_ioc_i2h_msg_u *) m;2442 2443	bfa_ioc_stats(ioc, ioc_isrs);2444 2445	switch (msg->mh.msg_id) {2446	case BFI_IOC_I2H_HBEAT:2447		break;2448 2449	case BFI_IOC_I2H_ENABLE_REPLY:2450		bfa_ioc_enable_reply(ioc,2451			(enum bfa_mode)msg->fw_event.port_mode,2452			msg->fw_event.cap_bm);2453		break;2454 2455	case BFI_IOC_I2H_DISABLE_REPLY:2456		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);2457		break;2458 2459	case BFI_IOC_I2H_GETATTR_REPLY:2460		bfa_ioc_getattr_reply(ioc);2461		break;2462 2463	default:2464		BUG_ON(1);2465	}2466}2467 2468/**2469 * bfa_nw_ioc_attach - IOC attach time initialization and setup.2470 *2471 * @ioc:	memory for IOC2472 * @bfa:	driver instance structure2473 * @cbfn:	callback function2474 */2475void2476bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)2477{2478	ioc->bfa	= bfa;2479	ioc->cbfn	= cbfn;2480	ioc->fcmode	= false;2481	ioc->pllinit	= false;2482	ioc->dbg_fwsave_once = true;2483	ioc->iocpf.ioc  = ioc;2484 2485	bfa_ioc_mbox_attach(ioc);2486	INIT_LIST_HEAD(&ioc->notify_q);2487 2488	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);2489	bfa_fsm_send_event(ioc, IOC_E_RESET);2490}2491 2492/* Driver detach time IOC cleanup. */2493void2494bfa_nw_ioc_detach(struct bfa_ioc *ioc)2495{2496	bfa_fsm_send_event(ioc, IOC_E_DETACH);2497 2498	/* Done with detach, empty the notify_q. */2499	INIT_LIST_HEAD(&ioc->notify_q);2500}2501 2502/**2503 * bfa_nw_ioc_pci_init - Setup IOC PCI properties.2504 *2505 * @ioc:	memory for IOC2506 * @pcidev:	PCI device information for this IOC2507 * @clscode:	class code2508 */2509void2510bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,2511		 enum bfi_pcifn_class clscode)2512{2513	ioc->clscode	= clscode;2514	ioc->pcidev	= *pcidev;2515 2516	/**2517	 * Initialize IOC and device personality2518	 */2519	ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;2520	ioc->asic_mode  = BFI_ASIC_MODE_FC;2521 2522	switch (pcidev->device_id) {2523	case PCI_DEVICE_ID_BROCADE_CT:2524		ioc->asic_gen = BFI_ASIC_GEN_CT;2525		ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;2526		ioc->asic_mode  = BFI_ASIC_MODE_ETH;2527		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;2528		ioc->ad_cap_bm = BFA_CM_CNA;2529		break;2530 2531	case BFA_PCI_DEVICE_ID_CT2:2532		ioc->asic_gen = BFI_ASIC_GEN_CT2;2533		if (clscode == BFI_PCIFN_CLASS_FC &&2534			pcidev->ssid == BFA_PCI_CT2_SSID_FC) {2535			ioc->asic_mode  = BFI_ASIC_MODE_FC16;2536			ioc->fcmode = true;2537			ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;2538			ioc->ad_cap_bm = BFA_CM_HBA;2539		} else {2540			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;2541			ioc->asic_mode  = BFI_ASIC_MODE_ETH;2542			if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {2543				ioc->port_mode =2544				ioc->port_mode_cfg = BFA_MODE_CNA;2545				ioc->ad_cap_bm = BFA_CM_CNA;2546			} else {2547				ioc->port_mode =2548				ioc->port_mode_cfg = BFA_MODE_NIC;2549				ioc->ad_cap_bm = BFA_CM_NIC;2550			}2551		}2552		break;2553 2554	default:2555		BUG_ON(1);2556	}2557 2558	/**2559	 * Set asic specific interfaces.2560	 */2561	if (ioc->asic_gen == BFI_ASIC_GEN_CT)2562		bfa_nw_ioc_set_ct_hwif(ioc);2563	else {2564		WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);2565		bfa_nw_ioc_set_ct2_hwif(ioc);2566		bfa_nw_ioc_ct2_poweron(ioc);2567	}2568 2569	bfa_ioc_map_port(ioc);2570	bfa_ioc_reg_init(ioc);2571}2572 2573/**2574 * bfa_nw_ioc_mem_claim - Initialize IOC dma memory2575 *2576 * @ioc:	memory for IOC2577 * @dm_kva:	kernel virtual address of IOC dma memory2578 * @dm_pa:	physical address of IOC dma memory2579 */2580void2581bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc,  u8 *dm_kva, u64 dm_pa)2582{2583	/**2584	 * dma memory for firmware attribute2585	 */2586	ioc->attr_dma.kva = dm_kva;2587	ioc->attr_dma.pa = dm_pa;2588	ioc->attr = (struct bfi_ioc_attr *) dm_kva;2589}2590 2591/* Return size of dma memory required. */2592u322593bfa_nw_ioc_meminfo(void)2594{2595	return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ);2596}2597 2598void2599bfa_nw_ioc_enable(struct bfa_ioc *ioc)2600{2601	bfa_ioc_stats(ioc, ioc_enables);2602	ioc->dbg_fwsave_once = true;2603 2604	bfa_fsm_send_event(ioc, IOC_E_ENABLE);2605}2606 2607void2608bfa_nw_ioc_disable(struct bfa_ioc *ioc)2609{2610	bfa_ioc_stats(ioc, ioc_disables);2611	bfa_fsm_send_event(ioc, IOC_E_DISABLE);2612}2613 2614/* Initialize memory for saving firmware trace. */2615void2616bfa_nw_ioc_debug_memclaim(struct bfa_ioc *ioc, void *dbg_fwsave)2617{2618	ioc->dbg_fwsave = dbg_fwsave;2619	ioc->dbg_fwsave_len = ioc->iocpf.auto_recover ? BNA_DBG_FWTRC_LEN : 0;2620}2621 2622static u322623bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)2624{2625	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);2626}2627 2628/* Register mailbox message handler function, to be called by common modules */2629void2630bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,2631		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)2632{2633	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;2634 2635	mod->mbhdlr[mc].cbfn	= cbfn;2636	mod->mbhdlr[mc].cbarg = cbarg;2637}2638 2639/**2640 * bfa_nw_ioc_mbox_queue - Queue a mailbox command request to firmware.2641 *2642 * @ioc:	IOC instance2643 * @cmd:	Mailbox command2644 * @cbfn:	callback function2645 * @cbarg:	arguments to callback2646 *2647 * Waits if mailbox is busy. Responsibility of caller to serialize2648 */2649bool2650bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd,2651			bfa_mbox_cmd_cbfn_t cbfn, void *cbarg)2652{2653	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;2654	u32			stat;2655 2656	cmd->cbfn = cbfn;2657	cmd->cbarg = cbarg;2658 2659	/**2660	 * If a previous command is pending, queue new command2661	 */2662	if (!list_empty(&mod->cmd_q)) {2663		list_add_tail(&cmd->qe, &mod->cmd_q);2664		return true;2665	}2666 2667	/**2668	 * If mailbox is busy, queue command for poll timer2669	 */2670	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);2671	if (stat) {2672		list_add_tail(&cmd->qe, &mod->cmd_q);2673		return true;2674	}2675 2676	/**2677	 * mailbox is free -- queue command to firmware2678	 */2679	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));2680 2681	return false;2682}2683 2684/* Handle mailbox interrupts */2685void2686bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)2687{2688	struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;2689	struct bfi_mbmsg m;2690	int				mc;2691 2692	if (bfa_ioc_msgget(ioc, &m)) {2693		/**2694		 * Treat IOC message class as special.2695		 */2696		mc = m.mh.msg_class;2697		if (mc == BFI_MC_IOC) {2698			bfa_ioc_isr(ioc, &m);2699			return;2700		}2701 2702		if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))2703			return;2704 2705		mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);2706	}2707 2708	bfa_ioc_lpu_read_stat(ioc);2709 2710	/**2711	 * Try to send pending mailbox commands2712	 */2713	bfa_ioc_mbox_poll(ioc);2714}2715 2716void2717bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)2718{2719	bfa_ioc_stats(ioc, ioc_hbfails);2720	bfa_ioc_stats_hb_count(ioc, ioc->hb_count);2721	bfa_fsm_send_event(ioc, IOC_E_HWERROR);2722}2723 2724/* return true if IOC is disabled */2725bool2726bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc)2727{2728	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||2729		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);2730}2731 2732/* return true if IOC is operational */2733bool2734bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)2735{2736	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);2737}2738 2739/* Add to IOC heartbeat failure notification queue. To be used by common2740 * modules such as cee, port, diag.2741 */2742void2743bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,2744			struct bfa_ioc_notify *notify)2745{2746	list_add_tail(&notify->qe, &ioc->notify_q);2747}2748 2749#define BFA_MFG_NAME "QLogic"2750static void2751bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,2752			 struct bfa_adapter_attr *ad_attr)2753{2754	struct bfi_ioc_attr *ioc_attr;2755 2756	ioc_attr = ioc->attr;2757 2758	bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);2759	bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);2760	bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);2761	bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);2762	memcpy(&ad_attr->vpd, &ioc_attr->vpd,2763		      sizeof(struct bfa_mfg_vpd));2764 2765	ad_attr->nports = bfa_ioc_get_nports(ioc);2766	ad_attr->max_speed = bfa_ioc_speed_sup(ioc);2767 2768	bfa_ioc_get_adapter_model(ioc, ad_attr->model);2769	/* For now, model descr uses same model string */2770	bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);2771 2772	ad_attr->card_type = ioc_attr->card_type;2773	ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);2774 2775	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))2776		ad_attr->prototype = 1;2777	else2778		ad_attr->prototype = 0;2779 2780	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);2781	bfa_nw_ioc_get_mac(ioc, ad_attr->mac);2782 2783	ad_attr->pcie_gen = ioc_attr->pcie_gen;2784	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;2785	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;2786	ad_attr->asic_rev = ioc_attr->asic_rev;2787 2788	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);2789}2790 2791static enum bfa_ioc_type2792bfa_ioc_get_type(struct bfa_ioc *ioc)2793{2794	if (ioc->clscode == BFI_PCIFN_CLASS_ETH)2795		return BFA_IOC_TYPE_LL;2796 2797	BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC));2798 2799	return (ioc->attr->port_mode == BFI_PORT_MODE_FC)2800		? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;2801}2802 2803static void2804bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)2805{2806	memcpy(serial_num,2807			(void *)ioc->attr->brcd_serialnum,2808			BFA_ADAPTER_SERIAL_NUM_LEN);2809}2810 2811static void2812bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)2813{2814	memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);2815}2816 2817static void2818bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)2819{2820	BUG_ON(!(chip_rev));2821 2822	memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN);2823 2824	chip_rev[0] = 'R';2825	chip_rev[1] = 'e';2826	chip_rev[2] = 'v';2827	chip_rev[3] = '-';2828	chip_rev[4] = ioc->attr->asic_rev;2829	chip_rev[5] = '\0';2830}2831 2832static void2833bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)2834{2835	memcpy(optrom_ver, ioc->attr->optrom_version,2836		      BFA_VERSION_LEN);2837}2838 2839static void2840bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)2841{2842	strscpy_pad(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);2843}2844 2845static void2846bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)2847{2848	struct bfi_ioc_attr *ioc_attr;2849 2850	BUG_ON(!(model));2851	memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN);2852 2853	ioc_attr = ioc->attr;2854 2855	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",2856		BFA_MFG_NAME, ioc_attr->card_type);2857}2858 2859static enum bfa_ioc_state2860bfa_ioc_get_state(struct bfa_ioc *ioc)2861{2862	enum bfa_iocpf_state iocpf_st;2863	enum bfa_ioc_state ioc_st = ioc_sm_to_state(ioc_sm_table, ioc->fsm);2864 2865	if (ioc_st == BFA_IOC_ENABLING ||2866		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {2867 2868		iocpf_st = iocpf_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);2869 2870		switch (iocpf_st) {2871		case BFA_IOCPF_SEMWAIT:2872			ioc_st = BFA_IOC_SEMWAIT;2873			break;2874 2875		case BFA_IOCPF_HWINIT:2876			ioc_st = BFA_IOC_HWINIT;2877			break;2878 2879		case BFA_IOCPF_FWMISMATCH:2880			ioc_st = BFA_IOC_FWMISMATCH;2881			break;2882 2883		case BFA_IOCPF_FAIL:2884			ioc_st = BFA_IOC_FAIL;2885			break;2886 2887		case BFA_IOCPF_INITFAIL:2888			ioc_st = BFA_IOC_INITFAIL;2889			break;2890 2891		default:2892			break;2893		}2894	}2895	return ioc_st;2896}2897 2898void2899bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)2900{2901	memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));2902 2903	ioc_attr->state = bfa_ioc_get_state(ioc);2904	ioc_attr->port_id = bfa_ioc_portid(ioc);2905	ioc_attr->port_mode = ioc->port_mode;2906 2907	ioc_attr->port_mode_cfg = ioc->port_mode_cfg;2908	ioc_attr->cap_bm = ioc->ad_cap_bm;2909 2910	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);2911 2912	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);2913 2914	ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc);2915	ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc);2916	ioc_attr->def_fn = bfa_ioc_is_default(ioc);2917	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);2918}2919 2920/* WWN public */2921static u642922bfa_ioc_get_pwwn(struct bfa_ioc *ioc)2923{2924	return ioc->attr->pwwn;2925}2926 2927void2928bfa_nw_ioc_get_mac(struct bfa_ioc *ioc, u8 *mac)2929{2930	ether_addr_copy(mac, ioc->attr->mac);2931}2932 2933/* Firmware failure detected. Start recovery actions. */2934static void2935bfa_ioc_recover(struct bfa_ioc *ioc)2936{2937	pr_crit("Heart Beat of IOC has failed\n");2938	bfa_ioc_stats(ioc, ioc_hbfails);2939	bfa_ioc_stats_hb_count(ioc, ioc->hb_count);2940	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);2941}2942 2943/* BFA IOC PF private functions */2944 2945static void2946bfa_iocpf_enable(struct bfa_ioc *ioc)2947{2948	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);2949}2950 2951static void2952bfa_iocpf_disable(struct bfa_ioc *ioc)2953{2954	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);2955}2956 2957static void2958bfa_iocpf_fail(struct bfa_ioc *ioc)2959{2960	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);2961}2962 2963static void2964bfa_iocpf_initfail(struct bfa_ioc *ioc)2965{2966	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);2967}2968 2969static void2970bfa_iocpf_getattrfail(struct bfa_ioc *ioc)2971{2972	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);2973}2974 2975static void2976bfa_iocpf_stop(struct bfa_ioc *ioc)2977{2978	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);2979}2980 2981void2982bfa_nw_iocpf_timeout(struct bfa_ioc *ioc)2983{2984	enum bfa_iocpf_state iocpf_st;2985 2986	iocpf_st = iocpf_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);2987 2988	if (iocpf_st == BFA_IOCPF_HWINIT)2989		bfa_ioc_poll_fwinit(ioc);2990	else2991		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);2992}2993 2994void2995bfa_nw_iocpf_sem_timeout(struct bfa_ioc *ioc)2996{2997	bfa_ioc_hw_sem_get(ioc);2998}2999 3000static void3001bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)3002{3003	u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);3004 3005	if (fwstate == BFI_IOC_DISABLED) {3006		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);3007		return;3008	}3009 3010	if (ioc->iocpf.poll_time >= BFA_IOC_TOV) {3011		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);3012	} else {3013		ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;3014		mod_timer(&ioc->iocpf_timer, jiffies +3015			msecs_to_jiffies(BFA_IOC_POLL_TOV));3016	}3017}3018 3019/*3020 *	Flash module specific3021 */3022 3023/*3024 * FLASH DMA buffer should be big enough to hold both MFG block and3025 * asic block(64k) at the same time and also should be 2k aligned to3026 * avoid write segement to cross sector boundary.3027 */3028#define BFA_FLASH_SEG_SZ	20483029#define BFA_FLASH_DMA_BUF_SZ	\3030	roundup(0x010000 + sizeof(struct bfa_mfg_block), BFA_FLASH_SEG_SZ)3031 3032static void3033bfa_flash_cb(struct bfa_flash *flash)3034{3035	flash->op_busy = 0;3036	if (flash->cbfn)3037		flash->cbfn(flash->cbarg, flash->status);3038}3039 3040static void3041bfa_flash_notify(void *cbarg, enum bfa_ioc_event event)3042{3043	struct bfa_flash *flash = cbarg;3044 3045	switch (event) {3046	case BFA_IOC_E_DISABLED:3047	case BFA_IOC_E_FAILED:3048		if (flash->op_busy) {3049			flash->status = BFA_STATUS_IOC_FAILURE;3050			flash->cbfn(flash->cbarg, flash->status);3051			flash->op_busy = 0;3052		}3053		break;3054	default:3055		break;3056	}3057}3058 3059/*3060 * Send flash write request.3061 */3062static void3063bfa_flash_write_send(struct bfa_flash *flash)3064{3065	struct bfi_flash_write_req *msg =3066			(struct bfi_flash_write_req *) flash->mb.msg;3067	u32	len;3068 3069	msg->type = be32_to_cpu(flash->type);3070	msg->instance = flash->instance;3071	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);3072	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?3073	       flash->residue : BFA_FLASH_DMA_BUF_SZ;3074	msg->length = be32_to_cpu(len);3075 3076	/* indicate if it's the last msg of the whole write operation */3077	msg->last = (len == flash->residue) ? 1 : 0;3078 3079	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,3080		    bfa_ioc_portid(flash->ioc));3081	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);3082	memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);3083	bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);3084 3085	flash->residue -= len;3086	flash->offset += len;3087}3088 3089/**3090 * bfa_flash_read_send - Send flash read request.3091 *3092 * @cbarg: callback argument3093 */3094static void3095bfa_flash_read_send(void *cbarg)3096{3097	struct bfa_flash *flash = cbarg;3098	struct bfi_flash_read_req *msg =3099			(struct bfi_flash_read_req *) flash->mb.msg;3100	u32	len;3101 3102	msg->type = be32_to_cpu(flash->type);3103	msg->instance = flash->instance;3104	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);3105	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?3106	       flash->residue : BFA_FLASH_DMA_BUF_SZ;3107	msg->length = be32_to_cpu(len);3108	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,3109		    bfa_ioc_portid(flash->ioc));3110	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);3111	bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);3112}3113 3114/**3115 * bfa_flash_intr - Process flash response messages upon receiving interrupts.3116 *3117 * @flasharg: flash structure3118 * @msg: message structure3119 */3120static void3121bfa_flash_intr(void *flasharg, struct bfi_mbmsg *msg)3122{3123	struct bfa_flash *flash = flasharg;3124	u32	status;3125 3126	union {3127		struct bfi_flash_query_rsp *query;3128		struct bfi_flash_write_rsp *write;3129		struct bfi_flash_read_rsp *read;3130		struct bfi_mbmsg   *msg;3131	} m;3132 3133	m.msg = msg;3134 3135	/* receiving response after ioc failure */3136	if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT)3137		return;3138 3139	switch (msg->mh.msg_id) {3140	case BFI_FLASH_I2H_QUERY_RSP:3141		status = be32_to_cpu(m.query->status);3142		if (status == BFA_STATUS_OK) {3143			u32	i;3144			struct bfa_flash_attr *attr, *f;3145 3146			attr = (struct bfa_flash_attr *) flash->ubuf;3147			f = (struct bfa_flash_attr *) flash->dbuf_kva;3148			attr->status = be32_to_cpu(f->status);3149			attr->npart = be32_to_cpu(f->npart);3150			for (i = 0; i < attr->npart; i++) {3151				attr->part[i].part_type =3152					be32_to_cpu(f->part[i].part_type);3153				attr->part[i].part_instance =3154					be32_to_cpu(f->part[i].part_instance);3155				attr->part[i].part_off =3156					be32_to_cpu(f->part[i].part_off);3157				attr->part[i].part_size =3158					be32_to_cpu(f->part[i].part_size);3159				attr->part[i].part_len =3160					be32_to_cpu(f->part[i].part_len);3161				attr->part[i].part_status =3162					be32_to_cpu(f->part[i].part_status);3163			}3164		}3165		flash->status = status;3166		bfa_flash_cb(flash);3167		break;3168	case BFI_FLASH_I2H_WRITE_RSP:3169		status = be32_to_cpu(m.write->status);3170		if (status != BFA_STATUS_OK || flash->residue == 0) {3171			flash->status = status;3172			bfa_flash_cb(flash);3173		} else3174			bfa_flash_write_send(flash);3175		break;3176	case BFI_FLASH_I2H_READ_RSP:3177		status = be32_to_cpu(m.read->status);3178		if (status != BFA_STATUS_OK) {3179			flash->status = status;3180			bfa_flash_cb(flash);3181		} else {3182			u32 len = be32_to_cpu(m.read->length);3183			memcpy(flash->ubuf + flash->offset,3184			       flash->dbuf_kva, len);3185			flash->residue -= len;3186			flash->offset += len;3187			if (flash->residue == 0) {3188				flash->status = status;3189				bfa_flash_cb(flash);3190			} else3191				bfa_flash_read_send(flash);3192		}3193		break;3194	case BFI_FLASH_I2H_BOOT_VER_RSP:3195	case BFI_FLASH_I2H_EVENT:3196		break;3197	default:3198		WARN_ON(1);3199	}3200}3201 3202/*3203 * Flash memory info API.3204 */3205u323206bfa_nw_flash_meminfo(void)3207{3208	return roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);3209}3210 3211/**3212 * bfa_nw_flash_attach - Flash attach API.3213 *3214 * @flash: flash structure3215 * @ioc: ioc structure3216 * @dev: device structure3217 */3218void3219bfa_nw_flash_attach(struct bfa_flash *flash, struct bfa_ioc *ioc, void *dev)3220{3221	flash->ioc = ioc;3222	flash->cbfn = NULL;3223	flash->cbarg = NULL;3224	flash->op_busy = 0;3225 3226	bfa_nw_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);3227	bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);3228	list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);3229}3230 3231/**3232 * bfa_nw_flash_memclaim - Claim memory for flash3233 *3234 * @flash: flash structure3235 * @dm_kva: pointer to virtual memory address3236 * @dm_pa: physical memory address3237 */3238void3239bfa_nw_flash_memclaim(struct bfa_flash *flash, u8 *dm_kva, u64 dm_pa)3240{3241	flash->dbuf_kva = dm_kva;3242	flash->dbuf_pa = dm_pa;3243	memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);3244	dm_kva += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);3245	dm_pa += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);3246}3247 3248/**3249 * bfa_nw_flash_get_attr - Get flash attribute.3250 *3251 * @flash: flash structure3252 * @attr: flash attribute structure3253 * @cbfn: callback function3254 * @cbarg: callback argument3255 *3256 * Return status.3257 */3258enum bfa_status3259bfa_nw_flash_get_attr(struct bfa_flash *flash, struct bfa_flash_attr *attr,3260		      bfa_cb_flash cbfn, void *cbarg)3261{3262	struct bfi_flash_query_req *msg =3263			(struct bfi_flash_query_req *) flash->mb.msg;3264 3265	if (!bfa_nw_ioc_is_operational(flash->ioc))3266		return BFA_STATUS_IOC_NON_OP;3267 3268	if (flash->op_busy)3269		return BFA_STATUS_DEVBUSY;3270 3271	flash->op_busy = 1;3272	flash->cbfn = cbfn;3273	flash->cbarg = cbarg;3274	flash->ubuf = (u8 *) attr;3275 3276	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,3277		    bfa_ioc_portid(flash->ioc));3278	bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr), flash->dbuf_pa);3279	bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);3280 3281	return BFA_STATUS_OK;3282}3283 3284/**3285 * bfa_nw_flash_update_part - Update flash partition.3286 *3287 * @flash: flash structure3288 * @type: flash partition type3289 * @instance: flash partition instance3290 * @buf: update data buffer3291 * @len: data buffer length3292 * @offset: offset relative to the partition starting address3293 * @cbfn: callback function3294 * @cbarg: callback argument3295 *3296 * Return status.3297 */3298enum bfa_status3299bfa_nw_flash_update_part(struct bfa_flash *flash, u32 type, u8 instance,3300			 void *buf, u32 len, u32 offset,3301			 bfa_cb_flash cbfn, void *cbarg)3302{3303	if (!bfa_nw_ioc_is_operational(flash->ioc))3304		return BFA_STATUS_IOC_NON_OP;3305 3306	/*3307	 * 'len' must be in word (4-byte) boundary3308	 */3309	if (!len || (len & 0x03))3310		return BFA_STATUS_FLASH_BAD_LEN;3311 3312	if (type == BFA_FLASH_PART_MFG)3313		return BFA_STATUS_EINVAL;3314 3315	if (flash->op_busy)3316		return BFA_STATUS_DEVBUSY;3317 3318	flash->op_busy = 1;3319	flash->cbfn = cbfn;3320	flash->cbarg = cbarg;3321	flash->type = type;3322	flash->instance = instance;3323	flash->residue = len;3324	flash->offset = 0;3325	flash->addr_off = offset;3326	flash->ubuf = buf;3327 3328	bfa_flash_write_send(flash);3329 3330	return BFA_STATUS_OK;3331}3332 3333/**3334 * bfa_nw_flash_read_part - Read flash partition.3335 *3336 * @flash: flash structure3337 * @type: flash partition type3338 * @instance: flash partition instance3339 * @buf: read data buffer3340 * @len: data buffer length3341 * @offset: offset relative to the partition starting address3342 * @cbfn: callback function3343 * @cbarg: callback argument3344 *3345 * Return status.3346 */3347enum bfa_status3348bfa_nw_flash_read_part(struct bfa_flash *flash, u32 type, u8 instance,3349		       void *buf, u32 len, u32 offset,3350		       bfa_cb_flash cbfn, void *cbarg)3351{3352	if (!bfa_nw_ioc_is_operational(flash->ioc))3353		return BFA_STATUS_IOC_NON_OP;3354 3355	/*3356	 * 'len' must be in word (4-byte) boundary3357	 */3358	if (!len || (len & 0x03))3359		return BFA_STATUS_FLASH_BAD_LEN;3360 3361	if (flash->op_busy)3362		return BFA_STATUS_DEVBUSY;3363 3364	flash->op_busy = 1;3365	flash->cbfn = cbfn;3366	flash->cbarg = cbarg;3367	flash->type = type;3368	flash->instance = instance;3369	flash->residue = len;3370	flash->offset = 0;3371	flash->addr_off = offset;3372	flash->ubuf = buf;3373 3374	bfa_flash_read_send(flash);3375 3376	return BFA_STATUS_OK;3377}3378