cachepc-linux

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

bfa_ioc.c (163781B)


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